17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 522eb7cb5Sgd78059 * Common Development and Distribution License (the "License"). 622eb7cb5Sgd78059 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*57f4a14aSGarrett D'Amore * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * 4-Byte Mouse Protocol 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <sys/param.h> 317c478bd9Sstevel@tonic-gate #include <sys/stream.h> 3222eb7cb5Sgd78059 #include <sys/strsun.h> 337c478bd9Sstevel@tonic-gate #include <sys/vuid_event.h> 34*57f4a14aSGarrett D'Amore #include "vuidmice.h" 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #ifdef VUIDM4P_DEBUG 377c478bd9Sstevel@tonic-gate #define VBUF_SIZE 511 387c478bd9Sstevel@tonic-gate static unsigned char vuidm4p_buf[VBUF_SIZE+1]; 397c478bd9Sstevel@tonic-gate static int vuidm4p_ptr = 0; 407c478bd9Sstevel@tonic-gate #endif 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #define VUID_BUT(b) BUT((b*2)+1) 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate /* 457c478bd9Sstevel@tonic-gate * VUID_BUT(0) BUT(1) LEFT BUTTON 467c478bd9Sstevel@tonic-gate * VUID_BUT(1) BUT(3) RIGHT BUTTON 477c478bd9Sstevel@tonic-gate */ 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #define MOUSE_NUMBUTTONS 3 /* Number of buttons */ 507c478bd9Sstevel@tonic-gate #define MOUSE_BUTTON_M (uchar_t)(0x40) /* Middle button */ 517c478bd9Sstevel@tonic-gate #define MOUSE_BUTTON_L (uchar_t)(0x20) /* Left button */ 527c478bd9Sstevel@tonic-gate #define MOUSE_BUTTON_R (uchar_t)(0x10) /* Right button */ 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate #define MOUSE_START_CODE (uchar_t)(0x40) /* Start code in char */ 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate #define MOUSE_START 0 /* Beginning of packet */ 577c478bd9Sstevel@tonic-gate #define MOUSE_BUTTON 1 /* Got button status */ 587c478bd9Sstevel@tonic-gate #define MOUSE_DELTA_X 2 /* got delta X */ 597c478bd9Sstevel@tonic-gate #define MOUSE_DELTA_Y 3 /* got delta Y */ 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate extern void VUID_PUTNEXT(queue_t *const, uchar_t, uchar_t, uchar_t, int); 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate int 647c478bd9Sstevel@tonic-gate VUID_OPEN(queue_t *const qp) 657c478bd9Sstevel@tonic-gate { 667c478bd9Sstevel@tonic-gate /* 677c478bd9Sstevel@tonic-gate * The current kdmconfig tables imply that this module can be used 687c478bd9Sstevel@tonic-gate * for both 2- and 3- button mice, so based on that evidence we 697c478bd9Sstevel@tonic-gate * can't assume a constant. It should be possible to autodetect 707c478bd9Sstevel@tonic-gate * based on the mouse's startup behavior - "M" means 2 buttons, 717c478bd9Sstevel@tonic-gate * "M3" means 3 buttons - but that's for another day. 727c478bd9Sstevel@tonic-gate */ 737c478bd9Sstevel@tonic-gate STATEP->nbuttons = 0; /* Don't know. */ 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate return (0); 767c478bd9Sstevel@tonic-gate } 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate static void 797c478bd9Sstevel@tonic-gate vuidm4p_sendButtonEvent(queue_t *const qp) 807c478bd9Sstevel@tonic-gate { 817c478bd9Sstevel@tonic-gate int b; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate /* for the LEFT and RIGHT button, see if it has changed */ 847c478bd9Sstevel@tonic-gate for (b = 0; b < 2; b++) { 857c478bd9Sstevel@tonic-gate uchar_t mask = 0x20 >> b; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate if ((STATEP->buttons & mask) != (STATEP->oldbuttons & mask)) 887c478bd9Sstevel@tonic-gate VUID_PUTNEXT(qp, VUID_BUT(b), FE_PAIR_NONE, 0, 897c478bd9Sstevel@tonic-gate ((STATEP->buttons & mask) ? 1 : 0)); 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate void 947c478bd9Sstevel@tonic-gate vuidm4p(queue_t *const qp, mblk_t *mp) 957c478bd9Sstevel@tonic-gate { 967c478bd9Sstevel@tonic-gate int r, code; 977c478bd9Sstevel@tonic-gate unsigned char *bufp; 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate bufp = mp->b_rptr; 10022eb7cb5Sgd78059 r = MBLKL(mp); 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate for (r--; r >= 0; r--) { 1037c478bd9Sstevel@tonic-gate code = *bufp++; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate #ifdef VUIDM4P_DEBUG 1067c478bd9Sstevel@tonic-gate vuidm4p_buf[vuidm4p_ptr] = code; 1077c478bd9Sstevel@tonic-gate vuidm4p_ptr = ((vuidm4p_ptr + 1) & VBUF_SIZE); 1087c478bd9Sstevel@tonic-gate #endif 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate if (code & MOUSE_START_CODE) { 1117c478bd9Sstevel@tonic-gate /* 1127c478bd9Sstevel@tonic-gate * sync it here 1137c478bd9Sstevel@tonic-gate */ 1147c478bd9Sstevel@tonic-gate STATEP->state = MOUSE_START; 1157c478bd9Sstevel@tonic-gate } 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate switch (STATEP->state) { 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * Start state. We stay here if the start code is not 1207c478bd9Sstevel@tonic-gate * received thus forcing us back into sync. When we 1217c478bd9Sstevel@tonic-gate * get a start code the button mask comes with it 1227c478bd9Sstevel@tonic-gate * forcing us to the next state. 1237c478bd9Sstevel@tonic-gate */ 1247c478bd9Sstevel@tonic-gate default: 1257c478bd9Sstevel@tonic-gate case MOUSE_START: 1267c478bd9Sstevel@tonic-gate /* look for sync */ 1277c478bd9Sstevel@tonic-gate if ((code & MOUSE_START_CODE) == 0) 1287c478bd9Sstevel@tonic-gate break; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate STATEP->deltax = STATEP->deltay = 0; 1317c478bd9Sstevel@tonic-gate STATEP->buttons = 0; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* Get the new state for the LEFT & RIGHT Button */ 1347c478bd9Sstevel@tonic-gate STATEP->buttons |= 1357c478bd9Sstevel@tonic-gate (code & (MOUSE_BUTTON_L | MOUSE_BUTTON_R)); 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate /* 1387c478bd9Sstevel@tonic-gate * bits 0 & 1 are bits 6 & 7 of X value 1397c478bd9Sstevel@tonic-gate * (Sign extend them with the cast.) 1407c478bd9Sstevel@tonic-gate */ 1417c478bd9Sstevel@tonic-gate STATEP->deltax = (signed char)((code & 0x03) << 6); 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate /* 1447c478bd9Sstevel@tonic-gate * bits 2 & 3 are bits 6 & 7 of Y value 1457c478bd9Sstevel@tonic-gate * (Sign extend them with the cast.) 1467c478bd9Sstevel@tonic-gate */ 1477c478bd9Sstevel@tonic-gate STATEP->deltay = (signed char)((code & 0x0c) << 4); 1487c478bd9Sstevel@tonic-gate STATEP->state = MOUSE_BUTTON; 1497c478bd9Sstevel@tonic-gate /* go to the next state */ 1507c478bd9Sstevel@tonic-gate break; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate case MOUSE_BUTTON: 1537c478bd9Sstevel@tonic-gate /* 1547c478bd9Sstevel@tonic-gate * We receive the remaining 6 bits of delta x, 1557c478bd9Sstevel@tonic-gate * forcing us to the next state. We just piece the 1567c478bd9Sstevel@tonic-gate * value of delta x together. 1577c478bd9Sstevel@tonic-gate */ 1587c478bd9Sstevel@tonic-gate STATEP->deltax |= code & 0x3f; 1597c478bd9Sstevel@tonic-gate STATEP->state = MOUSE_DELTA_X; 1607c478bd9Sstevel@tonic-gate break; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate /* 1637c478bd9Sstevel@tonic-gate * The last part of delta Y, and the packet *may be* 1647c478bd9Sstevel@tonic-gate * complete 1657c478bd9Sstevel@tonic-gate */ 1667c478bd9Sstevel@tonic-gate case MOUSE_DELTA_X: 1677c478bd9Sstevel@tonic-gate STATEP->deltay |= code & 0x3f; 1687c478bd9Sstevel@tonic-gate STATEP->state = MOUSE_DELTA_Y; 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate STATEP->buttons |= 1717c478bd9Sstevel@tonic-gate (STATEP->oldbuttons & MOUSE_BUTTON_M); 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate /* 1747c478bd9Sstevel@tonic-gate * If we can peek at the next two mouse characters, 1757c478bd9Sstevel@tonic-gate * and neither of them is the start of the next 1767c478bd9Sstevel@tonic-gate * packet, don't use this packet. 1777c478bd9Sstevel@tonic-gate */ 1787c478bd9Sstevel@tonic-gate if (r > 1 && !(bufp[0] & MOUSE_START_CODE) && 1797c478bd9Sstevel@tonic-gate !(bufp[1] & MOUSE_START_CODE)) { 1807c478bd9Sstevel@tonic-gate STATEP->state = MOUSE_START; 1817c478bd9Sstevel@tonic-gate break; 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate if (STATEP->buttons != STATEP->oldbuttons) { 1857c478bd9Sstevel@tonic-gate vuidm4p_sendButtonEvent(qp); 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* 1897c478bd9Sstevel@tonic-gate * remember state 1907c478bd9Sstevel@tonic-gate */ 1917c478bd9Sstevel@tonic-gate STATEP->oldbuttons = STATEP->buttons; 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate /* 1947c478bd9Sstevel@tonic-gate * generate motion Events for delta_x 1957c478bd9Sstevel@tonic-gate */ 1967c478bd9Sstevel@tonic-gate if (STATEP->deltax) 1977c478bd9Sstevel@tonic-gate VUID_PUTNEXT(qp, 1987c478bd9Sstevel@tonic-gate (uchar_t)LOC_X_DELTA, FE_PAIR_ABSOLUTE, 1997c478bd9Sstevel@tonic-gate (uchar_t)LOC_X_ABSOLUTE, STATEP->deltax); 2007c478bd9Sstevel@tonic-gate /* 2017c478bd9Sstevel@tonic-gate * Reverse the Sign for DELTA_Y 2027c478bd9Sstevel@tonic-gate */ 2037c478bd9Sstevel@tonic-gate if (STATEP->deltay) 2047c478bd9Sstevel@tonic-gate VUID_PUTNEXT(qp, 2057c478bd9Sstevel@tonic-gate (uchar_t)LOC_Y_DELTA, FE_PAIR_ABSOLUTE, 2067c478bd9Sstevel@tonic-gate (uchar_t)LOC_Y_ABSOLUTE, -STATEP->deltay); 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate STATEP->deltax = STATEP->deltay = 0; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate /* allow us to keep looking for an optional 4th byte */ 2117c478bd9Sstevel@tonic-gate break; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate case MOUSE_DELTA_Y: 2147c478bd9Sstevel@tonic-gate /* 2157c478bd9Sstevel@tonic-gate * We've seen delta Y. If we do NOT have the sync 2167c478bd9Sstevel@tonic-gate * bit set, this indicates the middle button's status. 2177c478bd9Sstevel@tonic-gate */ 2187c478bd9Sstevel@tonic-gate STATEP->state = MOUSE_START; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate /* 2217c478bd9Sstevel@tonic-gate * if we're here, the fourth byte is indeed present 2227c478bd9Sstevel@tonic-gate * to indicate something with the middle button. 2237c478bd9Sstevel@tonic-gate */ 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* 2267c478bd9Sstevel@tonic-gate * If we can peek at the next mouse character, and 2277c478bd9Sstevel@tonic-gate * its not the start of the next packet, don't use 2287c478bd9Sstevel@tonic-gate * this packet. 2297c478bd9Sstevel@tonic-gate */ 2307c478bd9Sstevel@tonic-gate if (r > 0 && !(bufp[0] & MOUSE_START_CODE)) 2317c478bd9Sstevel@tonic-gate break; 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate /* 2347c478bd9Sstevel@tonic-gate * Check if the byte is a valid middle button state. 2357c478bd9Sstevel@tonic-gate * It must either be 0x00 or 0x20 only. 2367c478bd9Sstevel@tonic-gate */ 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* 2397c478bd9Sstevel@tonic-gate * Get the new state for the MIDDLE Button 2407c478bd9Sstevel@tonic-gate * Left button set in 4th byte indicates that the 2417c478bd9Sstevel@tonic-gate * middle button is pressed, cleared means it 2427c478bd9Sstevel@tonic-gate * has been released. 2437c478bd9Sstevel@tonic-gate */ 2447c478bd9Sstevel@tonic-gate if (code == MOUSE_BUTTON_L) 2457c478bd9Sstevel@tonic-gate STATEP->buttons |= MOUSE_BUTTON_M; 2467c478bd9Sstevel@tonic-gate else if (code == 0) 2477c478bd9Sstevel@tonic-gate STATEP->buttons &= ~MOUSE_BUTTON_M; 2487c478bd9Sstevel@tonic-gate else { 2497c478bd9Sstevel@tonic-gate /* 2507c478bd9Sstevel@tonic-gate * Invalid data in the 4th byte of the packet. 2517c478bd9Sstevel@tonic-gate * Skip this byte. 2527c478bd9Sstevel@tonic-gate */ 2537c478bd9Sstevel@tonic-gate #ifdef VUIDM4P_DEBUG 2547c478bd9Sstevel@tonic-gate vuidm4p_break(); 2557c478bd9Sstevel@tonic-gate #endif 2567c478bd9Sstevel@tonic-gate break; 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate /* 2607c478bd9Sstevel@tonic-gate * generate an Event with the middle button's status 2617c478bd9Sstevel@tonic-gate */ 2627c478bd9Sstevel@tonic-gate if (STATEP->oldbuttons != STATEP->buttons) { 2637c478bd9Sstevel@tonic-gate VUID_PUTNEXT(qp, 2647c478bd9Sstevel@tonic-gate (uchar_t)MS_MIDDLE, FE_PAIR_NONE, 0, 2657c478bd9Sstevel@tonic-gate ((STATEP->buttons & MOUSE_BUTTON_M) ? 2667c478bd9Sstevel@tonic-gate 1 : 0)); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate /* 2707c478bd9Sstevel@tonic-gate * remember state 2717c478bd9Sstevel@tonic-gate */ 2727c478bd9Sstevel@tonic-gate STATEP->oldbuttons = STATEP->buttons; 2737c478bd9Sstevel@tonic-gate break; 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate freemsg(mp); 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate #ifdef VUIDM4P_DEBUG 2817c478bd9Sstevel@tonic-gate int 2827c478bd9Sstevel@tonic-gate vuidm4p_break() 2837c478bd9Sstevel@tonic-gate { 2847c478bd9Sstevel@tonic-gate char buf[VBUF_SIZE+1]; 2857c478bd9Sstevel@tonic-gate int i; 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate for (i = 0; i <= VBUF_SIZE; i++) { 2887c478bd9Sstevel@tonic-gate buf[i] - vuidm4p_buf[vuidm4p_ptr]; 2897c478bd9Sstevel@tonic-gate vuidm4p_ptr = ((vuidm4p_ptr + 1) & VBUF_SIZE); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate for (i = 0; i <= VBUF_SIZE; i++) { 2937c478bd9Sstevel@tonic-gate vuidm4p_buf[i] = buf[i]; 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate #endif 297