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