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 * 5-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 LOGI_NUMBUTTONS 3 /* Number of buttons */
37
38 #define LOGI_BMASK (uchar_t)7 /* Button mask in packet */
39 #define LOGI_NOT_BMASK (uchar_t)(~LOGI_BMASK) /* Rest of the bits */
40 #define LOGI_START_CODE (uchar_t)(0x80) /* Start code in char */
41
42 #define LOGI_START 0 /* Beginning of packet */
43 #define LOGI_BUTTON 1 /* Got button status */
44 #define LOGI_DELTA_X1 2 /* First of 2 delta X */
45 #define LOGI_DELTA_Y1 3 /* First of 2 delta Y */
46 #define LOGI_DELTA_X2 4 /* Second of 2 delta X */
47
48 extern void VUID_PUTNEXT(queue_t *const, uchar_t, uchar_t, uchar_t, int);
49
50 int
VUID_OPEN(queue_t * const qp)51 VUID_OPEN(queue_t *const qp)
52 {
53 /*
54 * The current kdmconfig tables imply that this module can be used
55 * for both 2- and 3- button mice, so based on that evidence we
56 * can't assume a constant. I don't know whether it's possible
57 * to autodetect.
58 */
59 STATEP->nbuttons = 0; /* Don't know. */
60
61 return (0);
62 }
63
64 static void
vuidm5p_sendButtonEvent(queue_t * const qp)65 vuidm5p_sendButtonEvent(queue_t *const qp)
66 {
67 int b;
68
69 /* for each button, see if it has changed */
70 for (b = 0; b < 3; b++) {
71 uchar_t mask = 4 >> b;
72
73 if ((STATEP->buttons&mask) != (STATEP->oldbuttons&mask))
74 VUID_PUTNEXT(qp, BUT(b+1), FE_PAIR_NONE, 0,
75 (STATEP->buttons & mask ? 1 : 0));
76 }
77 }
78
79 void
vuidm5p(queue_t * const qp,mblk_t * mp)80 vuidm5p(queue_t *const qp, mblk_t *mp)
81 {
82 int r, code;
83 uchar_t *bufp;
84
85 bufp = mp->b_rptr;
86 r = MBLKL(mp);
87
88 for (r--; r >= 0; r--) {
89 code = *bufp++;
90
91 switch (STATEP->state) {
92 /*
93 * Start state. We stay here if the start code is not
94 * received thus forcing us back into sync. When we
95 * get a start code the button mask comes with it
96 * forcing us to the next state.
97 */
98 default:
99 resync:
100 case LOGI_START:
101 if ((code & LOGI_NOT_BMASK) != LOGI_START_CODE)
102 break;
103
104 STATEP->state = LOGI_BUTTON;
105 STATEP->deltax = STATEP->deltay = 0;
106 STATEP->buttons = (~code) & LOGI_BMASK;
107 /* or xlate[code & ] */
108 break;
109
110 case LOGI_BUTTON:
111 /*
112 * We receive the first of 2 delta x which forces us
113 * to the next state. We just add the values of each
114 * delta x together.
115 */
116 if ((code & LOGI_NOT_BMASK) == LOGI_START_CODE) {
117 STATEP->state = LOGI_START;
118 goto resync;
119 }
120
121 /* (The cast sign extends the 8-bit value.) */
122 STATEP->deltax += (signed char)code;
123 STATEP->state = LOGI_DELTA_X1;
124 break;
125
126 case LOGI_DELTA_X1:
127 /*
128 * The first of 2 delta y. We just add
129 * the 2 delta y together
130 */
131 if ((code & LOGI_NOT_BMASK) == LOGI_START_CODE) {
132 STATEP->state = LOGI_START;
133 goto resync;
134 }
135
136 /* (The cast sign extends the 8-bit value.) */
137 STATEP->deltay += (signed char)code;
138 STATEP->state = LOGI_DELTA_Y1;
139 break;
140
141 case LOGI_DELTA_Y1:
142 /*
143 * The second of 2 delta x. We just add
144 * the 2 delta x together.
145 */
146 if ((code & LOGI_NOT_BMASK) == LOGI_START_CODE) {
147 STATEP->state = LOGI_START;
148 goto resync;
149 }
150
151 /* (The cast sign extends the 8-bit value.) */
152 STATEP->deltax += (signed char)code;
153 STATEP->state = LOGI_DELTA_X2;
154 break;
155
156 case LOGI_DELTA_X2:
157 /*
158 * The second of 2 delta y. We just add
159 * the 2 delta y together.
160 */
161 if ((code & LOGI_NOT_BMASK) == LOGI_START_CODE) {
162 STATEP->state = LOGI_START;
163 goto resync;
164 }
165
166 /* (The cast sign extends the 8-bit value.) */
167 STATEP->deltay += (signed char)code;
168 STATEP->state = LOGI_START;
169
170 /* check if motion has occurred and send event(s)... */
171 if (STATEP->deltax)
172 VUID_PUTNEXT(qp,
173 (uchar_t)LOC_X_DELTA, FE_PAIR_ABSOLUTE,
174 (uchar_t)LOC_X_ABSOLUTE, STATEP->deltax);
175
176 if (STATEP->deltay)
177 VUID_PUTNEXT(qp,
178 (uchar_t)LOC_Y_DELTA, FE_PAIR_ABSOLUTE,
179 (uchar_t)LOC_Y_ABSOLUTE, STATEP->deltay);
180
181 STATEP->deltax = STATEP->deltay = 0;
182
183 /* see if the buttons have changed */
184 if (STATEP->buttons != STATEP->oldbuttons) {
185 /* buttons have changed */
186 vuidm5p_sendButtonEvent(qp);
187
188 /* update new button state */
189 STATEP->oldbuttons = STATEP->buttons;
190 }
191 }
192 }
193 freemsg(mp);
194 }
195