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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * 2/3/5 Button PS/2 Mouse Protocol
29 * This module dynamically determines the number of buttons on the mouse.
32 #include <sys/param.h>
33 #include <sys/stream.h>
34 #include <sys/vuid_event.h>
36 #include <sys/vuid_wheel.h>
37 #include <sys/mouse.h>
38 #include <sys/strsun.h>
40 #include <sys/sunddi.h>
44 * BUT(2) MIDDLE BUTTON (if present)
48 #define PS2_BUTTONMASK 7 /* mask byte zero with this */
50 #define PS2_BUTTON_L (uchar_t)0x01 /* Left button pressed */
51 #define PS2_BUTTON_R (uchar_t)0x02 /* Right button pressed */
52 #define PS2_BUTTON_M (uchar_t)0x04 /* Middle button pressed */
53 #define PS2_DATA_XSIGN (uchar_t)0x10 /* X data sign bit */
54 #define PS2_DATA_YSIGN (uchar_t)0x20 /* Y data sign bit */
56 #define PS2_START 0 /* Beginning of packet */
57 #define PS2_BUTTON 1 /* Got button status */
58 #define PS2_MAYBE_REATTACH 2 /* Got button status */
59 #define PS2_DELTA_Y 3 /* Got delta X */
60 #define PS2_WHEEL_DELTA_Z 4
61 #define PS2_WHEEL5_DELTA_Z 5
62 #define PS2_WAIT_RESET_COMPLETE 6
63 #define PS2_WAIT_FOR_AA 7
64 #define PS2_WAIT_FOR_00 8
65 #define PS2_WAIT_SETRES0_ACK1 9
66 #define PS2_WAIT_SETRES0_ACK2 10 /* -+ must be consecutive */
67 #define PS2_WAIT_SCALE1_1_ACK 11 /* | */
68 #define PS2_WAIT_SCALE1_2_ACK 12 /* | */
69 #define PS2_WAIT_SCALE1_3_ACK 13 /* -+ */
70 #define PS2_WAIT_STATREQ_ACK 14 /* -+ */
71 #define PS2_WAIT_STATUS_1 15 /* | */
72 #define PS2_WAIT_STATUS_BUTTONS 16 /* | must stay in this order */
73 #define PS2_WAIT_STATUS_REV 17 /* -+ */
74 #define PS2_WAIT_STATUS_3 18
75 #define PS2_WAIT_WHEEL_SMPL1_CMD_ACK 19 /* Set the sample rate to 200 */
76 #define PS2_WAIT_WHEEL_SMPL1_RATE_ACK 20
77 #define PS2_WAIT_WHEEL_SMPL2_CMD_ACK 21 /* Set the sample rate to 200 */
78 #define PS2_WAIT_WHEEL_SMPL2_RATE_ACK 22
79 #define PS2_WAIT_WHEEL_SMPL3_CMD_ACK 23 /* Set the sample rate to 80 */
80 #define PS2_WAIT_WHEEL_SMPL3_RATE_ACK 24
81 #define PS2_WAIT_WHEEL_DEV_CMD 25
82 #define PS2_WAIT_WHEEL_DEV_ACK 26 /* Detected wheel mouse */
83 #define PS2_WAIT_WHEEL5_SMPL1_CMD_ACK 27 /* Set the sample rate to 200 */
84 #define PS2_WAIT_WHEEL5_SMPL1_RATE_ACK 28
85 #define PS2_WAIT_WHEEL5_SMPL2_CMD_ACK 29 /* Set the sample rate to 200 */
86 #define PS2_WAIT_WHEEL5_SMPL2_RATE_ACK 30
87 #define PS2_WAIT_WHEEL5_SMPL3_CMD_ACK 31 /* Set the sample rate to 100 */
88 #define PS2_WAIT_WHEEL5_SMPL3_RATE_ACK 32
89 #define PS2_WAIT_WHEEL5_DEV_CMD 33
90 #define PS2_WAIT_WHEEL5_DEV_ACK 34 /* Detected 5 button mouse */
91 #define PS2_WAIT_SETRES3_CMD 35
92 #define PS2_WAIT_SETRES3_ACK1 36
93 #define PS2_WAIT_SETRES3_ACK2 37
94 #define PS2_WAIT_STREAM_ACK 38
95 #define PS2_WAIT_ON_ACK 39
97 #define MOUSE_MODE_PLAIN 0 /* Normal PS/2 mouse - 3 byte msgs */
98 #define MOUSE_MODE_WHEEL 1 /* Wheel mouse - 4 byte msgs */
99 #define MOUSE_MODE_WHEEL5 2 /* Wheel + 5 btn mouse - 4 byte msgs */
101 #define PS2_FLAG_NO_EXTN 0x08 /* Mouse doesn't obey extended cmds */
102 #define PS2_FLAG_INIT_DONE 0x01 /* Mouse has been inited successfully */
103 #define PS2_FLAG_INIT_TIMEOUT 0x02 /* Mouse init timeout */
106 * The RESET command takes more time
107 * before the PS/2 mouse is ready
109 #define PS2_INIT_TMOUT_RESET 500000 /* 500ms for RESET command */
110 #define PS2_INIT_TMOUT_PER_CMD 200000 /* 200ms for each command-response */
111 #define PS2_INIT_TMOUT_PER_GROUP 500000 /* 500ms for group commands */
113 #define PS2_MAX_INIT_COUNT 5
115 static void vuidmice_send_wheel_event(queue_t
*const, uchar_t
,
116 uchar_t
, uchar_t
, int);
117 extern void VUID_PUTNEXT(queue_t
*const, uchar_t
, uchar_t
, uchar_t
, int);
118 extern void uniqtime32(struct timeval32
*);
119 static void VUID_INIT_TIMEOUT(void *q
);
122 * We apply timeout to nearly each command-response
123 * during initialization:
125 * Set timeout for SET RESOLUTION
126 * Set timeout for SET SCALE
127 * Set timeout for SET SAMPLE RATE
128 * Set timeout for STATUS REQUEST
129 * Set timeout for GET DEV
130 * Set timeout for SET STREAM MODE and ENABLE.
132 * But for simplicity, sometimes we just apply the timeout
133 * to a function with group commands (e.g. wheel-mouse detection).
137 vuid_set_timeout(queue_t
*const qp
, clock_t time
)
139 if (STATEP
->init_tid
!= 0)
140 (void) quntimeout(qp
, STATEP
->init_tid
);
141 STATEP
->init_tid
= qtimeout(qp
, VUID_INIT_TIMEOUT
,
142 qp
, drv_usectohz(time
));
146 vuid_cancel_timeout(queue_t
*const qp
)
148 (void) quntimeout(qp
, STATEP
->init_tid
);
149 STATEP
->init_tid
= 0;
153 * vuidmice_send_wheel_event
154 * Convert wheel data to firm_events
157 vuidmice_send_wheel_event(queue_t
*const qp
, uchar_t event_id
,
158 uchar_t event_pair_type
, uchar_t event_pair
, int event_value
)
163 if ((bp
= allocb((int)sizeof (Firm_event
), BPRI_HI
)) == NULL
) {
168 fep
= (void *)bp
->b_wptr
;
169 fep
->id
= vuid_id_addr(vuid_first(VUID_WHEEL
)) |
170 vuid_id_offset(event_id
);
171 fep
->pair_type
= event_pair_type
;
172 fep
->pair
= event_pair
;
173 fep
->value
= event_value
;
174 uniqtime32(&fep
->time
);
175 bp
->b_wptr
+= sizeof (Firm_event
);
177 if (canput(qp
->q_next
)) {
180 (void) putbq(qp
, bp
); /* read side is blocked */
186 sendButtonEvent(queue_t
*const qp
)
188 static int bmap
[3] = {1, 3, 2};
191 /* for each button, see if it has changed */
192 for (b
= 0; b
< STATEP
->nbuttons
; b
++) {
193 uchar_t mask
= 0x1 << b
;
195 if ((STATEP
->buttons
& mask
) != (STATEP
->oldbuttons
& mask
))
196 VUID_PUTNEXT(qp
, (uchar_t
)BUT(bmap
[b
]), FE_PAIR_NONE
, 0,
197 (STATEP
->buttons
& mask
? 1 : 0));
202 put1(queue_t
*const qp
, int c
)
206 if (bp
= allocb(1, BPRI_MED
)) {
207 *bp
->b_wptr
++ = (char)c
;
213 vuidmice_start_wdc_or_setres(queue_t
*qp
)
215 /* Set timeout for set res or sample rate */
216 vuid_set_timeout(qp
, PS2_INIT_TMOUT_PER_GROUP
);
219 * Start the wheel-mouse detection code. First, we look
220 * for standard wheel mice. If we set the sample rate
221 * to 200, 100, and then 80 and finally request the
222 * device ID, a wheel mouse will return an ID of 0x03.
223 * After that, we'll try for the wheel+5 variety. The
224 * incantation in this case is 200, 200, and 80. We'll
225 * get 0x04 back in that case.
227 if (STATEP
->inited
& PS2_FLAG_NO_EXTN
) {
228 STATEP
->state
= PS2_WAIT_SETRES3_ACK1
;
229 put1(WR(qp
), MSESETRES
);
231 STATEP
->state
= PS2_WAIT_WHEEL_SMPL1_CMD_ACK
;
232 put1(WR(qp
), MSECHGMOD
);
237 VUID_OPEN(queue_t
*const qp
)
239 STATEP
->format
= VUID_FIRM_EVENT
;
240 STATEP
->vuid_mouse_mode
= MOUSE_MODE_PLAIN
;
242 STATEP
->nbuttons
= 3;
244 STATEP
->state
= PS2_WAIT_RESET_COMPLETE
;
246 put1(WR(qp
), MSERESET
);
248 while ((STATEP
->state
!= PS2_START
) &&
249 !(STATEP
->inited
& PS2_FLAG_INIT_TIMEOUT
)) {
250 if (qwait_sig(qp
) == 0)
255 * Later the PS/2 mouse maybe re-attach, so here
256 * clear the init_count.
258 STATEP
->init_count
= 0;
264 VUID_CLOSE(queue_t
*const qp
)
266 if (STATEP
->init_tid
!= 0)
267 vuid_cancel_timeout(qp
);
271 VUID_INIT_TIMEOUT(void *q
)
275 STATEP
->init_tid
= 0;
278 * Some mice do not even send an error in response to
279 * the wheel mouse sample commands, so if we're in any of
280 * the PS2_WAIT_WHEEL_SMPL* states, and there has been
281 * a timeout, assume the mouse cannot handle the extended
282 * (wheel mouse) commands.
284 if ((STATEP
->state
== PS2_WAIT_WHEEL_SMPL1_CMD_ACK
) ||
285 (STATEP
->state
== PS2_WAIT_WHEEL_SMPL1_RATE_ACK
) ||
286 (STATEP
->state
== PS2_WAIT_WHEEL_SMPL2_RATE_ACK
) ||
287 (STATEP
->state
== PS2_WAIT_WHEEL_SMPL3_RATE_ACK
)) {
289 * We overload 'inited' to mark the PS/2 mouse
290 * as one which doesn't respond to extended commands.
293 STATEP
->inited
|= PS2_FLAG_NO_EXTN
;
298 * If the Logitech button detection sequence timed out at some point
299 * in the sequence, ignore it and skip to the next step in
300 * initialization. Do NOT count this as a timeout, so do NOT
301 * increment init_count.
303 if (STATEP
->state
>= PS2_WAIT_STATREQ_ACK
&&
304 STATEP
->state
<= PS2_WAIT_STATUS_REV
) {
306 /* See the comment under the PS2_WAIT_STATUS_BUTTONS case */
307 #if defined(VUID3PS2)
308 STATEP
->nbuttons
= 3;
310 STATEP
->nbuttons
= 2;
312 vuidmice_start_wdc_or_setres(qp
);
317 * If the initialization process has timed out too many times, even if
318 * a subset of the process was successful, stop trying and put the
319 * mouse in the only state from which it can recover -- waiting for an
320 * 0xAA 0x00 response (i.e. like one we get on resume from mouse8042
323 if (++STATEP
->init_count
>= PS2_MAX_INIT_COUNT
) {
324 STATEP
->inited
|= PS2_FLAG_INIT_TIMEOUT
;
325 STATEP
->state
= PS2_WAIT_FOR_AA
;
328 STATEP
->state
= PS2_WAIT_RESET_COMPLETE
;
330 /* Try to reset the mouse again */
331 put1(WR(qp
), MSERESET
);
336 VUID_QUEUE(queue_t
*const qp
, mblk_t
*mp
)
341 clock_t mouse_timeout
;
343 mouse_timeout
= drv_usectohz(250000);
344 now
= ddi_get_lbolt();
345 elapsed
= now
- STATEP
->last_event_lbolt
;
346 STATEP
->last_event_lbolt
= now
;
348 while (mp
->b_rptr
< mp
->b_wptr
) {
350 code
= *mp
->b_rptr
++;
352 switch (STATEP
->state
) {
355 * Start state. We stay here if the start code is not
356 * received thus forcing us back into sync. When we get a
357 * start code the button mask comes with it forcing us to
364 * 3-byte packet format
366 * Bit 7 6 5 4 3 2 1 0
367 * Byte ---- ---- ----- ----- -- ------ ------ ------
368 * 1 Y_Ov X_Ov Y_Sgn X_Sgn 1 MdlBtn RgtBtn LftBtn
369 * 2 |<--------------X Movement----------------->|
370 * 3 |<--------------Y Movement----------------->|
372 * 4-byte wheel packet format
374 * Bit 7 6 5 4 3 2 1 0
375 * Byte ---- ---- ----- ----- -- ------ ------ ------
376 * 1 Y_Ov X_Ov Y_Sgn X_Sgn 1 MdlBtn RgtBtn LftBtn
377 * 2 |<--------------X Movement----------------->|
378 * 3 |<--------------Y Movement----------------->|
379 * 4 |<--------------Z Movement----------------->|
381 * 4-byte wheel+5 packet format
383 * Bit 7 6 5 4 3 2 1 0
384 * Byte ---- ---- ----- ----- -- ------ ------ ------
385 * 1 Y_Ov X_Ov Y_Sgn X_Sgn 1 MdlBtn RgtBtn LftBtn
386 * 2 |<--------------X Movement----------------->|
387 * 3 |<--------------Y Movement----------------->|
388 * 4 0 0 5_Btn 4_Btn Z3 Z2 Z1 Z0
391 if (!(STATEP
->inited
& PS2_FLAG_INIT_DONE
)) {
392 STATEP
->sync_byte
= code
& 0x8;
393 STATEP
->inited
|= PS2_FLAG_INIT_DONE
;
396 * the PS/2 mouse data format doesn't have any sort of sync
397 * data to make sure we are in sync with the packet stream,
398 * but the Technical Reference manual states that bits 2 & 3
399 * of the first byte are reserved. Logitech uses bit 2 for
400 * the middle button. We HOPE that noone uses bit 3 though,
401 * and decide we're out of sync if bit 3 is not set here.
404 if ((code
^ STATEP
->sync_byte
) & 0x08) {
406 STATEP
->state
= PS2_START
;
407 break; /* toss the code */
410 /* get the button values */
411 STATEP
->buttons
= code
& PS2_BUTTONMASK
;
412 if (STATEP
->buttons
!= STATEP
->oldbuttons
) {
414 STATEP
->oldbuttons
= STATEP
->buttons
;
417 /* bit 5 indicates Y value is negative (the sign bit) */
418 if (code
& PS2_DATA_YSIGN
)
419 STATEP
->deltay
= -1 & ~0xff;
423 /* bit 4 is X sign bit */
424 if (code
& PS2_DATA_XSIGN
)
425 STATEP
->deltax
= -1 & ~0xff;
430 STATEP
->state
= PS2_MAYBE_REATTACH
;
432 STATEP
->state
= PS2_BUTTON
;
436 case PS2_WAIT_FOR_AA
:
438 * On Dell latitude D800, the initial MSE_ACK is
439 * received after the initialization sequence
440 * times out, so restart it here.
442 if (code
== MSE_ACK
) {
443 STATEP
->inited
&= ~PS2_FLAG_INIT_TIMEOUT
;
444 STATEP
->init_count
= 0;
445 STATEP
->state
= PS2_WAIT_RESET_COMPLETE
;
446 put1(WR(qp
), MSERESET
);
453 STATEP
->state
= PS2_WAIT_FOR_00
;
456 case PS2_WAIT_FOR_00
:
460 STATEP
->inited
&= ~PS2_FLAG_INIT_TIMEOUT
;
461 STATEP
->init_count
= 0;
462 STATEP
->state
= PS2_WAIT_RESET_COMPLETE
;
463 put1(WR(qp
), MSERESET
);
466 case PS2_MAYBE_REATTACH
:
467 if (code
== MSE_00
) {
468 STATEP
->state
= PS2_WAIT_RESET_COMPLETE
;
469 put1(WR(qp
), MSERESET
);
476 * Now for the 7 bits of delta x. "Or" in
477 * the sign bit and continue. This is ac-
478 * tually a signed 9 bit number, but I just
479 * truncate it to a signed char in order to
480 * avoid changing and retesting all of the
481 * mouse-related modules for this patch.
483 if (elapsed
> mouse_timeout
)
485 STATEP
->deltax
|= code
& 0xff;
486 STATEP
->state
= PS2_DELTA_Y
;
491 * This byte is delta Y. If this is a plain mouse,
492 * we're done. Wheel mice have two different flavors
496 if (elapsed
> mouse_timeout
) {
499 STATEP
->deltay
|= code
& 0xff;
501 if (STATEP
->vuid_mouse_mode
== MOUSE_MODE_WHEEL
) {
502 STATEP
->state
= PS2_WHEEL_DELTA_Z
;
504 } else if (STATEP
->vuid_mouse_mode
==
506 STATEP
->state
= PS2_WHEEL5_DELTA_Z
;
509 goto packet_complete
;
511 case PS2_WHEEL5_DELTA_Z
:
513 /* fourth physical button */
514 VUID_PUTNEXT(qp
, (uchar_t
)BUT(4),
516 VUID_PUTNEXT(qp
, (uchar_t
)BUT(4),
518 } else if (code
& 0x20) {
519 /* fifth physical button */
520 VUID_PUTNEXT(qp
, (uchar_t
)BUT(5),
522 VUID_PUTNEXT(qp
, (uchar_t
)BUT(5),
527 case PS2_WHEEL_DELTA_Z
:
529 * Check whether reporting vertical wheel
530 * movements is enabled
534 if (STATEP
->wheel_state_bf
& (1 <<
535 VUIDMICE_VERTICAL_WHEEL_ID
)) {
537 * PS/2 mouse reports -ve values
538 * when the wheel is scrolled up. So
539 * we need to convert it into +ve as
540 * X interprets a +ve value as wheel up event.
541 * Same is true for the horizontal wheel also.
542 * The mouse reports 0xf when scrolled up
543 * and 0x1 when scrolled down. This observation
544 * is based on Logitech, HCL,
545 * Microsoft and Black Cat mouse only
548 /* negative Z - wheel up */
550 vuidmice_send_wheel_event(qp
, 0,
551 FE_PAIR_NONE
, 0, -code
);
552 } else if (code
== 0x01) {
553 /* positive Z - wheel down */
554 vuidmice_send_wheel_event(qp
, 0,
555 FE_PAIR_NONE
, 0, -code
);
560 * Check whether reporting horizontal wheel
561 * movements is enabled
563 if (STATEP
->wheel_state_bf
&
564 (1 << VUIDMICE_HORIZONTAL_WHEEL_ID
)) {
567 * The mouse return -7 and +7 when it
568 * is scrolled horizontally
571 /* negative Z - wheel left */
572 vuidmice_send_wheel_event(qp
, 1,
574 } else if (code
== 0x07) {
575 /* positive Z - wheel right */
576 vuidmice_send_wheel_event(qp
, 1,
577 FE_PAIR_NONE
, 0, -1);
582 STATEP
->state
= PS2_START
;
584 * If we can peek at the next mouse character, and
585 * its not the start of the next packet, don't use
588 if (mp
->b_wptr
> mp
->b_rptr
&&
589 ((mp
->b_rptr
[0] ^ STATEP
->sync_byte
) & 0x08)) {
597 * send the info to the next level --
598 * need to send multiple events if we have both
599 * a delta *AND* button event(s)
602 /* motion has occurred ... */
604 VUID_PUTNEXT(qp
, (uchar_t
)LOC_X_DELTA
,
605 FE_PAIR_ABSOLUTE
, (uchar_t
)LOC_X_ABSOLUTE
,
609 VUID_PUTNEXT(qp
, (uchar_t
)LOC_Y_DELTA
,
610 FE_PAIR_ABSOLUTE
, (uchar_t
)LOC_Y_ABSOLUTE
,
613 STATEP
->deltax
= STATEP
->deltay
= 0;
616 case PS2_WAIT_RESET_COMPLETE
:
619 * If length is 1, code holds the data from the message.
620 * for lengths > 1, we look at *(mp->b_rptr + offset)
621 * for the rest of the data.
625 * A response with length 1 from the mouse
626 * driver can be either an ACK (the first part
627 * of the reset reply) or either MSEERROR or
628 * MSERESEND. Issue another reset if either
629 * of the latter are received. For mice that
630 * are not connected, MSERESEND is received
637 if (++STATEP
->init_count
>=
638 PS2_MAX_INIT_COUNT
) {
639 STATEP
->inited
|= PS2_FLAG_INIT_TIMEOUT
;
640 STATEP
->state
= PS2_WAIT_FOR_AA
;
642 put1(WR(qp
), MSERESET
);
647 } else if (length
!= 2) {
652 * The only possible 2-byte reply from mouse8042 is
653 * 0xAA 0x00. If the mouse doesn't send that, mouse8042
654 * will send a 1-byte error message, handled above by
655 * resetting the mouse.
658 /* Skip past the 0x00 (since `code' contains 0xAA) */
661 /* Reset completed successfully */
663 STATEP
->state
= PS2_WAIT_SETRES0_ACK1
;
665 /* Set timeout for set res */
666 vuid_set_timeout(qp
, PS2_INIT_TMOUT_PER_GROUP
);
668 /* Begin Logitech autodetect sequence */
669 put1(WR(qp
), MSESETRES
);
672 case PS2_WAIT_SETRES0_ACK1
:
673 if (code
!= MSE_ACK
) {
676 STATEP
->state
= PS2_WAIT_SETRES0_ACK2
;
680 case PS2_WAIT_SETRES0_ACK2
:
681 case PS2_WAIT_SCALE1_1_ACK
:
682 case PS2_WAIT_SCALE1_2_ACK
:
683 if (code
!= MSE_ACK
) {
687 put1(WR(qp
), MSESCALE1
);
690 case PS2_WAIT_SCALE1_3_ACK
:
691 if (code
!= MSE_ACK
) {
695 /* Set res and scale have been ok */
696 vuid_cancel_timeout(qp
);
698 STATEP
->state
= PS2_WAIT_STATREQ_ACK
;
700 /* Set timeout for status request */
701 vuid_set_timeout(qp
, PS2_INIT_TMOUT_PER_GROUP
);
703 put1(WR(qp
), MSESTATREQ
);
707 case PS2_WAIT_STATREQ_ACK
:
708 if (code
!= MSE_ACK
) {
711 STATEP
->state
= PS2_WAIT_STATUS_1
;
714 case PS2_WAIT_STATUS_1
:
715 STATEP
->state
= PS2_WAIT_STATUS_BUTTONS
;
718 case PS2_WAIT_STATUS_BUTTONS
:
720 STATEP
->nbuttons
= (uchar_t
)code
;
721 STATEP
->state
= (uchar_t
)PS2_WAIT_STATUS_REV
;
723 #if defined(VUID3PS2)
725 * It seems that there are some 3-button mice
726 * that don't play the Logitech autodetect
727 * game. One is a Mouse Systems mouse OEM'ed
730 * Until we find out how to autodetect these
731 * mice, we'll assume that if we're being
732 * compiled as vuid3ps2 and the mouse doesn't
733 * play the autodetect game, it's a 3-button
734 * mouse. This effectively disables
735 * autodetect for mice using vuid3ps2, but
736 * since vuid3ps2 is used only on x86 where
737 * we currently assume manual configuration,
738 * this shouldn't be a problem. At some point
739 * in the future when we *do* start using
740 * autodetect on x86, we should probably define
741 * VUIDPS2 instead of VUID3PS2. Even then,
742 * we could leave this code so that *some*
743 * mice could use autodetect and others not.
745 STATEP
->nbuttons
= 3;
747 STATEP
->nbuttons
= 2;
749 STATEP
->state
= PS2_WAIT_STATUS_3
;
753 case PS2_WAIT_STATUS_REV
:
756 case PS2_WAIT_STATUS_3
:
758 /* Status request completed successfully */
759 vuid_cancel_timeout(qp
);
761 vuidmice_start_wdc_or_setres(qp
);
764 case PS2_WAIT_WHEEL_SMPL1_CMD_ACK
:
765 if (code
!= MSE_ACK
) {
768 STATEP
->state
= PS2_WAIT_WHEEL_SMPL1_RATE_ACK
;
771 case PS2_WAIT_WHEEL_SMPL1_RATE_ACK
:
772 if (code
!= MSE_ACK
) {
775 STATEP
->state
= PS2_WAIT_WHEEL_SMPL2_CMD_ACK
;
776 put1(WR(qp
), MSECHGMOD
);
779 case PS2_WAIT_WHEEL_SMPL2_CMD_ACK
:
780 if (code
!= MSE_ACK
) {
783 STATEP
->state
= PS2_WAIT_WHEEL_SMPL2_RATE_ACK
;
787 case PS2_WAIT_WHEEL_SMPL2_RATE_ACK
:
788 if (code
!= MSE_ACK
) {
791 STATEP
->state
= PS2_WAIT_WHEEL_SMPL3_CMD_ACK
;
792 put1(WR(qp
), MSECHGMOD
);
795 case PS2_WAIT_WHEEL_SMPL3_CMD_ACK
:
796 if (code
!= MSE_ACK
) {
799 STATEP
->state
= PS2_WAIT_WHEEL_SMPL3_RATE_ACK
;
803 case PS2_WAIT_WHEEL_SMPL3_RATE_ACK
:
804 if (code
!= MSE_ACK
) {
808 /* Set sample rate completed successfully */
809 vuid_cancel_timeout(qp
);
811 STATEP
->state
= PS2_WAIT_WHEEL_DEV_CMD
;
813 /* Set timeout for get dev */
814 vuid_set_timeout(qp
, PS2_INIT_TMOUT_PER_CMD
);
816 put1(WR(qp
), MSEGETDEV
);
819 case PS2_WAIT_WHEEL_DEV_CMD
:
820 if (code
!= MSE_ACK
) {
823 STATEP
->state
= PS2_WAIT_WHEEL_DEV_ACK
;
826 case PS2_WAIT_WHEEL_DEV_ACK
:
828 /* Get dev completed successfully */
829 vuid_cancel_timeout(qp
);
832 STATEP
->state
= PS2_WAIT_SETRES3_ACK1
;
834 /* Set timeout for set res */
835 vuid_set_timeout(qp
, PS2_INIT_TMOUT_PER_CMD
);
837 put1(WR(qp
), MSESETRES
);
842 STATEP
->vuid_mouse_mode
= MOUSE_MODE_WHEEL
;
845 * Found wheel. By default enable the wheel.
847 STATEP
->wheel_state_bf
|= VUID_WHEEL_STATE_ENABLED
;
849 STATEP
->state
= PS2_WAIT_WHEEL5_SMPL1_CMD_ACK
;
851 /* Set timeout for set sample rate */
852 vuid_set_timeout(qp
, PS2_INIT_TMOUT_PER_GROUP
);
854 /* We're on a roll - try for wheel+5 */
855 put1(WR(qp
), MSECHGMOD
);
859 case PS2_WAIT_WHEEL5_SMPL1_CMD_ACK
:
860 if (code
!= MSE_ACK
) {
863 STATEP
->state
= PS2_WAIT_WHEEL5_SMPL1_RATE_ACK
;
867 case PS2_WAIT_WHEEL5_SMPL1_RATE_ACK
:
868 if (code
!= MSE_ACK
) {
871 STATEP
->state
= PS2_WAIT_WHEEL5_SMPL2_CMD_ACK
;
872 put1(WR(qp
), MSECHGMOD
);
875 case PS2_WAIT_WHEEL5_SMPL2_CMD_ACK
:
876 if (code
!= MSE_ACK
) {
879 STATEP
->state
= PS2_WAIT_WHEEL5_SMPL2_RATE_ACK
;
883 case PS2_WAIT_WHEEL5_SMPL2_RATE_ACK
:
884 if (code
!= MSE_ACK
) {
887 STATEP
->state
= PS2_WAIT_WHEEL5_SMPL3_CMD_ACK
;
888 put1(WR(qp
), MSECHGMOD
);
891 case PS2_WAIT_WHEEL5_SMPL3_CMD_ACK
:
892 if (code
!= MSE_ACK
) {
895 STATEP
->state
= PS2_WAIT_WHEEL5_SMPL3_RATE_ACK
;
899 case PS2_WAIT_WHEEL5_SMPL3_RATE_ACK
:
900 if (code
!= MSE_ACK
) {
904 /* Set sample rate completed successfully */
905 vuid_cancel_timeout(qp
);
907 STATEP
->state
= PS2_WAIT_WHEEL5_DEV_CMD
;
909 /* Set timeout for wheel5 get dev */
910 vuid_set_timeout(qp
, PS2_INIT_TMOUT_PER_CMD
);
912 put1(WR(qp
), MSEGETDEV
);
916 case PS2_WAIT_WHEEL5_DEV_CMD
:
917 if (code
!= MSE_ACK
) {
920 STATEP
->state
= PS2_WAIT_WHEEL5_DEV_ACK
;
923 case PS2_WAIT_WHEEL5_DEV_ACK
:
925 STATEP
->vuid_mouse_mode
= MOUSE_MODE_WHEEL5
;
926 STATEP
->nbuttons
= 5;
929 * Found wheel. By default enable the wheel.
931 STATEP
->wheel_state_bf
|=
932 VUID_WHEEL_STATE_ENABLED
<<
936 /* Wheel5 get dev completed successfully */
937 vuid_cancel_timeout(qp
);
941 case PS2_WAIT_SETRES3_CMD
:
942 STATEP
->state
= PS2_WAIT_SETRES3_ACK1
;
944 /* Set timeout for set res */
945 vuid_set_timeout(qp
, PS2_INIT_TMOUT_PER_CMD
);
947 put1(WR(qp
), MSESETRES
);
951 case PS2_WAIT_SETRES3_ACK1
:
952 if (code
!= MSE_ACK
) {
955 STATEP
->state
= PS2_WAIT_SETRES3_ACK2
;
959 case PS2_WAIT_SETRES3_ACK2
:
960 if (code
!= MSE_ACK
) {
964 /* Set res completed successfully */
965 vuid_cancel_timeout(qp
);
967 STATEP
->state
= PS2_WAIT_STREAM_ACK
;
969 /* Set timeout for enable */
970 vuid_set_timeout(qp
, PS2_INIT_TMOUT_PER_CMD
);
972 put1(WR(qp
), MSESTREAM
);
976 case PS2_WAIT_STREAM_ACK
:
977 if (code
!= MSE_ACK
) {
980 STATEP
->state
= PS2_WAIT_ON_ACK
;
984 case PS2_WAIT_ON_ACK
:
985 if (code
!= MSE_ACK
) {
989 /* Enable completed successfully */
992 * The entire initialization sequence
993 * is complete. Now, we can clear the
994 * init_count retry counter.
996 STATEP
->init_count
= 0;
997 vuid_cancel_timeout(qp
);
1000 STATEP
->state
= PS2_START
;