Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/usb/clients/usbinput/usbwcm/usbwcm.c
+++ new/usr/src/uts/common/io/usb/clients/usbinput/usbwcm/usbwcm.c
1 1 /*
2 2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
3 3 * Use is subject to license terms.
4 4 */
5 5
6 6 /*
7 7 * Copyright (c) 2007, 2008 Bartosz Fabianowski <freebsd@chillt.de>
8 8 * All rights reserved.
9 9 *
10 10 * Financed by the "Irish Research Council for Science, Engineering and
11 11 * Technology: funded by the National Development Plan"
12 12 *
13 13 * Redistribution and use in source and binary forms, with or without
14 14 * modification, are permitted provided that the following conditions
15 15 * are met:
16 16 * 1. Redistributions of source code must retain the above copyright
17 17 * notice, this list of conditions, and the following disclaimer.
18 18 * 2. Redistributions in binary form must reproduce the above copyright
19 19 * notice, this list of conditions and the following disclaimer in the
20 20 * documentation and/or other materials provided with the distribution.
21 21 *
22 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
26 26 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 32 * SUCH DAMAGE.
33 33 */
34 34
35 35 /*
36 36 * Copyright (c) 1998 The NetBSD Foundation, Inc.
37 37 * All rights reserved.
38 38 *
39 39 * This code is derived from software contributed to The NetBSD Foundation
40 40 * by Lennart Augustsson (lennart@augustsson.net) at
41 41 * Carlstedt Research & Technology.
42 42 *
43 43 * Redistribution and use in source and binary forms, with or without
44 44 * modification, are permitted provided that the following conditions
45 45 * are met:
46 46 * 1. Redistributions of source code must retain the above copyright
47 47 * notice, this list of conditions and the following disclaimer.
48 48 * 2. Redistributions in binary form must reproduce the above copyright
49 49 * notice, this list of conditions and the following disclaimer in the
50 50 * documentation and/or other materials provided with the distribution.
51 51 * 3. All advertising materials mentioning features or use of this software
52 52 * must display the following acknowledgement:
53 53 * This product includes software developed by the NetBSD
54 54 * Foundation, Inc. and its contributors.
55 55 * 4. Neither the name of The NetBSD Foundation nor the names of its
56 56 * contributors may be used to endorse or promote products derived
57 57 * from this software without specific prior written permission.
58 58 *
59 59 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
60 60 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
61 61 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
62 62 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
63 63 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
64 64 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
65 65 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
66 66 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
67 67 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
68 68 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
69 69 * POSSIBILITY OF SUCH DAMAGE.
70 70 */
71 71
72 72 #include <sys/stropts.h>
73 73 #include <sys/strsun.h>
74 74 #include <sys/termios.h>
75 75 #include <sys/termio.h>
76 76 #include <sys/strtty.h>
77 77 #include <sys/systm.h>
78 78
79 79 #include <sys/usb/usba/usbai_version.h>
80 80 #include <sys/usb/usba.h>
81 81 #include <sys/usb/usba/usbai_private.h>
82 82 #include <sys/usb/clients/hid/hid.h>
83 83 #include <sys/usb/clients/usbinput/usbwcm/usbwcm.h>
84 84
85 85 /* debugging information */
86 86 uint_t usbwcm_errmask = (uint_t)PRINT_MASK_ALL;
87 87 uint_t usbwcm_errlevel = USB_LOG_L2;
88 88 static usb_log_handle_t usbwcm_log_handle;
89 89
90 90 static void
91 91 uwacom_event(usbwcm_state_t *usbwcmp, uint_t type, uint_t idx, int val)
92 92 {
93 93 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
94 94 mblk_t *mp;
95 95
96 96 switch (type) {
97 97 case EVT_SYN:
98 98 if (sc->sc_sync)
99 99 return;
100 100 break;
101 101
102 102 case EVT_BTN:
103 103 if (sc->sc_btn[idx] == val)
104 104 return;
105 105
106 106 sc->sc_btn[idx] = val;
107 107 break;
108 108
109 109 case EVT_ABS:
110 110 if (sc->sc_abs[idx].fuzz) {
111 111 int dist = abs(val - sc->sc_abs[idx].value);
112 112
113 113 if (dist < sc->sc_abs[idx].fuzz >> 1) {
114 114 return;
115 115 } else if (dist < sc->sc_abs[idx].fuzz) {
116 116 val = (7 * sc->sc_abs[idx].value + val) >> 3;
117 117 } else if (dist < sc->sc_abs[idx].fuzz << 1) {
118 118 val = (sc->sc_abs[idx].value + val) >> 1;
119 119 }
120 120 }
121 121 if (sc->sc_abs[idx].value == val) {
122 122 return;
123 123 }
124 124
125 125 sc->sc_abs[idx].value = val;
126 126 break;
127 127
128 128 case EVT_REL:
129 129 if (!val)
130 130 return;
131 131 break;
132 132
133 133 case EVT_MSC:
134 134 break;
135 135
136 136 default:
137 137 return;
138 138 }
139 139
140 140 if ((mp = allocb(sizeof (struct event_input), BPRI_HI)) != NULL) {
141 141 struct event_input *ev = (struct event_input *)mp->b_wptr;
142 142
143 143 ev->type = (uint16_t)type;
144 144 ev->code = (uint16_t)idx;
145 145 ev->value = (int32_t)val;
146 146 uniqtime32(&ev->time);
147 147
148 148 mp->b_wptr += sizeof (struct event_input);
149 149 putnext(usbwcmp->usbwcm_rq, mp);
150 150 } else {
151 151 return;
152 152 }
153 153
154 154 sc->sc_sync = (type == EVT_SYN);
155 155 }
156 156
157 157 static void
158 158 uwacom_pos_events_graphire(usbwcm_state_t *usbwcmp, int x, int y)
159 159 {
160 160 uwacom_event(usbwcmp, EVT_ABS, ABS_X, x);
161 161 uwacom_event(usbwcmp, EVT_ABS, ABS_Y, y);
162 162 }
163 163
164 164 static void
165 165 uwacom_pen_events_graphire(usbwcm_state_t *usbwcmp, int prs, int stl1, int stl2)
166 166 {
167 167 uwacom_event(usbwcmp, EVT_ABS, ABS_PRESSURE, prs);
168 168 uwacom_event(usbwcmp, EVT_BTN, BTN_TIP, prs);
169 169 uwacom_event(usbwcmp, EVT_BTN, BTN_STYLUS_1, stl1);
170 170 uwacom_event(usbwcmp, EVT_BTN, BTN_STYLUS_2, stl2);
171 171 }
172 172
173 173 static void
174 174 uwacom_mouse_events_graphire(usbwcm_state_t *usbwcmp, int left, int middle,
175 175 int right, int wheel, int distance)
176 176 {
177 177 uwacom_event(usbwcmp, EVT_BTN, BTN_LEFT, left);
178 178 uwacom_event(usbwcmp, EVT_BTN, BTN_MIDDLE, middle);
179 179 uwacom_event(usbwcmp, EVT_BTN, BTN_RIGHT, right);
180 180 uwacom_event(usbwcmp, EVT_REL, REL_WHEEL, wheel);
181 181 uwacom_event(usbwcmp, EVT_ABS, ABS_DISTANCE, distance);
182 182 }
183 183
184 184 static void
185 185 uwacom_tool_events_graphire(usbwcm_state_t *usbwcmp, int idx, int proximity)
186 186 {
187 187 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
188 188
189 189 uwacom_event(usbwcmp, EVT_BTN, sc->sc_tool[idx], proximity);
190 190 uwacom_event(usbwcmp, EVT_ABS, ABS_MISC, sc->sc_tool_id[idx]);
191 191 if (sc->sc_serial[idx]) {
192 192 uwacom_event(usbwcmp, EVT_MSC, MSC_SERIAL, sc->sc_serial[idx]);
193 193 }
194 194
195 195 uwacom_event(usbwcmp, EVT_SYN, SYN_REPORT, 0);
196 196 }
197 197
198 198 static void
199 199 uwacom_pad_events_graphire4(usbwcm_state_t *usbwcmp, int b0, int b1, int b4,
200 200 int b5, int rel, int abs)
201 201 {
202 202 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_0, b0);
203 203 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_1, b1);
204 204 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_4, b4);
205 205 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_5, b5);
206 206 uwacom_event(usbwcmp, EVT_REL, REL_WHEEL, rel);
207 207 uwacom_event(usbwcmp, EVT_ABS, ABS_WHEEL, abs);
208 208 uwacom_tool_events_graphire(usbwcmp, 1, b0 | b1 | b4 | b5 | rel | abs);
209 209 }
210 210
211 211 static void
212 212 usbwcm_input_graphire(usbwcm_state_t *usbwcmp, mblk_t *mp)
213 213 {
214 214 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
215 215 uint8_t *packet = mp->b_rptr;
216 216
217 217 if (PACKET_BITS(0, 0, 8) != 0x02) {
218 218 USB_DPRINTF_L1(PRINT_MASK_ALL, usbwcm_log_handle,
219 219 "unknown report type %02x received\n",
220 220 PACKET_BITS(0, 0, 8));
221 221 return;
222 222 }
223 223
224 224 /* Tool in proximity */
225 225 if (PACKET_BIT(1, 7)) {
226 226 uwacom_pos_events_graphire(usbwcmp,
227 227 (PACKET_BITS(3, 0, 8) << 8) | PACKET_BITS(2, 0, 8),
228 228 (PACKET_BITS(5, 0, 8) << 8) | PACKET_BITS(4, 0, 8));
229 229
230 230 if (!PACKET_BIT(1, 6)) {
231 231 if (!PACKET_BIT(1, 5)) {
232 232 sc->sc_tool[0] = BTN_TOOL_PEN;
233 233 sc->sc_tool_id[0] = TOOL_ID_PEN;
234 234 } else {
235 235 sc->sc_tool[0] = BTN_TOOL_ERASER;
236 236 sc->sc_tool_id[0] = TOOL_ID_ERASER;
237 237 }
238 238
239 239 uwacom_pen_events_graphire(usbwcmp,
240 240 (PACKET_BIT(7, 0) << 8) | PACKET_BITS(6, 0, 8),
241 241 PACKET_BIT(1, 1), PACKET_BIT(1, 2));
242 242 } else {
243 243 int wheel, distance;
244 244
245 245 if (sc->sc_type->protocol == GRAPHIRE) {
246 246 wheel = (PACKET_BIT(1, 5) ?
247 247 0 : -(int8_t)PACKET_BITS(6, 0, 8));
248 248 distance = PACKET_BITS(7, 0, 6);
249 249 } else {
250 250 wheel = (PACKET_BIT(7, 2) << 2) -
251 251 PACKET_BITS(7, 0, 2);
252 252 distance = PACKET_BITS(6, 0, 6);
253 253 }
254 254
255 255 sc->sc_tool[0] = BTN_TOOL_MOUSE;
256 256 sc->sc_tool_id[0] = TOOL_ID_MOUSE;
257 257
258 258 uwacom_mouse_events_graphire(usbwcmp, PACKET_BIT(1, 0),
259 259 PACKET_BIT(1, 2), PACKET_BIT(1, 1), wheel,
260 260 distance);
261 261 }
262 262
263 263 uwacom_tool_events_graphire(usbwcmp, 0, 1);
264 264
265 265 /* Tool leaving proximity */
266 266 } else if (sc->sc_tool_id[0]) {
267 267 uwacom_pos_events_graphire(usbwcmp, 0, 0);
268 268
269 269 if (sc->sc_tool[0] == BTN_TOOL_MOUSE)
270 270 uwacom_mouse_events_graphire(usbwcmp, 0, 0, 0, 0, 0);
271 271 else
272 272 uwacom_pen_events_graphire(usbwcmp, 0, 0, 0);
273 273
274 274 sc->sc_tool_id[0] = 0;
275 275 uwacom_tool_events_graphire(usbwcmp, 0, 0);
276 276 }
277 277
278 278 /* Finger on pad: Graphire4 */
279 279 if ((sc->sc_type->protocol == GRAPHIRE4) && PACKET_BITS(7, 3, 5)) {
280 280 sc->sc_tool_id[1] = TOOL_ID_PAD;
281 281 uwacom_pad_events_graphire4(usbwcmp, PACKET_BIT(7, 6), 0,
282 282 PACKET_BIT(7, 7), 0,
283 283 PACKET_BITS(7, 3, 2) - (PACKET_BIT(7, 5) << 2), 0);
284 284
285 285 /* Finger on pad: MyOffice */
286 286 } else if ((sc->sc_type->protocol == MYOFFICE) &&
287 287 (PACKET_BITS(7, 3, 4) || PACKET_BITS(8, 0, 8))) {
288 288 sc->sc_tool_id[1] = TOOL_ID_PAD;
289 289 uwacom_pad_events_graphire4(usbwcmp, PACKET_BIT(7, 3),
290 290 PACKET_BIT(7, 4), PACKET_BIT(7, 5), PACKET_BIT(7, 6), 0,
291 291 PACKET_BITS(8, 0, 7));
292 292
293 293 /* Finger leaving pad */
294 294 } else if (sc->sc_tool_id[1]) {
295 295 sc->sc_tool_id[1] = 0;
296 296 uwacom_pad_events_graphire4(usbwcmp, 0, 0, 0, 0, 0, 0);
297 297 }
298 298 }
299 299
300 300 static void
301 301 uwacom_pos_events_intuos(usbwcm_state_t *usbwcmp, int x, int y, int distance)
302 302 {
303 303 uwacom_event(usbwcmp, EVT_ABS, ABS_X, x);
304 304 uwacom_event(usbwcmp, EVT_ABS, ABS_Y, y);
305 305 uwacom_event(usbwcmp, EVT_ABS, ABS_DISTANCE, distance);
306 306 }
307 307
308 308 static void
309 309 uwacom_pen_events_intuos(usbwcm_state_t *usbwcmp, uint8_t *packet)
310 310 {
311 311 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
312 312 int press, tilt_x, tilt_y, stl1, stl2;
313 313
314 314 switch (sc->sc_type->protocol) {
315 315 case INTUOS4S:
316 316 case INTUOS4L:
317 317 press = PACKET_BITS(7, 6, 10) << 1 | PACKET_BIT(1, 0);
318 318 break;
319 319 default:
320 320 press = PACKET_BITS(7, 6, 10);
321 321 break;
322 322 }
323 323
324 324 tilt_x = PACKET_BITS(8, 7, 7);
325 325 tilt_y = PACKET_BITS(8, 0, 7);
326 326 stl1 = PACKET_BIT(1, 1);
327 327 stl2 = PACKET_BIT(1, 2);
328 328
329 329 uwacom_event(usbwcmp, EVT_ABS, ABS_PRESSURE, press);
330 330 uwacom_event(usbwcmp, EVT_ABS, ABS_TILT_X, tilt_x);
331 331 uwacom_event(usbwcmp, EVT_ABS, ABS_TILT_Y, tilt_y);
332 332 uwacom_event(usbwcmp, EVT_BTN, BTN_TIP, press);
333 333 uwacom_event(usbwcmp, EVT_BTN, BTN_STYLUS_1, stl1);
334 334 uwacom_event(usbwcmp, EVT_BTN, BTN_STYLUS_2, stl2);
335 335 }
336 336
337 337 static void
338 338 uwacom_mouse_events_intuos(usbwcm_state_t *usbwcmp, uint8_t *packet)
339 339 {
340 340 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
341 341 int left, middle, right, extra, side, wheel;
342 342
343 343 switch (sc->sc_type->protocol) {
344 344 case INTUOS4S:
345 345 case INTUOS4L:
346 346 left = PACKET_BIT(6, 0);
347 347 middle = PACKET_BIT(6, 1);
348 348 right = PACKET_BIT(6, 2);
349 349 side = PACKET_BIT(6, 3);
350 350 extra = PACKET_BIT(6, 4);
351 351 wheel = PACKET_BIT(7, 7) - PACKET_BIT(7, 6);
352 352 break;
353 353
354 354 default:
355 355 left = PACKET_BIT(8, 2);
356 356 middle = PACKET_BIT(8, 3);
357 357 right = PACKET_BIT(8, 4);
358 358 extra = PACKET_BIT(8, 5);
359 359 side = PACKET_BIT(8, 6);
360 360 wheel = PACKET_BIT(8, 0) - PACKET_BIT(8, 1);
361 361 break;
362 362 }
363 363
364 364 uwacom_event(usbwcmp, EVT_BTN, BTN_LEFT, left);
365 365 uwacom_event(usbwcmp, EVT_BTN, BTN_MIDDLE, middle);
366 366 uwacom_event(usbwcmp, EVT_BTN, BTN_RIGHT, right);
367 367 uwacom_event(usbwcmp, EVT_BTN, BTN_EXTRA, extra);
368 368 uwacom_event(usbwcmp, EVT_BTN, BTN_SIDE, side);
369 369 uwacom_event(usbwcmp, EVT_REL, REL_WHEEL, wheel);
370 370 }
371 371
372 372 static void
373 373 uwacom_tool_events_intuos(usbwcm_state_t *usbwcmp, int idx, int proximity)
374 374 {
375 375 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
376 376
377 377 uwacom_event(usbwcmp, EVT_BTN, sc->sc_tool[idx], proximity);
378 378 uwacom_event(usbwcmp, EVT_ABS, ABS_MISC, sc->sc_tool_id[idx]);
379 379 uwacom_event(usbwcmp, EVT_MSC, MSC_SERIAL, sc->sc_serial[idx]);
380 380 uwacom_event(usbwcmp, EVT_SYN, SYN_REPORT, 0);
381 381 }
382 382
383 383 static void
384 384 uwacom_pad_events_intuos(usbwcm_state_t *usbwcmp, uint8_t *packet)
385 385 {
386 386 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
387 387 int b0, b1, b2, b3, b4, b5, b6, b7;
388 388 int rx, ry, prox;
389 389 int b8, whl, rot;
390 390
391 391 switch (sc->sc_type->protocol) {
392 392 case INTUOS4L:
393 393 b7 = PACKET_BIT(3, 6);
394 394 b8 = PACKET_BIT(3, 7);
395 395
396 396 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_7, b7);
397 397 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_8, b8);
398 398 /*FALLTHRU*/
399 399 case INTUOS4S:
400 400 b0 = PACKET_BIT(2, 0);
401 401 b1 = PACKET_BIT(3, 0);
402 402 b2 = PACKET_BIT(3, 1);
403 403 b3 = PACKET_BIT(3, 2);
404 404 b4 = PACKET_BIT(3, 3);
405 405 b5 = PACKET_BIT(3, 4);
406 406 b6 = PACKET_BIT(3, 5);
407 407
408 408 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_0, b0);
409 409 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_1, b1);
410 410 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_2, b2);
411 411 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_3, b3);
412 412 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_4, b4);
413 413 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_5, b5);
414 414 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_6, b6);
415 415
416 416 whl = PACKET_BIT(1, 7);
417 417 if (whl) {
418 418 rot = PACKET_BITS(1, 0, 7);
419 419 uwacom_event(usbwcmp, EVT_ABS, ABS_WHEEL, rot);
420 420 }
421 421
422 422 prox = b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8 | whl;
423 423 uwacom_tool_events_intuos(usbwcmp, 1, prox);
424 424
425 425 break;
426 426
427 427 default:
428 428 b0 = PACKET_BIT(5, 0);
429 429 b1 = PACKET_BIT(5, 1);
430 430 b2 = PACKET_BIT(5, 2);
431 431 b3 = PACKET_BIT(5, 3);
432 432 b4 = PACKET_BIT(6, 0);
433 433 b5 = PACKET_BIT(6, 1);
434 434 b6 = PACKET_BIT(6, 2);
435 435 b7 = PACKET_BIT(6, 3);
436 436 rx = PACKET_BITS(2, 0, 13);
437 437 ry = PACKET_BITS(4, 0, 13);
438 438
439 439 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_0, b0);
440 440 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_1, b1);
441 441 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_2, b2);
442 442 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_3, b3);
443 443 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_4, b4);
444 444 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_5, b5);
445 445 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_6, b6);
446 446 uwacom_event(usbwcmp, EVT_BTN, BTN_MISC_7, b7);
447 447 uwacom_event(usbwcmp, EVT_ABS, ABS_RX, rx);
448 448 uwacom_event(usbwcmp, EVT_ABS, ABS_RY, ry);
449 449
450 450 prox = b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7 | rx | ry;
451 451 uwacom_tool_events_intuos(usbwcmp, 1, prox);
452 452
453 453 break;
454 454 }
455 455 }
456 456
457 457 static void
458 458 usbwcm_input_intuos(usbwcm_state_t *usbwcmp, mblk_t *mp)
459 459 {
460 460 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
461 461 uint8_t *packet = mp->b_rptr;
462 462
463 463 switch (PACKET_BITS(0, 0, 8)) {
464 464 case 0x02:
465 465 switch (PACKET_BITS(1, 5, 2)) {
466 466 /* Tool entering proximity */
467 467 case 0x2:
468 468 sc->sc_tool_id[0] = PACKET_BITS(3, 4, 12);
469 469 sc->sc_serial[0] =
470 470 (PACKET_BIT(1, 1) ? PACKET_BITS(7, 4, 32) : 0);
471 471
472 472 switch (sc->sc_tool_id[0]) {
473 473 case 0x802: /* Intuos4 Grip Pen */
474 474 case 0x804: /* Intuos4 Art Marker */
475 475 case 0x823: /* Intuos3 Grip Pen */
476 476 case 0x885: /* Intuos3 Art Marker */
477 477 sc->sc_tool[0] = BTN_TOOL_PEN;
478 478 break;
479 479 case 0x80a: /* Intuos4 Grip Pen eraser */
480 480 case 0x82b: /* Intuos3 Grip Pen eraser */
481 481 sc->sc_tool[0] = BTN_TOOL_ERASER;
482 482 break;
483 483 case 0x017: /* Intuos3 2D mouse */
484 484 case 0x806: /* Intuos4 2D mouse */
485 485 sc->sc_tool[0] = BTN_TOOL_MOUSE;
486 486 break;
487 487 default:
488 488 USB_DPRINTF_L1(PRINT_MASK_ALL,
489 489 usbwcm_log_handle,
490 490 "unknown tool ID %03x seen\n",
491 491 sc->sc_tool_id[0]);
492 492 sc->sc_tool[0] = BTN_TOOL_PEN;
493 493 }
494 494 break;
495 495
496 496 /* Tool leaving proximity */
497 497 case 0x0:
498 498 uwacom_pos_events_intuos(usbwcmp, 0, 0, 0);
499 499
500 500 if (sc->sc_tool[0] == BTN_TOOL_MOUSE)
501 501 uwacom_mouse_events_intuos(usbwcmp, packet);
502 502 else
503 503 uwacom_pen_events_intuos(usbwcmp, packet);
504 504
505 505 sc->sc_tool_id[0] = 0;
506 506 uwacom_tool_events_intuos(usbwcmp, 0, 0);
507 507 break;
508 508
509 509 /* Tool motion, outbound */
510 510 case 0x1:
511 511 /* Outbound tracking is unreliable on the Cintiq */
512 512 if (sc->sc_type->protocol == CINTIQ)
513 513 break;
514 514
515 515 /* Tool motion */
516 516 /*FALLTHRU*/
517 517 case 0x3:
518 518 uwacom_pos_events_intuos(usbwcmp,
519 519 (PACKET_BITS(3, 0, 16) << 1) | PACKET_BIT(9, 1),
520 520 (PACKET_BITS(5, 0, 16) << 1) | PACKET_BIT(9, 0),
521 521 PACKET_BITS(9, 2, 6));
522 522
523 523 if (PACKET_BITS(1, 3, 2) == 0) {
524 524 uwacom_pen_events_intuos(usbwcmp, packet);
525 525
526 526 } else if (PACKET_BITS(1, 1, 4) == 0x5) {
527 527 int angle = 450 - PACKET_BITS(7, 6, 10);
528 528
529 529 if (PACKET_BIT(7, 5)) {
530 530 angle = (angle > 0 ? 900 : -900) -
531 531 angle;
532 532 }
533 533
534 534 uwacom_event(usbwcmp, EVT_ABS, ABS_Z, angle);
535 535 break;
536 536 } else if (PACKET_BITS(1, 1, 4) == 0x8) {
537 537 uwacom_mouse_events_intuos(usbwcmp, packet);
538 538 } else {
539 539 USB_DPRINTF_L1(PRINT_MASK_ALL,
540 540 usbwcm_log_handle,
541 541 "unsupported motion packet type %x "
542 542 "received\n", PACKET_BITS(1, 1, 4));
543 543 }
544 544
545 545 uwacom_tool_events_intuos(usbwcmp, 0, 1);
546 546 break;
547 547 }
548 548
549 549 break;
550 550
551 551 case 0x0c:
552 552 uwacom_pad_events_intuos(usbwcmp, packet);
553 553 break;
554 554
555 555 default:
556 556 USB_DPRINTF_L1(PRINT_MASK_ALL, usbwcm_log_handle,
557 557 "unknown report type %02x received\n",
558 558 PACKET_BITS(0, 0, 8));
559 559 }
560 560 }
561 561
562 562 static void
563 563 uwacom_init_abs(usbwcm_state_t *usbwcmp, int axis, int32_t min, int32_t max,
564 564 int32_t fuzz, int32_t flat)
565 565 {
566 566 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
567 567
568 568 sc->sc_abs[axis].min = min;
569 569 sc->sc_abs[axis].max = max;
570 570 sc->sc_abs[axis].fuzz = fuzz;
571 571 sc->sc_abs[axis].flat = flat;
572 572 }
573 573
574 574 static void
575 575 uwacom_init_graphire4(usbwcm_state_t *usbwcmp)
576 576 {
577 577 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
578 578
579 579 BM_SET_BIT(sc->sc_bm[0], EVT_MSC);
580 580 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_0);
581 581 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_4);
582 582 BM_SET_BIT(sc->sc_bm[1], BTN_TOOL_PAD);
583 583 BM_SET_BIT(sc->sc_bm[4], MSC_SERIAL);
584 584
585 585 sc->sc_tool[1] = BTN_TOOL_PAD;
586 586 sc->sc_serial[1] = SERIAL_PAD_GRAPHIRE4;
587 587 }
588 588
589 589 static void
590 590 uwacom_init_myoffice(usbwcm_state_t *usbwcmp)
591 591 {
592 592 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
593 593
594 594 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_1);
595 595 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_5);
596 596 BM_SET_BIT(sc->sc_bm[3], ABS_WHEEL);
597 597
598 598 uwacom_init_abs(usbwcmp, ABS_WHEEL, 0, 71, 0, 0);
599 599 }
600 600
601 601 static void
602 602 uwacom_init_intuos(usbwcm_state_t *usbwcmp)
603 603 {
604 604 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
605 605
606 606 BM_SET_BIT(sc->sc_bm[0], EVT_MSC);
607 607
608 608 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_0);
609 609 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_1);
610 610 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_2);
611 611 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_3);
612 612 BM_SET_BIT(sc->sc_bm[1], BTN_SIDE);
613 613 BM_SET_BIT(sc->sc_bm[1], BTN_EXTRA);
614 614 BM_SET_BIT(sc->sc_bm[1], BTN_TOOL_PAD);
615 615
616 616 BM_SET_BIT(sc->sc_bm[3], ABS_TILT_X);
617 617 BM_SET_BIT(sc->sc_bm[3], ABS_TILT_Y);
618 618
619 619 BM_SET_BIT(sc->sc_bm[4], MSC_SERIAL);
620 620
621 621 sc->sc_tool[1] = BTN_TOOL_PAD;
622 622 sc->sc_tool_id[1] = TOOL_ID_PAD;
623 623 sc->sc_serial[1] = SERIAL_PAD_INTUOS;
624 624 }
625 625
626 626 static void
627 627 uwacom_init_intuos3(usbwcm_state_t *usbwcmp)
628 628 {
629 629 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
630 630
631 631 BM_SET_BIT(sc->sc_bm[3], ABS_Z);
632 632 BM_SET_BIT(sc->sc_bm[3], ABS_RX);
633 633
634 634 uwacom_init_abs(usbwcmp, ABS_Z, -900, 899, 0, 0);
635 635 uwacom_init_abs(usbwcmp, ABS_RX, 0, 4096, 0, 0);
636 636 }
637 637
638 638 static void
639 639 uwacom_init_intuos3_large(usbwcm_state_t *usbwcmp)
640 640 {
641 641 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
642 642
643 643 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_4);
644 644 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_5);
645 645 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_6);
646 646 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_7);
647 647
648 648 BM_SET_BIT(sc->sc_bm[3], ABS_RY);
649 649
650 650 uwacom_init_abs(usbwcmp, ABS_RY, 0, 4096, 0, 0);
651 651 }
652 652
653 653 static void
654 654 uwacom_init_intuos4(usbwcm_state_t *usbwcmp)
655 655 {
656 656 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
657 657
658 658 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_4);
659 659 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_5);
660 660 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_6);
661 661
662 662 BM_SET_BIT(sc->sc_bm[3], ABS_Z);
663 663
664 664 uwacom_init_abs(usbwcmp, ABS_Z, -900, 899, 0, 0);
665 665 }
666 666 static void
667 667 uwacom_init_intuos4_large(usbwcm_state_t *usbwcmp)
668 668 {
669 669 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
670 670
671 671 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_7);
672 672 BM_SET_BIT(sc->sc_bm[1], BTN_MISC_8);
673 673 }
674 674
675 675 static int
676 676 uwacom_init(usbwcm_state_t *usbwcmp)
677 677 {
678 678 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
679 679
680 680 sc->sc_id.bus = ID_BUS_USB;
681 681 sc->sc_id.vendor = usbwcmp->usbwcm_devid.VendorId;
682 682 sc->sc_id.product = usbwcmp->usbwcm_devid.ProductId;
683 683
684 684 sc->sc_id.version = 0;
685 685
686 686 for (int i = 0; i < EVT_USED; ++i)
687 687 sc->sc_bm[i] = kmem_zalloc(bm_size[i], KM_SLEEP);
688 688
689 689 sc->sc_btn = kmem_zalloc(BTN_USED * sizeof (int), KM_SLEEP);
690 690 sc->sc_abs = kmem_zalloc(ABS_USED * sizeof (struct event_abs_axis),
691 691 KM_SLEEP);
692 692
693 693 BM_SET_BIT(sc->sc_bm[0], EVT_SYN);
694 694 BM_SET_BIT(sc->sc_bm[0], EVT_BTN);
695 695 BM_SET_BIT(sc->sc_bm[0], EVT_REL);
696 696 BM_SET_BIT(sc->sc_bm[0], EVT_ABS);
697 697
698 698 BM_SET_BIT(sc->sc_bm[1], BTN_LEFT);
699 699 BM_SET_BIT(sc->sc_bm[1], BTN_RIGHT);
700 700 BM_SET_BIT(sc->sc_bm[1], BTN_MIDDLE);
701 701 BM_SET_BIT(sc->sc_bm[1], BTN_TOOL_PEN);
702 702 BM_SET_BIT(sc->sc_bm[1], BTN_TOOL_ERASER);
703 703 BM_SET_BIT(sc->sc_bm[1], BTN_TOOL_MOUSE);
704 704 BM_SET_BIT(sc->sc_bm[1], BTN_TIP);
705 705 BM_SET_BIT(sc->sc_bm[1], BTN_STYLUS_1);
706 706 BM_SET_BIT(sc->sc_bm[1], BTN_STYLUS_2);
707 707
708 708 BM_SET_BIT(sc->sc_bm[2], REL_WHEEL);
709 709
710 710 BM_SET_BIT(sc->sc_bm[3], ABS_X);
711 711 BM_SET_BIT(sc->sc_bm[3], ABS_Y);
712 712 BM_SET_BIT(sc->sc_bm[3], ABS_PRESSURE);
713 713 BM_SET_BIT(sc->sc_bm[3], ABS_DISTANCE);
714 714 BM_SET_BIT(sc->sc_bm[3], ABS_MISC);
715 715
716 716 uwacom_init_abs(usbwcmp, ABS_X, 0, sc->sc_type->x_max, 4, 0);
717 717 uwacom_init_abs(usbwcmp, ABS_Y, 0, sc->sc_type->y_max, 4, 0);
718 718 uwacom_init_abs(usbwcmp, ABS_PRESSURE, 0, sc->sc_type->pressure_max,
719 719 0, 0);
720 720 uwacom_init_abs(usbwcmp, ABS_DISTANCE, 0,
721 721 uwacom_protocols[sc->sc_type->protocol].distance_max, 0, 0);
722 722
723 723 switch (sc->sc_type->protocol) {
724 724 case CINTIQ:
725 725 case INTUOS3L:
726 726 uwacom_init_intuos3_large(usbwcmp);
727 727 /*FALLTHRU*/
728 728 case INTUOS3S:
729 729 uwacom_init_intuos3(usbwcmp);
730 730 uwacom_init_intuos(usbwcmp);
731 731 break;
732 732
733 733 case INTUOS4L:
734 734 uwacom_init_intuos4_large(usbwcmp);
735 735 /*FALLTHRU*/
736 736 case INTUOS4S:
737 737 uwacom_init_intuos4(usbwcmp);
738 738 uwacom_init_intuos(usbwcmp);
739 739 break;
740 740 case MYOFFICE:
741 741 uwacom_init_myoffice(usbwcmp);
742 742 /*FALLTHRU*/
743 743 case GRAPHIRE4:
744 744 uwacom_init_graphire4(usbwcmp);
745 745 /*FALLTHRU*/
746 746 case GRAPHIRE:
747 747 break;
748 748 }
749 749
750 750 return (0);
751 751 }
752 752
753 753 /*
754 754 * usbwcm_match() :
755 755 * Match device with it's parameters.
756 756 */
757 757 static const struct uwacom_type *
758 758 usbwcm_match(uint16_t vid, uint16_t pid)
759 759 {
760 760 const struct uwacom_type *dev;
761 761
762 762 dev = uwacom_devs;
763 763 while (dev->devno.vid != 0 && dev->devno.pid != 0) {
764 764 if (dev->devno.vid == vid && dev->devno.pid == pid) {
765 765 return (dev);
766 766 }
767 767 dev++;
768 768 }
769 769
770 770 return (NULL);
771 771 }
772 772
773 773 /*
774 774 * usbwcm_probe() :
775 775 * Check the device type and protocol.
776 776 */
777 777 static int
778 778 usbwcm_probe(usbwcm_state_t *usbwcmp)
779 779 {
780 780 queue_t *q = usbwcmp->usbwcm_rq;
781 781 mblk_t *mctl_ptr;
782 782 struct iocblk mctlmsg;
783 783 hid_req_t *featr;
784 784
785 785 /* check device IDs */
786 786 mctlmsg.ioc_cmd = HID_GET_VID_PID;
787 787 mctlmsg.ioc_count = 0;
788 788
789 789 mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0);
790 790 if (mctl_ptr == NULL) {
791 791 return (ENOMEM);
792 792 }
793 793
794 794 putnext(usbwcmp->usbwcm_wq, mctl_ptr);
795 795 usbwcmp->usbwcm_flags |= USBWCM_QWAIT;
796 796
797 797 while (usbwcmp->usbwcm_flags & USBWCM_QWAIT) {
798 798 if (qwait_sig(q) == 0) {
799 799 usbwcmp->usbwcm_flags = 0;
800 800 return (EINTR);
801 801 }
802 802 }
803 803
804 804 usbwcmp->usbwcm_softc.sc_type =
805 805 usbwcm_match(usbwcmp->usbwcm_devid.VendorId,
806 806 usbwcmp->usbwcm_devid.ProductId);
807 807 if (!usbwcmp->usbwcm_softc.sc_type) {
808 808 USB_DPRINTF_L1(PRINT_MASK_ALL, usbwcm_log_handle,
809 809 "unsupported tablet model\n");
810 810 return (ENXIO);
811 811 }
812 812
813 813 if (uwacom_init(usbwcmp) != 0) {
814 814 return (ENXIO);
815 815 }
816 816
817 817 /* set feature: tablet mode */
818 818 featr = kmem_zalloc(sizeof (hid_req_t), KM_SLEEP);
819 819 featr->hid_req_version_no = HID_VERSION_V_0;
820 820 featr->hid_req_wValue = REPORT_TYPE_FEATURE | 2;
821 821 featr->hid_req_wLength = sizeof (uint8_t) * 2;
822 822 featr->hid_req_data[0] = 2;
823 823 featr->hid_req_data[1] = 2;
824 824
825 825 mctlmsg.ioc_cmd = HID_SET_REPORT;
826 826 mctlmsg.ioc_count = sizeof (featr);
827 827 mctl_ptr = usba_mk_mctl(mctlmsg, featr, sizeof (hid_req_t));
828 828 if (mctl_ptr != NULL) {
829 829 putnext(usbwcmp->usbwcm_wq, mctl_ptr);
830 830
831 831 /*
832 832 * Waiting for response of HID_SET_REPORT
833 833 * mctl for setting the feature.
834 834 */
835 835 usbwcmp->usbwcm_flags |= USBWCM_QWAIT;
836 836 while (usbwcmp->usbwcm_flags & USBWCM_QWAIT) {
837 837 qwait(q);
838 838 }
839 839 } else {
840 840 USB_DPRINTF_L1(PRINT_MASK_ALL, usbwcm_log_handle,
841 841 "enable tablet mode failed\n");
842 842 }
843 843
844 844 kmem_free(featr, sizeof (hid_req_t));
845 845
846 846 return (0);
847 847 }
848 848
849 849 /*
850 850 * usbwcm_copyreq() :
851 851 * helper function for usbwcm ioctls
852 852 */
853 853 static int
854 854 usbwcm_copyreq(mblk_t *mp, uint_t pvtsize, uint_t state, uint_t reqsize,
855 855 uint_t contsize, uint_t copytype)
856 856 {
857 857 usbwcm_copyin_t *copystat;
858 858 mblk_t *iocmp, *contmp;
859 859 struct copyreq *cq;
860 860 struct copyresp *cr;
861 861
862 862 if ((pvtsize == 0) && (state != 0)) {
863 863 cr = (struct copyresp *)mp->b_rptr;
864 864 iocmp = cr->cp_private;
865 865 }
866 866
867 867 cq = (struct copyreq *)mp->b_rptr;
868 868 if (mp->b_cont == NULL) {
869 869
870 870 return (EINVAL);
871 871 }
872 872
873 873 cq->cq_addr = *((caddr_t *)mp->b_cont->b_rptr);
874 874 cq->cq_size = reqsize;
875 875 cq->cq_flag = 0;
876 876
877 877 if (pvtsize) {
878 878 iocmp = (mblk_t *)allocb(pvtsize, BPRI_MED);
879 879 if (iocmp == NULL) {
880 880
881 881 return (EAGAIN);
882 882 }
883 883 cq->cq_private = iocmp;
884 884 iocmp = cq->cq_private;
885 885 } else {
886 886 /*
887 887 * Here we need to set cq_private even if there's
888 888 * no private data, otherwise its value will be
889 889 * TRANSPARENT (-1) on 64bit systems because it
890 890 * overlaps iocp->ioc_count. If user address (cq_addr)
891 891 * is invalid, it would cause panic later in
892 892 * usbwcm_copyin:
893 893 * freemsg((mblk_t *)copyresp->cp_private);
894 894 */
895 895 cq->cq_private = NULL;
896 896 }
897 897
898 898 if (state) {
899 899 copystat = (usbwcm_copyin_t *)iocmp->b_rptr;
900 900 copystat->state = state;
901 901 if (pvtsize) { /* M_COPYIN */
902 902 copystat->addr = cq->cq_addr;
903 903 } else {
904 904 cq->cq_addr = copystat->addr;
905 905 cq->cq_private = iocmp;
906 906 }
907 907 iocmp->b_wptr = iocmp->b_rptr + sizeof (usbwcm_copyin_t);
908 908 }
909 909
910 910 if (contsize) {
911 911 contmp = (mblk_t *)allocb(contsize, BPRI_MED);
912 912 if (contmp == NULL) {
913 913
914 914 return (EAGAIN);
915 915 }
916 916 if (mp->b_cont) {
917 917 freemsg(mp->b_cont);
918 918 mp->b_cont = contmp;
919 919 }
920 920 }
921 921
922 922 mp->b_datap->db_type = (unsigned char)copytype;
923 923 mp->b_wptr = mp->b_rptr + sizeof (struct copyreq);
924 924
925 925 return (0);
926 926 }
927 927
928 928 static void
929 929 usbwcm_miocack(queue_t *q, mblk_t *mp, int rval)
930 930 {
931 931 struct iocblk *iocbp = (struct iocblk *)mp->b_rptr;
932 932
933 933 mp->b_datap->db_type = M_IOCACK;
934 934 mp->b_wptr = mp->b_rptr + sizeof (struct iocblk);
935 935
936 936 iocbp->ioc_error = 0;
937 937 iocbp->ioc_count = 0;
938 938 iocbp->ioc_rval = rval;
939 939
940 940 if (mp->b_cont != NULL) {
941 941 freemsg(mp->b_cont);
942 942 mp->b_cont = NULL;
943 943 }
944 944
945 945 qreply(q, mp);
946 946 }
947 947
948 948 /*
949 949 * usbwcm_iocpy() :
950 950 * M_IOCDATA processing for IOCTL's
951 951 */
952 952 static void
953 953 usbwcm_iocpy(queue_t *q, mblk_t *mp)
954 954 {
955 955 usbwcm_state_t *usbwcmp = (usbwcm_state_t *)q->q_ptr;
956 956 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
957 957 struct copyresp *copyresp;
958 958 usbwcm_copyin_t *copystat;
959 959 mblk_t *datap, *ioctmp;
960 960 struct iocblk *iocbp;
961 961 int err = 0;
962 962
963 963 copyresp = (struct copyresp *)mp->b_rptr;
964 964 iocbp = (struct iocblk *)mp->b_rptr;
965 965 if (copyresp->cp_rval) {
966 966 err = EAGAIN;
967 967
968 968 goto out;
969 969 }
970 970
971 971 switch (copyresp->cp_cmd) {
972 972 default: {
973 973 int num = copyresp->cp_cmd & 0xff;
974 974 int len = IOCPARM_MASK & (copyresp->cp_cmd >> 16);
975 975
976 976 if (((copyresp->cp_cmd >> 8) & 0xFF) != 'E') {
977 977 putnext(q, mp); /* pass it down the line */
978 978 return;
979 979
980 980 } else if ((copyresp->cp_cmd & IOC_INOUT) != IOC_OUT) {
981 981 err = EINVAL;
982 982 break;
983 983 }
984 984
985 985 switch (num) {
986 986 case EUWACOMGETVERSION:
987 987 ioctmp = copyresp->cp_private;
988 988 copystat = (usbwcm_copyin_t *)ioctmp->b_rptr;
989 989 if (copystat->state == USBWCM_GETSTRUCT) {
990 990 if (mp->b_cont == NULL) {
991 991 err = EINVAL;
992 992
993 993 break;
994 994 }
995 995 datap = (mblk_t *)mp->b_cont;
996 996
997 997 *(int *)datap->b_rptr = 0x00010000;
998 998
999 999 if (err = usbwcm_copyreq(mp, 0,
1000 1000 USBWCM_GETRESULT, sizeof (int), 0,
1001 1001 M_COPYOUT)) {
1002 1002
1003 1003 goto out;
1004 1004 }
1005 1005 } else if (copystat->state == USBWCM_GETRESULT) {
1006 1006 freemsg(ioctmp);
1007 1007 usbwcm_miocack(q, mp, 0);
1008 1008 return;
1009 1009 }
1010 1010 break;
1011 1011
1012 1012 case EUWACOMGETID:
1013 1013 ioctmp = copyresp->cp_private;
1014 1014 copystat = (usbwcm_copyin_t *)ioctmp->b_rptr;
1015 1015 if (copystat->state == USBWCM_GETSTRUCT) {
1016 1016 if (mp->b_cont == NULL) {
1017 1017 err = EINVAL;
1018 1018
1019 1019 break;
1020 1020 }
1021 1021 datap = (mblk_t *)mp->b_cont;
1022 1022
1023 1023 bcopy(&sc->sc_id, datap->b_rptr,
1024 1024 sizeof (struct event_dev_id));
1025 1025
1026 1026 if (err = usbwcm_copyreq(mp, 0,
1027 1027 USBWCM_GETRESULT,
1028 1028 sizeof (struct event_dev_id), 0,
1029 1029 M_COPYOUT)) {
1030 1030
1031 1031 goto out;
1032 1032 }
1033 1033 } else if (copystat->state == USBWCM_GETRESULT) {
1034 1034 freemsg(ioctmp);
1035 1035 usbwcm_miocack(q, mp, 0);
1036 1036 return;
1037 1037 }
1038 1038 break;
1039 1039
1040 1040 default:
1041 1041 if (num >= EUWACOMGETBM &&
1042 1042 num < EUWACOMGETBM + EVT_USED) {
1043 1043 int idx = num - EUWACOMGETBM;
1044 1044 size_t length = min(bm_size[idx], len);
1045 1045
1046 1046 ioctmp = copyresp->cp_private;
1047 1047 copystat = (usbwcm_copyin_t *)ioctmp->b_rptr;
1048 1048 if (copystat->state == USBWCM_GETSTRUCT) {
1049 1049 if (mp->b_cont == NULL) {
1050 1050 err = EINVAL;
1051 1051
1052 1052 break;
1053 1053 }
1054 1054 datap = (mblk_t *)mp->b_cont;
1055 1055
1056 1056 bcopy(sc->sc_bm[idx], datap->b_rptr,
1057 1057 length);
1058 1058
1059 1059 if (err = usbwcm_copyreq(mp, 0,
1060 1060 USBWCM_GETRESULT, length, 0,
1061 1061 M_COPYOUT)) {
1062 1062
1063 1063 goto out;
1064 1064 }
1065 1065
1066 1066 } else if (copystat->state ==
1067 1067 USBWCM_GETRESULT) {
1068 1068 freemsg(ioctmp);
1069 1069 usbwcm_miocack(q, mp, length);
1070 1070 return;
1071 1071 }
1072 1072 break;
1073 1073
1074 1074 } else if (num >= EUWACOMGETABS &&
1075 1075 num < EUWACOMGETABS + ABS_USED) {
1076 1076 int idx = num - EUWACOMGETABS;
1077 1077
1078 1078 ioctmp = copyresp->cp_private;
1079 1079 copystat = (usbwcm_copyin_t *)ioctmp->b_rptr;
1080 1080 if (copystat->state == USBWCM_GETSTRUCT) {
1081 1081 if (mp->b_cont == NULL) {
1082 1082 err = EINVAL;
1083 1083
1084 1084 break;
1085 1085 }
1086 1086 datap = (mblk_t *)mp->b_cont;
1087 1087
1088 1088 bcopy(&sc->sc_abs[idx], datap->b_rptr,
1089 1089 sizeof (struct event_abs_axis));
1090 1090
1091 1091 if (err = usbwcm_copyreq(mp, 0,
1092 1092 USBWCM_GETRESULT,
1093 1093 sizeof (struct event_abs_axis), 0,
1094 1094 M_COPYOUT)) {
1095 1095
1096 1096 goto out;
1097 1097 }
1098 1098
1099 1099 } else if (copystat->state ==
1100 1100 USBWCM_GETRESULT) {
1101 1101 freemsg(ioctmp);
1102 1102 usbwcm_miocack(q, mp, 0);
1103 1103 return;
1104 1104 }
1105 1105 break;
1106 1106
1107 1107 } else {
1108 1108 err = EINVAL;
1109 1109 break;
1110 1110 }
1111 1111 }
1112 1112 }
1113 1113 }
1114 1114
1115 1115 out:
1116 1116 if (err) {
1117 1117 mp->b_datap->db_type = M_IOCNAK;
1118 1118 if (mp->b_cont) {
1119 1119 freemsg(mp->b_cont);
1120 1120 mp->b_cont = (mblk_t *)NULL;
1121 1121 }
1122 1122 if (copyresp->cp_private) {
1123 1123 freemsg((mblk_t *)copyresp->cp_private);
1124 1124 copyresp->cp_private = (mblk_t *)NULL;
1125 1125 }
1126 1126 iocbp->ioc_count = 0;
1127 1127 iocbp->ioc_error = err;
1128 1128 }
1129 1129
1130 1130 qreply(q, mp);
1131 1131 }
1132 1132
1133 1133 /*
1134 1134 * usbwcm_ioctl() :
1135 1135 * Process ioctls we recognize and own. Otherwise, NAK.
1136 1136 */
1137 1137 static void
1138 1138 usbwcm_ioctl(queue_t *q, mblk_t *mp)
1139 1139 {
1140 1140 usbwcm_state_t *usbwcmp = (usbwcm_state_t *)q->q_ptr;
1141 1141 struct uwacom_softc *sc;
1142 1142 mblk_t *datap;
1143 1143 struct iocblk *iocp;
1144 1144 int err = 0;
1145 1145
1146 1146 if (usbwcmp == NULL) {
1147 1147 miocnak(q, mp, 0, EINVAL);
1148 1148 return;
1149 1149 }
1150 1150
1151 1151 sc = &usbwcmp->usbwcm_softc;
1152 1152 iocp = (struct iocblk *)mp->b_rptr;
1153 1153
1154 1154 switch (iocp->ioc_cmd) {
1155 1155 default: {
1156 1156 int num = iocp->ioc_cmd & 0xff;
1157 1157 int len = IOCPARM_MASK & (iocp->ioc_cmd >> 16);
1158 1158
1159 1159 if (((iocp->ioc_cmd >> 8) & 0xFF) != 'E') {
1160 1160 putnext(q, mp); /* pass it down the line */
1161 1161 return;
1162 1162
1163 1163 } else if ((iocp->ioc_cmd & IOC_INOUT) != IOC_OUT) {
1164 1164 err = EINVAL;
1165 1165 break;
1166 1166 }
1167 1167
1168 1168 switch (num) {
1169 1169 case EUWACOMGETVERSION:
1170 1170 if (iocp->ioc_count == TRANSPARENT) {
1171 1171 if (err = usbwcm_copyreq(mp,
1172 1172 sizeof (usbwcm_copyin_t), USBWCM_GETSTRUCT,
1173 1173 sizeof (int), 0, M_COPYIN)) {
1174 1174 break;
1175 1175 }
1176 1176 freemsg(mp->b_cont);
1177 1177 mp->b_cont = (mblk_t *)NULL;
1178 1178
1179 1179 qreply(q, mp);
1180 1180 return;
1181 1181 }
1182 1182
1183 1183 if (mp->b_cont == NULL ||
1184 1184 iocp->ioc_count != sizeof (int)) {
1185 1185 err = EINVAL;
1186 1186 break;
1187 1187 }
1188 1188 datap = mp->b_cont;
1189 1189
1190 1190 *(int *)datap->b_rptr = 0x00010000;
1191 1191
1192 1192 break;
1193 1193
1194 1194 case EUWACOMGETID:
1195 1195 if (iocp->ioc_count == TRANSPARENT) {
1196 1196 if (err = usbwcm_copyreq(mp,
1197 1197 sizeof (usbwcm_copyin_t), USBWCM_GETSTRUCT,
1198 1198 sizeof (struct event_dev_id), 0,
1199 1199 M_COPYIN)) {
1200 1200 break;
1201 1201 }
1202 1202 freemsg(mp->b_cont);
1203 1203 mp->b_cont = (mblk_t *)NULL;
1204 1204
1205 1205 qreply(q, mp);
1206 1206 return;
1207 1207 }
1208 1208
1209 1209 if (mp->b_cont == NULL ||
1210 1210 iocp->ioc_count != sizeof (struct event_dev_id)) {
1211 1211 err = EINVAL;
1212 1212 break;
1213 1213 }
1214 1214 datap = mp->b_cont;
1215 1215
1216 1216 bcopy(&sc->sc_id, datap->b_rptr,
1217 1217 sizeof (struct event_dev_id));
1218 1218
1219 1219 break;
1220 1220
1221 1221 default:
1222 1222 if (num >= EUWACOMGETBM &&
1223 1223 num < EUWACOMGETBM + EVT_USED) {
1224 1224 int idx = num - EUWACOMGETBM;
1225 1225 size_t length = min(bm_size[idx], len);
1226 1226
1227 1227 if (iocp->ioc_count == TRANSPARENT) {
1228 1228 if (err = usbwcm_copyreq(mp,
1229 1229 sizeof (usbwcm_copyin_t),
1230 1230 USBWCM_GETSTRUCT, length, 0,
1231 1231 M_COPYIN)) {
1232 1232 break;
1233 1233 }
1234 1234 freemsg(mp->b_cont);
1235 1235 mp->b_cont = (mblk_t *)NULL;
1236 1236
1237 1237 qreply(q, mp);
1238 1238 return;
1239 1239 }
1240 1240
1241 1241 if (mp->b_cont == NULL ||
1242 1242 iocp->ioc_count != length) {
1243 1243 err = EINVAL;
1244 1244 break;
1245 1245 }
1246 1246 datap = mp->b_cont;
1247 1247
1248 1248 bcopy(sc->sc_bm[idx], datap->b_rptr, length);
1249 1249
1250 1250 break;
1251 1251
1252 1252 } else if (num >= EUWACOMGETABS &&
1253 1253 num < EUWACOMGETABS + ABS_USED) {
1254 1254 int idx = num - EUWACOMGETABS;
1255 1255
1256 1256 if (iocp->ioc_count == TRANSPARENT) {
1257 1257 if (err = usbwcm_copyreq(mp,
1258 1258 sizeof (usbwcm_copyin_t),
1259 1259 USBWCM_GETSTRUCT,
1260 1260 sizeof (struct event_abs_axis), 0,
1261 1261 M_COPYIN)) {
1262 1262 break;
1263 1263 }
1264 1264 freemsg(mp->b_cont);
1265 1265 mp->b_cont = (mblk_t *)NULL;
1266 1266
1267 1267 qreply(q, mp);
1268 1268 return;
1269 1269 }
1270 1270
1271 1271 if (mp->b_cont == NULL ||
1272 1272 iocp->ioc_count !=
1273 1273 sizeof (struct event_abs_axis)) {
1274 1274 err = EINVAL;
1275 1275 break;
1276 1276 }
1277 1277 datap = mp->b_cont;
1278 1278
1279 1279 bcopy(&sc->sc_abs[idx], datap->b_rptr,
1280 1280 sizeof (struct event_abs_axis));
1281 1281
1282 1282 break;
1283 1283
1284 1284 } else {
1285 1285 err = EINVAL;
1286 1286 break;
1287 1287 }
1288 1288 }
1289 1289 }
1290 1290 }
1291 1291
1292 1292 if (err != 0)
1293 1293 miocnak(q, mp, 0, err);
1294 1294 else {
1295 1295 iocp->ioc_rval = 0;
1296 1296 iocp->ioc_error = 0;
1297 1297 mp->b_datap->db_type = M_IOCACK;
1298 1298 qreply(q, mp);
1299 1299 /* REMOVE */
1300 1300 }
1301 1301
1302 1302 return;
1303 1303
1304 1304 }
1305 1305
1306 1306 /*
1307 1307 * usbwcm_input() :
1308 1308 *
1309 1309 * Wacom input routine; process data received from a device and
1310 1310 * assemble into a input event for the window system.
1311 1311 *
1312 1312 * Watch out for overflow!
1313 1313 */
1314 1314 static void
1315 1315 usbwcm_input(usbwcm_state_t *usbwcmp, mblk_t *mp)
1316 1316 {
1317 1317 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
1318 1318
1319 1319 switch (sc->sc_type->protocol) {
1320 1320 case GRAPHIRE:
1321 1321 case GRAPHIRE4:
1322 1322 case MYOFFICE:
1323 1323 usbwcm_input_graphire(usbwcmp, mp);
1324 1324 break;
1325 1325
1326 1326 case INTUOS3S:
1327 1327 case INTUOS3L:
1328 1328 case INTUOS4S:
1329 1329 case INTUOS4L:
1330 1330 case CINTIQ:
1331 1331 usbwcm_input_intuos(usbwcmp, mp);
1332 1332 break;
1333 1333 }
1334 1334 }
1335 1335
1336 1336 /*
1337 1337 * usbwcm_flush() :
1338 1338 * Resets the soft state to default values
1339 1339 * and sends M_FLUSH above.
1340 1340 */
1341 1341 static void
1342 1342 usbwcm_flush(usbwcm_state_t *usbwcmp)
1343 1343 {
1344 1344 queue_t *q;
1345 1345
1346 1346 if ((q = usbwcmp->usbwcm_rq) != NULL && q->q_next != NULL) {
1347 1347 (void) putnextctl1(q, M_FLUSH, FLUSHR);
1348 1348 }
1349 1349 }
1350 1350
1351 1351 /*
1352 1352 * usbwcm_mctl() :
1353 1353 * Handle M_CTL messages from hid. If
1354 1354 * we don't understand the command, free message.
1355 1355 */
1356 1356 static void
1357 1357 usbwcm_mctl(queue_t *q, mblk_t *mp)
1358 1358 {
1359 1359 usbwcm_state_t *usbwcmp = (usbwcm_state_t *)q->q_ptr;
1360 1360 struct iocblk *iocp;
1361 1361 caddr_t data = NULL;
1362 1362 struct iocblk mctlmsg;
1363 1363 mblk_t *mctl_ptr;
1364 1364 hid_req_t *featr;
1365 1365
1366 1366 iocp = (struct iocblk *)mp->b_rptr;
1367 1367 if (mp->b_cont != NULL)
1368 1368 data = (caddr_t)mp->b_cont->b_rptr;
1369 1369
1370 1370 switch (iocp->ioc_cmd) {
1371 1371 case HID_GET_VID_PID:
1372 1372 if ((data != NULL) &&
1373 1373 (iocp->ioc_count == sizeof (hid_vid_pid_t)) &&
1374 1374 (MBLKL(mp->b_cont) == iocp->ioc_count)) {
1375 1375 bcopy(data, &usbwcmp->usbwcm_devid, iocp->ioc_count);
1376 1376 }
1377 1377
1378 1378 freemsg(mp);
1379 1379 usbwcmp->usbwcm_flags &= ~USBWCM_QWAIT;
1380 1380 break;
1381 1381
1382 1382 case HID_CONNECT_EVENT:
1383 1383 /* set feature: tablet mode */
1384 1384 featr = kmem_zalloc(sizeof (hid_req_t), KM_SLEEP);
1385 1385 featr->hid_req_version_no = HID_VERSION_V_0;
1386 1386 featr->hid_req_wValue = REPORT_TYPE_FEATURE | 2;
1387 1387 featr->hid_req_wLength = sizeof (uint8_t) * 2;
1388 1388 featr->hid_req_data[0] = 2;
1389 1389 featr->hid_req_data[1] = 2;
1390 1390
1391 1391 mctlmsg.ioc_cmd = HID_SET_REPORT;
1392 1392 mctlmsg.ioc_count = sizeof (featr);
1393 1393 mctl_ptr = usba_mk_mctl(mctlmsg, featr, sizeof (hid_req_t));
1394 1394 if (mctl_ptr != NULL) {
1395 1395 putnext(usbwcmp->usbwcm_wq, mctl_ptr);
1396 1396 } else {
1397 1397 USB_DPRINTF_L1(PRINT_MASK_ALL, usbwcm_log_handle,
1398 1398 "enable tablet mode failed\n");
1399 1399 }
1400 1400
1401 1401 kmem_free(featr, sizeof (hid_req_t));
1402 1402 freemsg(mp);
1403 1403 break;
1404 1404
1405 1405 case HID_SET_REPORT:
1406 1406 /* FALLTHRU */
1407 1407
1408 1408 case HID_SET_PROTOCOL:
1409 1409 usbwcmp->usbwcm_flags &= ~USBWCM_QWAIT;
1410 1410 /* FALLTHRU */
1411 1411
1412 1412 default:
1413 1413 freemsg(mp);
1414 1414 }
1415 1415 }
1416 1416
1417 1417 /*
1418 1418 * usbwcm_open() :
1419 1419 * open() entry point for the USB wacom module.
1420 1420 */
1421 1421 /*ARGSUSED*/
1422 1422 static int
1423 1423 usbwcm_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
1424 1424 {
1425 1425 usbwcm_state_t *usbwcmp;
1426 1426
1427 1427 /* Clone opens are not allowed */
1428 1428 if (sflag != MODOPEN)
1429 1429 return (EINVAL);
1430 1430
1431 1431 /* If the module is already open, just return */
1432 1432 if (q->q_ptr) {
1433 1433 return (0);
1434 1434 }
1435 1435
1436 1436 /* allocate usbwcm state structure */
1437 1437 usbwcmp = kmem_zalloc(sizeof (usbwcm_state_t), KM_SLEEP);
1438 1438
1439 1439 q->q_ptr = usbwcmp;
1440 1440 WR(q)->q_ptr = usbwcmp;
1441 1441
1442 1442 usbwcmp->usbwcm_rq = q;
1443 1443 usbwcmp->usbwcm_wq = WR(q);
1444 1444
1445 1445 qprocson(q);
1446 1446
1447 1447 if (usbwcm_probe(usbwcmp) != 0) {
1448 1448
1449 1449 qprocsoff(q);
1450 1450 kmem_free(usbwcmp, sizeof (usbwcm_state_t));
1451 1451
1452 1452 return (EINVAL);
1453 1453 }
1454 1454
1455 1455 usbwcm_flush(usbwcmp);
1456 1456
1457 1457 usbwcmp->usbwcm_flags |= USBWCM_OPEN;
1458 1458 return (0);
1459 1459 }
1460 1460
1461 1461
1462 1462 /*
1463 1463 * usbwcm_close() :
1464 1464 * close() entry point for the USB wacom module.
1465 1465 */
1466 1466 /*ARGSUSED*/
1467 1467 static int
1468 1468 usbwcm_close(queue_t *q, int flag, cred_t *credp)
1469 1469 {
1470 1470 usbwcm_state_t *usbwcmp = q->q_ptr;
1471 1471 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
1472 1472
1473 1473 qprocsoff(q);
1474 1474
1475 1475 if (usbwcmp->usbwcm_bufcall) {
1476 1476 qunbufcall(q, (bufcall_id_t)(long)usbwcmp->usbwcm_bufcall);
1477 1477 usbwcmp->usbwcm_bufcall = 0;
1478 1478 }
1479 1479
1480 1480 if (usbwcmp->usbwcm_mioctl != NULL) {
1481 1481 /*
1482 1482 * We were holding an "ioctl" response pending the
1483 1483 * availability of an "mblk" to hold data to be passed up;
1484 1484 * another "ioctl" came through, which means that "ioctl"
1485 1485 * must have timed out or been aborted.
1486 1486 */
1487 1487 freemsg(usbwcmp->usbwcm_mioctl);
1488 1488 usbwcmp->usbwcm_mioctl = NULL;
1489 1489 }
1490 1490
1491 1491 for (int i = 0; i < EVT_USED; i++)
1492 1492 kmem_free(sc->sc_bm[i], bm_size[i]);
1493 1493
1494 1494 kmem_free(sc->sc_btn, BTN_USED * sizeof (int));
1495 1495 kmem_free(sc->sc_abs, ABS_USED * sizeof (struct event_abs_axis));
1496 1496 kmem_free(usbwcmp, sizeof (usbwcm_state_t));
1497 1497
1498 1498 q->q_ptr = WR(q)->q_ptr = NULL;
1499 1499 return (0);
1500 1500 }
1501 1501
1502 1502 /*
1503 1503 * usbwcm_wput() :
1504 1504 * wput() routine for the wacom module.
1505 1505 * Module below : hid, module above : consms
1506 1506 */
1507 1507 static int
1508 1508 usbwcm_wput(queue_t *q, mblk_t *mp)
1509 1509 {
1510 1510 switch (mp->b_datap->db_type) {
1511 1511
1512 1512 case M_FLUSH: /* Canonical flush handling */
1513 1513 if (*mp->b_rptr & FLUSHW) {
1514 1514 flushq(q, FLUSHDATA);
1515 1515 }
1516 1516 if (*mp->b_rptr & FLUSHR) {
1517 1517 flushq(RD(q), FLUSHDATA);
1518 1518 }
1519 1519 putnext(q, mp); /* pass it down the line. */
1520 1520 break;
1521 1521
1522 1522 case M_IOCTL:
1523 1523 usbwcm_ioctl(q, mp);
1524 1524 break;
1525 1525
1526 1526 case M_IOCDATA:
1527 1527 usbwcm_iocpy(q, mp);
1528 1528 break;
1529 1529
1530 1530 default:
1531 1531 putnext(q, mp); /* pass it down the line. */
1532 1532 }
1533 1533
1534 1534 return (0);
1535 1535 }
1536 1536
1537 1537 /*
1538 1538 * usbwcm_rput() :
1539 1539 * Put procedure for input from driver end of stream (read queue).
1540 1540 */
1541 1541 static void
1542 1542 usbwcm_rput(queue_t *q, mblk_t *mp)
1543 1543 {
1544 1544 usbwcm_state_t *usbwcmp = q->q_ptr;
1545 1545 struct uwacom_softc *sc = &usbwcmp->usbwcm_softc;
1546 1546 mblk_t *mp0 = mp;
1547 1547 int limit;
1548 1548
1549 1549 if (usbwcmp == 0) {
1550 1550 freemsg(mp); /* nobody's listening */
1551 1551 return;
1552 1552 }
1553 1553
1554 1554 switch (mp->b_datap->db_type) {
1555 1555 case M_FLUSH:
1556 1556 if (*mp->b_rptr & FLUSHW)
1557 1557 flushq(WR(q), FLUSHDATA);
1558 1558
1559 1559 if (*mp->b_rptr & FLUSHR)
1560 1560 flushq(q, FLUSHDATA);
1561 1561
1562 1562 freemsg(mp);
1563 1563 return;
1564 1564
1565 1565 case M_BREAK:
1566 1566 /*
1567 1567 * We don't have to handle this
1568 1568 * because nothing is sent from the downstream
1569 1569 */
1570 1570 freemsg(mp);
1571 1571 return;
1572 1572
1573 1573 case M_DATA:
1574 1574 if (!(usbwcmp->usbwcm_flags & USBWCM_OPEN)) {
1575 1575 freemsg(mp); /* not ready to listen */
1576 1576
1577 1577 return;
1578 1578 }
1579 1579
1580 1580 /*
1581 1581 * Make sure there are at least "limit" number of bytes.
1582 1582 */
1583 1583 limit = uwacom_protocols[sc->sc_type->protocol].packet_size;
1584 1584 if (MBLKL(mp0) == limit) { /* REMOVE */
1585 1585 do {
1586 1586 /* REMOVE */
1587 1587 usbwcm_input(usbwcmp, mp0);
1588 1588 mp0 = mp0->b_cont;
1589 1589 } while (mp0 != NULL); /* next block, if any */
1590 1590 }
1591 1591
1592 1592 freemsg(mp);
1593 1593 break;
1594 1594
1595 1595 case M_CTL:
1596 1596 usbwcm_mctl(q, mp);
1597 1597 return;
1598 1598
1599 1599 case M_ERROR:
1600 1600 /* REMOVE */
1601 1601 usbwcmp->usbwcm_flags &= ~USBWCM_QWAIT;
1602 1602
1603 1603 freemsg(mp);
1604 1604 return;
1605 1605 default:
1606 1606 putnext(q, mp);
1607 1607 return;
1608 1608 }
1609 1609 }
1610 1610
1611 1611
1612 1612 static struct module_info modinfo;
1613 1613
1614 1614 /* STREAMS entry points */
1615 1615
1616 1616 /* read side queue */
1617 1617 static struct qinit rinit = {
1618 1618 (int (*)())usbwcm_rput, /* put procedure not needed */
1619 1619 NULL, /* service procedure */
1620 1620 usbwcm_open, /* called on startup */
1621 1621 usbwcm_close, /* called on finish */
1622 1622 NULL, /* for future use */
1623 1623 &modinfo, /* module information structure */
1624 1624 NULL /* module statistics structure */
1625 1625 };
1626 1626
1627 1627 /* write side queue */
1628 1628 static struct qinit winit = {
1629 1629 usbwcm_wput, /* put procedure */
1630 1630 NULL, /* no service proecedure needed */
1631 1631 NULL, /* open not used on write side */
1632 1632 NULL, /* close not used on write side */
1633 1633 NULL, /* for future use */
1634 1634 &modinfo, /* module information structure */
1635 1635 NULL /* module statistics structure */
1636 1636 };
1637 1637
1638 1638 /* STREAMS table */
1639 1639 static struct streamtab strtab = {
1640 1640 &rinit,
1641 1641 &winit,
1642 1642 NULL, /* not a MUX */
1643 1643 NULL /* not a MUX */
1644 1644 };
1645 1645
1646 1646 /* Module linkage information */
1647 1647
1648 1648 static struct fmodsw modsw = {
1649 1649 "usbwcm",
1650 1650 &strtab,
1651 1651 D_MP | D_MTPERMOD
1652 1652 };
↓ open down ↓ |
1652 lines elided |
↑ open up ↑ |
1653 1653
1654 1654
1655 1655 static struct modlstrmod modlstr = {
1656 1656 &mod_strmodops,
1657 1657 "USB Wacom STRMOD",
1658 1658 &modsw
1659 1659 };
1660 1660
1661 1661 static struct modlinkage modlink = {
1662 1662 MODREV_1,
1663 - (void *)&modlstr,
1664 - NULL
1663 + { (void *)&modlstr, NULL }
1665 1664 };
1666 1665
1667 1666 static struct module_info modinfo = {
1668 1667 0x0ffff, /* module id number */
1669 1668 "usbwcm", /* module name */
1670 1669 0, /* min packet size accepted */
1671 1670 INFPSZ, /* max packet size accepted */
1672 1671 512, /* hi-water mark */
1673 1672 128 /* lo-water mark */
1674 1673 };
1675 1674
1676 1675
1677 1676 /* Module entry points */
1678 1677
1679 1678 int
1680 1679 _init(void)
1681 1680 {
1682 1681 int rval = mod_install(&modlink);
1683 1682
1684 1683 if (rval == 0) {
1685 1684 usbwcm_log_handle = usb_alloc_log_hdl(NULL, "usbwcm",
1686 1685 &usbwcm_errlevel, &usbwcm_errmask, NULL, 0);
1687 1686 }
1688 1687
1689 1688 return (rval);
1690 1689 }
1691 1690
1692 1691 int
1693 1692 _fini(void)
1694 1693 {
1695 1694 int rval = mod_remove(&modlink);
1696 1695
1697 1696 if (rval == 0) {
1698 1697 usb_free_log_hdl(usbwcm_log_handle);
1699 1698 }
1700 1699
1701 1700 return (rval);
1702 1701 }
1703 1702
1704 1703 int
1705 1704 _info(struct modinfo *modinfop)
1706 1705 {
1707 1706
1708 1707 return (mod_info(&modlink, modinfop));
1709 1708 }
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX