+/* TODO: poll_mouse doesn't work (enable remote mode and disable interrupt on init to test) */
+#define STAT_AUX_PENDING (KB_STAT_OUTBUF_FULL | KB_STAT_AUX)
+static inline int aux_pending(void)
+{
+ return (inb(KB_STATUS_PORT) & STAT_AUX_PENDING) == STAT_AUX_PENDING ? 1 : 0;
+}
+
+void poll_mouse(void)
+{
+ static int poll_state;
+ static unsigned char pkt[3];
+ unsigned char rd;
+
+ ser_printf("poll_mouse(%d)\n", poll_state);
+
+ switch(poll_state) {
+ case 0: /* send read mouse command */
+ kb_send_cmd(KB_CMD_PSAUX);
+ kb_send_data(AUX_CMD_READ_MOUSE);
+ ++poll_state;
+ break;
+
+ case 1: /* wait for ACK */
+ if(kb_wait_read()) {// && aux_pending()) {
+ if((rd = kb_read_data()) == KB_ACK) {
+ ++poll_state;
+ } else {
+ ser_printf("poll_mouse state 1: expected ack: %02x\n", (unsigned int)rd);
+ }
+ }
+ break;
+
+ case 2: /* read packet data */
+ case 3:
+ case 4:
+ if(kb_wait_read() && aux_pending()) {
+ int i = poll_state++ - 2;
+ pkt[i] = kb_read_data();
+ }
+ if(poll_state == 5) {
+ ser_printf("proc_mouse_data(%02x %02x %02x)\n", (unsigned int)pkt[0],
+ (unsigned int)pkt[1], (unsigned int)pkt[2]);
+ proc_mouse_data(pkt);
+ poll_state = 0;
+ }
+ break;
+
+ default:
+ ser_printf("poll_mouse reached state: %d\n", poll_state);
+ }
+}
+
+static void proc_mouse_data(unsigned char *data)
+{
+ int dx, dy;
+
+ if(data[0] & AUX_PKT0_OVF_BITS) {
+ /* consensus seems to be that if overflow bits are set, something is
+ * fucked, and it's best to re-initialize the mouse
+ */
+ /*init_mouse();*/
+ } else {
+ bnstate = data[0] & AUX_PKT0_BUTTON_BITS;
+ dx = data[1];
+ dy = data[2];
+
+ if(data[0] & AUX_PKT0_XSIGN) {
+ dx |= 0xffffff00;
+ }
+ if(data[0] & AUX_PKT0_YSIGN) {
+ dy |= 0xffffff00;
+ }
+
+ mx += dx;
+ my -= dy;
+
+ if(mx < bounds[0]) mx = bounds[0];
+ if(mx > bounds[2]) mx = bounds[2];
+ if(my < bounds[1]) my = bounds[1];
+ if(my > bounds[3]) my = bounds[3];
+ }
+}
+