10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate /* 300Sstevel@tonic-gate * 2/3/5 Button PS/2 Mouse Protocol 310Sstevel@tonic-gate * 320Sstevel@tonic-gate * This module dynamically determines the number of buttons on the mouse. 330Sstevel@tonic-gate */ 340Sstevel@tonic-gate 350Sstevel@tonic-gate #include <sys/param.h> 360Sstevel@tonic-gate #include <sys/stream.h> 370Sstevel@tonic-gate #include <sys/vuid_event.h> 380Sstevel@tonic-gate #include <sys/vuidmice.h> 390Sstevel@tonic-gate #include <sys/vuid_wheel.h> 400Sstevel@tonic-gate #include <sys/mouse.h> 410Sstevel@tonic-gate #include <sys/ddi.h> 420Sstevel@tonic-gate #include <sys/sunddi.h> 430Sstevel@tonic-gate 440Sstevel@tonic-gate /* 450Sstevel@tonic-gate * BUT(1) LEFT BUTTON 460Sstevel@tonic-gate * BUT(2) MIDDLE BUTTON (if present) 470Sstevel@tonic-gate * BUT(3) RIGHT BUTTON 480Sstevel@tonic-gate */ 490Sstevel@tonic-gate 500Sstevel@tonic-gate #define PS2_BUTTONMASK 7 /* mask byte zero with this */ 510Sstevel@tonic-gate 520Sstevel@tonic-gate #define PS2_BUTTON_L (uchar_t)0x01 /* Left button pressed */ 530Sstevel@tonic-gate #define PS2_BUTTON_R (uchar_t)0x02 /* Right button pressed */ 540Sstevel@tonic-gate #define PS2_BUTTON_M (uchar_t)0x04 /* Middle button pressed */ 550Sstevel@tonic-gate #define PS2_DATA_XSIGN (uchar_t)0x10 /* X data sign bit */ 560Sstevel@tonic-gate #define PS2_DATA_YSIGN (uchar_t)0x20 /* Y data sign bit */ 570Sstevel@tonic-gate 580Sstevel@tonic-gate #define PS2_START 0 /* Beginning of packet */ 590Sstevel@tonic-gate #define PS2_BUTTON 1 /* Got button status */ 600Sstevel@tonic-gate #define PS2_MAYBE_REATTACH 2 /* Got button status */ 610Sstevel@tonic-gate #define PS2_DELTA_Y 3 /* Got delta X */ 620Sstevel@tonic-gate #define PS2_WHEEL_DELTA_Z 4 630Sstevel@tonic-gate #define PS2_WHEEL5_DELTA_Z 5 640Sstevel@tonic-gate #define PS2_WAIT_RESET_ACK 6 650Sstevel@tonic-gate #define PS2_WAIT_RESET_AA 7 660Sstevel@tonic-gate #define PS2_WAIT_RESET_00 8 670Sstevel@tonic-gate #define PS2_WAIT_SETRES0_ACK1 9 680Sstevel@tonic-gate #define PS2_WAIT_SETRES0_ACK2 10 /* -+ must be consecutive */ 690Sstevel@tonic-gate #define PS2_WAIT_SCALE1_1_ACK 11 /* | */ 700Sstevel@tonic-gate #define PS2_WAIT_SCALE1_2_ACK 12 /* | */ 710Sstevel@tonic-gate #define PS2_WAIT_SCALE1_3_ACK 13 /* -+ */ 720Sstevel@tonic-gate #define PS2_WAIT_STATREQ_ACK 14 730Sstevel@tonic-gate #define PS2_WAIT_STATUS_1 15 740Sstevel@tonic-gate #define PS2_WAIT_STATUS_BUTTONS 16 750Sstevel@tonic-gate #define PS2_WAIT_STATUS_REV 17 760Sstevel@tonic-gate #define PS2_WAIT_STATUS_3 18 770Sstevel@tonic-gate #define PS2_WAIT_WHEEL_SMPL1_CMD_ACK 19 /* Set the sample rate to 200 */ 780Sstevel@tonic-gate #define PS2_WAIT_WHEEL_SMPL1_RATE_ACK 20 790Sstevel@tonic-gate #define PS2_WAIT_WHEEL_SMPL2_CMD_ACK 21 /* Set the sample rate to 200 */ 800Sstevel@tonic-gate #define PS2_WAIT_WHEEL_SMPL2_RATE_ACK 22 810Sstevel@tonic-gate #define PS2_WAIT_WHEEL_SMPL3_CMD_ACK 23 /* Set the sample rate to 80 */ 820Sstevel@tonic-gate #define PS2_WAIT_WHEEL_SMPL3_RATE_ACK 24 830Sstevel@tonic-gate #define PS2_WAIT_WHEEL_DEV_CMD 25 840Sstevel@tonic-gate #define PS2_WAIT_WHEEL_DEV_ACK 26 /* Detected wheel mouse */ 850Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_SMPL1_CMD_ACK 27 /* Set the sample rate to 200 */ 860Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_SMPL1_RATE_ACK 28 870Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_SMPL2_CMD_ACK 29 /* Set the sample rate to 200 */ 880Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_SMPL2_RATE_ACK 30 890Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_SMPL3_CMD_ACK 31 /* Set the sample rate to 100 */ 900Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_SMPL3_RATE_ACK 32 910Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_DEV_CMD 33 920Sstevel@tonic-gate #define PS2_WAIT_WHEEL5_DEV_ACK 34 /* Detected 5 button mouse */ 930Sstevel@tonic-gate #define PS2_WAIT_SETRES3_CMD 35 940Sstevel@tonic-gate #define PS2_WAIT_SETRES3_ACK1 36 950Sstevel@tonic-gate #define PS2_WAIT_SETRES3_ACK2 37 960Sstevel@tonic-gate #define PS2_WAIT_STREAM_ACK 38 970Sstevel@tonic-gate #define PS2_WAIT_ON_ACK 39 980Sstevel@tonic-gate 990Sstevel@tonic-gate #define MSE_AA 0xaa 1000Sstevel@tonic-gate #define MSE_00 0x00 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate #define MOUSE_MODE_PLAIN 0 /* Normal PS/2 mouse - 3 byte msgs */ 1030Sstevel@tonic-gate #define MOUSE_MODE_WHEEL 1 /* Wheel mouse - 4 byte msgs */ 1040Sstevel@tonic-gate #define MOUSE_MODE_WHEEL5 2 /* Wheel + 5 btn mouse - 4 byte msgs */ 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate #define PS2_FLAG_NO_EXTN 0x08 /* Mouse doesn't obey extended cmds */ 1070Sstevel@tonic-gate #define PS2_FLAG_INIT_DONE 0x01 /* Mouse has been inited successfully */ 1080Sstevel@tonic-gate #define PS2_FLAG_INIT_TIMEOUT 0x02 /* Mouse init timeout */ 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate /* 1110Sstevel@tonic-gate * The RESET command takes more time 1120Sstevel@tonic-gate * before the PS/2 mouse is ready 1130Sstevel@tonic-gate */ 1140Sstevel@tonic-gate #define PS2_INIT_TMOUT_RESET 500000 /* 500ms for RESET command */ 1150Sstevel@tonic-gate #define PS2_INIT_TMOUT_PER_CMD 200000 /* 200ms for each command-response */ 116*993Slq150181 #define PS2_INIT_TMOUT_PER_GROUP 500000 /* 500ms for group commands */ 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate #define PS2_MAX_INIT_COUNT 5 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate static void vuidmice_send_wheel_event(queue_t *const, uchar_t, 1220Sstevel@tonic-gate uchar_t, uchar_t, int); 1230Sstevel@tonic-gate extern void VUID_PUTNEXT(queue_t *const, uchar_t, uchar_t, uchar_t, int); 1240Sstevel@tonic-gate extern void uniqtime32(struct timeval32 *); 1250Sstevel@tonic-gate static void VUID_INIT_TIMEOUT(void *q); 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate /* 1280Sstevel@tonic-gate * We apply timeout to nearly each command-response 1290Sstevel@tonic-gate * during initialization: 1300Sstevel@tonic-gate * 1310Sstevel@tonic-gate * Set timeout for RESET 1320Sstevel@tonic-gate * Set timeout for SET RESOLUTION 1330Sstevel@tonic-gate * Set timeout for SET SCALE 1340Sstevel@tonic-gate * Set timeout for SET SAMPLE RATE 1350Sstevel@tonic-gate * Set timeout for STATUS REQUEST 1360Sstevel@tonic-gate * Set timeout for GET DEV 1370Sstevel@tonic-gate * Set timeout for SET STREAM MODE and ENABLE. 1380Sstevel@tonic-gate * 1390Sstevel@tonic-gate * But for simplicity, sometimes we just apply the timeout 140*993Slq150181 * to a function with group commands (e.g. wheel-mouse detection). 1410Sstevel@tonic-gate * 1420Sstevel@tonic-gate */ 1430Sstevel@tonic-gate static void 1440Sstevel@tonic-gate vuid_set_timeout(queue_t *const qp, clock_t time) 1450Sstevel@tonic-gate { 1460Sstevel@tonic-gate ASSERT(STATEP->init_tid == 0); 1470Sstevel@tonic-gate STATEP->init_tid = qtimeout(qp, VUID_INIT_TIMEOUT, 1480Sstevel@tonic-gate qp, drv_usectohz(time)); 1490Sstevel@tonic-gate } 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate static void 1520Sstevel@tonic-gate vuid_cancel_timeout(queue_t *const qp) 1530Sstevel@tonic-gate { 1540Sstevel@tonic-gate ASSERT(STATEP->init_tid != 0); 1550Sstevel@tonic-gate (void) quntimeout(qp, STATEP->init_tid); 1560Sstevel@tonic-gate STATEP->init_tid = 0; 1570Sstevel@tonic-gate } 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate /* 1600Sstevel@tonic-gate * vuidmice_send_wheel_event 1610Sstevel@tonic-gate * Convert wheel data to firm_events 1620Sstevel@tonic-gate */ 1630Sstevel@tonic-gate static void 1640Sstevel@tonic-gate vuidmice_send_wheel_event(queue_t *const qp, uchar_t event_id, 1650Sstevel@tonic-gate uchar_t event_pair_type, uchar_t event_pair, int event_value) 1660Sstevel@tonic-gate { 1670Sstevel@tonic-gate mblk_t *bp; 1680Sstevel@tonic-gate Firm_event *fep; 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate if ((bp = allocb((int)sizeof (Firm_event), BPRI_HI)) == NULL) { 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate return; 1730Sstevel@tonic-gate } 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate fep = (Firm_event *)bp->b_wptr; 1760Sstevel@tonic-gate fep->id = vuid_id_addr(vuid_first(VUID_WHEEL)) | 1770Sstevel@tonic-gate vuid_id_offset(event_id); 1780Sstevel@tonic-gate fep->pair_type = event_pair_type; 1790Sstevel@tonic-gate fep->pair = event_pair; 1800Sstevel@tonic-gate fep->value = event_value; 1810Sstevel@tonic-gate uniqtime32(&fep->time); 1820Sstevel@tonic-gate bp->b_wptr += sizeof (Firm_event); 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate if (canput(qp->q_next)) { 1850Sstevel@tonic-gate putnext(qp, bp); 1860Sstevel@tonic-gate } else { 1870Sstevel@tonic-gate (void) putbq(qp, bp); /* read side is blocked */ 1880Sstevel@tonic-gate } 1890Sstevel@tonic-gate } 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate static void 1930Sstevel@tonic-gate sendButtonEvent(queue_t *const qp) 1940Sstevel@tonic-gate { 1950Sstevel@tonic-gate static int bmap[3] = {1, 3, 2}; 1960Sstevel@tonic-gate uint_t b; 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate /* for each button, see if it has changed */ 1990Sstevel@tonic-gate for (b = 0; b < STATEP->nbuttons; b++) { 2000Sstevel@tonic-gate uchar_t mask = 0x1 << b; 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate if ((STATEP->buttons & mask) != (STATEP->oldbuttons & mask)) 2030Sstevel@tonic-gate VUID_PUTNEXT(qp, (uchar_t)BUT(bmap[b]), FE_PAIR_NONE, 0, 2040Sstevel@tonic-gate (STATEP->buttons & mask ? 1 : 0)); 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate } 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate void 2090Sstevel@tonic-gate put1(queue_t *const qp, int c) 2100Sstevel@tonic-gate { 2110Sstevel@tonic-gate mblk_t *bp; 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate if (bp = allocb(1, BPRI_MED)) { 2140Sstevel@tonic-gate *bp->b_wptr++ = (char)c; 2150Sstevel@tonic-gate putnext(qp, bp); 2160Sstevel@tonic-gate } 2170Sstevel@tonic-gate } 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate int 2200Sstevel@tonic-gate VUID_OPEN(queue_t *const qp) 2210Sstevel@tonic-gate { 2220Sstevel@tonic-gate STATEP->format = VUID_FIRM_EVENT; 2230Sstevel@tonic-gate STATEP->vuid_mouse_mode = MOUSE_MODE_PLAIN; 2240Sstevel@tonic-gate STATEP->inited = 0; 2250Sstevel@tonic-gate STATEP->nbuttons = 3; 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate STATEP->state = PS2_WAIT_RESET_ACK; 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate /* Set timeout for reset */ 2300Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_RESET); 2310Sstevel@tonic-gate 232*993Slq150181 put1(WR(qp), MSERESET); 233*993Slq150181 2340Sstevel@tonic-gate while ((STATEP->state != PS2_START) && 2350Sstevel@tonic-gate !(STATEP->inited & PS2_FLAG_INIT_TIMEOUT)) { 2360Sstevel@tonic-gate if (qwait_sig(qp) == 0) 2370Sstevel@tonic-gate break; 2380Sstevel@tonic-gate } 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate /* 2410Sstevel@tonic-gate * Later the PS/2 mouse maybe re-attach, so here 2420Sstevel@tonic-gate * clear the init_count. 2430Sstevel@tonic-gate */ 2440Sstevel@tonic-gate STATEP->init_count = 0; 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate return (0); 2470Sstevel@tonic-gate } 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate void 2500Sstevel@tonic-gate VUID_CLOSE(queue_t *const qp) 2510Sstevel@tonic-gate { 2520Sstevel@tonic-gate if (STATEP->init_tid != 0) 2530Sstevel@tonic-gate vuid_cancel_timeout(qp); 2540Sstevel@tonic-gate } 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate static void 2570Sstevel@tonic-gate VUID_INIT_TIMEOUT(void *q) 2580Sstevel@tonic-gate { 2590Sstevel@tonic-gate queue_t *qp = q; 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate STATEP->init_tid = 0; 2620Sstevel@tonic-gate 263822Ssethg /* 264822Ssethg * Some mice do not even send an error in response to 265822Ssethg * the wheel mouse sample commands, so if we're in any of 266822Ssethg * the PS2_WAIT_WHEEL_SMPL* states, and there has been 267822Ssethg * a timeout, assume the mouse cannot handle the extended 268822Ssethg * (wheel mouse) commands. 269822Ssethg */ 270822Ssethg if ((STATEP->state == PS2_WAIT_WHEEL_SMPL1_CMD_ACK) || 271822Ssethg (STATEP->state == PS2_WAIT_WHEEL_SMPL1_RATE_ACK) || 2720Sstevel@tonic-gate (STATEP->state == PS2_WAIT_WHEEL_SMPL2_RATE_ACK) || 2730Sstevel@tonic-gate (STATEP->state == PS2_WAIT_WHEEL_SMPL3_RATE_ACK)) { 2740Sstevel@tonic-gate /* 2750Sstevel@tonic-gate * We overload 'inited' to mark the PS/2 mouse 2760Sstevel@tonic-gate * as one which doesn't respond to extended commands. 2770Sstevel@tonic-gate */ 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate STATEP->inited |= PS2_FLAG_NO_EXTN; 2800Sstevel@tonic-gate } 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate if (++STATEP->init_count >= PS2_MAX_INIT_COUNT) { 2830Sstevel@tonic-gate STATEP->inited |= PS2_FLAG_INIT_TIMEOUT; 2840Sstevel@tonic-gate return; 2850Sstevel@tonic-gate } 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate 2880Sstevel@tonic-gate STATEP->state = PS2_WAIT_RESET_ACK; 2890Sstevel@tonic-gate 290*993Slq150181 vuid_set_timeout(qp, PS2_INIT_TMOUT_RESET); 291*993Slq150181 2920Sstevel@tonic-gate /* try again */ 2930Sstevel@tonic-gate put1(WR(qp), MSERESET); 2940Sstevel@tonic-gate } 2950Sstevel@tonic-gate 2960Sstevel@tonic-gate void 2970Sstevel@tonic-gate VUID_QUEUE(queue_t *const qp, mblk_t *mp) 2980Sstevel@tonic-gate { 2990Sstevel@tonic-gate int code; 3000Sstevel@tonic-gate clock_t now; 3010Sstevel@tonic-gate clock_t elapsed; 3020Sstevel@tonic-gate clock_t mouse_timeout; 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate mouse_timeout = drv_usectohz(250000); 3050Sstevel@tonic-gate now = ddi_get_lbolt(); 3060Sstevel@tonic-gate elapsed = now - STATEP->last_event_lbolt; 3070Sstevel@tonic-gate STATEP->last_event_lbolt = now; 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate while (mp->b_rptr < mp->b_wptr) { 3100Sstevel@tonic-gate code = *mp->b_rptr++; 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate switch (STATEP->state) { 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate /* 3150Sstevel@tonic-gate * Start state. We stay here if the start code is not 3160Sstevel@tonic-gate * received thus forcing us back into sync. When we get a 3170Sstevel@tonic-gate * start code the button mask comes with it forcing us to 3180Sstevel@tonic-gate * to the next state. 3190Sstevel@tonic-gate */ 3200Sstevel@tonic-gate restart: 3210Sstevel@tonic-gate case PS2_START: 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate /* 3240Sstevel@tonic-gate * 3-byte packet format 3250Sstevel@tonic-gate * 3260Sstevel@tonic-gate * Bit 7 6 5 4 3 2 1 0 3270Sstevel@tonic-gate * Byte ---- ---- ----- ----- -- ------ ------ ------ 3280Sstevel@tonic-gate * 1 Y_Ov X_Ov Y_Sgn X_Sgn 1 MdlBtn RgtBtn LftBtn 3290Sstevel@tonic-gate * 2 |<--------------X Movement----------------->| 3300Sstevel@tonic-gate * 3 |<--------------Y Movement----------------->| 3310Sstevel@tonic-gate * 3320Sstevel@tonic-gate * 4-byte wheel packet format 3330Sstevel@tonic-gate * 3340Sstevel@tonic-gate * Bit 7 6 5 4 3 2 1 0 3350Sstevel@tonic-gate * Byte ---- ---- ----- ----- -- ------ ------ ------ 3360Sstevel@tonic-gate * 1 Y_Ov X_Ov Y_Sgn X_Sgn 1 MdlBtn RgtBtn LftBtn 3370Sstevel@tonic-gate * 2 |<--------------X Movement----------------->| 3380Sstevel@tonic-gate * 3 |<--------------Y Movement----------------->| 3390Sstevel@tonic-gate * 4 |<--------------Z Movement----------------->| 3400Sstevel@tonic-gate * 3410Sstevel@tonic-gate * 4-byte wheel+5 packet format 3420Sstevel@tonic-gate * 3430Sstevel@tonic-gate * Bit 7 6 5 4 3 2 1 0 3440Sstevel@tonic-gate * Byte ---- ---- ----- ----- -- ------ ------ ------ 3450Sstevel@tonic-gate * 1 Y_Ov X_Ov Y_Sgn X_Sgn 1 MdlBtn RgtBtn LftBtn 3460Sstevel@tonic-gate * 2 |<--------------X Movement----------------->| 3470Sstevel@tonic-gate * 3 |<--------------Y Movement----------------->| 3480Sstevel@tonic-gate * 4 0 0 5_Btn 4_Btn Z3 Z2 Z1 Z0 3490Sstevel@tonic-gate */ 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate if (!(STATEP->inited & PS2_FLAG_INIT_DONE)) { 3520Sstevel@tonic-gate STATEP->sync_byte = code & 0x8; 3530Sstevel@tonic-gate STATEP->inited |= PS2_FLAG_INIT_DONE; 3540Sstevel@tonic-gate } 3550Sstevel@tonic-gate /* 3560Sstevel@tonic-gate * the PS/2 mouse data format doesn't have any sort of sync 3570Sstevel@tonic-gate * data to make sure we are in sync with the packet stream, 3580Sstevel@tonic-gate * but the Technical Reference manual states that bits 2 & 3 3590Sstevel@tonic-gate * of the first byte are reserved. Logitech uses bit 2 for 3600Sstevel@tonic-gate * the middle button. We HOPE that noone uses bit 3 though, 3610Sstevel@tonic-gate * and decide we're out of sync if bit 3 is not set here. 3620Sstevel@tonic-gate */ 3630Sstevel@tonic-gate 3640Sstevel@tonic-gate if ((code ^ STATEP->sync_byte) & 0x08) { 3650Sstevel@tonic-gate /* bit 3 not set */ 3660Sstevel@tonic-gate STATEP->state = PS2_START; 3670Sstevel@tonic-gate break; /* toss the code */ 3680Sstevel@tonic-gate } 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate /* get the button values */ 3710Sstevel@tonic-gate STATEP->buttons = code & PS2_BUTTONMASK; 3720Sstevel@tonic-gate if (STATEP->buttons != STATEP->oldbuttons) { 3730Sstevel@tonic-gate sendButtonEvent(qp); 3740Sstevel@tonic-gate STATEP->oldbuttons = STATEP->buttons; 3750Sstevel@tonic-gate } 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate /* bit 5 indicates Y value is negative (the sign bit) */ 3780Sstevel@tonic-gate if (code & PS2_DATA_YSIGN) 3790Sstevel@tonic-gate STATEP->deltay = -1 & ~0xff; 3800Sstevel@tonic-gate else 3810Sstevel@tonic-gate STATEP->deltay = 0; 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate /* bit 4 is X sign bit */ 3840Sstevel@tonic-gate if (code & PS2_DATA_XSIGN) 3850Sstevel@tonic-gate STATEP->deltax = -1 & ~0xff; 3860Sstevel@tonic-gate else 3870Sstevel@tonic-gate STATEP->deltax = 0; 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate if (code == MSE_AA) 3900Sstevel@tonic-gate STATEP->state = PS2_MAYBE_REATTACH; 3910Sstevel@tonic-gate else 3920Sstevel@tonic-gate STATEP->state = PS2_BUTTON; 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate break; 3950Sstevel@tonic-gate 3960Sstevel@tonic-gate case PS2_MAYBE_REATTACH: 3970Sstevel@tonic-gate if (code == MSE_00) { 3980Sstevel@tonic-gate STATEP->state = PS2_WAIT_RESET_ACK; 3990Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_RESET); 400*993Slq150181 put1(WR(qp), MSERESET); 4010Sstevel@tonic-gate break; 4020Sstevel@tonic-gate } 4030Sstevel@tonic-gate /*FALLTHROUGH*/ 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate case PS2_BUTTON: 4060Sstevel@tonic-gate /* 4070Sstevel@tonic-gate * Now for the 7 bits of delta x. "Or" in 4080Sstevel@tonic-gate * the sign bit and continue. This is ac- 4090Sstevel@tonic-gate * tually a signed 9 bit number, but I just 4100Sstevel@tonic-gate * truncate it to a signed char in order to 4110Sstevel@tonic-gate * avoid changing and retesting all of the 4120Sstevel@tonic-gate * mouse-related modules for this patch. 4130Sstevel@tonic-gate */ 4140Sstevel@tonic-gate if (elapsed > mouse_timeout) 4150Sstevel@tonic-gate goto restart; 4160Sstevel@tonic-gate STATEP->deltax |= code & 0xff; 4170Sstevel@tonic-gate STATEP->state = PS2_DELTA_Y; 4180Sstevel@tonic-gate break; 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate case PS2_DELTA_Y: 4210Sstevel@tonic-gate /* 4220Sstevel@tonic-gate * This byte is delta Y. If this is a plain mouse, 4230Sstevel@tonic-gate * we're done. Wheel mice have two different flavors 4240Sstevel@tonic-gate * of fourth byte. 4250Sstevel@tonic-gate */ 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate if (elapsed > mouse_timeout) { 4280Sstevel@tonic-gate goto restart; 4290Sstevel@tonic-gate } 4300Sstevel@tonic-gate STATEP->deltay |= code & 0xff; 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate if (STATEP->vuid_mouse_mode == MOUSE_MODE_WHEEL) { 4330Sstevel@tonic-gate STATEP->state = PS2_WHEEL_DELTA_Z; 4340Sstevel@tonic-gate break; 4350Sstevel@tonic-gate } else if (STATEP->vuid_mouse_mode == 4360Sstevel@tonic-gate MOUSE_MODE_WHEEL5) { 4370Sstevel@tonic-gate STATEP->state = PS2_WHEEL5_DELTA_Z; 4380Sstevel@tonic-gate break; 4390Sstevel@tonic-gate } 4400Sstevel@tonic-gate goto packet_complete; 4410Sstevel@tonic-gate 4420Sstevel@tonic-gate case PS2_WHEEL5_DELTA_Z: 4430Sstevel@tonic-gate if (code & 0x10) { 4440Sstevel@tonic-gate /* fourth physical button */ 4450Sstevel@tonic-gate VUID_PUTNEXT(qp, (uchar_t)BUT(4), 4460Sstevel@tonic-gate FE_PAIR_NONE, 0, 1); 4470Sstevel@tonic-gate VUID_PUTNEXT(qp, (uchar_t)BUT(4), 4480Sstevel@tonic-gate FE_PAIR_NONE, 0, 0); 4490Sstevel@tonic-gate } else if (code & 0x20) { 4500Sstevel@tonic-gate /* fifth physical button */ 4510Sstevel@tonic-gate VUID_PUTNEXT(qp, (uchar_t)BUT(5), 4520Sstevel@tonic-gate FE_PAIR_NONE, 0, 1); 4530Sstevel@tonic-gate VUID_PUTNEXT(qp, (uchar_t)BUT(5), 4540Sstevel@tonic-gate FE_PAIR_NONE, 0, 0); 4550Sstevel@tonic-gate } 4560Sstevel@tonic-gate /*FALLTHROUGH*/ 4570Sstevel@tonic-gate 4580Sstevel@tonic-gate case PS2_WHEEL_DELTA_Z: 4590Sstevel@tonic-gate /* 4600Sstevel@tonic-gate * Check whether reporting vertical wheel 4610Sstevel@tonic-gate * movements is enabled 4620Sstevel@tonic-gate */ 4630Sstevel@tonic-gate code &= 0xf; 4640Sstevel@tonic-gate 4650Sstevel@tonic-gate if (STATEP->wheel_state_bf & (1 << 4660Sstevel@tonic-gate VUIDMICE_VERTICAL_WHEEL_ID)) { 4670Sstevel@tonic-gate /* 4680Sstevel@tonic-gate * PS/2 mouse reports -ve values 4690Sstevel@tonic-gate * when the wheel is scrolled up. So 4700Sstevel@tonic-gate * we need to convert it into +ve as 4710Sstevel@tonic-gate * X interprets a +ve value as wheel up event. 4720Sstevel@tonic-gate * Same is true for the horizontal wheel also. 4730Sstevel@tonic-gate * The mouse reports 0xf when scrolled up 4740Sstevel@tonic-gate * and 0x1 when scrolled down. This observation 4750Sstevel@tonic-gate * is based on Logitech, HCL, 4760Sstevel@tonic-gate * Microsoft and Black Cat mouse only 4770Sstevel@tonic-gate */ 4780Sstevel@tonic-gate if (code == 0xf) { 4790Sstevel@tonic-gate /* negative Z - wheel up */ 4800Sstevel@tonic-gate code |= 0xfffffff0; 4810Sstevel@tonic-gate vuidmice_send_wheel_event(qp, 0, 4820Sstevel@tonic-gate FE_PAIR_NONE, 0, -code); 4830Sstevel@tonic-gate } else if (code == 0x01) { 4840Sstevel@tonic-gate /* positive Z - wheel down */ 4850Sstevel@tonic-gate vuidmice_send_wheel_event(qp, 0, 4860Sstevel@tonic-gate FE_PAIR_NONE, 0, -code); 4870Sstevel@tonic-gate } 4880Sstevel@tonic-gate } 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate /* 4910Sstevel@tonic-gate * Check whether reporting horizontal wheel 4920Sstevel@tonic-gate * movements is enabled 4930Sstevel@tonic-gate */ 4940Sstevel@tonic-gate if (STATEP->wheel_state_bf & 4950Sstevel@tonic-gate (1 << VUIDMICE_HORIZONTAL_WHEEL_ID)) { 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate /* 4980Sstevel@tonic-gate * The mouse return -7 and +7 when it 4990Sstevel@tonic-gate * is scrolled horizontally 5000Sstevel@tonic-gate */ 5010Sstevel@tonic-gate if (code == 0x09) { 5020Sstevel@tonic-gate /* negative Z - wheel left */ 5030Sstevel@tonic-gate vuidmice_send_wheel_event(qp, 1, 5040Sstevel@tonic-gate FE_PAIR_NONE, 0, 1); 5050Sstevel@tonic-gate } else if (code == 0x07) { 5060Sstevel@tonic-gate /* positive Z - wheel right */ 5070Sstevel@tonic-gate vuidmice_send_wheel_event(qp, 1, 5080Sstevel@tonic-gate FE_PAIR_NONE, 0, -1); 5090Sstevel@tonic-gate } 5100Sstevel@tonic-gate } 5110Sstevel@tonic-gate 5120Sstevel@tonic-gate packet_complete: 5130Sstevel@tonic-gate STATEP->state = PS2_START; 5140Sstevel@tonic-gate /* 5150Sstevel@tonic-gate * If we can peek at the next mouse character, and 5160Sstevel@tonic-gate * its not the start of the next packet, don't use 5170Sstevel@tonic-gate * this packet. 5180Sstevel@tonic-gate */ 5190Sstevel@tonic-gate if ((mp->b_wptr - mp->b_rptr) > 0 && 5200Sstevel@tonic-gate ((mp->b_rptr[0] ^ STATEP->sync_byte) & 0x08)) { 5210Sstevel@tonic-gate /* 5220Sstevel@tonic-gate * bit 3 not set 5230Sstevel@tonic-gate */ 5240Sstevel@tonic-gate break; 5250Sstevel@tonic-gate } 5260Sstevel@tonic-gate 5270Sstevel@tonic-gate /* 5280Sstevel@tonic-gate * send the info to the next level -- 5290Sstevel@tonic-gate * need to send multiple events if we have both 5300Sstevel@tonic-gate * a delta *AND* button event(s) 5310Sstevel@tonic-gate */ 5320Sstevel@tonic-gate 5330Sstevel@tonic-gate /* motion has occurred ... */ 5340Sstevel@tonic-gate if (STATEP->deltax) 5350Sstevel@tonic-gate VUID_PUTNEXT(qp, (uchar_t)LOC_X_DELTA, 5360Sstevel@tonic-gate FE_PAIR_ABSOLUTE, (uchar_t)LOC_X_ABSOLUTE, 5370Sstevel@tonic-gate STATEP->deltax); 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate if (STATEP->deltay) 5400Sstevel@tonic-gate VUID_PUTNEXT(qp, (uchar_t)LOC_Y_DELTA, 5410Sstevel@tonic-gate FE_PAIR_ABSOLUTE, (uchar_t)LOC_Y_ABSOLUTE, 5420Sstevel@tonic-gate STATEP->deltay); 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate STATEP->deltax = STATEP->deltay = 0; 5450Sstevel@tonic-gate break; 5460Sstevel@tonic-gate 5470Sstevel@tonic-gate case PS2_WAIT_RESET_ACK: 5480Sstevel@tonic-gate if (code != MSE_ACK) { 5490Sstevel@tonic-gate break; 5500Sstevel@tonic-gate } 551*993Slq150181 552*993Slq150181 /* 553*993Slq150181 * On Dell latitude D800, we find that the MSE_ACK is 554*993Slq150181 * coming up even after timeout in VUID_OPEN during 555*993Slq150181 * early boot. So here (PS2_WAIT_RESET_ACK) we check 556*993Slq150181 * if timeout happened before, if true, we reset the 557*993Slq150181 * timeout to restart the initialization. 558*993Slq150181 */ 559*993Slq150181 if (STATEP->inited & PS2_FLAG_INIT_TIMEOUT) { 560*993Slq150181 STATEP->inited &= ~PS2_FLAG_INIT_TIMEOUT; 561*993Slq150181 vuid_set_timeout(qp, PS2_INIT_TMOUT_RESET); 562*993Slq150181 } 563*993Slq150181 5640Sstevel@tonic-gate STATEP->state = PS2_WAIT_RESET_AA; 5650Sstevel@tonic-gate break; 5660Sstevel@tonic-gate 5670Sstevel@tonic-gate case PS2_WAIT_RESET_AA: 5680Sstevel@tonic-gate if (code != MSE_AA) { 5690Sstevel@tonic-gate break; 5700Sstevel@tonic-gate } 5710Sstevel@tonic-gate STATEP->state = PS2_WAIT_RESET_00; 5720Sstevel@tonic-gate break; 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate case PS2_WAIT_RESET_00: 5750Sstevel@tonic-gate if (code != MSE_00) { 5760Sstevel@tonic-gate break; 5770Sstevel@tonic-gate } 5780Sstevel@tonic-gate 5790Sstevel@tonic-gate /* Reset has been ok */ 5800Sstevel@tonic-gate vuid_cancel_timeout(qp); 5810Sstevel@tonic-gate 5820Sstevel@tonic-gate STATEP->state = PS2_WAIT_SETRES0_ACK1; 5830Sstevel@tonic-gate 5840Sstevel@tonic-gate /* Set timeout for set res */ 585*993Slq150181 vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_GROUP); 5860Sstevel@tonic-gate 587*993Slq150181 put1(WR(qp), MSESETRES); 5880Sstevel@tonic-gate break; 5890Sstevel@tonic-gate 5900Sstevel@tonic-gate case PS2_WAIT_SETRES0_ACK1: 5910Sstevel@tonic-gate if (code != MSE_ACK) { 5920Sstevel@tonic-gate break; 5930Sstevel@tonic-gate } 594*993Slq150181 STATEP->state = PS2_WAIT_SETRES0_ACK2; 5950Sstevel@tonic-gate put1(WR(qp), 0); 5960Sstevel@tonic-gate break; 5970Sstevel@tonic-gate 5980Sstevel@tonic-gate case PS2_WAIT_SETRES0_ACK2: 5990Sstevel@tonic-gate case PS2_WAIT_SCALE1_1_ACK: 6000Sstevel@tonic-gate case PS2_WAIT_SCALE1_2_ACK: 6010Sstevel@tonic-gate if (code != MSE_ACK) { 6020Sstevel@tonic-gate break; 6030Sstevel@tonic-gate } 604*993Slq150181 STATEP->state++; 6050Sstevel@tonic-gate put1(WR(qp), MSESCALE1); 6060Sstevel@tonic-gate break; 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate case PS2_WAIT_SCALE1_3_ACK: 6090Sstevel@tonic-gate if (code != MSE_ACK) { 6100Sstevel@tonic-gate break; 6110Sstevel@tonic-gate } 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate /* Set res and scale have been ok */ 6140Sstevel@tonic-gate vuid_cancel_timeout(qp); 6150Sstevel@tonic-gate 6160Sstevel@tonic-gate STATEP->state = PS2_WAIT_STATREQ_ACK; 6170Sstevel@tonic-gate 6180Sstevel@tonic-gate /* Set timeout for status request */ 619*993Slq150181 vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_GROUP); 620*993Slq150181 621*993Slq150181 put1(WR(qp), MSESTATREQ); 6220Sstevel@tonic-gate 6230Sstevel@tonic-gate break; 6240Sstevel@tonic-gate 6250Sstevel@tonic-gate case PS2_WAIT_STATREQ_ACK: 6260Sstevel@tonic-gate if (code != MSE_ACK) { 6270Sstevel@tonic-gate break; 6280Sstevel@tonic-gate } 6290Sstevel@tonic-gate STATEP->state = PS2_WAIT_STATUS_1; 6300Sstevel@tonic-gate break; 6310Sstevel@tonic-gate 6320Sstevel@tonic-gate case PS2_WAIT_STATUS_1: 6330Sstevel@tonic-gate STATEP->state = PS2_WAIT_STATUS_BUTTONS; 6340Sstevel@tonic-gate break; 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate case PS2_WAIT_STATUS_BUTTONS: 6370Sstevel@tonic-gate if (code != 0) { 6380Sstevel@tonic-gate STATEP->nbuttons = (uchar_t)code; 6390Sstevel@tonic-gate STATEP->state = (uchar_t)PS2_WAIT_STATUS_REV; 6400Sstevel@tonic-gate } else { 6410Sstevel@tonic-gate #if defined(VUID3PS2) 6420Sstevel@tonic-gate /* 6430Sstevel@tonic-gate * It seems that there are some 3-button mice 6440Sstevel@tonic-gate * that don't play the Logitech autodetect 6450Sstevel@tonic-gate * game. One is a Mouse Systems mouse OEM'ed 6460Sstevel@tonic-gate * by Intergraph. 6470Sstevel@tonic-gate * 6480Sstevel@tonic-gate * Until we find out how to autodetect these 6490Sstevel@tonic-gate * mice, we'll assume that if we're being 6500Sstevel@tonic-gate * compiled as vuid3ps2 and the mouse doesn't 6510Sstevel@tonic-gate * play the autodetect game, it's a 3-button 6520Sstevel@tonic-gate * mouse. This effectively disables 6530Sstevel@tonic-gate * autodetect for mice using vuid3ps2, but 6540Sstevel@tonic-gate * since vuid3ps2 is used only on x86 where 6550Sstevel@tonic-gate * we currently assume manual configuration, 6560Sstevel@tonic-gate * this shouldn't be a problem. At some point 6570Sstevel@tonic-gate * in the future when we *do* start using 6580Sstevel@tonic-gate * autodetect on x86, we should probably define 6590Sstevel@tonic-gate * VUIDPS2 instead of VUID3PS2. Even then, 6600Sstevel@tonic-gate * we could leave this code so that *some* 6610Sstevel@tonic-gate * mice could use autodetect and others not. 6620Sstevel@tonic-gate */ 6630Sstevel@tonic-gate STATEP->nbuttons = 3; 6640Sstevel@tonic-gate #else 6650Sstevel@tonic-gate STATEP->nbuttons = 2; 6660Sstevel@tonic-gate #endif 6670Sstevel@tonic-gate STATEP->state = PS2_WAIT_STATUS_3; 6680Sstevel@tonic-gate } 6690Sstevel@tonic-gate break; 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate case PS2_WAIT_STATUS_REV: 6720Sstevel@tonic-gate /*FALLTHROUGH*/ 6730Sstevel@tonic-gate 6740Sstevel@tonic-gate case PS2_WAIT_STATUS_3: 6750Sstevel@tonic-gate 6760Sstevel@tonic-gate /* Status request has been ok */ 6770Sstevel@tonic-gate vuid_cancel_timeout(qp); 6780Sstevel@tonic-gate 679*993Slq150181 /* Set timeout for set res or sample rate */ 680*993Slq150181 vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_GROUP); 681*993Slq150181 6820Sstevel@tonic-gate /* 6830Sstevel@tonic-gate * Start the wheel-mouse detection code. First, we look 6840Sstevel@tonic-gate * for standard wheel mice. If we set the sample rate 6850Sstevel@tonic-gate * to 200, 100, and then 80 and finally request the 6860Sstevel@tonic-gate * device ID, a wheel mouse will return an ID of 0x03. 6870Sstevel@tonic-gate * After that, we'll try for the wheel+5 variety. The 6880Sstevel@tonic-gate * incantation in this case is 200, 200, and 80. We'll 6890Sstevel@tonic-gate * get 0x04 back in that case. 6900Sstevel@tonic-gate */ 6910Sstevel@tonic-gate if (STATEP->inited & PS2_FLAG_NO_EXTN) { 6920Sstevel@tonic-gate STATEP->state = PS2_WAIT_SETRES3_ACK1; 6930Sstevel@tonic-gate put1(WR(qp), MSESETRES); 6940Sstevel@tonic-gate } else { 695*993Slq150181 STATEP->state = PS2_WAIT_WHEEL_SMPL1_CMD_ACK; 6960Sstevel@tonic-gate put1(WR(qp), MSECHGMOD); 6970Sstevel@tonic-gate } 6980Sstevel@tonic-gate 6990Sstevel@tonic-gate break; 7000Sstevel@tonic-gate case PS2_WAIT_WHEEL_SMPL1_CMD_ACK: 7010Sstevel@tonic-gate if (code != MSE_ACK) { 7020Sstevel@tonic-gate break; 7030Sstevel@tonic-gate } 704*993Slq150181 STATEP->state = PS2_WAIT_WHEEL_SMPL1_RATE_ACK; 7050Sstevel@tonic-gate put1(WR(qp), 200); 7060Sstevel@tonic-gate break; 7070Sstevel@tonic-gate case PS2_WAIT_WHEEL_SMPL1_RATE_ACK: 7080Sstevel@tonic-gate if (code != MSE_ACK) { 7090Sstevel@tonic-gate break; 7100Sstevel@tonic-gate } 711*993Slq150181 STATEP->state = PS2_WAIT_WHEEL_SMPL2_CMD_ACK; 7120Sstevel@tonic-gate put1(WR(qp), MSECHGMOD); 7130Sstevel@tonic-gate break; 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate case PS2_WAIT_WHEEL_SMPL2_CMD_ACK: 7160Sstevel@tonic-gate if (code != MSE_ACK) { 7170Sstevel@tonic-gate break; 7180Sstevel@tonic-gate } 719*993Slq150181 STATEP->state = PS2_WAIT_WHEEL_SMPL2_RATE_ACK; 7200Sstevel@tonic-gate put1(WR(qp), 100); 7210Sstevel@tonic-gate break; 7220Sstevel@tonic-gate 7230Sstevel@tonic-gate case PS2_WAIT_WHEEL_SMPL2_RATE_ACK: 7240Sstevel@tonic-gate if (code != MSE_ACK) { 7250Sstevel@tonic-gate break; 7260Sstevel@tonic-gate } 727*993Slq150181 STATEP->state = PS2_WAIT_WHEEL_SMPL3_CMD_ACK; 7280Sstevel@tonic-gate put1(WR(qp), MSECHGMOD); 7290Sstevel@tonic-gate break; 7300Sstevel@tonic-gate 7310Sstevel@tonic-gate case PS2_WAIT_WHEEL_SMPL3_CMD_ACK: 7320Sstevel@tonic-gate if (code != MSE_ACK) { 7330Sstevel@tonic-gate break; 7340Sstevel@tonic-gate } 735*993Slq150181 STATEP->state = PS2_WAIT_WHEEL_SMPL3_RATE_ACK; 7360Sstevel@tonic-gate put1(WR(qp), 80); 7370Sstevel@tonic-gate break; 7380Sstevel@tonic-gate 7390Sstevel@tonic-gate case PS2_WAIT_WHEEL_SMPL3_RATE_ACK: 7400Sstevel@tonic-gate if (code != MSE_ACK) { 7410Sstevel@tonic-gate break; 7420Sstevel@tonic-gate } 7430Sstevel@tonic-gate 7440Sstevel@tonic-gate /* Set sample rate has been ok */ 7450Sstevel@tonic-gate vuid_cancel_timeout(qp); 7460Sstevel@tonic-gate 7470Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL_DEV_CMD; 7480Sstevel@tonic-gate 7490Sstevel@tonic-gate /* Set timeout for get dev */ 7500Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD); 7510Sstevel@tonic-gate 752*993Slq150181 put1(WR(qp), MSEGETDEV); 7530Sstevel@tonic-gate break; 7540Sstevel@tonic-gate 7550Sstevel@tonic-gate case PS2_WAIT_WHEEL_DEV_CMD: 7560Sstevel@tonic-gate if (code != MSE_ACK) { 7570Sstevel@tonic-gate break; 7580Sstevel@tonic-gate } 7590Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL_DEV_ACK; 7600Sstevel@tonic-gate break; 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate case PS2_WAIT_WHEEL_DEV_ACK: 7630Sstevel@tonic-gate 7640Sstevel@tonic-gate /* Get dev has been ok */ 7650Sstevel@tonic-gate vuid_cancel_timeout(qp); 7660Sstevel@tonic-gate 7670Sstevel@tonic-gate if (code != 0x03) { 7680Sstevel@tonic-gate STATEP->state = PS2_WAIT_SETRES3_ACK1; 7690Sstevel@tonic-gate 7700Sstevel@tonic-gate /* Set timeout for set res */ 7710Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD); 7720Sstevel@tonic-gate 773*993Slq150181 put1(WR(qp), MSESETRES); 774*993Slq150181 7750Sstevel@tonic-gate break; 7760Sstevel@tonic-gate } 7770Sstevel@tonic-gate 7780Sstevel@tonic-gate STATEP->vuid_mouse_mode = MOUSE_MODE_WHEEL; 7790Sstevel@tonic-gate 7800Sstevel@tonic-gate /* 7810Sstevel@tonic-gate * Found wheel. By default enable the wheel. 7820Sstevel@tonic-gate */ 7830Sstevel@tonic-gate STATEP->wheel_state_bf |= VUID_WHEEL_STATE_ENABLED; 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL5_SMPL1_CMD_ACK; 7860Sstevel@tonic-gate 7870Sstevel@tonic-gate /* Set timeout for set sample rate */ 788*993Slq150181 vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_GROUP); 789*993Slq150181 790*993Slq150181 /* We're on a roll - try for wheel+5 */ 791*993Slq150181 put1(WR(qp), MSECHGMOD); 7920Sstevel@tonic-gate 7930Sstevel@tonic-gate break; 7940Sstevel@tonic-gate 7950Sstevel@tonic-gate case PS2_WAIT_WHEEL5_SMPL1_CMD_ACK: 7960Sstevel@tonic-gate if (code != MSE_ACK) { 7970Sstevel@tonic-gate break; 7980Sstevel@tonic-gate } 799*993Slq150181 STATEP->state = PS2_WAIT_WHEEL5_SMPL1_RATE_ACK; 8000Sstevel@tonic-gate put1(WR(qp), 200); 8010Sstevel@tonic-gate break; 8020Sstevel@tonic-gate 8030Sstevel@tonic-gate case PS2_WAIT_WHEEL5_SMPL1_RATE_ACK: 8040Sstevel@tonic-gate if (code != MSE_ACK) { 8050Sstevel@tonic-gate break; 8060Sstevel@tonic-gate } 807*993Slq150181 STATEP->state = PS2_WAIT_WHEEL5_SMPL2_CMD_ACK; 8080Sstevel@tonic-gate put1(WR(qp), MSECHGMOD); 8090Sstevel@tonic-gate break; 8100Sstevel@tonic-gate 8110Sstevel@tonic-gate case PS2_WAIT_WHEEL5_SMPL2_CMD_ACK: 8120Sstevel@tonic-gate if (code != MSE_ACK) { 8130Sstevel@tonic-gate break; 8140Sstevel@tonic-gate } 815*993Slq150181 STATEP->state = PS2_WAIT_WHEEL5_SMPL2_RATE_ACK; 8160Sstevel@tonic-gate put1(WR(qp), 200); 8170Sstevel@tonic-gate break; 8180Sstevel@tonic-gate 8190Sstevel@tonic-gate case PS2_WAIT_WHEEL5_SMPL2_RATE_ACK: 8200Sstevel@tonic-gate if (code != MSE_ACK) { 8210Sstevel@tonic-gate break; 8220Sstevel@tonic-gate } 823*993Slq150181 STATEP->state = PS2_WAIT_WHEEL5_SMPL3_CMD_ACK; 8240Sstevel@tonic-gate put1(WR(qp), MSECHGMOD); 8250Sstevel@tonic-gate break; 8260Sstevel@tonic-gate 8270Sstevel@tonic-gate case PS2_WAIT_WHEEL5_SMPL3_CMD_ACK: 8280Sstevel@tonic-gate if (code != MSE_ACK) { 8290Sstevel@tonic-gate break; 8300Sstevel@tonic-gate } 831*993Slq150181 STATEP->state = PS2_WAIT_WHEEL5_SMPL3_RATE_ACK; 8320Sstevel@tonic-gate put1(WR(qp), 80); 8330Sstevel@tonic-gate break; 8340Sstevel@tonic-gate 8350Sstevel@tonic-gate case PS2_WAIT_WHEEL5_SMPL3_RATE_ACK: 8360Sstevel@tonic-gate if (code != MSE_ACK) { 8370Sstevel@tonic-gate break; 8380Sstevel@tonic-gate } 8390Sstevel@tonic-gate 8400Sstevel@tonic-gate /* Set sample rate has been ok */ 8410Sstevel@tonic-gate vuid_cancel_timeout(qp); 8420Sstevel@tonic-gate 8430Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL5_DEV_CMD; 8440Sstevel@tonic-gate 8450Sstevel@tonic-gate /* Set timeout for wheel5 get dev */ 8460Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD); 8470Sstevel@tonic-gate 848*993Slq150181 put1(WR(qp), MSEGETDEV); 849*993Slq150181 8500Sstevel@tonic-gate break; 8510Sstevel@tonic-gate 8520Sstevel@tonic-gate case PS2_WAIT_WHEEL5_DEV_CMD: 8530Sstevel@tonic-gate if (code != MSE_ACK) { 8540Sstevel@tonic-gate break; 8550Sstevel@tonic-gate } 8560Sstevel@tonic-gate STATEP->state = PS2_WAIT_WHEEL5_DEV_ACK; 8570Sstevel@tonic-gate break; 8580Sstevel@tonic-gate 8590Sstevel@tonic-gate case PS2_WAIT_WHEEL5_DEV_ACK: 8600Sstevel@tonic-gate if (code == 0x04) { 8610Sstevel@tonic-gate STATEP->vuid_mouse_mode = MOUSE_MODE_WHEEL5; 8620Sstevel@tonic-gate STATEP->nbuttons = 5; 8630Sstevel@tonic-gate 8640Sstevel@tonic-gate /* 8650Sstevel@tonic-gate * Found wheel. By default enable the wheel. 8660Sstevel@tonic-gate */ 8670Sstevel@tonic-gate STATEP->wheel_state_bf |= 8680Sstevel@tonic-gate VUID_WHEEL_STATE_ENABLED << 8690Sstevel@tonic-gate MOUSE_MODE_WHEEL; 8700Sstevel@tonic-gate } 8710Sstevel@tonic-gate 8720Sstevel@tonic-gate /* Wheel5 get dev has been ok */ 8730Sstevel@tonic-gate vuid_cancel_timeout(qp); 8740Sstevel@tonic-gate 8750Sstevel@tonic-gate /* FALLTHROUGH */ 8760Sstevel@tonic-gate 8770Sstevel@tonic-gate case PS2_WAIT_SETRES3_CMD: 8780Sstevel@tonic-gate STATEP->state = PS2_WAIT_SETRES3_ACK1; 8790Sstevel@tonic-gate 8800Sstevel@tonic-gate /* Set timeout for set res */ 8810Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD); 8820Sstevel@tonic-gate 883*993Slq150181 put1(WR(qp), MSESETRES); 884*993Slq150181 8850Sstevel@tonic-gate break; 8860Sstevel@tonic-gate 8870Sstevel@tonic-gate case PS2_WAIT_SETRES3_ACK1: 8880Sstevel@tonic-gate if (code != MSE_ACK) { 8890Sstevel@tonic-gate break; 8900Sstevel@tonic-gate } 891*993Slq150181 STATEP->state = PS2_WAIT_SETRES3_ACK2; 8920Sstevel@tonic-gate put1(WR(qp), 3); 8930Sstevel@tonic-gate break; 8940Sstevel@tonic-gate 8950Sstevel@tonic-gate case PS2_WAIT_SETRES3_ACK2: 8960Sstevel@tonic-gate if (code != MSE_ACK) { 8970Sstevel@tonic-gate break; 8980Sstevel@tonic-gate } 8990Sstevel@tonic-gate 9000Sstevel@tonic-gate /* Set res has been ok */ 9010Sstevel@tonic-gate vuid_cancel_timeout(qp); 9020Sstevel@tonic-gate 9030Sstevel@tonic-gate STATEP->state = PS2_WAIT_STREAM_ACK; 9040Sstevel@tonic-gate 9050Sstevel@tonic-gate /* Set timeout for enable */ 9060Sstevel@tonic-gate vuid_set_timeout(qp, PS2_INIT_TMOUT_PER_CMD); 9070Sstevel@tonic-gate 908*993Slq150181 put1(WR(qp), MSESTREAM); 909*993Slq150181 9100Sstevel@tonic-gate break; 9110Sstevel@tonic-gate 9120Sstevel@tonic-gate case PS2_WAIT_STREAM_ACK: 9130Sstevel@tonic-gate if (code != MSE_ACK) { 9140Sstevel@tonic-gate break; 9150Sstevel@tonic-gate } 916*993Slq150181 STATEP->state = PS2_WAIT_ON_ACK; 9170Sstevel@tonic-gate put1(WR(qp), MSEON); 9180Sstevel@tonic-gate break; 9190Sstevel@tonic-gate 9200Sstevel@tonic-gate case PS2_WAIT_ON_ACK: 9210Sstevel@tonic-gate if (code != MSE_ACK) { 9220Sstevel@tonic-gate break; 9230Sstevel@tonic-gate } 9240Sstevel@tonic-gate 9250Sstevel@tonic-gate /* Enable has been ok */ 9260Sstevel@tonic-gate vuid_cancel_timeout(qp); 9270Sstevel@tonic-gate 9280Sstevel@tonic-gate STATEP->state = PS2_START; 9290Sstevel@tonic-gate break; 9300Sstevel@tonic-gate } 9310Sstevel@tonic-gate } 9320Sstevel@tonic-gate freemsg(mp); 9330Sstevel@tonic-gate } 934