SerialMouse.cpp (2085B)
1 #include <i386/io.h> 2 #include <blt/syscall.h> 3 #include <stdio.h> 4 #include "SerialMouse.h" 5 #include "util.h" 6 7 #define POLL 1 8 9 const int kBaudRate = 1200; 10 const int kPortBase = 0x3f8; 11 12 SerialMouse::SerialMouse(int xmax, int ymax) 13 : fXPos(xmax / 2), 14 fYPos(ymax / 2), 15 fXMax(xmax), 16 fYMax(ymax) 17 { 18 unsigned short divisor = 115200 / kBaudRate; 19 20 outb(0, kPortBase + 1); // No interrupts for now 21 outb(0, kPortBase + 4); // clear DTR and RTS 22 23 outb(0x80, kPortBase + 3); // load divisor latch 24 outb((divisor & 0xff), kPortBase); // divisor LSB 25 outb((divisor >> 8), kPortBase + 1); // divisor MSB 26 outb(2, kPortBase + 3); // clear DLAB, set up for 7N1 27 28 outb(3, kPortBase + 4); // Say hello. Raise DTR and RTS 29 if (SerialRead() == 'M') 30 printf("Detected MS serial mouse\n"); 31 } 32 33 34 // The data is sent in 3 byte packets in following format: 35 // D7 D6 D5 D4 D3 D2 D1 D0 36 // 1. X 1 LB RB Y7 Y6 X7 X6 37 // 2. X 0 X5 X4 X3 X2 X1 X0 38 // 3. X 0 Y5 Y4 Y3 Y2 Y1 Y0 39 void SerialMouse::GetPos(int *out_x, int *out_y, int *out_buttons) 40 { 41 char b1; 42 43 // loop until we get to the beginning of a packet 44 while (true) { 45 b1 = SerialRead(); 46 if ((b1 & (1 << 6)) != 0) 47 break; // beginning of packet 48 } 49 50 char b2 = SerialRead(); 51 char b3 = SerialRead(); 52 53 fXPos += (int)(char)((b1 << 6) | (b2 & 0x3f)); 54 fYPos += (int)(char)(((b1 << 4) & 0xc0) | (b3 & 0x3f)); 55 56 fXPos = min(fXPos, fXMax); 57 fXPos = max(fXPos, 0); 58 fYPos = min(fYPos, fYMax); 59 fYPos = max(fYPos, 0); 60 61 *out_buttons = (b1 >> 4) & 3; 62 *out_x = fXPos; 63 *out_y = fYPos; 64 } 65 66 unsigned char SerialMouse::SerialRead() 67 { 68 while (true) { 69 #if POLL 70 while ((inb(kPortBase + 5) & 1) == 0) 71 ; 72 #else 73 os_handle_irq(4); 74 outb(1, kPortBase + 1); // Interrupt on recieve ready 75 os_sleep_irq(); 76 int id = inb(kPortBase + 2); 77 if ((id & 1) == 0 || (id >> 1) != 2) 78 continue; // Not for me 79 #endif 80 81 break; 82 } 83 84 return inb(kPortBase); 85 } 86