1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * 3-Byte Mouse Protocol 30 */ 31 32 #include <sys/param.h> 33 #include <sys/stream.h> 34 #include <sys/strsun.h> 35 #include <sys/vuid_event.h> 36 #include <sys/vuidmice.h> 37 38 #define VUID_BUT(b) BUT((b*2)+1) 39 40 /* 41 * VUID_BUT(0) BUT(1) LEFT BUTTON 42 * VUID_BUT(1) BUT(3) RIGHT BUTTON 43 */ 44 45 #define MOUSE_BUTTON_L (uchar_t)(0x20) /* Left button pressed */ 46 #define MOUSE_BUTTON_R (uchar_t)(0x10) /* Right button pressed */ 47 48 #define MOUSE_START_CODE (uchar_t)(0x40) /* Start code in char */ 49 50 #define MOUSE_START 0 /* Beginning of packet */ 51 #define MOUSE_BUTTON 1 /* Got button status */ 52 #define MOUSE_DELTA_X 2 /* got delta X */ 53 54 extern void VUID_PUTNEXT(queue_t *const, uchar_t, uchar_t, uchar_t, int); 55 56 int 57 VUID_OPEN(queue_t *const qp) 58 { 59 STATEP->nbuttons = 2; 60 61 return (0); 62 } 63 64 static void 65 vuidm3p_sendButtonEvent(queue_t *const qp) 66 { 67 int b; 68 69 if ((STATEP->buttons == 0x30) && (!STATEP->oldbuttons)) { 70 /* 71 * both buttons going down simultaneously means button 72 * two going down 73 */ 74 vuidm3p_putnext(qp, (uchar_t)MS_MIDDLE, FE_PAIR_NONE, 0, 1); 75 return; 76 } else if ((!STATEP->buttons) && (STATEP->oldbuttons == 0x30)) { 77 /* 78 * both buttons going up simultaneously means button 79 * two going up 80 */ 81 vuidm3p_putnext(qp, (uchar_t)MS_MIDDLE, FE_PAIR_NONE, 0, 0); 82 return; 83 } 84 85 /* 86 * for each button, see if it has changed 87 */ 88 for (b = 0; b < 2; b++) { 89 uchar_t mask = 0x20 >> b; 90 91 if ((STATEP->buttons & mask) != (STATEP->oldbuttons & mask)) 92 VUID_PUTNEXT(qp, VUID_BUT(b), FE_PAIR_NONE, 0, 93 (STATEP->buttons & mask ? 1 : 0)); 94 } 95 } 96 97 void 98 vuidm3p(queue_t *const qp, mblk_t *mp) 99 { 100 int r, code; 101 uchar_t *bufp; 102 103 bufp = mp->b_rptr; 104 r = MBLKL(mp); 105 106 for (r--; r >= 0; r--) { 107 code = *bufp++; 108 109 /* strip the high-order bit (mouse sends 7-bit data) */ 110 code &= 0x7f; 111 112 switch (STATEP->state) { 113 114 /* 115 * Start state. We stay here if the start code is not 116 * received thus forcing us back into sync. When we 117 * get a start code the button mask comes with it 118 * forcing us to the next state. 119 */ 120 121 default: 122 case MOUSE_START: 123 start_code: 124 STATEP->deltax = STATEP->deltay = 0; 125 126 /* look for sync */ 127 if ((code & MOUSE_START_CODE) == 0) 128 break; 129 130 STATEP->buttons = code & 0x30; 131 132 if (STATEP->buttons != STATEP->oldbuttons) { 133 vuidm3p_sendButtonEvent(qp); 134 /* 135 * remember state 136 */ 137 STATEP->oldbuttons = STATEP->buttons; 138 } 139 140 /* 141 * bits 0 & 1 are bits 6 & 7 of X value 142 * (Sign extend them with the cast.) 143 */ 144 STATEP->deltax = (signed char)((code & 0x03) << 6); 145 146 /* 147 * bits 2 & 3 are bits 6 & 7 of Y value 148 * (Sign extend them with the cast.) 149 */ 150 STATEP->deltay = (signed char)((code & 0x0c) << 4); 151 152 /* 153 * go to the next state 154 */ 155 STATEP->state = MOUSE_BUTTON; 156 break; 157 158 /* 159 * We receive the remaining 6 bits of delta x, forcing 160 * us to the next state. We just piece the value of 161 * delta x together. 162 */ 163 case MOUSE_BUTTON: 164 if (code & MOUSE_START_CODE) { 165 STATEP->state = MOUSE_START; 166 goto start_code; /* restart */ 167 } 168 169 STATEP->deltax |= code & 0x3f; 170 STATEP->state = MOUSE_DELTA_X; 171 break; 172 173 /* 174 * The last part of delta Y, and the packet 175 * *may be* complete 176 */ 177 case MOUSE_DELTA_X: 178 if (code & MOUSE_START_CODE) { 179 STATEP->state = MOUSE_START; 180 goto start_code; /* restart */ 181 } 182 183 STATEP->deltay |= code & 0x3f; 184 185 /* 186 * generate motion Event 187 */ 188 if (STATEP->deltax) 189 VUID_PUTNEXT(qp, (uchar_t)LOC_X_DELTA, 190 FE_PAIR_ABSOLUTE, (uchar_t)LOC_X_ABSOLUTE, 191 STATEP->deltax); 192 193 if (STATEP->deltay) 194 VUID_PUTNEXT(qp, (uchar_t)LOC_Y_DELTA, 195 FE_PAIR_ABSOLUTE, (uchar_t)LOC_Y_ABSOLUTE, 196 -STATEP->deltay); 197 198 STATEP->deltax = STATEP->deltay = 0; 199 break; 200 } 201 } 202 203 freemsg(mp); 204 } 205