openblt

a hobby OS from the late 90s
git clone http://frotz.net/git/openblt.git
Log | Files | Refs | LICENSE

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