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/usbms/usbms.c
+++ new/usr/src/uts/common/io/usb/clients/usbms/usbms.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25
26 26 #include <sys/usb/usba/usbai_version.h>
27 27 #include <sys/usb/usba.h>
28 28 #include <sys/usb/clients/hid/hid.h>
29 29 #include <sys/usb/clients/hidparser/hidparser.h>
30 30
31 31 #include <sys/stropts.h>
32 32 #include <sys/strsun.h>
33 33 #include <sys/vuid_event.h>
34 34 #include <sys/vuid_wheel.h>
35 35 #include <sys/termios.h>
36 36 #include <sys/termio.h>
37 37 #include <sys/strtty.h>
38 38 #include <sys/msreg.h>
39 39 #include <sys/msio.h>
40 40
41 41 #include <sys/usb/clients/usbms/usbms.h>
42 42
43 43 /* debugging information */
44 44 uint_t usbms_errmask = (uint_t)PRINT_MASK_ALL;
45 45 uint_t usbms_errlevel = USB_LOG_L2;
46 46 static usb_log_handle_t usbms_log_handle;
47 47
48 48 static struct streamtab usbms_streamtab;
49 49
50 50 static struct fmodsw fsw = {
51 51 "usbms",
52 52 &usbms_streamtab,
53 53 D_MP | D_MTPERMOD
54 54 };
55 55
56 56 /*
↓ open down ↓ |
56 lines elided |
↑ open up ↑ |
57 57 * Module linkage information for the kernel.
58 58 */
59 59 static struct modlstrmod modlstrmod = {
60 60 &mod_strmodops,
61 61 "USB mouse streams",
62 62 &fsw
63 63 };
64 64
65 65 static struct modlinkage modlinkage = {
66 66 MODREV_1,
67 - (void *)&modlstrmod,
68 - NULL
67 + { (void *)&modlstrmod, NULL }
69 68 };
70 69
71 70
72 71 int
73 72 _init(void)
74 73 {
75 74 int rval = mod_install(&modlinkage);
76 75
77 76 if (rval == 0) {
78 77 usbms_log_handle = usb_alloc_log_hdl(NULL, "usbms",
79 78 &usbms_errlevel, &usbms_errmask, NULL, 0);
80 79 }
81 80
82 81 return (rval);
83 82 }
84 83
85 84 int
86 85 _fini(void)
87 86 {
88 87 int rval = mod_remove(&modlinkage);
89 88
90 89 if (rval == 0) {
91 90 usb_free_log_hdl(usbms_log_handle);
92 91 }
93 92
94 93 return (rval);
95 94 }
96 95
97 96
98 97 int
99 98 _info(struct modinfo *modinfop)
100 99 {
101 100
102 101 return (mod_info(&modlinkage, modinfop));
103 102 }
104 103
105 104
106 105 /* Function prototypes */
107 106 static void usbms_reioctl(void *);
108 107 static void usbms_ioctl(queue_t *, mblk_t *);
109 108 static int usbms_open();
110 109 static int usbms_close();
111 110 static int usbms_wput();
112 111 static void usbms_rput();
113 112 static void usbms_mctl_receive(
114 113 register queue_t *q,
115 114 register mblk_t *mp);
116 115
117 116 static void usbms_rserv(queue_t *q);
118 117 static void usbms_miocdata(
119 118 register queue_t *q,
120 119 register mblk_t *mp);
121 120
122 121 static void usbms_resched(void *);
123 122
124 123 static int usbms_getparms(
125 124 register Ms_parms *data,
126 125 usbms_state_t *usbmsp);
127 126
128 127 static int usbms_setparms(
129 128 register Ms_parms *data,
130 129 usbms_state_t *usbmsp);
131 130
132 131 static int usbms_get_screen_parms(
133 132 register queue_t *q,
134 133 register mblk_t *datap);
135 134
136 135 static void usbms_flush(usbms_state_t *usbmsp);
137 136
138 137 static void usbms_incr(void *);
139 138 static void usbms_input(
140 139 usbms_state_t *usbmsp,
141 140 mblk_t *mp);
142 141 static void usbms_rserv_vuid_button(
143 142 queue_t *q,
144 143 struct usbmouseinfo *mi,
145 144 mblk_t **bpaddr);
146 145
147 146 static void usbms_rserv_vuid_event_y(
148 147 queue_t *q,
149 148 struct usbmouseinfo *mi,
150 149 mblk_t **bpaddr);
151 150 static void usbms_rserv_vuid_event_x(
152 151 queue_t *q,
153 152 struct usbmouseinfo *mi,
154 153 mblk_t **bpaddr);
155 154 static void usbms_rserv_vuid_event_wheel(
156 155 queue_t *,
157 156 struct usbmouseinfo *,
158 157 mblk_t **,
159 158 ushort_t id);
160 159 static int usbms_check_for_wheels(usbms_state_t *);
161 160 static int usbms_make_copyreq(
162 161 mblk_t *,
163 162 uint_t pvtsize,
164 163 uint_t state,
165 164 uint_t reqsize,
166 165 uint_t contsize,
167 166 uint_t copytype);
168 167 static int usbms_service_wheel_info(
169 168 queue_t *,
170 169 mblk_t *);
171 170 static int usbms_service_wheel_state(
172 171 queue_t *,
173 172 mblk_t *,
174 173 uint_t cmd);
175 174 static void usbms_ack_ioctl(mblk_t *);
176 175 static int usbms_read_input_data_format(usbms_state_t *);
177 176 static mblk_t *usbms_setup_abs_mouse_event();
178 177 static int usbms_get_coordinate(
179 178 uint_t pos,
180 179 uint_t len,
181 180 mblk_t *mp);
182 181 extern void uniqtime32();
183 182
184 183 /*
185 184 * Device driver qinit functions
186 185 */
187 186 static struct module_info usbms_mod_info = {
188 187 0x0ffff, /* module id number */
189 188 "usbms", /* module name */
190 189 0, /* min packet size accepted */
191 190 INFPSZ, /* max packet size accepted */
192 191 512, /* hi-water mark */
193 192 128 /* lo-water mark */
194 193 };
195 194
196 195 /* read side queue information structure */
197 196 static struct qinit rinit = {
198 197 (int (*)())usbms_rput, /* put procedure not needed */
199 198 (int (*)())usbms_rserv, /* service procedure */
200 199 usbms_open, /* called on startup */
201 200 usbms_close, /* called on finish */
202 201 NULL, /* for future use */
203 202 &usbms_mod_info, /* module information structure */
204 203 NULL /* module statistics structure */
205 204 };
206 205
207 206 /* write side queue information structure */
208 207 static struct qinit winit = {
209 208 usbms_wput, /* put procedure */
210 209 NULL, /* no service proecedure needed */
211 210 NULL, /* open not used on write side */
212 211 NULL, /* close not used on write side */
213 212 NULL, /* for future use */
214 213 &usbms_mod_info, /* module information structure */
215 214 NULL /* module statistics structure */
216 215 };
217 216
218 217 static struct streamtab usbms_streamtab = {
219 218 &rinit,
220 219 &winit,
221 220 NULL, /* not a MUX */
222 221 NULL /* not a MUX */
223 222 };
224 223
225 224 /*
226 225 * Message when overrun circular buffer
227 226 */
228 227 static int overrun_msg;
229 228
230 229 /* Increment when overrun circular buffer */
231 230 static int overrun_cnt;
232 231
233 232 extern int hz;
234 233
235 234 /*
236 235 * Mouse buffer size in bytes. Place here as variable so that one could
237 236 * massage it using adb if it turns out to be too small.
238 237 */
239 238 static uint16_t usbms_buf_bytes = USBMS_BUF_BYTES;
240 239
241 240
242 241 /*
243 242 * Regular STREAMS Entry points
244 243 */
245 244
246 245 /*
247 246 * usbms_open() :
248 247 * open() entry point for the USB mouse module.
249 248 */
250 249 /*ARGSUSED*/
251 250 static int
252 251 usbms_open(queue_t *q,
253 252 dev_t *devp,
254 253 int flag,
255 254 int sflag,
256 255 cred_t *credp)
257 256
258 257 {
259 258 register struct usbmousebuf *mousebufp;
260 259 register struct ms_softc *msd_soft;
261 260 usbms_state_t *usbmsp;
262 261 struct iocblk mctlmsg;
263 262 mblk_t *mctl_ptr;
264 263
265 264
266 265 /* Clone opens are not allowed */
267 266 if (sflag != MODOPEN)
268 267 return (EINVAL);
269 268
270 269 /* If the module is already open, just return */
271 270 if (q->q_ptr) {
272 271 return (0);
273 272 }
274 273
275 274 /* allocate usbms state structure */
276 275 usbmsp = kmem_zalloc(sizeof (usbms_state_t), KM_SLEEP);
277 276
278 277 q->q_ptr = usbmsp;
279 278 WR(q)->q_ptr = usbmsp;
280 279
281 280 usbmsp->usbms_rq_ptr = q;
282 281 usbmsp->usbms_wq_ptr = WR(q);
283 282
284 283 qprocson(q);
285 284
286 285 /*
287 286 * Set up private data.
288 287 */
289 288 usbmsp->usbms_state = USBMS_WAIT_BUTN;
290 289 usbmsp->usbms_iocpending = NULL;
291 290 usbmsp->usbms_jitter_thresh = USBMS_JITTER_THRESH;
292 291 usbmsp->usbms_speedlimit = USBMS_SPEEDLIMIT;
293 292 usbmsp->usbms_speedlaw = USBMS_SPEEDLAW;
294 293 usbmsp->usbms_speed_count = USBMS_SPEED_COUNT;
295 294
296 295 msd_soft = &usbmsp->usbms_softc;
297 296
298 297 /*
299 298 * Initially set the format to MS_VUID_FORMAT
300 299 */
301 300 msd_soft->ms_readformat = MS_VUID_FORMAT;
302 301
303 302 /*
304 303 * Allocate buffer and initialize data.
305 304 */
306 305 msd_soft->ms_bufbytes = usbms_buf_bytes;
307 306 mousebufp = kmem_zalloc((uint_t)msd_soft->ms_bufbytes,
308 307 KM_SLEEP);
309 308
310 309 /* Truncation will happen */
311 310 mousebufp->mb_size = (uint16_t)((msd_soft->ms_bufbytes -
312 311 sizeof (struct usbmousebuf)) /
313 312 sizeof (struct usbmouseinfo));
314 313 mousebufp->mb_info = (struct usbmouseinfo *)((char *)mousebufp +
315 314 sizeof (struct usbmousebuf));
316 315 usbmsp->usbms_buf = mousebufp;
317 316 msd_soft->ms_vuidaddr = VKEY_FIRST;
318 317 usbmsp->usbms_jittertimeout = JITTER_TIMEOUT;
319 318
320 319 /* request hid report descriptor from HID */
321 320 mctlmsg.ioc_cmd = HID_GET_PARSER_HANDLE;
322 321 mctlmsg.ioc_count = 0;
323 322
324 323 mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0);
325 324 if (mctl_ptr == NULL) {
326 325 qprocsoff(q);
327 326 kmem_free(usbmsp->usbms_buf, msd_soft->ms_bufbytes);
328 327 kmem_free(usbmsp, sizeof (usbms_state_t));
329 328
330 329 return (ENOMEM);
331 330 }
332 331
333 332 usbmsp->usbms_flags |= USBMS_QWAIT;
334 333 putnext(usbmsp->usbms_wq_ptr, mctl_ptr);
335 334
336 335 /*
337 336 * Now that signal has been sent, wait for report descriptor. Cleanup
338 337 * if user signals in the mean time (as when this gets opened in an
339 338 * inappropriate context and the user types a ^C).
340 339 */
341 340 while (usbmsp->usbms_flags & USBMS_QWAIT) {
342 341
343 342 if (qwait_sig(q) == 0) {
344 343 qprocsoff(q);
345 344 kmem_free(usbmsp->usbms_buf, msd_soft->ms_bufbytes);
346 345 kmem_free(usbmsp, sizeof (usbms_state_t));
347 346
348 347 return (EINTR);
349 348 }
350 349 }
351 350
352 351 if (usbmsp->usbms_report_descr_handle != NULL) {
353 352 if (hidparser_get_usage_attribute(
354 353 usbmsp->usbms_report_descr_handle,
355 354 0,
356 355 HIDPARSER_ITEM_INPUT,
357 356 USBMS_USAGE_PAGE_BUTTON,
358 357 0,
359 358 HIDPARSER_ITEM_REPORT_COUNT,
360 359 (int32_t *)&usbmsp->usbms_num_buttons) ==
361 360 HIDPARSER_SUCCESS) {
362 361 if (usbmsp->usbms_num_buttons > USB_MS_MAX_BUTTON_NO)
363 362 usbmsp->usbms_num_buttons =
364 363 USB_MS_MAX_BUTTON_NO;
365 364 USB_DPRINTF_L2(PRINT_MASK_ALL,
366 365 usbms_log_handle, "Num of buttons is : %d",
367 366 usbmsp->usbms_num_buttons);
368 367 } else {
369 368 USB_DPRINTF_L3(PRINT_MASK_OPEN,
370 369 usbms_log_handle,
371 370 "hidparser_get_usage_attribute failed : "
372 371 "Set to default number of buttons(3).");
373 372
374 373 usbmsp->usbms_num_buttons = USB_MS_DEFAULT_BUTTON_NO;
375 374 }
376 375 } else {
377 376 USB_DPRINTF_L1(PRINT_MASK_ALL,
378 377 usbms_log_handle, "Invalid HID "
379 378 "Descriptor Tree. Set to default value(3 buttons).");
380 379 usbmsp->usbms_num_buttons = USB_MS_DEFAULT_BUTTON_NO;
381 380 }
382 381
383 382 /* check if this mouse has wheel */
384 383 if (usbms_check_for_wheels(usbmsp) == USB_FAILURE) {
385 384 USB_DPRINTF_L2(PRINT_MASK_ALL, usbms_log_handle,
386 385 "No wheels detected");
387 386 } else {
388 387 USB_DPRINTF_L2(PRINT_MASK_ALL, usbms_log_handle,
389 388 "Wheel detected");
390 389 }
391 390
392 391 usbms_flush(usbmsp);
393 392
394 393 /* get the data format from the hid descriptor */
395 394 if (usbms_read_input_data_format(usbmsp) != USB_SUCCESS) {
396 395
397 396 qprocsoff(q);
398 397 kmem_free(usbmsp->usbms_buf, msd_soft->ms_bufbytes);
399 398 kmem_free(usbmsp, sizeof (usbms_state_t));
400 399
401 400 return (EINVAL);
402 401 }
403 402
404 403 usbmsp->usbms_flags |= USBMS_OPEN;
405 404
406 405 USB_DPRINTF_L3(PRINT_MASK_OPEN, usbms_log_handle,
407 406 "usbms_open exiting");
408 407
409 408 return (0);
410 409 }
411 410
412 411
413 412 /*
414 413 * usbms_close() :
415 414 * close() entry point for the USB mouse module.
416 415 */
417 416 /*ARGSUSED*/
418 417 static int
419 418 usbms_close(queue_t *q,
420 419 int flag,
421 420 cred_t *credp)
422 421 {
423 422 usbms_state_t *usbmsp = q->q_ptr;
424 423 register struct ms_softc *ms = &usbmsp->usbms_softc;
425 424
426 425 USB_DPRINTF_L3(PRINT_MASK_CLOSE, usbms_log_handle,
427 426 "usbms_close entering");
428 427
429 428 qprocsoff(q);
430 429
431 430 if (usbmsp->usbms_jitter) {
432 431 (void) quntimeout(q,
433 432 (timeout_id_t)(long)usbmsp->usbms_timeout_id);
434 433 usbmsp->usbms_jitter = 0;
435 434 }
436 435 if (usbmsp->usbms_reioctl_id) {
437 436 qunbufcall(q, (bufcall_id_t)(long)usbmsp->usbms_reioctl_id);
438 437 usbmsp->usbms_reioctl_id = 0;
439 438 }
440 439 if (usbmsp->usbms_resched_id) {
441 440 qunbufcall(q, (bufcall_id_t)usbmsp->usbms_resched_id);
442 441 usbmsp->usbms_resched_id = 0;
443 442 }
444 443 if (usbmsp->usbms_iocpending != NULL) {
445 444 /*
446 445 * We were holding an "ioctl" response pending the
447 446 * availability of an "mblk" to hold data to be passed up;
448 447 * another "ioctl" came through, which means that "ioctl"
449 448 * must have timed out or been aborted.
450 449 */
451 450 freemsg(usbmsp->usbms_iocpending);
452 451 usbmsp->usbms_iocpending = NULL;
453 452 }
454 453
455 454
456 455 /* Free mouse buffer */
457 456 if (usbmsp->usbms_buf != NULL) {
458 457 kmem_free(usbmsp->usbms_buf, ms->ms_bufbytes);
459 458 }
460 459
461 460 kmem_free(usbmsp, sizeof (usbms_state_t));
462 461
463 462 q->q_ptr = NULL;
464 463 WR(q)->q_ptr = NULL;
465 464
466 465
467 466 USB_DPRINTF_L3(PRINT_MASK_CLOSE, usbms_log_handle,
468 467 "usbms_close exiting");
469 468
470 469 return (0);
471 470 }
472 471
473 472
474 473 /*
475 474 * usbms_rserv() :
476 475 * Read queue service routine.
477 476 * Turn buffered mouse events into stream messages.
478 477 */
479 478 static void
480 479 usbms_rserv(queue_t *q)
481 480 {
482 481 usbms_state_t *usbmsp = q->q_ptr;
483 482 struct ms_softc *ms;
484 483 struct usbmousebuf *b;
485 484 struct usbmouseinfo *mi;
486 485 mblk_t *bp;
487 486 ushort_t i, loop;
488 487 uchar_t nbutt = (uchar_t)usbmsp->usbms_num_buttons;
489 488
490 489 ms = &usbmsp->usbms_softc;
491 490 b = usbmsp->usbms_buf;
492 491
493 492 USB_DPRINTF_L3(PRINT_MASK_SERV, usbms_log_handle,
494 493 "usbms_rserv entering");
495 494
496 495 while (canputnext(q) && ms->ms_oldoff != b->mb_off) {
497 496 mi = &b->mb_info[ms->ms_oldoff];
498 497 switch (ms->ms_readformat) {
499 498
500 499 case MS_3BYTE_FORMAT: {
501 500 register char *cp;
502 501
503 502 if ((usbmsp->usbms_idf).xlen != 1) {
504 503 USB_DPRINTF_L3(PRINT_MASK_SERV,
505 504 usbms_log_handle,
506 505 "Can't set to 3 byte format. Length != 1");
507 506
508 507 return;
509 508 }
510 509 if ((bp = allocb(3, BPRI_HI)) != NULL) {
511 510 cp = (char *)bp->b_wptr;
512 511
513 512 *cp++ = 0x80 | (mi->mi_buttons & 0xFF);
514 513 /* Update read buttons */
515 514 ms->ms_prevbuttons = mi->mi_buttons;
516 515
517 516 *cp++ = (mi->mi_x & 0xFF);
518 517 *cp++ = ((-mi->mi_y) & 0xFF);
519 518 /* lower pri to avoid mouse droppings */
520 519 bp->b_wptr = (uchar_t *)cp;
521 520 putnext(q, bp);
522 521 } else {
523 522 if (usbmsp->usbms_resched_id) {
524 523 qunbufcall(q,
525 524 (bufcall_id_t)usbmsp->
526 525 usbms_resched_id);
527 526 }
528 527 usbmsp->usbms_resched_id = qbufcall(q,
529 528 (size_t)3,
530 529 (uint_t)BPRI_HI,
531 530 (void (*)())usbms_resched,
532 531 (void *) usbmsp);
533 532 if (usbmsp->usbms_resched_id == 0)
534 533
535 534 return; /* try again later */
536 535 /* bufcall failed; just pitch this event */
537 536 /* or maybe flush queue? */
538 537 }
539 538 ms->ms_oldoff++; /* next event */
540 539
541 540 /* circular buffer wraparound */
542 541 if (ms->ms_oldoff >= b->mb_size) {
543 542 ms->ms_oldoff = 0;
544 543 }
545 544 break;
546 545 }
547 546
548 547 case MS_VUID_FORMAT:
549 548 default: {
550 549
551 550 do {
552 551 bp = NULL;
553 552
554 553 switch (ms->ms_eventstate) {
555 554
556 555 case EVENT_WHEEL:
557 556 loop = (usbmsp->usbms_num_wheels ?
558 557 1 : 0);
559 558
560 559 if (usbmsp->usbms_num_wheels) {
561 560 for (i = 0; i < loop; i++) {
562 561 usbms_rserv_vuid_event_wheel
563 562 (q, mi, &bp, i);
564 563 }
565 564 }
566 565
567 566 break;
568 567 case EVENT_BUT8:
569 568 case EVENT_BUT7:
570 569 case EVENT_BUT6:
571 570 case EVENT_BUT5:
572 571 case EVENT_BUT4:
573 572 case EVENT_BUT3: /* Send right button */
574 573 case EVENT_BUT2: /* Send middle button */
575 574 case EVENT_BUT1: /* Send left button */
576 575 usbms_rserv_vuid_button(q, mi, &bp);
577 576
578 577 break;
579 578 case EVENT_Y:
580 579 usbms_rserv_vuid_event_y(q, mi, &bp);
581 580
582 581 break;
583 582 case EVENT_X:
584 583 usbms_rserv_vuid_event_x(q, mi, &bp);
585 584
586 585 break;
587 586 default:
588 587 /* start again */
589 588 ms->ms_eventstate = EVENT_WHEEL;
590 589
591 590 break;
592 591 }
593 592 if (bp != NULL) {
594 593 /* lower pri to avoid mouse droppings */
595 594 bp->b_wptr += sizeof (Firm_event);
596 595 putnext(q, bp);
597 596 }
598 597 if (ms->ms_eventstate == EVENT_X) {
599 598 ms->ms_eventstate = EVENT_WHEEL;
600 599 } else if (ms->ms_eventstate == EVENT_WHEEL) {
601 600 ms->ms_oldoff++; /* next event */
602 601 /* circular buffer wraparound */
603 602 if (ms->ms_oldoff >= b->mb_size) {
604 603 ms->ms_oldoff = 0;
605 604 }
606 605 ms->ms_eventstate = EVENT_BUT(nbutt);
607 606 } else
608 607 ms->ms_eventstate--;
609 608 } while (ms->ms_eventstate != EVENT_BUT(nbutt));
610 609 }
611 610 }
612 611 }
613 612 USB_DPRINTF_L3(PRINT_MASK_SERV, usbms_log_handle,
614 613 "usbms_rserv exiting");
615 614 }
616 615
617 616
618 617 /*
619 618 * usbms_rserv_vuid_event_wheel
620 619 * convert wheel data to firm events
621 620 */
622 621 static void
623 622 usbms_rserv_vuid_event_wheel(queue_t *q,
624 623 struct usbmouseinfo *mi,
625 624 mblk_t **bpaddr,
626 625 ushort_t id)
627 626 {
628 627 Firm_event *fep;
629 628 mblk_t *tmp;
630 629 struct ms_softc *ms;
631 630 usbms_state_t *usbmsp = (usbms_state_t *)q->q_ptr;
632 631
633 632 if (!(usbmsp->usbms_wheel_state_bf & (1 << id))) {
634 633
635 634 return;
636 635 }
637 636 ms = &usbmsp->usbms_softc;
638 637 if (mi->mi_z) {
639 638 if ((tmp = allocb(sizeof (Firm_event), BPRI_HI)) != NULL) {
640 639 fep = (Firm_event *)tmp->b_wptr;
641 640 fep->id = vuid_id_addr(vuid_first(VUID_WHEEL)) |
642 641 vuid_id_offset(id);
643 642 fep->pair_type = FE_PAIR_NONE;
644 643 fep->pair = NULL;
645 644 fep->value = mi->mi_z;
646 645 fep->time = mi->mi_time;
647 646 *bpaddr = tmp;
648 647 } else {
649 648 if (usbmsp->usbms_resched_id) {
650 649 qunbufcall(q,
651 650 (bufcall_id_t)usbmsp->usbms_resched_id);
652 651 }
653 652 usbmsp->usbms_resched_id =
654 653 qbufcall(q, sizeof (Firm_event), BPRI_HI,
655 654 (void (*)())usbms_resched, (void *) usbmsp);
656 655 if (usbmsp->usbms_resched_id == 0) {
657 656 /* try again later */
658 657
659 658 return;
660 659 }
661 660
662 661 /* flush the queue */
663 662 ms->ms_eventstate = EVENT_WHEEL;
664 663 }
665 664 }
666 665 }
667 666
668 667
669 668 /*
670 669 * usbms_rserv_vuid_button() :
671 670 * Process a VUID button event
672 671 */
673 672 static void
674 673 usbms_rserv_vuid_button(queue_t *q,
675 674 struct usbmouseinfo *mi,
676 675 mblk_t **bpaddr)
677 676 {
678 677 usbms_state_t *usbmsp = q->q_ptr;
679 678 struct ms_softc *ms;
680 679 int button_number;
681 680 uchar_t hwbit = 0x0;
682 681 Firm_event *fep;
683 682 mblk_t *bp;
684 683 uchar_t nbutt;
685 684
686 685 ms = &usbmsp->usbms_softc;
687 686
688 687 /* Test button. Send an event if it changed. */
689 688 nbutt = (uchar_t)usbmsp->usbms_num_buttons;
690 689 button_number = nbutt - (EVENT_BUT(nbutt) - ms->ms_eventstate) - 1;
691 690 switch (button_number) {
692 691 case 2:
693 692 /* Right button */
694 693 hwbit = 0x01;
695 694
696 695 break;
697 696 case 1:
698 697 /*
699 698 * On two-button mice, the second button is the "right"
700 699 * button. There is no "middle". The vuidps2.c file has
701 700 * a bmap[] array in sendButtonEvent(). We do something
702 701 * equivalent here ONLY in the case of two-button mice.
703 702 */
704 703 if (nbutt == 2) {
705 704 hwbit = 0x01;
706 705 /*
707 706 * Trick the vuid message into thinking it's a
708 707 * right-button click also.
709 708 */
710 709 button_number = 2;
711 710 } else {
712 711 /* ... otherwise, it's just the middle button */
713 712 hwbit = 0x02;
714 713 }
715 714 break;
716 715 case 0:
717 716 /* Left button */
718 717 hwbit = 0x04;
719 718
720 719 break;
721 720 default :
722 721 /* Any other button */
723 722 hwbit = USBMS_BUT(nbutt) >> (EVENT_BUT(nbutt) -
724 723 ms->ms_eventstate);
725 724
726 725 break;
727 726 }
728 727
729 728 if ((ms->ms_prevbuttons & hwbit) !=
730 729 (mi->mi_buttons & hwbit)) {
731 730 if ((bp = allocb(sizeof (Firm_event),
732 731 BPRI_HI)) != NULL) {
733 732 *bpaddr = bp;
734 733 fep = (Firm_event *)bp->b_wptr;
735 734 fep->id = vuid_id_addr(
736 735 ms->ms_vuidaddr) |
737 736 vuid_id_offset(BUT(1)
738 737 + button_number);
739 738 fep->pair_type = FE_PAIR_NONE;
740 739 fep->pair = 0;
741 740
742 741 /*
743 742 * Update read buttons and set
744 743 * value
745 744 */
746 745 if (mi->mi_buttons & hwbit) {
747 746 fep->value = 0;
748 747 ms->ms_prevbuttons |=
749 748 hwbit;
750 749 } else {
751 750 fep->value = 1;
752 751 ms->ms_prevbuttons &=
753 752 ~hwbit;
754 753 }
755 754 fep->time = mi->mi_time;
756 755 } else {
757 756 if (usbmsp->usbms_resched_id) {
758 757 qunbufcall(q,
759 758 (bufcall_id_t)usbmsp->usbms_resched_id);
760 759 }
761 760 usbmsp->usbms_resched_id =
762 761 qbufcall(q,
763 762 sizeof (Firm_event),
764 763 BPRI_HI,
765 764 (void (*)())usbms_resched,
766 765 (void *) usbmsp);
767 766 if (usbmsp->usbms_resched_id == 0)
768 767 /* try again later */
769 768 return;
770 769 /*
771 770 * bufcall failed; just pitch
772 771 * this event
773 772 */
774 773 /* or maybe flush queue? */
775 774 ms->ms_eventstate = EVENT_WHEEL;
776 775 }
777 776 }
778 777 }
779 778
780 779 /*
781 780 * usbms_rserv_vuid_event_y() :
782 781 * Process a VUID y-event
783 782 */
784 783 static void
785 784 usbms_rserv_vuid_event_y(register queue_t *q,
786 785 register struct usbmouseinfo *mi,
787 786 mblk_t **bpaddr)
788 787 {
789 788 usbms_state_t *usbmsp = q->q_ptr;
790 789 register struct ms_softc *ms;
791 790 register Firm_event *fep;
792 791 mblk_t *bp;
793 792
794 793 ms = &usbmsp->usbms_softc;
795 794
796 795 /*
797 796 * The (max, 0) message and (0, max) message are always sent before
798 797 * the button click message is sent on the IBM Bladecenter. Stop
799 798 * their sending may prevent the coordinate from moving to the
800 799 * (max, max).
801 800 */
802 801 if (!(((usbmsp->usbms_idf).yattr) & HID_MAIN_ITEM_RELATIVE)) {
803 802 if ((mi->mi_x == 0) &&
804 803 (mi->mi_y == usbmsp->usbms_logical_Ymax)) {
805 804
806 805 return;
807 806 }
808 807 }
809 808
810 809 /* Send y if changed. */
811 810 if (mi->mi_y != 0) {
812 811 if ((bp = allocb(sizeof (Firm_event),
813 812 BPRI_HI)) != NULL) {
814 813 *bpaddr = bp;
815 814 fep = (Firm_event *)bp->b_wptr;
816 815 if (((usbmsp->usbms_idf).yattr) &
817 816 HID_MAIN_ITEM_RELATIVE) {
818 817 fep->id = vuid_id_addr(
819 818 ms->ms_vuidaddr) |
820 819 vuid_id_offset(
821 820 LOC_Y_DELTA);
822 821 fep->pair_type =
823 822 FE_PAIR_ABSOLUTE;
824 823 fep->pair =
825 824 (uchar_t)LOC_Y_ABSOLUTE;
826 825 fep->value = -(mi->mi_y);
827 826 } else {
828 827 fep->id = vuid_id_addr(
829 828 ms->ms_vuidaddr) |
830 829 vuid_id_offset(
831 830 LOC_Y_ABSOLUTE);
832 831 fep->pair_type = FE_PAIR_DELTA;
833 832 fep->pair = (uchar_t)LOC_Y_DELTA;
834 833 fep->value = (mi->mi_y *
835 834 ((usbmsp->usbms_resolution).height) /
836 835 usbmsp->usbms_logical_Ymax);
837 836 if ((mi->mi_y *
838 837 ((usbmsp->usbms_resolution).height) %
839 838 usbmsp->usbms_logical_Ymax) >=
840 839 (usbmsp->usbms_logical_Ymax / 2)) {
841 840 fep->value ++;
842 841 }
843 842 }
844 843 fep->time = mi->mi_time;
845 844 } else {
846 845 if (usbmsp->usbms_resched_id) {
847 846 qunbufcall(q,
848 847 (bufcall_id_t)usbmsp->usbms_resched_id);
849 848 }
850 849 usbmsp->usbms_resched_id =
851 850 qbufcall(q,
852 851 sizeof (Firm_event),
853 852 BPRI_HI,
854 853 (void (*)())usbms_resched,
855 854 (void *)usbmsp);
856 855 if (usbmsp->usbms_resched_id == 0) {
857 856 /* try again later */
858 857 return;
859 858 }
860 859
861 860 /*
862 861 * bufcall failed; just pitch
863 862 * this event
864 863 */
865 864 /* or maybe flush queue? */
866 865 ms->ms_eventstate = EVENT_WHEEL;
867 866 }
868 867 }
869 868 }
870 869
871 870 /*
872 871 * usbms_rserv_vuid_event_x() :
873 872 * Process a VUID x-event
874 873 */
875 874 static void
876 875 usbms_rserv_vuid_event_x(register queue_t *q,
877 876 register struct usbmouseinfo *mi,
878 877 mblk_t **bpaddr)
879 878 {
880 879 usbms_state_t *usbmsp = q->q_ptr;
881 880 register struct ms_softc *ms;
882 881 register Firm_event *fep;
883 882 mblk_t *bp;
884 883
885 884 ms = &usbmsp->usbms_softc;
886 885
887 886 /*
888 887 * The (max, 0) message and (0, max) message are always sent before
889 888 * the button click message is sent on the IBM Bladecenter. Stop
890 889 * their sending may prevent the coordinate from moving to the
891 890 * (max, max).
892 891 */
893 892 if (!(((usbmsp->usbms_idf).xattr) & HID_MAIN_ITEM_RELATIVE)) {
894 893 if ((mi->mi_y == 0) &&
895 894 (mi->mi_x == usbmsp->usbms_logical_Xmax)) {
896 895
897 896 return;
898 897 }
899 898 }
900 899
901 900 /* Send x if changed. */
902 901 if (mi->mi_x != 0) {
903 902 if ((bp = allocb(sizeof (Firm_event),
904 903 BPRI_HI)) != NULL) {
905 904 *bpaddr = bp;
906 905 fep = (Firm_event *)bp->b_wptr;
907 906 if (((usbmsp->usbms_idf).xattr) &
908 907 HID_MAIN_ITEM_RELATIVE) {
909 908 fep->id = vuid_id_addr(
910 909 ms->ms_vuidaddr) |
911 910 vuid_id_offset(LOC_X_DELTA);
912 911 fep->pair_type =
913 912 FE_PAIR_ABSOLUTE;
914 913 fep->pair =
915 914 (uchar_t)LOC_X_ABSOLUTE;
916 915 fep->value = mi->mi_x;
917 916 } else {
918 917 fep->id = vuid_id_addr(ms->ms_vuidaddr) |
919 918 vuid_id_offset(LOC_X_ABSOLUTE);
920 919 fep->pair_type = FE_PAIR_DELTA;
921 920 fep->pair = (uchar_t)LOC_X_DELTA;
922 921 fep->value = (mi->mi_x *
923 922 ((usbmsp->usbms_resolution).width) /
924 923 usbmsp->usbms_logical_Xmax);
925 924 if ((mi->mi_x *
926 925 ((usbmsp->usbms_resolution).width) %
927 926 usbmsp->usbms_logical_Xmax) >=
928 927 (usbmsp->usbms_logical_Xmax / 2)) {
929 928 fep->value ++;
930 929 }
931 930 }
932 931 fep->time = mi->mi_time;
933 932 } else {
934 933 if (usbmsp->usbms_resched_id)
935 934 qunbufcall(q,
936 935 (bufcall_id_t)usbmsp->usbms_resched_id);
937 936 usbmsp->usbms_resched_id =
938 937 qbufcall(q,
939 938 sizeof (Firm_event),
940 939 BPRI_HI,
941 940 (void (*)())usbms_resched,
942 941 (void *) usbmsp);
943 942 if (usbmsp->usbms_resched_id == 0)
944 943 /* try again later */
945 944 return;
946 945
947 946 /*
948 947 * bufcall failed; just
949 948 * pitch this event
950 949 */
951 950 /* or maybe flush queue? */
952 951 ms->ms_eventstate = EVENT_WHEEL;
953 952 }
954 953 }
955 954 }
956 955
957 956 /*
958 957 * usbms_resched() :
959 958 * Callback routine for the qbufcall() in case
960 959 * of allocb() failure. When buffer becomes
961 960 * available, this function is called and
962 961 * enables the queue.
963 962 */
964 963 static void
965 964 usbms_resched(void * usbmsp)
966 965 {
967 966 register queue_t *q;
968 967 register usbms_state_t *tmp_usbmsp = (usbms_state_t *)usbmsp;
969 968
970 969 tmp_usbmsp->usbms_resched_id = 0;
971 970 if ((q = tmp_usbmsp->usbms_rq_ptr) != 0)
972 971 qenable(q); /* run the service procedure */
973 972 }
974 973
975 974 /*
976 975 * usbms_wput() :
977 976 * wput() routine for the mouse module.
978 977 * Module below : hid, module above : consms
979 978 */
980 979 static int
981 980 usbms_wput(queue_t *q,
982 981 mblk_t *mp)
983 982 {
984 983 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
985 984 "usbms_wput entering");
986 985 switch (mp->b_datap->db_type) {
987 986
988 987 case M_FLUSH: /* Canonical flush handling */
989 988 if (*mp->b_rptr & FLUSHW) {
990 989 flushq(q, FLUSHDATA);
991 990 }
992 991
993 992 if (*mp->b_rptr & FLUSHR) {
994 993 flushq(RD(q), FLUSHDATA);
995 994 }
996 995
997 996 putnext(q, mp); /* pass it down the line. */
998 997 break;
999 998
1000 999 case M_IOCTL:
1001 1000 usbms_ioctl(q, mp);
1002 1001 break;
1003 1002
1004 1003 case M_IOCDATA:
1005 1004 usbms_miocdata(q, mp);
1006 1005
1007 1006 break;
1008 1007 default:
1009 1008 putnext(q, mp); /* pass it down the line. */
1010 1009 }
1011 1010
1012 1011 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
1013 1012 "usbms_wput exiting");
1014 1013
1015 1014 return (0);
1016 1015 }
1017 1016
1018 1017
1019 1018 /*
1020 1019 * usbms_ioctl() :
1021 1020 * Process ioctls we recognize and own. Otherwise, NAK.
1022 1021 */
1023 1022 static void
1024 1023 usbms_ioctl(register queue_t *q,
1025 1024 register mblk_t *mp)
1026 1025 {
1027 1026 usbms_state_t *usbmsp = (usbms_state_t *)q->q_ptr;
1028 1027 register struct ms_softc *ms;
1029 1028 register struct iocblk *iocp;
1030 1029 Vuid_addr_probe *addr_probe;
1031 1030 uint_t ioctlrespsize;
1032 1031 int err = 0;
1033 1032 mblk_t *datap;
1034 1033 ushort_t transparent = 0;
1035 1034 boolean_t report_abs = B_FALSE;
1036 1035 mblk_t *mb;
1037 1036
1038 1037 USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbms_log_handle,
1039 1038 "usbms_ioctl entering");
1040 1039
1041 1040 if (usbmsp == NULL) {
1042 1041 miocnak(q, mp, 0, EINVAL);
1043 1042
1044 1043 return;
1045 1044 }
1046 1045 ms = &usbmsp->usbms_softc;
1047 1046
1048 1047 iocp = (struct iocblk *)mp->b_rptr;
1049 1048 switch (iocp->ioc_cmd) {
1050 1049
1051 1050 case VUIDSFORMAT:
1052 1051 err = miocpullup(mp, sizeof (int));
1053 1052 if (err != 0)
1054 1053 break;
1055 1054
1056 1055 if (*(int *)mp->b_cont->b_rptr == ms->ms_readformat) {
1057 1056 break;
1058 1057 }
1059 1058 ms->ms_readformat = *(int *)mp->b_cont->b_rptr;
1060 1059 /*
1061 1060 * Flush mouse buffer because the messages upstream of us
1062 1061 * are in the old format.
1063 1062 */
1064 1063
1065 1064 usbms_flush(usbmsp);
1066 1065 break;
1067 1066
1068 1067 case VUIDGFORMAT:
1069 1068 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
1070 1069 ioctlrespsize = sizeof (int);
1071 1070 goto allocfailure;
1072 1071 }
1073 1072 *(int *)datap->b_wptr = ms->ms_readformat;
1074 1073 datap->b_wptr += sizeof (int);
1075 1074 freemsg(mp->b_cont);
1076 1075 mp->b_cont = datap;
1077 1076 iocp->ioc_count = sizeof (int);
1078 1077 break;
1079 1078
1080 1079 case VUIDGADDR:
1081 1080 case VUIDSADDR:
1082 1081 err = miocpullup(mp, sizeof (Vuid_addr_probe));
1083 1082 if (err != 0)
1084 1083 break;
1085 1084
1086 1085 addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
1087 1086 if (addr_probe->base != VKEY_FIRST) {
1088 1087 err = ENODEV;
1089 1088 break;
1090 1089 }
1091 1090 if (iocp->ioc_cmd == VUIDSADDR)
1092 1091 ms->ms_vuidaddr = addr_probe->data.next;
1093 1092 else
1094 1093 addr_probe->data.current = ms->ms_vuidaddr;
1095 1094 break;
1096 1095
1097 1096 case MSIOGETPARMS:
1098 1097 if ((datap = allocb(sizeof (Ms_parms), BPRI_HI)) == NULL) {
1099 1098 ioctlrespsize = sizeof (Ms_parms);
1100 1099 goto allocfailure;
1101 1100 }
1102 1101 err = usbms_getparms((Ms_parms *)datap->b_wptr, usbmsp);
1103 1102 datap->b_wptr += sizeof (Ms_parms);
1104 1103 freemsg(mp->b_cont);
1105 1104 mp->b_cont = datap;
1106 1105 iocp->ioc_count = sizeof (Ms_parms);
1107 1106 break;
1108 1107
1109 1108 case MSIOSETPARMS:
1110 1109 err = miocpullup(mp, sizeof (Ms_parms));
1111 1110 if (err != 0)
1112 1111 break;
1113 1112 err = usbms_setparms((Ms_parms *)mp->b_cont->b_rptr, usbmsp);
1114 1113 break;
1115 1114
1116 1115 case MSIOBUTTONS:
1117 1116 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
1118 1117 ioctlrespsize = sizeof (int);
1119 1118 goto allocfailure;
1120 1119 }
1121 1120 *(int *)datap->b_wptr = (int)usbmsp->usbms_num_buttons;
1122 1121 datap->b_wptr += sizeof (int);
1123 1122 freemsg(mp->b_cont);
1124 1123 mp->b_cont = datap;
1125 1124 iocp->ioc_count = sizeof (int);
1126 1125
1127 1126 break;
1128 1127 case VUIDGWHEELCOUNT:
1129 1128 /*
1130 1129 * New IOCTL support. Since it's explicitly mentioned that
1131 1130 * you can't add more ioctls to stream head's hard coded
1132 1131 * list, we have to do the transparent ioctl processing
1133 1132 * which is heavy.
1134 1133 */
1135 1134
1136 1135 /* Currently support for only one wheel */
1137 1136
1138 1137 if (iocp->ioc_count == TRANSPARENT) {
1139 1138 transparent = 1;
1140 1139 if (err = usbms_make_copyreq(mp, 0, 0, sizeof (int),
1141 1140 0, M_COPYOUT)) {
1142 1141
1143 1142 break;
1144 1143 }
1145 1144 }
1146 1145 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
1147 1146 ioctlrespsize = sizeof (int);
1148 1147
1149 1148 goto allocfailure;
1150 1149 }
1151 1150 *((int *)datap->b_wptr) = (usbmsp->usbms_num_wheels ? 1 : 0);
1152 1151 datap->b_wptr += sizeof (int);
1153 1152 if (mp->b_cont) {
1154 1153 freemsg(mp->b_cont);
1155 1154 mp->b_cont = NULL;
1156 1155 }
1157 1156 mp->b_cont = datap;
1158 1157 if (transparent) {
1159 1158 qreply(q, mp);
1160 1159
1161 1160 return;
1162 1161 }
1163 1162
1164 1163 break;
1165 1164 case VUIDGWHEELINFO:
1166 1165 if (iocp->ioc_count == TRANSPARENT) {
1167 1166 if (err = usbms_make_copyreq(mp,
1168 1167 sizeof (usbms_iocstate_t),
1169 1168 USBMS_GETSTRUCT,
1170 1169 sizeof (wheel_info),
1171 1170 0,
1172 1171 M_COPYIN)) {
1173 1172
1174 1173 break;
1175 1174 }
1176 1175 /*
1177 1176 * If there is no b_cont the earlier func. will fail.
1178 1177 * Hence there is no need for an explicit check here.
1179 1178 */
1180 1179 freemsg(mp->b_cont);
1181 1180 mp->b_cont = (mblk_t *)NULL;
1182 1181 qreply(q, mp);
1183 1182
1184 1183 return;
1185 1184 }
1186 1185 if (mp->b_cont == NULL || iocp->ioc_count !=
1187 1186 sizeof (wheel_info)) {
1188 1187 err = EINVAL;
1189 1188 break;
1190 1189 }
1191 1190 datap = mp->b_cont;
1192 1191 err = usbms_service_wheel_info(q, datap);
1193 1192
1194 1193 break;
1195 1194 case VUIDGWHEELSTATE:
1196 1195 if (iocp->ioc_count == TRANSPARENT) {
1197 1196 if (err = usbms_make_copyreq(mp,
1198 1197 sizeof (usbms_iocstate_t),
1199 1198 USBMS_GETSTRUCT,
1200 1199 sizeof (wheel_state),
1201 1200 0,
1202 1201 M_COPYIN)) {
1203 1202
1204 1203 break;
1205 1204 }
1206 1205 freemsg(mp->b_cont);
1207 1206 mp->b_cont = (mblk_t *)NULL;
1208 1207 qreply(q, mp);
1209 1208
1210 1209 return;
1211 1210 }
1212 1211 if ((mp->b_cont == NULL) ||
1213 1212 (iocp->ioc_count != sizeof (wheel_state))) {
1214 1213 err = EINVAL;
1215 1214
1216 1215 break;
1217 1216 }
1218 1217 datap = mp->b_cont;
1219 1218 err = usbms_service_wheel_state(q, datap, VUIDGWHEELSTATE);
1220 1219
1221 1220 break;
1222 1221 case VUIDSWHEELSTATE:
1223 1222 if (iocp->ioc_count == TRANSPARENT) {
1224 1223 if (err = usbms_make_copyreq(mp,
1225 1224 sizeof (usbms_iocstate_t),
1226 1225 USBMS_GETSTRUCT,
1227 1226 sizeof (wheel_state),
1228 1227 0,
1229 1228 M_COPYIN)) {
1230 1229
1231 1230 break;
1232 1231 }
1233 1232 freemsg(mp->b_cont);
1234 1233 mp->b_cont = (mblk_t *)NULL;
1235 1234 qreply(q, mp);
1236 1235
1237 1236 return;
1238 1237 }
1239 1238 if (mp->b_cont == NULL) {
1240 1239 err = EINVAL;
1241 1240
1242 1241 break;
1243 1242 }
1244 1243 datap = mp->b_cont;
1245 1244 err = usbms_service_wheel_state(q, datap, VUIDSWHEELSTATE);
1246 1245
1247 1246 break;
1248 1247 case MSIOSRESOLUTION:
1249 1248 if (iocp->ioc_count == TRANSPARENT) {
1250 1249 if (err = usbms_make_copyreq(mp,
1251 1250 sizeof (usbms_iocstate_t),
1252 1251 USBMS_GETSTRUCT,
1253 1252 sizeof (Ms_screen_resolution),
1254 1253 0,
1255 1254 M_COPYIN)) {
1256 1255
1257 1256 break;
1258 1257 }
1259 1258
1260 1259 freemsg(mp->b_cont);
1261 1260 mp->b_cont = (mblk_t *)NULL;
1262 1261 qreply(q, mp);
1263 1262
1264 1263 return;
1265 1264 }
1266 1265 if (mp->b_cont == NULL) {
1267 1266 err = EINVAL;
1268 1267
1269 1268 break;
1270 1269 }
1271 1270 datap = mp->b_cont;
1272 1271 err = usbms_get_screen_parms(q, datap);
1273 1272 /*
1274 1273 * Create the absolute mouse type event.
1275 1274 * It is used for the hotplug absolute mouse.
1276 1275 */
1277 1276 if ((!((usbmsp->usbms_idf).xattr & HID_MAIN_ITEM_RELATIVE)) &&
1278 1277 (usbmsp->usbms_rpt_abs == B_FALSE)) {
1279 1278 report_abs = B_TRUE;
1280 1279 }
1281 1280
1282 1281 break;
1283 1282
1284 1283 default:
1285 1284 putnext(q, mp); /* pass it down the line */
1286 1285
1287 1286 return;
1288 1287 } /* switch */
1289 1288
1290 1289 if (err != 0)
1291 1290 miocnak(q, mp, 0, err);
1292 1291 else {
1293 1292 iocp->ioc_rval = 0;
1294 1293 iocp->ioc_error = 0;
1295 1294 mp->b_datap->db_type = M_IOCACK;
1296 1295 qreply(q, mp);
1297 1296
1298 1297 if (report_abs == B_TRUE) {
1299 1298 /* send the abs mouse type event to the upper level */
1300 1299 if ((mb = usbms_setup_abs_mouse_event()) != NULL) {
1301 1300 usbmsp->usbms_rpt_abs = B_TRUE;
1302 1301 qreply(q, mb);
1303 1302 }
1304 1303 }
1305 1304 }
1306 1305
1307 1306 return;
1308 1307
1309 1308 allocfailure:
1310 1309 /*
1311 1310 * We needed to allocate something to handle this "ioctl", but
1312 1311 * couldn't; save this "ioctl" and arrange to get called back when
1313 1312 * it's more likely that we can get what we need.
1314 1313 * If there's already one being saved, throw it out, since it
1315 1314 * must have timed out.
1316 1315 */
1317 1316 freemsg(usbmsp->usbms_iocpending);
1318 1317 usbmsp->usbms_iocpending = mp;
1319 1318 if (usbmsp->usbms_reioctl_id) {
1320 1319 qunbufcall(q, (bufcall_id_t)usbmsp->usbms_reioctl_id);
1321 1320 }
1322 1321 usbmsp->usbms_reioctl_id = qbufcall(q, ioctlrespsize, BPRI_HI,
1323 1322 (void (*)())usbms_reioctl,
1324 1323 (void *)usbmsp);
1325 1324 }
1326 1325
1327 1326
1328 1327 /*
1329 1328 * M_IOCDATA processing for IOCTL's: VUIDGWHEELCOUNT, VUIDGWHEELINFO,
1330 1329 * VUIDGWHEELSTATE, VUIDSWHEELSTATE & MSIOSRESOLUTION.
1331 1330 */
1332 1331 static void
1333 1332 usbms_miocdata(register queue_t *q,
1334 1333 register mblk_t *mp)
1335 1334 {
1336 1335 struct copyresp *copyresp;
1337 1336 struct iocblk *iocbp;
1338 1337 mblk_t *datap;
1339 1338 mblk_t *ioctmp;
1340 1339 usbms_iocstate_t *usbmsioc;
1341 1340 int err = 0;
1342 1341
1343 1342 copyresp = (struct copyresp *)mp->b_rptr;
1344 1343 iocbp = (struct iocblk *)mp->b_rptr;
1345 1344 if (copyresp->cp_rval) {
1346 1345 err = EAGAIN;
1347 1346
1348 1347 goto err;
1349 1348 }
1350 1349 switch (copyresp->cp_cmd) {
1351 1350
1352 1351 case VUIDGWHEELCOUNT:
1353 1352 usbms_ack_ioctl(mp);
1354 1353
1355 1354 break;
1356 1355 case VUIDGWHEELINFO:
1357 1356 ioctmp = copyresp->cp_private;
1358 1357 usbmsioc = (usbms_iocstate_t *)ioctmp->b_rptr;
1359 1358 if (usbmsioc->ioc_state == USBMS_GETSTRUCT) {
1360 1359 if (mp->b_cont == NULL) {
1361 1360 err = EINVAL;
1362 1361
1363 1362 break;
1364 1363 }
1365 1364 datap = (mblk_t *)mp->b_cont;
1366 1365 if (err = usbms_service_wheel_info(q, datap)) {
1367 1366
1368 1367 goto err;
1369 1368 }
1370 1369 if (err = usbms_make_copyreq(mp, 0, USBMS_GETRESULT,
1371 1370 sizeof (wheel_info), 0, M_COPYOUT)) {
1372 1371
1373 1372 goto err;
1374 1373 }
1375 1374 } else if (usbmsioc->ioc_state == USBMS_GETRESULT) {
1376 1375 freemsg(ioctmp);
1377 1376 usbms_ack_ioctl(mp);
1378 1377 }
1379 1378
1380 1379 break;
1381 1380 case VUIDGWHEELSTATE:
1382 1381 ioctmp = (mblk_t *)copyresp->cp_private;
1383 1382 usbmsioc = (usbms_iocstate_t *)ioctmp->b_rptr;
1384 1383 if (usbmsioc->ioc_state == USBMS_GETSTRUCT) {
1385 1384 if (mp->b_cont == NULL) {
1386 1385 err = EINVAL;
1387 1386
1388 1387 break;
1389 1388 }
1390 1389 if (err = usbms_service_wheel_state(q, mp->b_cont,
1391 1390 VUIDGWHEELSTATE)) {
1392 1391 goto err;
1393 1392 }
1394 1393 if (err = usbms_make_copyreq(mp, 0, USBMS_GETRESULT,
1395 1394 sizeof (wheel_state), 0, M_COPYOUT)) {
1396 1395
1397 1396 goto err;
1398 1397 }
1399 1398 } else if (usbmsioc->ioc_state == USBMS_GETRESULT) {
1400 1399 freemsg(ioctmp);
1401 1400 usbms_ack_ioctl(mp);
1402 1401 }
1403 1402
1404 1403 break;
1405 1404 case VUIDSWHEELSTATE:
1406 1405 ioctmp = (mblk_t *)copyresp->cp_private;
1407 1406 usbmsioc = (usbms_iocstate_t *)ioctmp->b_rptr;
1408 1407 if (mp->b_cont == NULL) {
1409 1408 err = EINVAL;
1410 1409
1411 1410 break;
1412 1411 }
1413 1412 if (err = usbms_service_wheel_state(q, mp->b_cont,
1414 1413 VUIDSWHEELSTATE)) {
1415 1414
1416 1415 goto err;
1417 1416 }
1418 1417 freemsg(ioctmp);
1419 1418 usbms_ack_ioctl(mp);
1420 1419
1421 1420 break;
1422 1421 case MSIOSRESOLUTION:
1423 1422 ioctmp = (mblk_t *)copyresp->cp_private;
1424 1423 usbmsioc = (usbms_iocstate_t *)ioctmp->b_rptr;
1425 1424 if (mp->b_cont == NULL) {
1426 1425 err = EINVAL;
1427 1426
1428 1427 break;
1429 1428 }
1430 1429 if (err = usbms_get_screen_parms(q, mp->b_cont)) {
1431 1430
1432 1431 goto err;
1433 1432 }
1434 1433 freemsg(ioctmp);
1435 1434 usbms_ack_ioctl(mp);
1436 1435
1437 1436 break;
1438 1437 default:
1439 1438 err = EINVAL;
1440 1439 break;
1441 1440 }
1442 1441
1443 1442 err:
1444 1443 if (err) {
1445 1444 mp->b_datap->db_type = M_IOCNAK;
1446 1445 if (mp->b_cont) {
1447 1446 freemsg(mp->b_cont);
1448 1447 mp->b_cont = (mblk_t *)NULL;
1449 1448 }
1450 1449 if (copyresp->cp_private) {
1451 1450 freemsg((mblk_t *)copyresp->cp_private);
1452 1451 copyresp->cp_private = (mblk_t *)NULL;
1453 1452 }
1454 1453 iocbp->ioc_count = 0;
1455 1454 iocbp->ioc_error = err;
1456 1455 }
1457 1456 qreply(q, mp);
1458 1457 }
1459 1458
1460 1459
1461 1460 /*
1462 1461 * usbms_reioctl() :
1463 1462 * This function is set up as call-back function should an ioctl fail.
1464 1463 * It retries the ioctl.
1465 1464 */
1466 1465 static void
1467 1466 usbms_reioctl(void * usbms_addr)
1468 1467 {
1469 1468 usbms_state_t *usbmsp = (usbms_state_t *)usbms_addr;
1470 1469 register queue_t *q;
1471 1470 register mblk_t *mp;
1472 1471
1473 1472 q = usbmsp->usbms_wq_ptr;
1474 1473 if ((mp = usbmsp->usbms_iocpending) != NULL) {
1475 1474 usbmsp->usbms_iocpending = NULL; /* not pending any more */
1476 1475 usbms_ioctl(q, mp);
1477 1476 }
1478 1477 }
1479 1478
1480 1479 /*
1481 1480 * usbms_getparms() :
1482 1481 * Called from MSIOGETPARMS ioctl to get the
1483 1482 * current jitter_thesh, speed_law and speed_limit
1484 1483 * values.
1485 1484 */
1486 1485 static int
1487 1486 usbms_getparms(register Ms_parms *data,
1488 1487 usbms_state_t *usbmsp)
1489 1488 {
1490 1489 data->jitter_thresh = usbmsp->usbms_jitter_thresh;
1491 1490 data->speed_law = usbmsp->usbms_speedlaw;
1492 1491 data->speed_limit = usbmsp->usbms_speedlimit;
1493 1492
1494 1493 return (0);
1495 1494 }
1496 1495
1497 1496
1498 1497 /*
1499 1498 * usbms_setparms() :
1500 1499 * Called from MSIOSETPARMS ioctl to set the
1501 1500 * current jitter_thesh, speed_law and speed_limit
1502 1501 * values.
1503 1502 */
1504 1503 static int
1505 1504 usbms_setparms(register Ms_parms *data,
1506 1505 usbms_state_t *usbmsp)
1507 1506 {
1508 1507 usbmsp->usbms_jitter_thresh = data->jitter_thresh;
1509 1508 usbmsp->usbms_speedlaw = data->speed_law;
1510 1509 usbmsp->usbms_speedlimit = data->speed_limit;
1511 1510
1512 1511 return (0);
1513 1512 }
1514 1513
1515 1514 /*
1516 1515 * usbms_flush() :
1517 1516 * Resets the ms_softc structure to default values
1518 1517 * and sends M_FLUSH above.
1519 1518 */
1520 1519 static void
1521 1520 usbms_flush(usbms_state_t *usbmsp)
1522 1521 {
1523 1522 register struct ms_softc *ms = &usbmsp->usbms_softc;
1524 1523 register queue_t *q;
1525 1524
1526 1525 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
1527 1526 "usbms_flush entering");
1528 1527
1529 1528 ms->ms_oldoff = 0;
1530 1529 ms->ms_eventstate = EVENT_BUT(usbmsp->usbms_num_buttons);
1531 1530 usbmsp->usbms_buf->mb_off = 0;
1532 1531 ms->ms_prevbuttons = (char)USB_NO_BUT_PRESSED;
1533 1532 usbmsp->usbms_oldbutt = ms->ms_prevbuttons;
1534 1533 if ((q = usbmsp->usbms_rq_ptr) != NULL && q->q_next != NULL) {
1535 1534 (void) putnextctl1(q, M_FLUSH, FLUSHR);
1536 1535 }
1537 1536
1538 1537 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
1539 1538 "usbms_flush exiting");
1540 1539 }
1541 1540
1542 1541
1543 1542 /*
1544 1543 * usbms_rput() :
1545 1544 * Put procedure for input from driver end of stream (read queue).
1546 1545 */
1547 1546 static void
1548 1547 usbms_rput(queue_t *q,
1549 1548 mblk_t *mp)
1550 1549 {
1551 1550 usbms_state_t *usbmsp = q->q_ptr;
1552 1551 mblk_t *tmp_mp;
1553 1552 ushort_t limit = (usbmsp->usbms_idf).tlen;
1554 1553
1555 1554 /* Maintain the original mp */
1556 1555 tmp_mp = mp;
1557 1556
1558 1557 if (usbmsp == 0) {
1559 1558 freemsg(mp); /* nobody's listening */
1560 1559
1561 1560 return;
1562 1561 }
1563 1562
1564 1563 switch (mp->b_datap->db_type) {
1565 1564
1566 1565 case M_FLUSH:
1567 1566 if (*mp->b_rptr & FLUSHW)
1568 1567 flushq(WR(q), FLUSHDATA);
1569 1568 if (*mp->b_rptr & FLUSHR)
1570 1569 flushq(q, FLUSHDATA);
1571 1570 freemsg(mp);
1572 1571
1573 1572 return;
1574 1573
1575 1574 case M_BREAK:
1576 1575 /*
1577 1576 * We don't have to handle this
1578 1577 * because nothing is sent from the downstream
1579 1578 */
1580 1579
1581 1580 freemsg(mp);
1582 1581
1583 1582 return;
1584 1583
1585 1584 case M_DATA:
1586 1585 if (!(usbmsp->usbms_flags & USBMS_OPEN)) {
1587 1586 freemsg(mp); /* not ready to listen */
1588 1587
1589 1588 return;
1590 1589 }
1591 1590 break;
1592 1591
1593 1592 case M_CTL:
1594 1593 usbms_mctl_receive(q, mp);
1595 1594
1596 1595 return;
1597 1596
1598 1597 case M_ERROR:
1599 1598 usbmsp->usbms_protoerr = 1;
1600 1599 usbmsp->usbms_flags &= ~USBMS_QWAIT;
1601 1600 if (*mp->b_rptr == ENODEV) {
1602 1601 putnext(q, mp);
1603 1602 } else {
1604 1603 freemsg(mp);
1605 1604 }
1606 1605
1607 1606 return;
1608 1607 default:
1609 1608 putnext(q, mp);
1610 1609
1611 1610 return;
1612 1611 }
1613 1612
1614 1613 /*
1615 1614 * A data message, consisting of bytes from the mouse.
1616 1615 * Make sure there are atleast "limit" number of bytes.
1617 1616 */
1618 1617 if ((MBLKL(tmp_mp) < limit) || ((MBLKL(tmp_mp) == limit) &&
1619 1618 (usbmsp->usbms_rptid != HID_REPORT_ID_UNDEFINED))) {
1620 1619 freemsg(mp);
1621 1620 return;
1622 1621 }
1623 1622 do {
1624 1623 if (usbmsp->usbms_rptid != HID_REPORT_ID_UNDEFINED) {
1625 1624 if (*(tmp_mp->b_rptr) != usbmsp->usbms_rptid) {
1626 1625 freemsg(mp);
1627 1626
1628 1627 return;
1629 1628 } else {
1630 1629 /* We skip the report id prefix. */
1631 1630 tmp_mp->b_rptr++;
1632 1631 }
1633 1632 }
1634 1633
1635 1634 usbms_input(usbmsp, tmp_mp);
1636 1635 } while ((tmp_mp = tmp_mp->b_cont) != NULL); /* next block, if any */
1637 1636
1638 1637 freemsg(mp);
1639 1638 }
1640 1639
1641 1640
1642 1641 /*
1643 1642 * usbms_mctl_receive() :
1644 1643 * Handle M_CTL messages from hid. If
1645 1644 * we don't understand the command, free message.
1646 1645 */
1647 1646 static void
1648 1647 usbms_mctl_receive(register queue_t *q,
1649 1648 register mblk_t *mp)
1650 1649 {
1651 1650 usbms_state_t *usbmsd = (usbms_state_t *)q->q_ptr;
1652 1651 struct iocblk *iocp;
1653 1652 caddr_t data;
1654 1653
1655 1654
1656 1655 iocp = (struct iocblk *)mp->b_rptr;
1657 1656 if (mp->b_cont != NULL)
1658 1657 data = (caddr_t)mp->b_cont->b_rptr;
1659 1658
1660 1659 switch (iocp->ioc_cmd) {
1661 1660
1662 1661 case HID_GET_PARSER_HANDLE:
1663 1662 if ((data != NULL) &&
1664 1663 (iocp->ioc_count == sizeof (hidparser_handle_t)) &&
1665 1664 (MBLKL(mp->b_cont) == iocp->ioc_count)) {
1666 1665 usbmsd->usbms_report_descr_handle =
1667 1666 *(hidparser_handle_t *)data;
1668 1667 } else {
1669 1668 usbmsd->usbms_report_descr_handle = NULL;
1670 1669 }
1671 1670 freemsg(mp);
1672 1671 usbmsd->usbms_flags &= ~USBMS_QWAIT;
1673 1672 break;
1674 1673 case HID_SET_PROTOCOL:
1675 1674 usbmsd->usbms_flags &= ~USBMS_QWAIT;
1676 1675
1677 1676 /* FALLTHRU */
1678 1677 default:
1679 1678 freemsg(mp);
1680 1679 break;
1681 1680 }
1682 1681 }
1683 1682
1684 1683
1685 1684 /*
1686 1685 * usbms_input() :
1687 1686 *
1688 1687 * Mouse input routine; process a byte received from a mouse and
1689 1688 * assemble into a mouseinfo message for the window system.
1690 1689 *
1691 1690 * The USB mouse send a three-byte packet organized as
1692 1691 * button, dx, dy
1693 1692 * where dx and dy can be any signed byte value. The mouseinfo message
1694 1693 * is organized as
1695 1694 * dx, dy, button, timestamp
1696 1695 * Our strategy is to collect but, dx & dy three-byte packet, then
1697 1696 * send the mouseinfo message up.
1698 1697 *
1699 1698 * Basic algorithm: throw away bytes until we get a [potential]
1700 1699 * button byte. Collect button; Collect dx; Collect dy; Send button,
1701 1700 * dx, dy, timestamp.
1702 1701 *
1703 1702 * Watch out for overflow!
1704 1703 */
1705 1704 static void
1706 1705 usbms_input(usbms_state_t *usbmsp,
1707 1706 mblk_t *mp)
1708 1707 {
1709 1708 register struct usbmousebuf *b;
1710 1709 register struct usbmouseinfo *mi;
1711 1710 register int jitter_radius;
1712 1711 register int32_t nbutt;
1713 1712 ushort_t i;
1714 1713 char c;
1715 1714
1716 1715 nbutt = usbmsp->usbms_num_buttons;
1717 1716 b = usbmsp->usbms_buf;
1718 1717
1719 1718 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle,
1720 1719 "usbms_input entering");
1721 1720
1722 1721 if (b == NULL) {
1723 1722
1724 1723 return;
1725 1724 }
1726 1725
1727 1726 mi = &b->mb_info[b->mb_off];
1728 1727
1729 1728 /*
1730 1729 * Lower 3 bits are middle, right, left.
1731 1730 */
1732 1731 c = mp->b_rptr[(usbmsp->usbms_idf).bpos];
1733 1732 mi->mi_buttons = (char)USB_NO_BUT_PRESSED;
1734 1733 if (c & USBMS_BUT(1)) { /* left button is pressed */
1735 1734 mi->mi_buttons = mi->mi_buttons & USB_LEFT_BUT_PRESSED;
1736 1735 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR,
1737 1736 usbms_log_handle,
1738 1737 "left button pressed");
1739 1738 }
1740 1739 if (c & USBMS_BUT(2)) { /* right button is pressed */
1741 1740 mi->mi_buttons = mi->mi_buttons & USB_RIGHT_BUT_PRESSED;
1742 1741 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR,
1743 1742 usbms_log_handle,
1744 1743 "right button pressed");
1745 1744 }
1746 1745 if (c & USBMS_BUT(3)) { /* middle button is pressed */
1747 1746 mi->mi_buttons = mi->mi_buttons &
1748 1747 USB_MIDDLE_BUT_PRESSED;
1749 1748 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR,
1750 1749 usbms_log_handle,
1751 1750 "middle button pressed");
1752 1751 }
1753 1752
1754 1753 if (nbutt > 3) {
1755 1754 for (i = 4; i < (nbutt + 1); i++) {
1756 1755 if (c & USBMS_BUT(i)) {
1757 1756 mi->mi_buttons = mi->mi_buttons &
1758 1757 USB_BUT_PRESSED(i);
1759 1758 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR,
1760 1759 usbms_log_handle,
1761 1760 "%d button pressed", i);
1762 1761 }
1763 1762 }
1764 1763 }
1765 1764
1766 1765 /* get the delta X and Y from the sample */
1767 1766 mi->mi_x += usbms_get_coordinate((usbmsp->usbms_idf).xpos,
1768 1767 (usbmsp->usbms_idf).xlen, mp);
1769 1768
1770 1769 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR,
1771 1770 usbms_log_handle, "x = %d", (int)mi->mi_x);
1772 1771
1773 1772 uniqtime32(&mi->mi_time); /* record time when sample arrived */
1774 1773
1775 1774 mi->mi_y += usbms_get_coordinate((usbmsp->usbms_idf).ypos,
1776 1775 (usbmsp->usbms_idf).ylen, mp);
1777 1776
1778 1777 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle,
1779 1778 "y = %d", (int)mi->mi_y);
1780 1779
1781 1780 /*
1782 1781 * Check the wheel data in the current event.
1783 1782 * If it exists, the wheel data is got from the sample.
1784 1783 */
1785 1784
1786 1785 if (usbmsp->usbms_num_wheels) {
1787 1786 mi->mi_z += usbms_get_coordinate((usbmsp->usbms_idf).zpos,
1788 1787 (usbmsp->usbms_idf).zlen, mp);
1789 1788
1790 1789 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle,
1791 1790 "z = %d", (int)mi->mi_z);
1792 1791 }
1793 1792
1794 1793 if (usbmsp->usbms_jitter) {
1795 1794 (void) quntimeout(usbmsp->usbms_rq_ptr,
1796 1795 (timeout_id_t)usbmsp->usbms_timeout_id);
1797 1796 usbmsp->usbms_jitter = 0;
1798 1797 }
1799 1798
1800 1799 if (!usbmsp->usbms_num_wheels) {
1801 1800 mi->mi_z = 0;
1802 1801 }
1803 1802
1804 1803 /*
1805 1804 * If there is a wheel movement or a change in the button state,
1806 1805 * send the data up immediately.
1807 1806 */
1808 1807 if (!(mi->mi_z) && (mi->mi_buttons == usbmsp->usbms_oldbutt)) {
1809 1808 /*
1810 1809 * Buttons did not change; did position?
1811 1810 */
1812 1811 if (mi->mi_x == 0 && mi->mi_y == 0) {
1813 1812 /* no, position did not change */
1814 1813
1815 1814 return;
1816 1815 }
1817 1816
1818 1817 /*
1819 1818 * Did the mouse move more than the jitter threshhold?
1820 1819 */
1821 1820 jitter_radius = usbmsp->usbms_jitter_thresh;
1822 1821 if (USB_ABS((int)mi->mi_x) <= jitter_radius &&
1823 1822 USB_ABS((int)mi->mi_y) <= jitter_radius) {
1824 1823 /*
1825 1824 * Mouse moved less than the jitter threshhold.
1826 1825 * Don't indicate an event; keep accumulating motions.
1827 1826 * After "jittertimeout" ticks expire, treat
1828 1827 * the accumulated delta as the real delta.
1829 1828 */
1830 1829 usbmsp->usbms_jitter = 1;
1831 1830 usbmsp->usbms_timeout_id =
1832 1831 qtimeout(usbmsp->usbms_rq_ptr,
1833 1832 (void (*)())usbms_incr,
1834 1833 (void *)usbmsp,
1835 1834 (clock_t)usbmsp->usbms_jittertimeout);
1836 1835
1837 1836 return;
1838 1837 }
1839 1838 }
1840 1839 usbmsp->usbms_oldbutt = mi->mi_buttons;
1841 1840 usbms_incr(usbmsp);
1842 1841
1843 1842 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle,
1844 1843 "usbms_input exiting");
1845 1844 }
1846 1845
1847 1846
1848 1847 /*
1849 1848 * usbms_get_coordinate():
1850 1849 * get the X, Y, WHEEL coordinate values
1851 1850 */
1852 1851 static int
1853 1852 usbms_get_coordinate(uint_t pos, uint_t len, mblk_t *mp)
1854 1853 {
1855 1854 uint_t utmp, bitval, val;
1856 1855 int i, xyz;
1857 1856
1858 1857 /* get the unsigned int value from the bit stream */
1859 1858 utmp = 0;
1860 1859 for (i = (pos + len - 1); i >= (int)pos; i--) {
1861 1860 bitval = (mp->b_rptr[i/8] & (1 << (i%8))) >> (i%8);
1862 1861 utmp = utmp * 2 + bitval;
1863 1862 }
1864 1863
1865 1864 /* convert the unsigned int value into int value */
1866 1865 val = 1 << (len - 1);
1867 1866 xyz = (int)(utmp - val);
1868 1867 if (xyz < 0)
1869 1868 xyz += val;
1870 1869 else if (xyz == 0)
1871 1870 xyz = -(val - 1);
1872 1871 else
1873 1872 xyz -= val;
1874 1873
1875 1874 return (xyz);
1876 1875 }
1877 1876
1878 1877
1879 1878 /*
1880 1879 * usbms_incr() :
1881 1880 * Increment the mouse sample pointer.
1882 1881 * Called either immediately after a sample or after a jitter timeout.
1883 1882 */
1884 1883 static void
1885 1884 usbms_incr(void *arg)
1886 1885 {
1887 1886 usbms_state_t *usbmsp = arg;
1888 1887 register struct ms_softc *ms = &usbmsp->usbms_softc;
1889 1888 register struct usbmousebuf *b;
1890 1889 register struct usbmouseinfo *mi;
1891 1890 register int xc, yc, zc;
1892 1891 register int wake;
1893 1892 register int speedl = usbmsp->usbms_speedlimit;
1894 1893 register int xabs, yabs;
1895 1894
1896 1895 /*
1897 1896 * No longer waiting for jitter timeout
1898 1897 */
1899 1898 usbmsp->usbms_jitter = 0;
1900 1899
1901 1900 b = usbmsp->usbms_buf;
1902 1901
1903 1902 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle,
1904 1903 "usbms_incr entering");
1905 1904
1906 1905 if (b == NULL) {
1907 1906
1908 1907 return;
1909 1908 }
1910 1909 mi = &b->mb_info[b->mb_off];
1911 1910 if (usbmsp->usbms_speedlaw) {
1912 1911 xabs = USB_ABS((int)mi->mi_x);
1913 1912 yabs = USB_ABS((int)mi->mi_y);
1914 1913 if (xabs > speedl || yabs > speedl) {
1915 1914 usbmsp->usbms_speed_count++;
1916 1915 }
1917 1916 if (xabs > speedl) {
1918 1917 mi->mi_x = 0;
1919 1918 }
1920 1919 if (yabs > speedl) {
1921 1920 mi->mi_y = 0;
1922 1921 }
1923 1922 }
1924 1923
1925 1924
1926 1925 xc = yc = zc = 0;
1927 1926
1928 1927 /* See if we need to wake up anyone waiting for input */
1929 1928 wake = b->mb_off == ms->ms_oldoff;
1930 1929
1931 1930 /* Adjust circular buffer pointer */
1932 1931 if (++b->mb_off >= b->mb_size) {
1933 1932 b->mb_off = 0;
1934 1933 mi = b->mb_info;
1935 1934 } else {
1936 1935 mi++;
1937 1936 }
1938 1937
1939 1938 /*
1940 1939 * If over-took read index then flush buffer so that mouse state
1941 1940 * is consistent.
1942 1941 */
1943 1942 if (b->mb_off == ms->ms_oldoff) {
1944 1943 if (overrun_msg) {
1945 1944 USB_DPRINTF_L1(PRINT_MASK_ALL, usbms_log_handle,
1946 1945 "Mouse buffer flushed when overrun.");
1947 1946 }
1948 1947 usbms_flush(usbmsp);
1949 1948 overrun_cnt++;
1950 1949 mi = b->mb_info;
1951 1950 }
1952 1951
1953 1952 /* Remember current buttons and fractional part of x & y */
1954 1953 mi->mi_buttons = (char)USB_NO_BUT_PRESSED;
1955 1954 mi->mi_x = xc;
1956 1955 mi->mi_y = yc;
1957 1956 mi->mi_z = zc;
1958 1957
1959 1958 if (wake) {
1960 1959 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle,
1961 1960 "usbms_incr run service");
1962 1961 qenable(usbmsp->usbms_rq_ptr); /* run the service proc */
1963 1962 }
1964 1963 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle,
1965 1964 "usbms_incr exiting");
1966 1965 }
1967 1966
1968 1967
1969 1968 /*
1970 1969 * usbms_check_for_wheels
1971 1970 * return SUCCESS if wheel is found, else return FAILURE
1972 1971 */
1973 1972 static int
1974 1973 usbms_check_for_wheels(usbms_state_t *usbmsp)
1975 1974 {
1976 1975 int rval, report_id;
1977 1976
1978 1977
1979 1978 if (usbmsp->usbms_report_descr_handle) {
1980 1979 /* Get the report id that has mouse data */
1981 1980 if (hidparser_get_usage_attribute(
1982 1981 usbmsp->usbms_report_descr_handle,
1983 1982 0, /* Doesn't matter */
1984 1983 HIDPARSER_ITEM_INPUT,
1985 1984 HID_GENERIC_DESKTOP,
1986 1985 HID_GD_X,
1987 1986 HIDPARSER_ITEM_REPORT_ID,
1988 1987 &usbmsp->usbms_rptid) == HIDPARSER_NOT_FOUND) {
1989 1988 usbmsp->usbms_rptid = HID_REPORT_ID_UNDEFINED;
1990 1989 report_id = 0;
1991 1990 } else {
1992 1991 report_id = usbmsp->usbms_rptid;
1993 1992 }
1994 1993
1995 1994 /* find no. of wheels in this report */
1996 1995 rval = hidparser_get_usage_attribute(
1997 1996 usbmsp->usbms_report_descr_handle,
1998 1997 report_id,
1999 1998 HIDPARSER_ITEM_INPUT,
2000 1999 HID_GENERIC_DESKTOP,
2001 2000 HID_GD_WHEEL,
2002 2001 HIDPARSER_ITEM_REPORT_COUNT,
2003 2002 &usbmsp->usbms_num_wheels);
2004 2003 if (rval == HIDPARSER_SUCCESS) {
2005 2004 /*
2006 2005 * Found wheel. By default enable the wheel.
2007 2006 * Currently only enable only the first wheel.
2008 2007 */
2009 2008 usbmsp->usbms_wheel_state_bf |=
2010 2009 VUID_WHEEL_STATE_ENABLED;
2011 2010
2012 2011 return (USB_SUCCESS);
2013 2012 }
2014 2013 }
2015 2014 usbmsp->usbms_num_wheels = 0;
2016 2015
2017 2016 return (USB_FAILURE);
2018 2017 }
2019 2018
2020 2019
2021 2020 /*
2022 2021 * usbms_make_copyreq
2023 2022 * helper function for usbms ioctls
2024 2023 */
2025 2024 static int
2026 2025 usbms_make_copyreq(mblk_t *mp,
2027 2026 uint_t pvtsize,
2028 2027 uint_t state,
2029 2028 uint_t reqsize,
2030 2029 uint_t contsize,
2031 2030 uint_t copytype)
2032 2031 {
2033 2032
2034 2033 struct copyreq *cq;
2035 2034 struct copyresp *cr;
2036 2035 mblk_t *ioctmp;
2037 2036 mblk_t *conttmp;
2038 2037 usbms_iocstate_t *usbmsioc;
2039 2038
2040 2039 if ((!pvtsize) && state) {
2041 2040 cr = (struct copyresp *)mp->b_rptr;
2042 2041 ioctmp = cr->cp_private;
2043 2042 }
2044 2043 cq = (struct copyreq *)mp->b_rptr;
2045 2044 if (mp->b_cont == NULL) {
2046 2045
2047 2046 return (EINVAL);
2048 2047 }
2049 2048 cq->cq_addr = *((caddr_t *)mp->b_cont->b_rptr);
2050 2049 cq->cq_size = reqsize;
2051 2050 cq->cq_flag = 0;
2052 2051 if (pvtsize) {
2053 2052 ioctmp = (mblk_t *)allocb(pvtsize, BPRI_MED);
2054 2053 if (ioctmp == NULL) {
2055 2054
2056 2055 return (EAGAIN);
2057 2056 }
2058 2057 cq->cq_private = ioctmp;
2059 2058 ioctmp = cq->cq_private;
2060 2059 } else {
2061 2060 /*
2062 2061 * Here we need to set cq_private even if there's
2063 2062 * no private data, otherwise its value will be
2064 2063 * TRANSPARENT (-1) on 64bit systems because it
2065 2064 * overlaps iocp->ioc_count. If user address (cq_addr)
2066 2065 * is invalid, it would cause panic later in
2067 2066 * usbms_miocdata:
2068 2067 * freemsg((mblk_t *)copyresp->cp_private);
2069 2068 */
2070 2069 cq->cq_private = NULL;
2071 2070 }
2072 2071 if (state) {
2073 2072 usbmsioc = (usbms_iocstate_t *)ioctmp->b_rptr;
2074 2073 usbmsioc->ioc_state = state;
2075 2074 if (pvtsize) { /* M_COPYIN */
2076 2075 usbmsioc->u_addr = cq->cq_addr;
2077 2076 } else {
2078 2077 cq->cq_addr = usbmsioc->u_addr;
2079 2078 cq->cq_private = ioctmp;
2080 2079 }
2081 2080 ioctmp->b_wptr = ioctmp->b_rptr + sizeof (usbms_iocstate_t);
2082 2081 }
2083 2082 if (contsize) {
2084 2083 conttmp = (mblk_t *)allocb(contsize, BPRI_MED);
2085 2084 if (conttmp == NULL) {
2086 2085
2087 2086 return (EAGAIN);
2088 2087 }
2089 2088 if (mp->b_cont) {
2090 2089 freemsg(mp->b_cont);
2091 2090 mp->b_cont = conttmp;
2092 2091 }
2093 2092 }
2094 2093 mp->b_datap->db_type = (unsigned char)copytype;
2095 2094 mp->b_wptr = mp->b_rptr + sizeof (struct copyreq);
2096 2095
2097 2096 return (USB_SUCCESS);
2098 2097 }
2099 2098
2100 2099
2101 2100 static int
2102 2101 usbms_service_wheel_info(register queue_t *q, register mblk_t *datap)
2103 2102 {
2104 2103
2105 2104 wheel_info *wi;
2106 2105 usbms_state_t *usbmsp = (usbms_state_t *)q->q_ptr;
2107 2106 uint_t err;
2108 2107
2109 2108 wi = (wheel_info *)datap->b_rptr;
2110 2109 if (wi->vers != VUID_WHEEL_INFO_VERS) {
2111 2110 err = EINVAL;
2112 2111
2113 2112 return (err);
2114 2113 }
2115 2114 if (wi->id > (usbmsp->usbms_num_wheels - 1)) {
2116 2115 err = EINVAL;
2117 2116
2118 2117 return (err);
2119 2118 }
2120 2119 wi->format = (usbmsp->usbms_wheel_orient_bf & (1 << wi->id)) ?
2121 2120 VUID_WHEEL_FORMAT_HORIZONTAL : VUID_WHEEL_FORMAT_VERTICAL;
2122 2121
2123 2122 return (USB_SUCCESS);
2124 2123 }
2125 2124
2126 2125
2127 2126 static int
2128 2127 usbms_service_wheel_state(register queue_t *q,
2129 2128 register mblk_t *datap,
2130 2129 register uint_t cmd)
2131 2130 {
2132 2131
2133 2132 wheel_state *ws;
2134 2133 uint_t err;
2135 2134 usbms_state_t *usbmsp = (usbms_state_t *)q->q_ptr;
2136 2135
2137 2136 ws = (wheel_state *)datap->b_rptr;
2138 2137 if (ws->vers != VUID_WHEEL_STATE_VERS) {
2139 2138 err = EINVAL;
2140 2139
2141 2140 return (err);
2142 2141 }
2143 2142 if (ws->id > (usbmsp->usbms_num_wheels - 1)) {
2144 2143 err = EINVAL;
2145 2144
2146 2145 return (err);
2147 2146 }
2148 2147
2149 2148 switch (cmd) {
2150 2149 case VUIDGWHEELSTATE:
2151 2150 ws->stateflags = (usbmsp->usbms_wheel_state_bf >> ws->id) &
2152 2151 VUID_WHEEL_STATE_ENABLED;
2153 2152
2154 2153 break;
2155 2154 case VUIDSWHEELSTATE:
2156 2155 usbmsp->usbms_wheel_state_bf = (ws->stateflags << ws->id) |
2157 2156 (~(1 << ws->id) & usbmsp->usbms_wheel_state_bf);
2158 2157
2159 2158 break;
2160 2159 default:
2161 2160 err = EINVAL;
2162 2161
2163 2162 return (err);
2164 2163 }
2165 2164
2166 2165 return (USB_SUCCESS);
2167 2166 }
2168 2167
2169 2168
2170 2169 /*
2171 2170 * usbms_get_screen_parms() :
2172 2171 * Called from MSIOSRESOLUTION ioctl to get the
2173 2172 * current screen height/width params from X.
2174 2173 */
2175 2174 static int
2176 2175 usbms_get_screen_parms(register queue_t *q,
2177 2176 register mblk_t *datap)
2178 2177 {
2179 2178
2180 2179 usbms_state_t *usbmsp = (usbms_state_t *)q->q_ptr;
2181 2180 Ms_screen_resolution *res = &(usbmsp->usbms_resolution);
2182 2181 Ms_screen_resolution *data;
2183 2182
2184 2183 data = (Ms_screen_resolution *)datap->b_rptr;
2185 2184 res->height = data->height;
2186 2185 res->width = data->width;
2187 2186
2188 2187 return (USB_SUCCESS);
2189 2188 }
2190 2189
2191 2190
2192 2191 static void
2193 2192 usbms_ack_ioctl(mblk_t *mp)
2194 2193 {
2195 2194
2196 2195 struct iocblk *iocbp = (struct iocblk *)mp->b_rptr;
2197 2196
2198 2197 mp->b_datap->db_type = M_IOCACK;
2199 2198 mp->b_wptr = mp->b_rptr + sizeof (struct iocblk);
2200 2199 iocbp->ioc_error = 0;
2201 2200 iocbp->ioc_count = 0;
2202 2201 iocbp->ioc_rval = 0;
2203 2202 if (mp->b_cont != NULL) {
2204 2203 freemsg(mp->b_cont);
2205 2204 mp->b_cont = NULL;
2206 2205 }
2207 2206 }
2208 2207
2209 2208
2210 2209 /*
2211 2210 * usbms_setup_abs_mouse_event() :
2212 2211 * Called from MSIOSRESOLUTION ioctl to create
2213 2212 * the absolute mouse type firm event.
2214 2213 */
2215 2214 static mblk_t *
2216 2215 usbms_setup_abs_mouse_event()
2217 2216 {
2218 2217 mblk_t *mb;
2219 2218 Firm_event *fep;
2220 2219
2221 2220 if ((mb = allocb(sizeof (Firm_event), BPRI_HI)) != NULL) {
2222 2221 fep = (Firm_event *)mb->b_wptr;
2223 2222 fep->id = MOUSE_TYPE_ABSOLUTE;
2224 2223 fep->pair_type = FE_PAIR_NONE;
2225 2224 fep->pair = NULL;
2226 2225 fep->value = NULL;
2227 2226 mb->b_wptr += sizeof (Firm_event);
2228 2227 } else {
2229 2228 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
2230 2229 "No resource to report ABS mouse event");
2231 2230 }
2232 2231
2233 2232 return (mb);
2234 2233 }
2235 2234
2236 2235
2237 2236 /*
2238 2237 * usbms_read_input_data_format() :
2239 2238 * Get the mouse packet length and usages' length.
2240 2239 * Check whether X and Y are relative or absolute.
2241 2240 *
2242 2241 * If they are absolute, the X and Y logical max values
2243 2242 * will be got. A firm event will be created and sent
2244 2243 * to the upper level.
2245 2244 */
2246 2245 int
2247 2246 usbms_read_input_data_format(usbms_state_t *usbmsp)
2248 2247 {
2249 2248
2250 2249 hidparser_rpt_t *ms_rpt;
2251 2250 uint_t i, button_page;
2252 2251 uint_t limit = 0;
2253 2252 uint32_t rptcnt, rptsz;
2254 2253 usbms_idf *idf = &(usbmsp->usbms_idf);
2255 2254 Ms_screen_resolution *res = &(usbmsp->usbms_resolution);
2256 2255 mblk_t *mb;
2257 2256 register queue_t *q;
2258 2257 int rval;
2259 2258
2260 2259 usbmsp->usbms_rpt_abs = B_FALSE;
2261 2260
2262 2261 /* allocate hidparser report structure */
2263 2262 ms_rpt = kmem_zalloc(sizeof (hidparser_rpt_t), KM_SLEEP);
2264 2263
2265 2264 /*
2266 2265 * Check what is the total length of the mouse packet
2267 2266 * and get the usages and their lengths in order
2268 2267 */
2269 2268
2270 2269 rval = hidparser_get_usage_list_in_order(
2271 2270 usbmsp->usbms_report_descr_handle,
2272 2271 usbmsp->usbms_rptid,
2273 2272 HIDPARSER_ITEM_INPUT,
2274 2273 ms_rpt);
2275 2274
2276 2275 if (rval != HIDPARSER_SUCCESS) {
2277 2276
2278 2277 kmem_free(ms_rpt, sizeof (hidparser_rpt_t));
2279 2278 return (USB_FAILURE);
2280 2279 }
2281 2280
2282 2281 button_page = 0;
2283 2282 for (i = 0; i < ms_rpt->no_of_usages; i++) {
2284 2283 rptcnt = ms_rpt->usage_descr[i].rptcnt;
2285 2284 rptsz = ms_rpt->usage_descr[i].rptsz;
2286 2285 if ((ms_rpt->usage_descr[i].usage_page ==
2287 2286 HID_BUTTON_PAGE) && (!button_page)) {
2288 2287 idf->bpos = limit;
2289 2288 limit += (rptcnt * rptsz);
2290 2289 button_page = 1;
2291 2290 continue;
2292 2291 }
2293 2292
2294 2293 switch (ms_rpt->usage_descr[i].usage_id) {
2295 2294
2296 2295 case HID_GD_X:
2297 2296 idf->xpos = limit;
2298 2297 idf->xlen = rptsz;
2299 2298 limit += rptsz;
2300 2299 break;
2301 2300 case HID_GD_Y:
2302 2301 idf->ypos = limit;
2303 2302 idf->ylen = rptsz;
2304 2303 limit += rptsz;
2305 2304 break;
2306 2305 case HID_GD_Z:
2307 2306 /*
2308 2307 * z-axis not yet supported, just skip it.
2309 2308 *
2310 2309 * It would be ideal if the HID_GD_Z data would be
2311 2310 * reported as horizontal wheel, and HID_GD_WHEEL
2312 2311 * as vertical wheel.
2313 2312 *
2314 2313 * We can not use the default case, because
2315 2314 * that skips rptcnt*rptsz, but for an
2316 2315 * "Apple Might Mouse" rptsz must be used.
2317 2316 */
2318 2317 limit += rptsz;
2319 2318 break;
2320 2319 case HID_GD_WHEEL:
2321 2320 idf->zpos = limit;
2322 2321 idf->zlen = rptsz;
2323 2322 limit += rptsz;
2324 2323 break;
2325 2324 default:
2326 2325 limit += rptcnt * rptsz;
2327 2326 break;
2328 2327 }
2329 2328 }
2330 2329
2331 2330 kmem_free(ms_rpt, sizeof (hidparser_rpt_t));
2332 2331
2333 2332 /* get the length of sending data */
2334 2333 idf->tlen = limit / 8;
2335 2334
2336 2335 /* Check whether X and Y are relative or absolute */
2337 2336 rval = hidparser_get_main_item_data_descr(
2338 2337 usbmsp->usbms_report_descr_handle,
2339 2338 usbmsp->usbms_rptid,
2340 2339 HIDPARSER_ITEM_INPUT,
2341 2340 HID_GENERIC_DESKTOP,
2342 2341 HID_GD_X,
2343 2342 &idf->xattr);
2344 2343
2345 2344 if (rval != HIDPARSER_SUCCESS) {
2346 2345
2347 2346 return (USB_FAILURE);
2348 2347 }
2349 2348
2350 2349 /* For the time being assume that Y also has the same attr */
2351 2350 idf->yattr = idf->xattr;
2352 2351
2353 2352 /* get the logical_maximum for X and Y respectively */
2354 2353 if (!(idf->xattr & HID_MAIN_ITEM_RELATIVE)) {
2355 2354
2356 2355 /* the data format can't be parsed correctly */
2357 2356 if (limit % 8) {
2358 2357 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
2359 2358 "Wrong data packet include %d bits", limit);
2360 2359
2361 2360 return (USB_FAILURE);
2362 2361 }
2363 2362 if (hidparser_get_usage_attribute(
2364 2363 usbmsp->usbms_report_descr_handle,
2365 2364 usbmsp->usbms_rptid,
2366 2365 HIDPARSER_ITEM_INPUT,
2367 2366 HID_GENERIC_DESKTOP,
2368 2367 HID_GD_X,
2369 2368 HIDPARSER_ITEM_LOGICAL_MAXIMUM,
2370 2369 &usbmsp->usbms_logical_Xmax) != HIDPARSER_SUCCESS) {
2371 2370
2372 2371 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
2373 2372 "fail to get X logical max.");
2374 2373
2375 2374 return (USB_FAILURE);
2376 2375 }
2377 2376 if (hidparser_get_usage_attribute(
2378 2377 usbmsp->usbms_report_descr_handle,
2379 2378 usbmsp->usbms_rptid,
2380 2379 HIDPARSER_ITEM_INPUT,
2381 2380 HID_GENERIC_DESKTOP,
2382 2381 HID_GD_Y,
2383 2382 HIDPARSER_ITEM_LOGICAL_MAXIMUM,
2384 2383 &usbmsp->usbms_logical_Ymax) != HIDPARSER_SUCCESS) {
2385 2384
2386 2385 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
2387 2386 "fail to get Y logical max.");
2388 2387
2389 2388 return (USB_FAILURE);
2390 2389 }
2391 2390
2392 2391 if (usbmsp->usbms_logical_Xmax == 0) {
2393 2392 USB_DPRINTF_L3(PRINT_MASK_ALL,
2394 2393 usbms_log_handle,
2395 2394 "X logical max value is zero");
2396 2395
2397 2396 return (USB_FAILURE);
2398 2397 }
2399 2398
2400 2399 if (usbmsp->usbms_logical_Ymax == 0) {
2401 2400 USB_DPRINTF_L3(PRINT_MASK_ALL,
2402 2401 usbms_log_handle,
2403 2402 "Y logical max value is zero");
2404 2403
2405 2404 return (USB_FAILURE);
2406 2405 }
2407 2406
2408 2407 res->height = USBMS_DEFAULT_RES_HEIGHT;
2409 2408 res->width = USBMS_DEFAULT_RES_WIDTH;
2410 2409
2411 2410 /* The wheel is not supported in current remote kvms. */
2412 2411 usbmsp->usbms_num_wheels = 0;
2413 2412 q = usbmsp->usbms_rq_ptr;
2414 2413 if ((mb = usbms_setup_abs_mouse_event()) != NULL) {
2415 2414 putnext(q, mb);
2416 2415 } else {
2417 2416
2418 2417 return (USB_NO_RESOURCES);
2419 2418 }
2420 2419 }
2421 2420
2422 2421 return (USB_SUCCESS);
2423 2422 }
↓ open down ↓ |
2345 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX