1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * 2/3/5 Button PS/2 Mouse Protocol 31*0Sstevel@tonic-gate * 32*0Sstevel@tonic-gate * This module dynamically determines the number of buttons on the mouse. 33*0Sstevel@tonic-gate */ 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate #include <sys/param.h> 36*0Sstevel@tonic-gate #include <sys/stream.h> 37*0Sstevel@tonic-gate #include <sys/vuid_event.h> 38*0Sstevel@tonic-gate #include <sys/vuidmice.h> 39*0Sstevel@tonic-gate #include <sys/vuid_wheel.h> 40*0Sstevel@tonic-gate #include <sys/mouse.h> 41*0Sstevel@tonic-gate #include <sys/ddi.h> 42*0Sstevel@tonic-gate #include <sys/sunddi.h> 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate /* 45*0Sstevel@tonic-gate * BUT(1) LEFT BUTTON 46*0Sstevel@tonic-gate * BUT(2) MIDDLE BUTTON (if present) 47*0Sstevel@tonic-gate * BUT(3) RIGHT BUTTON 48*0Sstevel@tonic-gate */ 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate #define PS2_BUTTONMASK 7 /* mask byte zero with this */ 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate #define PS2_BUTTON_L (uchar_t)0x01 /* Left button pressed */ 53*0Sstevel@tonic-gate #define PS2_BUTTON_R (uchar_t)0x02 /* Right button pressed */ 54*0Sstevel@tonic-gate #define PS2_BUTTON_M (uchar_t)0x04 /* Middle button pressed */ 55*0Sstevel@tonic-gate #define PS2_DATA_XSIGN (uchar_t)0x10 /* X data sign bit */ 56*0Sstevel@tonic-gate #define PS2_DATA_YSIGN (uchar_t)0x20 /* Y data sign bit */ 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate #define PS2_START 0 /* Beginning of packet */ 59*0Sstevel@tonic-gate #define PS2_BUTTON 1 /* Got button status */ 60*0Sstevel@tonic-gate #define PS2_MAYBE_REATTACH 2 /* Got button status */ 61*0Sstevel@tonic-gate #define PS2_DELTA_Y 3 /* Got delta X */ 62*0Sstevel@tonic-gate #define PS2_WHEEL_DELTA_Z 4 63*0Sstevel@tonic-gate #define PS2_WHEEL5_DELTA_Z 5 64*0Sstevel@tonic-gate #define PS2_WAIT_RESET_ACK 6 65*0Sstevel@tonic-gate #define PS2_WAIT_RESET_AA 7 66*0Sstevel@tonic-gate #define PS2_WAIT_RESET_00 8 67*0Sstevel@tonic-gate #define PS2_WAIT_SETRES0_ACK1 9 68*0Sstevel@tonic-gate #define PS2_WAIT_SETRES0_ACK2 10 /* -+ must be consecutive */ 69*0Sstevel@tonic-gate #define PS2_WAIT_SCALE1_1_ACK 11 /* | */ 70*0Sstevel@tonic-gate #define PS2_WAIT_SCALE1_2_ACK 12 /* | */ 71*0Sstevel@tonic-gate #define PS2_WAIT_SCALE1_3_ACK 13 /* -+ */ 72*0Sstevel@tonic-gate #define PS2_WAIT_STATREQ_ACK 14 73*0Sstevel@tonic-gate #define PS2_WAIT_STATUS_1 15 74*0Sstevel@tonic-gate #define PS2_WAIT_STATUS_BUTTONS 16 75*0Sstevel@tonic-gate #define PS2_WAIT_STATUS_REV 17 76*0Sstevel@tonic-gate #define PS2_WAIT_STATUS_3 18 77*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL_SMPL1_CMD_ACK 19 /* Set the sample rate to 200 */ 78*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL_SMPL1_RATE_ACK 20 79*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL_SMPL2_CMD_ACK 21 /* Set the sample rate to 200 */ 80*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL_SMPL2_RATE_ACK 22 81*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL_SMPL3_CMD_ACK 23 /* Set the sample rate to 80 */ 82*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL_SMPL3_RATE_ACK 24 83*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL_DEV_CMD 25 84*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL_DEV_ACK 26 /* Detected wheel mouse */ 85*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_SMPL1_CMD_ACK 27 /* Set the sample rate to 200 */ 86*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_SMPL1_RATE_ACK 28 87*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_SMPL2_CMD_ACK 29 /* Set the sample rate to 200 */ 88*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_SMPL2_RATE_ACK 30 89*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_SMPL3_CMD_ACK 31 /* Set the sample rate to 100 */ 90*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_SMPL3_RATE_ACK 32 91*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_DEV_CMD 33 92*0Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_DEV_ACK 34 /* Detected 5 button mouse */ 93*0Sstevel@tonic-gate #define PS2_WAIT_SETRES3_CMD 35 94*0Sstevel@tonic-gate #define PS2_WAIT_SETRES3_ACK1 36 95*0Sstevel@tonic-gate #define PS2_WAIT_SETRES3_ACK2 37 96*0Sstevel@tonic-gate #define PS2_WAIT_STREAM_ACK 38 97*0Sstevel@tonic-gate #define PS2_WAIT_ON_ACK 39 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate #define MSE_AA 0xaa 100*0Sstevel@tonic-gate #define MSE_00 0x00 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate #define MOUSE_MODE_PLAIN 0 /* Normal PS/2 mouse - 3 byte msgs */ 103*0Sstevel@tonic-gate #define MOUSE_MODE_WHEEL 1 /* Wheel mouse - 4 byte msgs */ 104*0Sstevel@tonic-gate #define MOUSE_MODE_WHEEL5 2 /* Wheel + 5 btn mouse - 4 byte msgs */ 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate #define PS2_FLAG_NO_EXTN 0x08 /* Mouse doesn't obey extended cmds */ 107*0Sstevel@tonic-gate #define PS2_FLAG_INIT_DONE 0x01 /* Mouse has been inited successfully */ 108*0Sstevel@tonic-gate #define PS2_FLAG_INIT_TIMEOUT 0x02 /* Mouse init timeout */ 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate /* 111*0Sstevel@tonic-gate * The RESET command takes more time 112*0Sstevel@tonic-gate * before the PS/2 mouse is ready 113*0Sstevel@tonic-gate */ 114*0Sstevel@tonic-gate #define PS2_INIT_TMOUT_RESET 500000 /* 500ms for RESET command */ 115*0Sstevel@tonic-gate #define PS2_INIT_TMOUT_PER_CMD 200000 /* 200ms for each command-response */ 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate #define PS2_MAX_INIT_COUNT 5 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate static void vuidmice_send_wheel_event(queue_t *const, uchar_t, 121*0Sstevel@tonic-gate uchar_t, uchar_t, int); 122*0Sstevel@tonic-gate extern void VUID_PUTNEXT(queue_t *const, uchar_t, uchar_t, uchar_t, int); 123*0Sstevel@tonic-gate extern void uniqtime32(struct timeval32 *); 124*0Sstevel@tonic-gate static void VUID_INIT_TIMEOUT(void *q); 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate /* 127*0Sstevel@tonic-gate * We apply timeout to nearly each command-response 128*0Sstevel@tonic-gate * during initialization: 129*0Sstevel@tonic-gate * 130*0Sstevel@tonic-gate * Set timeout for RESET 131*0Sstevel@tonic-gate * Set timeout for SET RESOLUTION 132*0Sstevel@tonic-gate * Set timeout for SET SCALE 133*0Sstevel@tonic-gate * Set timeout for SET SAMPLE RATE 134*0Sstevel@tonic-gate * Set timeout for STATUS REQUEST 135*0Sstevel@tonic-gate * Set timeout for GET DEV 136*0Sstevel@tonic-gate * Set timeout for SET STREAM MODE and ENABLE. 137*0Sstevel@tonic-gate * 138*0Sstevel@tonic-gate * But for simplicity, sometimes we just apply the timeout 139*0Sstevel@tonic-gate * to a function (e.g. wheel-mouse detection). 140*0Sstevel@tonic-gate * 141*0Sstevel@tonic-gate */ 142*0Sstevel@tonic-gate static void 143*0Sstevel@tonic-gate vuid_set_timeout(queue_t *const qp, clock_t time) 144*0Sstevel@tonic-gate { 145*0Sstevel@tonic-gate ASSERT(STATEP->init_tid == 0); 146*0Sstevel@tonic-gate STATEP->init_tid = qtimeout(qp, VUID_INIT_TIMEOUT, 147*0Sstevel@tonic-gate qp, drv_usectohz(time)); 148*0Sstevel@tonic-gate } 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate static void 151*0Sstevel@tonic-gate vuid_cancel_timeout(queue_t *const qp) 152*0Sstevel@tonic-gate { 153*0Sstevel@tonic-gate ASSERT(STATEP->init_tid != 0); 154*0Sstevel@tonic-gate (void) quntimeout(qp, STATEP->init_tid); 155*0Sstevel@tonic-gate STATEP->init_tid = 0; 156*0Sstevel@tonic-gate } 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate /* 159*0Sstevel@tonic-gate * vuidmice_send_wheel_event 160*0Sstevel@tonic-gate * Convert wheel data to firm_events 161*0Sstevel@tonic-gate */ 162*0Sstevel@tonic-gate static void 163*0Sstevel@tonic-gate vuidmice_send_wheel_event(queue_t *const qp, uchar_t event_id, 164*0Sstevel@tonic-gate uchar_t event_pair_type, uchar_t event_pair, int event_value) 165*0Sstevel@tonic-gate { 166*0Sstevel@tonic-gate mblk_t *bp; 167*0Sstevel@tonic-gate Firm_event *fep; 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate if ((bp = allocb((int)sizeof (Firm_event), BPRI_HI)) == NULL) { 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate return; 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate fep = (Firm_event *)bp->b_wptr; 175*0Sstevel@tonic-gate fep->id = vuid_id_addr(vuid_first(VUID_WHEEL)) | 176*0Sstevel@tonic-gate vuid_id_offset(event_id); 177*0Sstevel@tonic-gate fep->pair_type = event_pair_type; 178*0Sstevel@tonic-gate fep->pair = event_pair; 179*0Sstevel@tonic-gate fep->value = event_value; 180*0Sstevel@tonic-gate uniqtime32(&fep->time); 181*0Sstevel@tonic-gate bp->b_wptr += sizeof (Firm_event); 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate if (canput(qp->q_next)) { 184*0Sstevel@tonic-gate putnext(qp, bp); 185*0Sstevel@tonic-gate } else { 186*0Sstevel@tonic-gate (void) putbq(qp, bp); /* read side is blocked */ 187*0Sstevel@tonic-gate } 188*0Sstevel@tonic-gate } 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate static void 192*0Sstevel@tonic-gate sendButtonEvent(queue_t *const qp) 193*0Sstevel@tonic-gate { 194*0Sstevel@tonic-gate static int bmap[3] = {1, 3, 2}; 195*0Sstevel@tonic-gate uint_t b; 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate /* for each button, see if it has changed */ 198*0Sstevel@tonic-gate for (b = 0; b < STATEP->nbuttons; b++) { 199*0Sstevel@tonic-gate uchar_t mask = 0x1 << b; 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate if ((STATEP->buttons & mask) != (STATEP->oldbuttons & mask)) 202*0Sstevel@tonic-gate VUID_PUTNEXT(qp, (uchar_t)BUT(bmap[b]), FE_PAIR_NONE, 0, 203*0Sstevel@tonic-gate (STATEP->buttons & mask ? 1 : 0)); 204*0Sstevel@tonic-gate } 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate void 208*0Sstevel@tonic-gate put1(queue_t *const qp, int c) 209*0Sstevel@tonic-gate { 210*0Sstevel@tonic-gate mblk_t *bp; 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate if (bp = allocb(1, BPRI_MED)) { 213*0Sstevel@tonic-gate *bp->b_wptr++ = (char)c; 214*0Sstevel@tonic-gate putnext(qp, bp); 215*0Sstevel@tonic-gate } 216*0Sstevel@tonic-gate } 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate int 219*0Sstevel@tonic-gate VUID_OPEN(queue_t *const qp) 220*0Sstevel@tonic-gate { 221*0Sstevel@tonic-gate STATEP->format = VUID_FIRM_EVENT; 222*0Sstevel@tonic-gate STATEP->vuid_mouse_mode = MOUSE_MODE_PLAIN; 223*0Sstevel@tonic-gate STATEP->inited = 0; 224*0Sstevel@tonic-gate STATEP->nbuttons = 3; 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_RESET_ACK; 227*0Sstevel@tonic-gate put1(WR(qp), MSERESET); 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate /* Set timeout for reset */ 230*0Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_RESET); 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate while ((STATEP->state != PS2_START) && 233*0Sstevel@tonic-gate !(STATEP->inited & PS2_FLAG_INIT_TIMEOUT)) { 234*0Sstevel@tonic-gate if (qwait_sig(qp) == 0) 235*0Sstevel@tonic-gate break; 236*0Sstevel@tonic-gate } 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate /* 239*0Sstevel@tonic-gate * Later the PS/2 mouse maybe re-attach, so here 240*0Sstevel@tonic-gate * clear the init_count. 241*0Sstevel@tonic-gate */ 242*0Sstevel@tonic-gate STATEP->init_count = 0; 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate return (0); 245*0Sstevel@tonic-gate } 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate void 248*0Sstevel@tonic-gate VUID_CLOSE(queue_t *const qp) 249*0Sstevel@tonic-gate { 250*0Sstevel@tonic-gate if (STATEP->init_tid != 0) 251*0Sstevel@tonic-gate vuid_cancel_timeout(qp); 252*0Sstevel@tonic-gate } 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate static void 255*0Sstevel@tonic-gate VUID_INIT_TIMEOUT(void *q) 256*0Sstevel@tonic-gate { 257*0Sstevel@tonic-gate queue_t *qp = q; 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate STATEP->init_tid = 0; 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate if ((STATEP->state == PS2_WAIT_WHEEL_SMPL1_RATE_ACK) || 262*0Sstevel@tonic-gate (STATEP->state == PS2_WAIT_WHEEL_SMPL2_RATE_ACK) || 263*0Sstevel@tonic-gate (STATEP->state == PS2_WAIT_WHEEL_SMPL3_RATE_ACK)) { 264*0Sstevel@tonic-gate /* 265*0Sstevel@tonic-gate * We overload 'inited' to mark the PS/2 mouse 266*0Sstevel@tonic-gate * as one which doesn't respond to extended commands. 267*0Sstevel@tonic-gate */ 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate STATEP->inited |= PS2_FLAG_NO_EXTN; 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate if (++STATEP->init_count >= PS2_MAX_INIT_COUNT) { 273*0Sstevel@tonic-gate STATEP->inited |= PS2_FLAG_INIT_TIMEOUT; 274*0Sstevel@tonic-gate return; 275*0Sstevel@tonic-gate } 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_RESET_ACK; 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate /* try again */ 281*0Sstevel@tonic-gate put1(WR(qp), MSERESET); 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_RESET); 284*0Sstevel@tonic-gate } 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate void 287*0Sstevel@tonic-gate VUID_QUEUE(queue_t *const qp, mblk_t *mp) 288*0Sstevel@tonic-gate { 289*0Sstevel@tonic-gate int code; 290*0Sstevel@tonic-gate clock_t now; 291*0Sstevel@tonic-gate clock_t elapsed; 292*0Sstevel@tonic-gate clock_t mouse_timeout; 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate mouse_timeout = drv_usectohz(250000); 295*0Sstevel@tonic-gate now = ddi_get_lbolt(); 296*0Sstevel@tonic-gate elapsed = now - STATEP->last_event_lbolt; 297*0Sstevel@tonic-gate STATEP->last_event_lbolt = now; 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate while (mp->b_rptr < mp->b_wptr) { 300*0Sstevel@tonic-gate code = *mp->b_rptr++; 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate switch (STATEP->state) { 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate /* 305*0Sstevel@tonic-gate * Start state. We stay here if the start code is not 306*0Sstevel@tonic-gate * received thus forcing us back into sync. When we get a 307*0Sstevel@tonic-gate * start code the button mask comes with it forcing us to 308*0Sstevel@tonic-gate * to the next state. 309*0Sstevel@tonic-gate */ 310*0Sstevel@tonic-gate restart: 311*0Sstevel@tonic-gate case PS2_START: 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate /* 314*0Sstevel@tonic-gate * 3-byte packet format 315*0Sstevel@tonic-gate * 316*0Sstevel@tonic-gate * Bit 7 6 5 4 3 2 1 0 317*0Sstevel@tonic-gate * Byte ---- ---- ----- ----- -- ------ ------ ------ 318*0Sstevel@tonic-gate * 1 Y_Ov X_Ov Y_Sgn X_Sgn 1 MdlBtn RgtBtn LftBtn 319*0Sstevel@tonic-gate * 2 |<--------------X Movement----------------->| 320*0Sstevel@tonic-gate * 3 |<--------------Y Movement----------------->| 321*0Sstevel@tonic-gate * 322*0Sstevel@tonic-gate * 4-byte wheel packet format 323*0Sstevel@tonic-gate * 324*0Sstevel@tonic-gate * Bit 7 6 5 4 3 2 1 0 325*0Sstevel@tonic-gate * Byte ---- ---- ----- ----- -- ------ ------ ------ 326*0Sstevel@tonic-gate * 1 Y_Ov X_Ov Y_Sgn X_Sgn 1 MdlBtn RgtBtn LftBtn 327*0Sstevel@tonic-gate * 2 |<--------------X Movement----------------->| 328*0Sstevel@tonic-gate * 3 |<--------------Y Movement----------------->| 329*0Sstevel@tonic-gate * 4 |<--------------Z Movement----------------->| 330*0Sstevel@tonic-gate * 331*0Sstevel@tonic-gate * 4-byte wheel+5 packet format 332*0Sstevel@tonic-gate * 333*0Sstevel@tonic-gate * Bit 7 6 5 4 3 2 1 0 334*0Sstevel@tonic-gate * Byte ---- ---- ----- ----- -- ------ ------ ------ 335*0Sstevel@tonic-gate * 1 Y_Ov X_Ov Y_Sgn X_Sgn 1 MdlBtn RgtBtn LftBtn 336*0Sstevel@tonic-gate * 2 |<--------------X Movement----------------->| 337*0Sstevel@tonic-gate * 3 |<--------------Y Movement----------------->| 338*0Sstevel@tonic-gate * 4 0 0 5_Btn 4_Btn Z3 Z2 Z1 Z0 339*0Sstevel@tonic-gate */ 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate if (!(STATEP->inited & PS2_FLAG_INIT_DONE)) { 342*0Sstevel@tonic-gate STATEP->sync_byte = code & 0x8; 343*0Sstevel@tonic-gate STATEP->inited |= PS2_FLAG_INIT_DONE; 344*0Sstevel@tonic-gate } 345*0Sstevel@tonic-gate /* 346*0Sstevel@tonic-gate * the PS/2 mouse data format doesn't have any sort of sync 347*0Sstevel@tonic-gate * data to make sure we are in sync with the packet stream, 348*0Sstevel@tonic-gate * but the Technical Reference manual states that bits 2 & 3 349*0Sstevel@tonic-gate * of the first byte are reserved. Logitech uses bit 2 for 350*0Sstevel@tonic-gate * the middle button. We HOPE that noone uses bit 3 though, 351*0Sstevel@tonic-gate * and decide we're out of sync if bit 3 is not set here. 352*0Sstevel@tonic-gate */ 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate if ((code ^ STATEP->sync_byte) & 0x08) { 355*0Sstevel@tonic-gate /* bit 3 not set */ 356*0Sstevel@tonic-gate STATEP->state = PS2_START; 357*0Sstevel@tonic-gate break; /* toss the code */ 358*0Sstevel@tonic-gate } 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate /* get the button values */ 361*0Sstevel@tonic-gate STATEP->buttons = code & PS2_BUTTONMASK; 362*0Sstevel@tonic-gate if (STATEP->buttons != STATEP->oldbuttons) { 363*0Sstevel@tonic-gate sendButtonEvent(qp); 364*0Sstevel@tonic-gate STATEP->oldbuttons = STATEP->buttons; 365*0Sstevel@tonic-gate } 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate /* bit 5 indicates Y value is negative (the sign bit) */ 368*0Sstevel@tonic-gate if (code & PS2_DATA_YSIGN) 369*0Sstevel@tonic-gate STATEP->deltay = -1 & ~0xff; 370*0Sstevel@tonic-gate else 371*0Sstevel@tonic-gate STATEP->deltay = 0; 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate /* bit 4 is X sign bit */ 374*0Sstevel@tonic-gate if (code & PS2_DATA_XSIGN) 375*0Sstevel@tonic-gate STATEP->deltax = -1 & ~0xff; 376*0Sstevel@tonic-gate else 377*0Sstevel@tonic-gate STATEP->deltax = 0; 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate if (code == MSE_AA) 380*0Sstevel@tonic-gate STATEP->state = PS2_MAYBE_REATTACH; 381*0Sstevel@tonic-gate else 382*0Sstevel@tonic-gate STATEP->state = PS2_BUTTON; 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate break; 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate case PS2_MAYBE_REATTACH: 387*0Sstevel@tonic-gate if (code == MSE_00) { 388*0Sstevel@tonic-gate put1(WR(qp), MSERESET); 389*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_RESET_ACK; 390*0Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_RESET); 391*0Sstevel@tonic-gate break; 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate /*FALLTHROUGH*/ 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate case PS2_BUTTON: 396*0Sstevel@tonic-gate /* 397*0Sstevel@tonic-gate * Now for the 7 bits of delta x. "Or" in 398*0Sstevel@tonic-gate * the sign bit and continue. This is ac- 399*0Sstevel@tonic-gate * tually a signed 9 bit number, but I just 400*0Sstevel@tonic-gate * truncate it to a signed char in order to 401*0Sstevel@tonic-gate * avoid changing and retesting all of the 402*0Sstevel@tonic-gate * mouse-related modules for this patch. 403*0Sstevel@tonic-gate */ 404*0Sstevel@tonic-gate if (elapsed > mouse_timeout) 405*0Sstevel@tonic-gate goto restart; 406*0Sstevel@tonic-gate STATEP->deltax |= code & 0xff; 407*0Sstevel@tonic-gate STATEP->state = PS2_DELTA_Y; 408*0Sstevel@tonic-gate break; 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate case PS2_DELTA_Y: 411*0Sstevel@tonic-gate /* 412*0Sstevel@tonic-gate * This byte is delta Y. If this is a plain mouse, 413*0Sstevel@tonic-gate * we're done. Wheel mice have two different flavors 414*0Sstevel@tonic-gate * of fourth byte. 415*0Sstevel@tonic-gate */ 416*0Sstevel@tonic-gate 417*0Sstevel@tonic-gate if (elapsed > mouse_timeout) { 418*0Sstevel@tonic-gate goto restart; 419*0Sstevel@tonic-gate } 420*0Sstevel@tonic-gate STATEP->deltay |= code & 0xff; 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate if (STATEP->vuid_mouse_mode == MOUSE_MODE_WHEEL) { 423*0Sstevel@tonic-gate STATEP->state = PS2_WHEEL_DELTA_Z; 424*0Sstevel@tonic-gate break; 425*0Sstevel@tonic-gate } else if (STATEP->vuid_mouse_mode == 426*0Sstevel@tonic-gate MOUSE_MODE_WHEEL5) { 427*0Sstevel@tonic-gate STATEP->state = PS2_WHEEL5_DELTA_Z; 428*0Sstevel@tonic-gate break; 429*0Sstevel@tonic-gate } 430*0Sstevel@tonic-gate goto packet_complete; 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate case PS2_WHEEL5_DELTA_Z: 433*0Sstevel@tonic-gate if (code & 0x10) { 434*0Sstevel@tonic-gate /* fourth physical button */ 435*0Sstevel@tonic-gate VUID_PUTNEXT(qp, (uchar_t)BUT(4), 436*0Sstevel@tonic-gate FE_PAIR_NONE, 0, 1); 437*0Sstevel@tonic-gate VUID_PUTNEXT(qp, (uchar_t)BUT(4), 438*0Sstevel@tonic-gate FE_PAIR_NONE, 0, 0); 439*0Sstevel@tonic-gate } else if (code & 0x20) { 440*0Sstevel@tonic-gate /* fifth physical button */ 441*0Sstevel@tonic-gate VUID_PUTNEXT(qp, (uchar_t)BUT(5), 442*0Sstevel@tonic-gate FE_PAIR_NONE, 0, 1); 443*0Sstevel@tonic-gate VUID_PUTNEXT(qp, (uchar_t)BUT(5), 444*0Sstevel@tonic-gate FE_PAIR_NONE, 0, 0); 445*0Sstevel@tonic-gate } 446*0Sstevel@tonic-gate /*FALLTHROUGH*/ 447*0Sstevel@tonic-gate 448*0Sstevel@tonic-gate case PS2_WHEEL_DELTA_Z: 449*0Sstevel@tonic-gate /* 450*0Sstevel@tonic-gate * Check whether reporting vertical wheel 451*0Sstevel@tonic-gate * movements is enabled 452*0Sstevel@tonic-gate */ 453*0Sstevel@tonic-gate code &= 0xf; 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate if (STATEP->wheel_state_bf & (1 << 456*0Sstevel@tonic-gate VUIDMICE_VERTICAL_WHEEL_ID)) { 457*0Sstevel@tonic-gate /* 458*0Sstevel@tonic-gate * PS/2 mouse reports -ve values 459*0Sstevel@tonic-gate * when the wheel is scrolled up. So 460*0Sstevel@tonic-gate * we need to convert it into +ve as 461*0Sstevel@tonic-gate * X interprets a +ve value as wheel up event. 462*0Sstevel@tonic-gate * Same is true for the horizontal wheel also. 463*0Sstevel@tonic-gate * The mouse reports 0xf when scrolled up 464*0Sstevel@tonic-gate * and 0x1 when scrolled down. This observation 465*0Sstevel@tonic-gate * is based on Logitech, HCL, 466*0Sstevel@tonic-gate * Microsoft and Black Cat mouse only 467*0Sstevel@tonic-gate */ 468*0Sstevel@tonic-gate if (code == 0xf) { 469*0Sstevel@tonic-gate /* negative Z - wheel up */ 470*0Sstevel@tonic-gate code |= 0xfffffff0; 471*0Sstevel@tonic-gate vuidmice_send_wheel_event(qp, 0, 472*0Sstevel@tonic-gate FE_PAIR_NONE, 0, -code); 473*0Sstevel@tonic-gate } else if (code == 0x01) { 474*0Sstevel@tonic-gate /* positive Z - wheel down */ 475*0Sstevel@tonic-gate vuidmice_send_wheel_event(qp, 0, 476*0Sstevel@tonic-gate FE_PAIR_NONE, 0, -code); 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate } 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate /* 481*0Sstevel@tonic-gate * Check whether reporting horizontal wheel 482*0Sstevel@tonic-gate * movements is enabled 483*0Sstevel@tonic-gate */ 484*0Sstevel@tonic-gate if (STATEP->wheel_state_bf & 485*0Sstevel@tonic-gate (1 << VUIDMICE_HORIZONTAL_WHEEL_ID)) { 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate /* 488*0Sstevel@tonic-gate * The mouse return -7 and +7 when it 489*0Sstevel@tonic-gate * is scrolled horizontally 490*0Sstevel@tonic-gate */ 491*0Sstevel@tonic-gate if (code == 0x09) { 492*0Sstevel@tonic-gate /* negative Z - wheel left */ 493*0Sstevel@tonic-gate vuidmice_send_wheel_event(qp, 1, 494*0Sstevel@tonic-gate FE_PAIR_NONE, 0, 1); 495*0Sstevel@tonic-gate } else if (code == 0x07) { 496*0Sstevel@tonic-gate /* positive Z - wheel right */ 497*0Sstevel@tonic-gate vuidmice_send_wheel_event(qp, 1, 498*0Sstevel@tonic-gate FE_PAIR_NONE, 0, -1); 499*0Sstevel@tonic-gate } 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate packet_complete: 503*0Sstevel@tonic-gate STATEP->state = PS2_START; 504*0Sstevel@tonic-gate /* 505*0Sstevel@tonic-gate * If we can peek at the next mouse character, and 506*0Sstevel@tonic-gate * its not the start of the next packet, don't use 507*0Sstevel@tonic-gate * this packet. 508*0Sstevel@tonic-gate */ 509*0Sstevel@tonic-gate if ((mp->b_wptr - mp->b_rptr) > 0 && 510*0Sstevel@tonic-gate ((mp->b_rptr[0] ^ STATEP->sync_byte) & 0x08)) { 511*0Sstevel@tonic-gate /* 512*0Sstevel@tonic-gate * bit 3 not set 513*0Sstevel@tonic-gate */ 514*0Sstevel@tonic-gate break; 515*0Sstevel@tonic-gate } 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate /* 518*0Sstevel@tonic-gate * send the info to the next level -- 519*0Sstevel@tonic-gate * need to send multiple events if we have both 520*0Sstevel@tonic-gate * a delta *AND* button event(s) 521*0Sstevel@tonic-gate */ 522*0Sstevel@tonic-gate 523*0Sstevel@tonic-gate /* motion has occurred ... */ 524*0Sstevel@tonic-gate if (STATEP->deltax) 525*0Sstevel@tonic-gate VUID_PUTNEXT(qp, (uchar_t)LOC_X_DELTA, 526*0Sstevel@tonic-gate FE_PAIR_ABSOLUTE, (uchar_t)LOC_X_ABSOLUTE, 527*0Sstevel@tonic-gate STATEP->deltax); 528*0Sstevel@tonic-gate 529*0Sstevel@tonic-gate if (STATEP->deltay) 530*0Sstevel@tonic-gate VUID_PUTNEXT(qp, (uchar_t)LOC_Y_DELTA, 531*0Sstevel@tonic-gate FE_PAIR_ABSOLUTE, (uchar_t)LOC_Y_ABSOLUTE, 532*0Sstevel@tonic-gate STATEP->deltay); 533*0Sstevel@tonic-gate 534*0Sstevel@tonic-gate STATEP->deltax = STATEP->deltay = 0; 535*0Sstevel@tonic-gate break; 536*0Sstevel@tonic-gate 537*0Sstevel@tonic-gate case PS2_WAIT_RESET_ACK: 538*0Sstevel@tonic-gate if (code != MSE_ACK) { 539*0Sstevel@tonic-gate break; 540*0Sstevel@tonic-gate } 541*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_RESET_AA; 542*0Sstevel@tonic-gate break; 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate case PS2_WAIT_RESET_AA: 545*0Sstevel@tonic-gate if (code != MSE_AA) { 546*0Sstevel@tonic-gate break; 547*0Sstevel@tonic-gate } 548*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_RESET_00; 549*0Sstevel@tonic-gate break; 550*0Sstevel@tonic-gate 551*0Sstevel@tonic-gate case PS2_WAIT_RESET_00: 552*0Sstevel@tonic-gate if (code != MSE_00) { 553*0Sstevel@tonic-gate break; 554*0Sstevel@tonic-gate } 555*0Sstevel@tonic-gate 556*0Sstevel@tonic-gate /* Reset has been ok */ 557*0Sstevel@tonic-gate vuid_cancel_timeout(qp); 558*0Sstevel@tonic-gate 559*0Sstevel@tonic-gate put1(WR(qp), MSESETRES); 560*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_SETRES0_ACK1; 561*0Sstevel@tonic-gate 562*0Sstevel@tonic-gate /* Set timeout for set res */ 563*0Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD); 564*0Sstevel@tonic-gate 565*0Sstevel@tonic-gate break; 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate case PS2_WAIT_SETRES0_ACK1: 568*0Sstevel@tonic-gate if (code != MSE_ACK) { 569*0Sstevel@tonic-gate break; 570*0Sstevel@tonic-gate } 571*0Sstevel@tonic-gate put1(WR(qp), 0); 572*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_SETRES0_ACK2; 573*0Sstevel@tonic-gate break; 574*0Sstevel@tonic-gate 575*0Sstevel@tonic-gate case PS2_WAIT_SETRES0_ACK2: 576*0Sstevel@tonic-gate case PS2_WAIT_SCALE1_1_ACK: 577*0Sstevel@tonic-gate case PS2_WAIT_SCALE1_2_ACK: 578*0Sstevel@tonic-gate if (code != MSE_ACK) { 579*0Sstevel@tonic-gate break; 580*0Sstevel@tonic-gate } 581*0Sstevel@tonic-gate put1(WR(qp), MSESCALE1); 582*0Sstevel@tonic-gate STATEP->state++; 583*0Sstevel@tonic-gate break; 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate case PS2_WAIT_SCALE1_3_ACK: 586*0Sstevel@tonic-gate if (code != MSE_ACK) { 587*0Sstevel@tonic-gate break; 588*0Sstevel@tonic-gate } 589*0Sstevel@tonic-gate 590*0Sstevel@tonic-gate /* Set res and scale have been ok */ 591*0Sstevel@tonic-gate vuid_cancel_timeout(qp); 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gate put1(WR(qp), MSESTATREQ); 594*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_STATREQ_ACK; 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate /* Set timeout for status request */ 597*0Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD); 598*0Sstevel@tonic-gate 599*0Sstevel@tonic-gate break; 600*0Sstevel@tonic-gate 601*0Sstevel@tonic-gate case PS2_WAIT_STATREQ_ACK: 602*0Sstevel@tonic-gate if (code != MSE_ACK) { 603*0Sstevel@tonic-gate break; 604*0Sstevel@tonic-gate } 605*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_STATUS_1; 606*0Sstevel@tonic-gate break; 607*0Sstevel@tonic-gate 608*0Sstevel@tonic-gate case PS2_WAIT_STATUS_1: 609*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_STATUS_BUTTONS; 610*0Sstevel@tonic-gate break; 611*0Sstevel@tonic-gate 612*0Sstevel@tonic-gate case PS2_WAIT_STATUS_BUTTONS: 613*0Sstevel@tonic-gate if (code != 0) { 614*0Sstevel@tonic-gate STATEP->nbuttons = (uchar_t)code; 615*0Sstevel@tonic-gate STATEP->state = (uchar_t)PS2_WAIT_STATUS_REV; 616*0Sstevel@tonic-gate } else { 617*0Sstevel@tonic-gate #if defined(VUID3PS2) 618*0Sstevel@tonic-gate /* 619*0Sstevel@tonic-gate * It seems that there are some 3-button mice 620*0Sstevel@tonic-gate * that don't play the Logitech autodetect 621*0Sstevel@tonic-gate * game. One is a Mouse Systems mouse OEM'ed 622*0Sstevel@tonic-gate * by Intergraph. 623*0Sstevel@tonic-gate * 624*0Sstevel@tonic-gate * Until we find out how to autodetect these 625*0Sstevel@tonic-gate * mice, we'll assume that if we're being 626*0Sstevel@tonic-gate * compiled as vuid3ps2 and the mouse doesn't 627*0Sstevel@tonic-gate * play the autodetect game, it's a 3-button 628*0Sstevel@tonic-gate * mouse. This effectively disables 629*0Sstevel@tonic-gate * autodetect for mice using vuid3ps2, but 630*0Sstevel@tonic-gate * since vuid3ps2 is used only on x86 where 631*0Sstevel@tonic-gate * we currently assume manual configuration, 632*0Sstevel@tonic-gate * this shouldn't be a problem. At some point 633*0Sstevel@tonic-gate * in the future when we *do* start using 634*0Sstevel@tonic-gate * autodetect on x86, we should probably define 635*0Sstevel@tonic-gate * VUIDPS2 instead of VUID3PS2. Even then, 636*0Sstevel@tonic-gate * we could leave this code so that *some* 637*0Sstevel@tonic-gate * mice could use autodetect and others not. 638*0Sstevel@tonic-gate */ 639*0Sstevel@tonic-gate STATEP->nbuttons = 3; 640*0Sstevel@tonic-gate #else 641*0Sstevel@tonic-gate STATEP->nbuttons = 2; 642*0Sstevel@tonic-gate #endif 643*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_STATUS_3; 644*0Sstevel@tonic-gate } 645*0Sstevel@tonic-gate break; 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate case PS2_WAIT_STATUS_REV: 648*0Sstevel@tonic-gate /*FALLTHROUGH*/ 649*0Sstevel@tonic-gate 650*0Sstevel@tonic-gate case PS2_WAIT_STATUS_3: 651*0Sstevel@tonic-gate 652*0Sstevel@tonic-gate /* Status request has been ok */ 653*0Sstevel@tonic-gate vuid_cancel_timeout(qp); 654*0Sstevel@tonic-gate 655*0Sstevel@tonic-gate /* 656*0Sstevel@tonic-gate * Start the wheel-mouse detection code. First, we look 657*0Sstevel@tonic-gate * for standard wheel mice. If we set the sample rate 658*0Sstevel@tonic-gate * to 200, 100, and then 80 and finally request the 659*0Sstevel@tonic-gate * device ID, a wheel mouse will return an ID of 0x03. 660*0Sstevel@tonic-gate * After that, we'll try for the wheel+5 variety. The 661*0Sstevel@tonic-gate * incantation in this case is 200, 200, and 80. We'll 662*0Sstevel@tonic-gate * get 0x04 back in that case. 663*0Sstevel@tonic-gate */ 664*0Sstevel@tonic-gate if (STATEP->inited & PS2_FLAG_NO_EXTN) { 665*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_SETRES3_ACK1; 666*0Sstevel@tonic-gate put1(WR(qp), MSESETRES); 667*0Sstevel@tonic-gate } else { 668*0Sstevel@tonic-gate put1(WR(qp), MSECHGMOD); 669*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL_SMPL1_CMD_ACK; 670*0Sstevel@tonic-gate } 671*0Sstevel@tonic-gate 672*0Sstevel@tonic-gate /* Set timeout for set res or sample rate */ 673*0Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD); 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate break; 676*0Sstevel@tonic-gate case PS2_WAIT_WHEEL_SMPL1_CMD_ACK: 677*0Sstevel@tonic-gate if (code != MSE_ACK) { 678*0Sstevel@tonic-gate break; 679*0Sstevel@tonic-gate } 680*0Sstevel@tonic-gate put1(WR(qp), 200); 681*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL_SMPL1_RATE_ACK; 682*0Sstevel@tonic-gate break; 683*0Sstevel@tonic-gate case PS2_WAIT_WHEEL_SMPL1_RATE_ACK: 684*0Sstevel@tonic-gate if (code != MSE_ACK) { 685*0Sstevel@tonic-gate break; 686*0Sstevel@tonic-gate } 687*0Sstevel@tonic-gate put1(WR(qp), MSECHGMOD); 688*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL_SMPL2_CMD_ACK; 689*0Sstevel@tonic-gate break; 690*0Sstevel@tonic-gate 691*0Sstevel@tonic-gate case PS2_WAIT_WHEEL_SMPL2_CMD_ACK: 692*0Sstevel@tonic-gate if (code != MSE_ACK) { 693*0Sstevel@tonic-gate break; 694*0Sstevel@tonic-gate } 695*0Sstevel@tonic-gate put1(WR(qp), 100); 696*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL_SMPL2_RATE_ACK; 697*0Sstevel@tonic-gate break; 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate case PS2_WAIT_WHEEL_SMPL2_RATE_ACK: 700*0Sstevel@tonic-gate if (code != MSE_ACK) { 701*0Sstevel@tonic-gate break; 702*0Sstevel@tonic-gate } 703*0Sstevel@tonic-gate put1(WR(qp), MSECHGMOD); 704*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL_SMPL3_CMD_ACK; 705*0Sstevel@tonic-gate break; 706*0Sstevel@tonic-gate 707*0Sstevel@tonic-gate case PS2_WAIT_WHEEL_SMPL3_CMD_ACK: 708*0Sstevel@tonic-gate if (code != MSE_ACK) { 709*0Sstevel@tonic-gate break; 710*0Sstevel@tonic-gate } 711*0Sstevel@tonic-gate put1(WR(qp), 80); 712*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL_SMPL3_RATE_ACK; 713*0Sstevel@tonic-gate break; 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate case PS2_WAIT_WHEEL_SMPL3_RATE_ACK: 716*0Sstevel@tonic-gate if (code != MSE_ACK) { 717*0Sstevel@tonic-gate break; 718*0Sstevel@tonic-gate } 719*0Sstevel@tonic-gate 720*0Sstevel@tonic-gate /* Set sample rate has been ok */ 721*0Sstevel@tonic-gate vuid_cancel_timeout(qp); 722*0Sstevel@tonic-gate 723*0Sstevel@tonic-gate put1(WR(qp), MSEGETDEV); 724*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL_DEV_CMD; 725*0Sstevel@tonic-gate 726*0Sstevel@tonic-gate /* Set timeout for get dev */ 727*0Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD); 728*0Sstevel@tonic-gate 729*0Sstevel@tonic-gate break; 730*0Sstevel@tonic-gate 731*0Sstevel@tonic-gate case PS2_WAIT_WHEEL_DEV_CMD: 732*0Sstevel@tonic-gate if (code != MSE_ACK) { 733*0Sstevel@tonic-gate break; 734*0Sstevel@tonic-gate } 735*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL_DEV_ACK; 736*0Sstevel@tonic-gate break; 737*0Sstevel@tonic-gate 738*0Sstevel@tonic-gate case PS2_WAIT_WHEEL_DEV_ACK: 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gate /* Get dev has been ok */ 741*0Sstevel@tonic-gate vuid_cancel_timeout(qp); 742*0Sstevel@tonic-gate 743*0Sstevel@tonic-gate if (code != 0x03) { 744*0Sstevel@tonic-gate put1(WR(qp), MSESETRES); 745*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_SETRES3_ACK1; 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gate /* Set timeout for set res */ 748*0Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD); 749*0Sstevel@tonic-gate 750*0Sstevel@tonic-gate break; 751*0Sstevel@tonic-gate } 752*0Sstevel@tonic-gate 753*0Sstevel@tonic-gate STATEP->vuid_mouse_mode = MOUSE_MODE_WHEEL; 754*0Sstevel@tonic-gate 755*0Sstevel@tonic-gate /* 756*0Sstevel@tonic-gate * Found wheel. By default enable the wheel. 757*0Sstevel@tonic-gate */ 758*0Sstevel@tonic-gate STATEP->wheel_state_bf |= VUID_WHEEL_STATE_ENABLED; 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate /* We're on a roll - try for wheel+5 */ 761*0Sstevel@tonic-gate put1(WR(qp), MSECHGMOD); 762*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL5_SMPL1_CMD_ACK; 763*0Sstevel@tonic-gate 764*0Sstevel@tonic-gate /* Set timeout for set sample rate */ 765*0Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD); 766*0Sstevel@tonic-gate 767*0Sstevel@tonic-gate break; 768*0Sstevel@tonic-gate 769*0Sstevel@tonic-gate case PS2_WAIT_WHEEL5_SMPL1_CMD_ACK: 770*0Sstevel@tonic-gate if (code != MSE_ACK) { 771*0Sstevel@tonic-gate break; 772*0Sstevel@tonic-gate } 773*0Sstevel@tonic-gate put1(WR(qp), 200); 774*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL5_SMPL1_RATE_ACK; 775*0Sstevel@tonic-gate break; 776*0Sstevel@tonic-gate 777*0Sstevel@tonic-gate case PS2_WAIT_WHEEL5_SMPL1_RATE_ACK: 778*0Sstevel@tonic-gate if (code != MSE_ACK) { 779*0Sstevel@tonic-gate break; 780*0Sstevel@tonic-gate } 781*0Sstevel@tonic-gate put1(WR(qp), MSECHGMOD); 782*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL5_SMPL2_CMD_ACK; 783*0Sstevel@tonic-gate break; 784*0Sstevel@tonic-gate 785*0Sstevel@tonic-gate case PS2_WAIT_WHEEL5_SMPL2_CMD_ACK: 786*0Sstevel@tonic-gate if (code != MSE_ACK) { 787*0Sstevel@tonic-gate break; 788*0Sstevel@tonic-gate } 789*0Sstevel@tonic-gate put1(WR(qp), 200); 790*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL5_SMPL2_RATE_ACK; 791*0Sstevel@tonic-gate break; 792*0Sstevel@tonic-gate 793*0Sstevel@tonic-gate case PS2_WAIT_WHEEL5_SMPL2_RATE_ACK: 794*0Sstevel@tonic-gate if (code != MSE_ACK) { 795*0Sstevel@tonic-gate break; 796*0Sstevel@tonic-gate } 797*0Sstevel@tonic-gate put1(WR(qp), MSECHGMOD); 798*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL5_SMPL3_CMD_ACK; 799*0Sstevel@tonic-gate break; 800*0Sstevel@tonic-gate 801*0Sstevel@tonic-gate case PS2_WAIT_WHEEL5_SMPL3_CMD_ACK: 802*0Sstevel@tonic-gate if (code != MSE_ACK) { 803*0Sstevel@tonic-gate break; 804*0Sstevel@tonic-gate } 805*0Sstevel@tonic-gate put1(WR(qp), 80); 806*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL5_SMPL3_RATE_ACK; 807*0Sstevel@tonic-gate break; 808*0Sstevel@tonic-gate 809*0Sstevel@tonic-gate case PS2_WAIT_WHEEL5_SMPL3_RATE_ACK: 810*0Sstevel@tonic-gate if (code != MSE_ACK) { 811*0Sstevel@tonic-gate break; 812*0Sstevel@tonic-gate } 813*0Sstevel@tonic-gate 814*0Sstevel@tonic-gate /* Set sample rate has been ok */ 815*0Sstevel@tonic-gate vuid_cancel_timeout(qp); 816*0Sstevel@tonic-gate 817*0Sstevel@tonic-gate put1(WR(qp), MSEGETDEV); 818*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL5_DEV_CMD; 819*0Sstevel@tonic-gate 820*0Sstevel@tonic-gate /* Set timeout for wheel5 get dev */ 821*0Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD); 822*0Sstevel@tonic-gate 823*0Sstevel@tonic-gate break; 824*0Sstevel@tonic-gate 825*0Sstevel@tonic-gate case PS2_WAIT_WHEEL5_DEV_CMD: 826*0Sstevel@tonic-gate if (code != MSE_ACK) { 827*0Sstevel@tonic-gate break; 828*0Sstevel@tonic-gate } 829*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL5_DEV_ACK; 830*0Sstevel@tonic-gate break; 831*0Sstevel@tonic-gate 832*0Sstevel@tonic-gate case PS2_WAIT_WHEEL5_DEV_ACK: 833*0Sstevel@tonic-gate if (code == 0x04) { 834*0Sstevel@tonic-gate STATEP->vuid_mouse_mode = MOUSE_MODE_WHEEL5; 835*0Sstevel@tonic-gate STATEP->nbuttons = 5; 836*0Sstevel@tonic-gate 837*0Sstevel@tonic-gate /* 838*0Sstevel@tonic-gate * Found wheel. By default enable the wheel. 839*0Sstevel@tonic-gate */ 840*0Sstevel@tonic-gate STATEP->wheel_state_bf |= 841*0Sstevel@tonic-gate VUID_WHEEL_STATE_ENABLED << 842*0Sstevel@tonic-gate MOUSE_MODE_WHEEL; 843*0Sstevel@tonic-gate } 844*0Sstevel@tonic-gate 845*0Sstevel@tonic-gate /* Wheel5 get dev has been ok */ 846*0Sstevel@tonic-gate vuid_cancel_timeout(qp); 847*0Sstevel@tonic-gate 848*0Sstevel@tonic-gate /* FALLTHROUGH */ 849*0Sstevel@tonic-gate 850*0Sstevel@tonic-gate case PS2_WAIT_SETRES3_CMD: 851*0Sstevel@tonic-gate put1(WR(qp), MSESETRES); 852*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_SETRES3_ACK1; 853*0Sstevel@tonic-gate 854*0Sstevel@tonic-gate /* Set timeout for set res */ 855*0Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD); 856*0Sstevel@tonic-gate 857*0Sstevel@tonic-gate break; 858*0Sstevel@tonic-gate 859*0Sstevel@tonic-gate case PS2_WAIT_SETRES3_ACK1: 860*0Sstevel@tonic-gate if (code != MSE_ACK) { 861*0Sstevel@tonic-gate break; 862*0Sstevel@tonic-gate } 863*0Sstevel@tonic-gate put1(WR(qp), 3); 864*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_SETRES3_ACK2; 865*0Sstevel@tonic-gate break; 866*0Sstevel@tonic-gate 867*0Sstevel@tonic-gate case PS2_WAIT_SETRES3_ACK2: 868*0Sstevel@tonic-gate if (code != MSE_ACK) { 869*0Sstevel@tonic-gate break; 870*0Sstevel@tonic-gate } 871*0Sstevel@tonic-gate 872*0Sstevel@tonic-gate /* Set res has been ok */ 873*0Sstevel@tonic-gate vuid_cancel_timeout(qp); 874*0Sstevel@tonic-gate 875*0Sstevel@tonic-gate put1(WR(qp), MSESTREAM); 876*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_STREAM_ACK; 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate /* Set timeout for enable */ 879*0Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD); 880*0Sstevel@tonic-gate 881*0Sstevel@tonic-gate break; 882*0Sstevel@tonic-gate 883*0Sstevel@tonic-gate case PS2_WAIT_STREAM_ACK: 884*0Sstevel@tonic-gate if (code != MSE_ACK) { 885*0Sstevel@tonic-gate break; 886*0Sstevel@tonic-gate } 887*0Sstevel@tonic-gate put1(WR(qp), MSEON); 888*0Sstevel@tonic-gate STATEP->state = PS2_WAIT_ON_ACK; 889*0Sstevel@tonic-gate break; 890*0Sstevel@tonic-gate 891*0Sstevel@tonic-gate case PS2_WAIT_ON_ACK: 892*0Sstevel@tonic-gate if (code != MSE_ACK) { 893*0Sstevel@tonic-gate break; 894*0Sstevel@tonic-gate } 895*0Sstevel@tonic-gate 896*0Sstevel@tonic-gate /* Enable has been ok */ 897*0Sstevel@tonic-gate vuid_cancel_timeout(qp); 898*0Sstevel@tonic-gate 899*0Sstevel@tonic-gate STATEP->state = PS2_START; 900*0Sstevel@tonic-gate break; 901*0Sstevel@tonic-gate } 902*0Sstevel@tonic-gate } 903*0Sstevel@tonic-gate freemsg(mp); 904*0Sstevel@tonic-gate } 905