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