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.
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.
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]
22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
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>
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>
41 #include <sys/usb/clients/usbms/usbms.h>
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
;
48 static struct streamtab usbms_streamtab
;
50 static struct fmodsw fsw
= {
57 * Module linkage information for the kernel.
59 static struct modlstrmod modlstrmod
= {
65 static struct modlinkage modlinkage
= {
75 int rval
= mod_install(&modlinkage
);
78 usbms_log_handle
= usb_alloc_log_hdl(NULL
, "usbms",
79 &usbms_errlevel
, &usbms_errmask
, NULL
, 0);
88 int rval
= mod_remove(&modlinkage
);
91 usb_free_log_hdl(usbms_log_handle
);
99 _info(struct modinfo
*modinfop
)
102 return (mod_info(&modlinkage
, modinfop
));
106 /* Function prototypes */
107 static void usbms_reioctl(void *);
108 static void usbms_ioctl(queue_t
*, mblk_t
*);
109 static int usbms_open();
110 static int usbms_close();
111 static int usbms_wput();
112 static void usbms_rput();
113 static void usbms_mctl_receive(
115 register mblk_t
*mp
);
117 static void usbms_rserv(queue_t
*q
);
118 static void usbms_miocdata(
120 register mblk_t
*mp
);
122 static void usbms_resched(void *);
124 static int usbms_getparms(
125 register Ms_parms
*data
,
126 usbms_state_t
*usbmsp
);
128 static int usbms_setparms(
129 register Ms_parms
*data
,
130 usbms_state_t
*usbmsp
);
132 static int usbms_get_screen_parms(
134 register mblk_t
*datap
);
136 static void usbms_flush(usbms_state_t
*usbmsp
);
138 static void usbms_incr(void *);
139 static void usbms_input(
140 usbms_state_t
*usbmsp
,
142 static void usbms_rserv_vuid_button(
144 struct usbmouseinfo
*mi
,
147 static void usbms_rserv_vuid_event_y(
149 struct usbmouseinfo
*mi
,
151 static void usbms_rserv_vuid_event_x(
153 struct usbmouseinfo
*mi
,
155 static void usbms_rserv_vuid_event_wheel(
157 struct usbmouseinfo
*,
160 static int usbms_check_for_wheels(usbms_state_t
*);
161 static int usbms_make_copyreq(
168 static int usbms_service_wheel_info(
171 static int usbms_service_wheel_state(
175 static void usbms_ack_ioctl(mblk_t
*);
176 static int usbms_read_input_data_format(usbms_state_t
*);
177 static mblk_t
*usbms_setup_abs_mouse_event();
178 static int usbms_get_coordinate(
182 extern void uniqtime32();
185 * Device driver qinit functions
187 static struct module_info usbms_mod_info
= {
188 0x0ffff, /* module id number */
189 "usbms", /* module name */
190 0, /* min packet size accepted */
191 INFPSZ
, /* max packet size accepted */
192 512, /* hi-water mark */
193 128 /* lo-water mark */
196 /* read side queue information structure */
197 static struct qinit rinit
= {
198 (int (*)())usbms_rput
, /* put procedure not needed */
199 (int (*)())usbms_rserv
, /* service procedure */
200 usbms_open
, /* called on startup */
201 usbms_close
, /* called on finish */
202 NULL
, /* for future use */
203 &usbms_mod_info
, /* module information structure */
204 NULL
/* module statistics structure */
207 /* write side queue information structure */
208 static struct qinit winit
= {
209 usbms_wput
, /* put procedure */
210 NULL
, /* no service proecedure needed */
211 NULL
, /* open not used on write side */
212 NULL
, /* close not used on write side */
213 NULL
, /* for future use */
214 &usbms_mod_info
, /* module information structure */
215 NULL
/* module statistics structure */
218 static struct streamtab usbms_streamtab
= {
221 NULL
, /* not a MUX */
226 * Message when overrun circular buffer
228 static int overrun_msg
;
230 /* Increment when overrun circular buffer */
231 static int overrun_cnt
;
236 * Mouse buffer size in bytes. Place here as variable so that one could
237 * massage it using adb if it turns out to be too small.
239 static uint16_t usbms_buf_bytes
= USBMS_BUF_BYTES
;
243 * Regular STREAMS Entry points
248 * open() entry point for the USB mouse module.
252 usbms_open(queue_t
*q
,
258 register struct usbmousebuf
*mousebufp
;
259 register struct ms_softc
*msd_soft
;
260 usbms_state_t
*usbmsp
;
261 struct iocblk mctlmsg
;
265 /* Clone opens are not allowed */
266 if (sflag
!= MODOPEN
)
269 /* If the module is already open, just return */
274 /* allocate usbms state structure */
275 usbmsp
= kmem_zalloc(sizeof (usbms_state_t
), KM_SLEEP
);
278 WR(q
)->q_ptr
= usbmsp
;
280 usbmsp
->usbms_rq_ptr
= q
;
281 usbmsp
->usbms_wq_ptr
= WR(q
);
286 * Set up private data.
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
;
295 msd_soft
= &usbmsp
->usbms_softc
;
298 * Initially set the format to MS_VUID_FORMAT
300 msd_soft
->ms_readformat
= MS_VUID_FORMAT
;
303 * Allocate buffer and initialize data.
305 msd_soft
->ms_bufbytes
= usbms_buf_bytes
;
306 mousebufp
= kmem_zalloc((uint_t
)msd_soft
->ms_bufbytes
, KM_SLEEP
);
308 /* Truncation will happen */
309 mousebufp
->mb_size
= (uint16_t)((msd_soft
->ms_bufbytes
-
310 sizeof (struct usbmousebuf
)) / sizeof (struct usbmouseinfo
));
311 mousebufp
->mb_info
= (struct usbmouseinfo
*)((char *)mousebufp
+
312 sizeof (struct usbmousebuf
));
313 usbmsp
->usbms_buf
= mousebufp
;
314 msd_soft
->ms_vuidaddr
= VKEY_FIRST
;
315 usbmsp
->usbms_jittertimeout
= JITTER_TIMEOUT
;
317 /* request hid report descriptor from HID */
318 mctlmsg
.ioc_cmd
= HID_GET_PARSER_HANDLE
;
319 mctlmsg
.ioc_count
= 0;
321 mctl_ptr
= usba_mk_mctl(mctlmsg
, NULL
, 0);
322 if (mctl_ptr
== NULL
) {
324 kmem_free(usbmsp
->usbms_buf
, msd_soft
->ms_bufbytes
);
325 kmem_free(usbmsp
, sizeof (usbms_state_t
));
330 usbmsp
->usbms_flags
|= USBMS_QWAIT
;
331 putnext(usbmsp
->usbms_wq_ptr
, mctl_ptr
);
334 * Now that signal has been sent, wait for report descriptor. Cleanup
335 * if user signals in the mean time (as when this gets opened in an
336 * inappropriate context and the user types a ^C).
338 while (usbmsp
->usbms_flags
& USBMS_QWAIT
) {
340 if (qwait_sig(q
) == 0) {
342 kmem_free(usbmsp
->usbms_buf
, msd_soft
->ms_bufbytes
);
343 kmem_free(usbmsp
, sizeof (usbms_state_t
));
349 if (usbmsp
->usbms_report_descr_handle
!= NULL
) {
350 if (hidparser_get_usage_attribute(
351 usbmsp
->usbms_report_descr_handle
,
353 HIDPARSER_ITEM_INPUT
,
354 USBMS_USAGE_PAGE_BUTTON
,
356 HIDPARSER_ITEM_REPORT_COUNT
,
357 (int32_t *)&usbmsp
->usbms_num_buttons
) ==
359 if (usbmsp
->usbms_num_buttons
> USB_MS_MAX_BUTTON_NO
)
360 usbmsp
->usbms_num_buttons
=
361 USB_MS_MAX_BUTTON_NO
;
362 USB_DPRINTF_L2(PRINT_MASK_ALL
,
363 usbms_log_handle
, "Num of buttons is : %d",
364 usbmsp
->usbms_num_buttons
);
366 USB_DPRINTF_L3(PRINT_MASK_OPEN
,
368 "hidparser_get_usage_attribute failed : "
369 "Set to default number of buttons(3).");
371 usbmsp
->usbms_num_buttons
= USB_MS_DEFAULT_BUTTON_NO
;
374 USB_DPRINTF_L1(PRINT_MASK_ALL
,
375 usbms_log_handle
, "Invalid HID "
376 "Descriptor Tree. Set to default value(3 buttons).");
377 usbmsp
->usbms_num_buttons
= USB_MS_DEFAULT_BUTTON_NO
;
380 /* check if this mouse has wheel */
381 if (usbms_check_for_wheels(usbmsp
) == USB_FAILURE
) {
382 USB_DPRINTF_L2(PRINT_MASK_ALL
, usbms_log_handle
,
383 "No wheels detected");
385 USB_DPRINTF_L2(PRINT_MASK_ALL
, usbms_log_handle
,
391 /* get the data format from the hid descriptor */
392 if (usbms_read_input_data_format(usbmsp
) != USB_SUCCESS
) {
395 kmem_free(usbmsp
->usbms_buf
, msd_soft
->ms_bufbytes
);
396 kmem_free(usbmsp
, sizeof (usbms_state_t
));
401 usbmsp
->usbms_flags
|= USBMS_OPEN
;
403 USB_DPRINTF_L3(PRINT_MASK_OPEN
, usbms_log_handle
,
404 "usbms_open exiting");
412 * close() entry point for the USB mouse module.
416 usbms_close(queue_t
*q
,
420 usbms_state_t
*usbmsp
= q
->q_ptr
;
421 register struct ms_softc
*ms
= &usbmsp
->usbms_softc
;
423 USB_DPRINTF_L3(PRINT_MASK_CLOSE
, usbms_log_handle
,
424 "usbms_close entering");
428 if (usbmsp
->usbms_jitter
) {
430 (timeout_id_t
)(long)usbmsp
->usbms_timeout_id
);
431 usbmsp
->usbms_jitter
= 0;
433 if (usbmsp
->usbms_reioctl_id
) {
434 qunbufcall(q
, (bufcall_id_t
)(long)usbmsp
->usbms_reioctl_id
);
435 usbmsp
->usbms_reioctl_id
= 0;
437 if (usbmsp
->usbms_resched_id
) {
438 qunbufcall(q
, (bufcall_id_t
)usbmsp
->usbms_resched_id
);
439 usbmsp
->usbms_resched_id
= 0;
441 if (usbmsp
->usbms_iocpending
!= NULL
) {
443 * We were holding an "ioctl" response pending the
444 * availability of an "mblk" to hold data to be passed up;
445 * another "ioctl" came through, which means that "ioctl"
446 * must have timed out or been aborted.
448 freemsg(usbmsp
->usbms_iocpending
);
449 usbmsp
->usbms_iocpending
= NULL
;
453 /* Free mouse buffer */
454 if (usbmsp
->usbms_buf
!= NULL
) {
455 kmem_free(usbmsp
->usbms_buf
, ms
->ms_bufbytes
);
458 kmem_free(usbmsp
, sizeof (usbms_state_t
));
464 USB_DPRINTF_L3(PRINT_MASK_CLOSE
, usbms_log_handle
,
465 "usbms_close exiting");
473 * Read queue service routine.
474 * Turn buffered mouse events into stream messages.
477 usbms_rserv(queue_t
*q
)
479 usbms_state_t
*usbmsp
= q
->q_ptr
;
481 struct usbmousebuf
*b
;
482 struct usbmouseinfo
*mi
;
485 uchar_t nbutt
= (uchar_t
)usbmsp
->usbms_num_buttons
;
487 ms
= &usbmsp
->usbms_softc
;
488 b
= usbmsp
->usbms_buf
;
490 USB_DPRINTF_L3(PRINT_MASK_SERV
, usbms_log_handle
,
491 "usbms_rserv entering");
493 while (canputnext(q
) && ms
->ms_oldoff
!= b
->mb_off
) {
494 mi
= &b
->mb_info
[ms
->ms_oldoff
];
495 switch (ms
->ms_readformat
) {
497 case MS_3BYTE_FORMAT
: {
500 if ((usbmsp
->usbms_idf
).xlen
!= 1) {
501 USB_DPRINTF_L3(PRINT_MASK_SERV
,
503 "Can't set to 3 byte format. Length != 1");
507 if ((bp
= allocb(3, BPRI_HI
)) != NULL
) {
508 cp
= (char *)bp
->b_wptr
;
510 *cp
++ = 0x80 | (mi
->mi_buttons
& 0xFF);
511 /* Update read buttons */
512 ms
->ms_prevbuttons
= mi
->mi_buttons
;
514 *cp
++ = (mi
->mi_x
& 0xFF);
515 *cp
++ = ((-mi
->mi_y
) & 0xFF);
516 /* lower pri to avoid mouse droppings */
517 bp
->b_wptr
= (uchar_t
*)cp
;
520 if (usbmsp
->usbms_resched_id
) {
522 (bufcall_id_t
)usbmsp
->
525 usbmsp
->usbms_resched_id
= qbufcall(q
,
528 (void (*)())usbms_resched
,
530 if (usbmsp
->usbms_resched_id
== 0)
532 return; /* try again later */
533 /* bufcall failed; just pitch this event */
534 /* or maybe flush queue? */
536 ms
->ms_oldoff
++; /* next event */
538 /* circular buffer wraparound */
539 if (ms
->ms_oldoff
>= b
->mb_size
) {
551 switch (ms
->ms_eventstate
) {
554 loop
= (usbmsp
->usbms_num_wheels
?
557 if (usbmsp
->usbms_num_wheels
) {
558 for (i
= 0; i
< loop
; i
++) {
559 usbms_rserv_vuid_event_wheel
570 case EVENT_BUT3
: /* Send right button */
571 case EVENT_BUT2
: /* Send middle button */
572 case EVENT_BUT1
: /* Send left button */
573 usbms_rserv_vuid_button(q
, mi
, &bp
);
577 usbms_rserv_vuid_event_y(q
, mi
, &bp
);
581 usbms_rserv_vuid_event_x(q
, mi
, &bp
);
586 ms
->ms_eventstate
= EVENT_WHEEL
;
591 /* lower pri to avoid mouse droppings */
592 bp
->b_wptr
+= sizeof (Firm_event
);
595 if (ms
->ms_eventstate
== EVENT_X
) {
596 ms
->ms_eventstate
= EVENT_WHEEL
;
597 } else if (ms
->ms_eventstate
== EVENT_WHEEL
) {
598 ms
->ms_oldoff
++; /* next event */
599 /* circular buffer wraparound */
600 if (ms
->ms_oldoff
>= b
->mb_size
) {
603 ms
->ms_eventstate
= EVENT_BUT(nbutt
);
606 } while (ms
->ms_eventstate
!= EVENT_BUT(nbutt
));
610 USB_DPRINTF_L3(PRINT_MASK_SERV
, usbms_log_handle
,
611 "usbms_rserv exiting");
616 * usbms_rserv_vuid_event_wheel
617 * convert wheel data to firm events
620 usbms_rserv_vuid_event_wheel(queue_t
*q
,
621 struct usbmouseinfo
*mi
,
628 usbms_state_t
*usbmsp
= (usbms_state_t
*)q
->q_ptr
;
630 if (!(usbmsp
->usbms_wheel_state_bf
& (1 << id
))) {
634 ms
= &usbmsp
->usbms_softc
;
636 if ((tmp
= allocb(sizeof (Firm_event
), BPRI_HI
)) != NULL
) {
637 fep
= (Firm_event
*)tmp
->b_wptr
;
638 fep
->id
= vuid_id_addr(vuid_first(VUID_WHEEL
)) |
640 fep
->pair_type
= FE_PAIR_NONE
;
642 fep
->value
= mi
->mi_z
;
643 fep
->time
= mi
->mi_time
;
646 if (usbmsp
->usbms_resched_id
) {
648 (bufcall_id_t
)usbmsp
->usbms_resched_id
);
650 usbmsp
->usbms_resched_id
=
651 qbufcall(q
, sizeof (Firm_event
), BPRI_HI
,
652 (void (*)())usbms_resched
, (void *) usbmsp
);
653 if (usbmsp
->usbms_resched_id
== 0) {
654 /* try again later */
659 /* flush the queue */
660 ms
->ms_eventstate
= EVENT_WHEEL
;
667 * usbms_rserv_vuid_button() :
668 * Process a VUID button event
671 usbms_rserv_vuid_button(queue_t
*q
,
672 struct usbmouseinfo
*mi
,
675 usbms_state_t
*usbmsp
= q
->q_ptr
;
683 ms
= &usbmsp
->usbms_softc
;
685 /* Test button. Send an event if it changed. */
686 nbutt
= (uchar_t
)usbmsp
->usbms_num_buttons
;
687 button_number
= nbutt
- (EVENT_BUT(nbutt
) - ms
->ms_eventstate
) - 1;
688 switch (button_number
) {
696 * On two-button mice, the second button is the "right"
697 * button. There is no "middle". The vuidps2.c file has
698 * a bmap[] array in sendButtonEvent(). We do something
699 * equivalent here ONLY in the case of two-button mice.
704 * Trick the vuid message into thinking it's a
705 * right-button click also.
709 /* ... otherwise, it's just the middle button */
719 /* Any other button */
720 hwbit
= USBMS_BUT(nbutt
) >> (EVENT_BUT(nbutt
) -
726 if ((ms
->ms_prevbuttons
& hwbit
) !=
727 (mi
->mi_buttons
& hwbit
)) {
728 if ((bp
= allocb(sizeof (Firm_event
),
731 fep
= (Firm_event
*)bp
->b_wptr
;
732 fep
->id
= vuid_id_addr(
734 vuid_id_offset(BUT(1)
736 fep
->pair_type
= FE_PAIR_NONE
;
740 * Update read buttons and set
743 if (mi
->mi_buttons
& hwbit
) {
745 ms
->ms_prevbuttons
|=
749 ms
->ms_prevbuttons
&=
752 fep
->time
= mi
->mi_time
;
754 if (usbmsp
->usbms_resched_id
) {
756 (bufcall_id_t
)usbmsp
->usbms_resched_id
);
758 usbmsp
->usbms_resched_id
=
762 (void (*)())usbms_resched
,
764 if (usbmsp
->usbms_resched_id
== 0)
765 /* try again later */
768 * bufcall failed; just pitch
771 /* or maybe flush queue? */
772 ms
->ms_eventstate
= EVENT_WHEEL
;
778 * usbms_rserv_vuid_event_y() :
779 * Process a VUID y-event
782 usbms_rserv_vuid_event_y(register queue_t
*q
,
783 register struct usbmouseinfo
*mi
,
786 usbms_state_t
*usbmsp
= q
->q_ptr
;
787 register struct ms_softc
*ms
;
788 register Firm_event
*fep
;
791 ms
= &usbmsp
->usbms_softc
;
794 * The (max, 0) message and (0, max) message are always sent before
795 * the button click message is sent on the IBM Bladecenter. Stop
796 * their sending may prevent the coordinate from moving to the
799 if (!(((usbmsp
->usbms_idf
).yattr
) & HID_MAIN_ITEM_RELATIVE
)) {
800 if ((mi
->mi_x
== 0) &&
801 (mi
->mi_y
== usbmsp
->usbms_logical_Ymax
)) {
807 /* Send y if changed. */
809 if ((bp
= allocb(sizeof (Firm_event
),
812 fep
= (Firm_event
*)bp
->b_wptr
;
813 if (((usbmsp
->usbms_idf
).yattr
) &
814 HID_MAIN_ITEM_RELATIVE
) {
815 fep
->id
= vuid_id_addr(
822 (uchar_t
)LOC_Y_ABSOLUTE
;
823 fep
->value
= -(mi
->mi_y
);
825 fep
->id
= vuid_id_addr(
829 fep
->pair_type
= FE_PAIR_DELTA
;
830 fep
->pair
= (uchar_t
)LOC_Y_DELTA
;
831 fep
->value
= (mi
->mi_y
*
832 ((usbmsp
->usbms_resolution
).height
) /
833 usbmsp
->usbms_logical_Ymax
);
835 ((usbmsp
->usbms_resolution
).height
) %
836 usbmsp
->usbms_logical_Ymax
) >=
837 (usbmsp
->usbms_logical_Ymax
/ 2)) {
841 fep
->time
= mi
->mi_time
;
843 if (usbmsp
->usbms_resched_id
) {
845 (bufcall_id_t
)usbmsp
->usbms_resched_id
);
847 usbmsp
->usbms_resched_id
=
851 (void (*)())usbms_resched
,
853 if (usbmsp
->usbms_resched_id
== 0) {
854 /* try again later */
859 * bufcall failed; just pitch
862 /* or maybe flush queue? */
863 ms
->ms_eventstate
= EVENT_WHEEL
;
869 * usbms_rserv_vuid_event_x() :
870 * Process a VUID x-event
873 usbms_rserv_vuid_event_x(register queue_t
*q
,
874 register struct usbmouseinfo
*mi
,
877 usbms_state_t
*usbmsp
= q
->q_ptr
;
878 register struct ms_softc
*ms
;
879 register Firm_event
*fep
;
882 ms
= &usbmsp
->usbms_softc
;
885 * The (max, 0) message and (0, max) message are always sent before
886 * the button click message is sent on the IBM Bladecenter. Stop
887 * their sending may prevent the coordinate from moving to the
890 if (!(((usbmsp
->usbms_idf
).xattr
) & HID_MAIN_ITEM_RELATIVE
)) {
891 if ((mi
->mi_y
== 0) &&
892 (mi
->mi_x
== usbmsp
->usbms_logical_Xmax
)) {
898 /* Send x if changed. */
900 if ((bp
= allocb(sizeof (Firm_event
),
903 fep
= (Firm_event
*)bp
->b_wptr
;
904 if (((usbmsp
->usbms_idf
).xattr
) &
905 HID_MAIN_ITEM_RELATIVE
) {
906 fep
->id
= vuid_id_addr(
908 vuid_id_offset(LOC_X_DELTA
);
912 (uchar_t
)LOC_X_ABSOLUTE
;
913 fep
->value
= mi
->mi_x
;
915 fep
->id
= vuid_id_addr(ms
->ms_vuidaddr
) |
916 vuid_id_offset(LOC_X_ABSOLUTE
);
917 fep
->pair_type
= FE_PAIR_DELTA
;
918 fep
->pair
= (uchar_t
)LOC_X_DELTA
;
919 fep
->value
= (mi
->mi_x
*
920 ((usbmsp
->usbms_resolution
).width
) /
921 usbmsp
->usbms_logical_Xmax
);
923 ((usbmsp
->usbms_resolution
).width
) %
924 usbmsp
->usbms_logical_Xmax
) >=
925 (usbmsp
->usbms_logical_Xmax
/ 2)) {
929 fep
->time
= mi
->mi_time
;
931 if (usbmsp
->usbms_resched_id
)
933 (bufcall_id_t
)usbmsp
->usbms_resched_id
);
934 usbmsp
->usbms_resched_id
=
938 (void (*)())usbms_resched
,
940 if (usbmsp
->usbms_resched_id
== 0)
941 /* try again later */
945 * bufcall failed; just
948 /* or maybe flush queue? */
949 ms
->ms_eventstate
= EVENT_WHEEL
;
956 * Callback routine for the qbufcall() in case
957 * of allocb() failure. When buffer becomes
958 * available, this function is called and
962 usbms_resched(void * usbmsp
)
965 register usbms_state_t
*tmp_usbmsp
= (usbms_state_t
*)usbmsp
;
967 tmp_usbmsp
->usbms_resched_id
= 0;
968 if ((q
= tmp_usbmsp
->usbms_rq_ptr
) != 0)
969 qenable(q
); /* run the service procedure */
974 * wput() routine for the mouse module.
975 * Module below : hid, module above : consms
978 usbms_wput(queue_t
*q
,
981 USB_DPRINTF_L3(PRINT_MASK_ALL
, usbms_log_handle
,
982 "usbms_wput entering");
983 switch (mp
->b_datap
->db_type
) {
985 case M_FLUSH
: /* Canonical flush handling */
986 if (*mp
->b_rptr
& FLUSHW
) {
987 flushq(q
, FLUSHDATA
);
990 if (*mp
->b_rptr
& FLUSHR
) {
991 flushq(RD(q
), FLUSHDATA
);
994 putnext(q
, mp
); /* pass it down the line. */
1002 usbms_miocdata(q
, mp
);
1006 putnext(q
, mp
); /* pass it down the line. */
1009 USB_DPRINTF_L3(PRINT_MASK_ALL
, usbms_log_handle
,
1010 "usbms_wput exiting");
1018 * Process ioctls we recognize and own. Otherwise, NAK.
1021 usbms_ioctl(register queue_t
*q
,
1022 register mblk_t
*mp
)
1024 usbms_state_t
*usbmsp
= (usbms_state_t
*)q
->q_ptr
;
1025 register struct ms_softc
*ms
;
1026 register struct iocblk
*iocp
;
1027 Vuid_addr_probe
*addr_probe
;
1028 uint_t ioctlrespsize
;
1031 ushort_t transparent
= 0;
1032 boolean_t report_abs
= B_FALSE
;
1035 USB_DPRINTF_L3(PRINT_MASK_IOCTL
, usbms_log_handle
,
1036 "usbms_ioctl entering");
1038 if (usbmsp
== NULL
) {
1039 miocnak(q
, mp
, 0, EINVAL
);
1043 ms
= &usbmsp
->usbms_softc
;
1045 iocp
= (struct iocblk
*)mp
->b_rptr
;
1046 switch (iocp
->ioc_cmd
) {
1049 err
= miocpullup(mp
, sizeof (int));
1053 if (*(int *)mp
->b_cont
->b_rptr
== ms
->ms_readformat
) {
1056 ms
->ms_readformat
= *(int *)mp
->b_cont
->b_rptr
;
1058 * Flush mouse buffer because the messages upstream of us
1059 * are in the old format.
1062 usbms_flush(usbmsp
);
1066 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
1067 ioctlrespsize
= sizeof (int);
1070 *(int *)datap
->b_wptr
= ms
->ms_readformat
;
1071 datap
->b_wptr
+= sizeof (int);
1072 freemsg(mp
->b_cont
);
1074 iocp
->ioc_count
= sizeof (int);
1079 err
= miocpullup(mp
, sizeof (Vuid_addr_probe
));
1083 addr_probe
= (Vuid_addr_probe
*)mp
->b_cont
->b_rptr
;
1084 if (addr_probe
->base
!= VKEY_FIRST
) {
1088 if (iocp
->ioc_cmd
== VUIDSADDR
)
1089 ms
->ms_vuidaddr
= addr_probe
->data
.next
;
1091 addr_probe
->data
.current
= ms
->ms_vuidaddr
;
1095 if ((datap
= allocb(sizeof (Ms_parms
), BPRI_HI
)) == NULL
) {
1096 ioctlrespsize
= sizeof (Ms_parms
);
1099 err
= usbms_getparms((Ms_parms
*)datap
->b_wptr
, usbmsp
);
1100 datap
->b_wptr
+= sizeof (Ms_parms
);
1101 freemsg(mp
->b_cont
);
1103 iocp
->ioc_count
= sizeof (Ms_parms
);
1107 err
= miocpullup(mp
, sizeof (Ms_parms
));
1110 err
= usbms_setparms((Ms_parms
*)mp
->b_cont
->b_rptr
, usbmsp
);
1114 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
1115 ioctlrespsize
= sizeof (int);
1118 *(int *)datap
->b_wptr
= (int)usbmsp
->usbms_num_buttons
;
1119 datap
->b_wptr
+= sizeof (int);
1120 freemsg(mp
->b_cont
);
1122 iocp
->ioc_count
= sizeof (int);
1125 case VUIDGWHEELCOUNT
:
1127 * New IOCTL support. Since it's explicitly mentioned that
1128 * you can't add more ioctls to stream head's hard coded
1129 * list, we have to do the transparent ioctl processing
1133 /* Currently support for only one wheel */
1135 if (iocp
->ioc_count
== TRANSPARENT
) {
1137 if (err
= usbms_make_copyreq(mp
, 0, 0, sizeof (int),
1143 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
1144 ioctlrespsize
= sizeof (int);
1148 *((int *)datap
->b_wptr
) = (usbmsp
->usbms_num_wheels
? 1 : 0);
1149 datap
->b_wptr
+= sizeof (int);
1151 freemsg(mp
->b_cont
);
1162 case VUIDGWHEELINFO
:
1163 if (iocp
->ioc_count
== TRANSPARENT
) {
1164 if (err
= usbms_make_copyreq(mp
,
1165 sizeof (usbms_iocstate_t
),
1167 sizeof (wheel_info
),
1174 * If there is no b_cont the earlier func. will fail.
1175 * Hence there is no need for an explicit check here.
1177 freemsg(mp
->b_cont
);
1183 if (mp
->b_cont
== NULL
|| iocp
->ioc_count
!=
1184 sizeof (wheel_info
)) {
1189 err
= usbms_service_wheel_info(q
, datap
);
1192 case VUIDGWHEELSTATE
:
1193 if (iocp
->ioc_count
== TRANSPARENT
) {
1194 if (err
= usbms_make_copyreq(mp
,
1195 sizeof (usbms_iocstate_t
),
1197 sizeof (wheel_state
),
1203 freemsg(mp
->b_cont
);
1209 if ((mp
->b_cont
== NULL
) ||
1210 (iocp
->ioc_count
!= sizeof (wheel_state
))) {
1216 err
= usbms_service_wheel_state(q
, datap
, VUIDGWHEELSTATE
);
1219 case VUIDSWHEELSTATE
:
1220 if (iocp
->ioc_count
== TRANSPARENT
) {
1221 if (err
= usbms_make_copyreq(mp
,
1222 sizeof (usbms_iocstate_t
),
1224 sizeof (wheel_state
),
1230 freemsg(mp
->b_cont
);
1236 if (mp
->b_cont
== NULL
) {
1242 err
= usbms_service_wheel_state(q
, datap
, VUIDSWHEELSTATE
);
1245 case MSIOSRESOLUTION
:
1246 if (iocp
->ioc_count
== TRANSPARENT
) {
1247 if (err
= usbms_make_copyreq(mp
,
1248 sizeof (usbms_iocstate_t
),
1250 sizeof (Ms_screen_resolution
),
1257 freemsg(mp
->b_cont
);
1263 if (mp
->b_cont
== NULL
) {
1269 err
= usbms_get_screen_parms(q
, datap
);
1271 * Create the absolute mouse type event.
1272 * It is used for the hotplug absolute mouse.
1274 if ((!((usbmsp
->usbms_idf
).xattr
& HID_MAIN_ITEM_RELATIVE
)) &&
1275 (usbmsp
->usbms_rpt_abs
== B_FALSE
)) {
1276 report_abs
= B_TRUE
;
1282 putnext(q
, mp
); /* pass it down the line */
1288 miocnak(q
, mp
, 0, err
);
1291 iocp
->ioc_error
= 0;
1292 mp
->b_datap
->db_type
= M_IOCACK
;
1295 if (report_abs
== B_TRUE
) {
1296 /* send the abs mouse type event to the upper level */
1297 if ((mb
= usbms_setup_abs_mouse_event()) != NULL
) {
1298 usbmsp
->usbms_rpt_abs
= B_TRUE
;
1308 * We needed to allocate something to handle this "ioctl", but
1309 * couldn't; save this "ioctl" and arrange to get called back when
1310 * it's more likely that we can get what we need.
1311 * If there's already one being saved, throw it out, since it
1312 * must have timed out.
1314 freemsg(usbmsp
->usbms_iocpending
);
1315 usbmsp
->usbms_iocpending
= mp
;
1316 if (usbmsp
->usbms_reioctl_id
) {
1317 qunbufcall(q
, (bufcall_id_t
)usbmsp
->usbms_reioctl_id
);
1319 usbmsp
->usbms_reioctl_id
= qbufcall(q
, ioctlrespsize
, BPRI_HI
,
1320 (void (*)())usbms_reioctl
,
1326 * M_IOCDATA processing for IOCTL's: VUIDGWHEELCOUNT, VUIDGWHEELINFO,
1327 * VUIDGWHEELSTATE, VUIDSWHEELSTATE & MSIOSRESOLUTION.
1330 usbms_miocdata(register queue_t
*q
,
1331 register mblk_t
*mp
)
1333 struct copyresp
*copyresp
;
1334 struct iocblk
*iocbp
;
1337 usbms_iocstate_t
*usbmsioc
;
1340 copyresp
= (struct copyresp
*)mp
->b_rptr
;
1341 iocbp
= (struct iocblk
*)mp
->b_rptr
;
1342 if (copyresp
->cp_rval
) {
1347 switch (copyresp
->cp_cmd
) {
1349 case VUIDGWHEELCOUNT
:
1350 usbms_ack_ioctl(mp
);
1353 case VUIDGWHEELINFO
:
1354 ioctmp
= copyresp
->cp_private
;
1355 usbmsioc
= (usbms_iocstate_t
*)ioctmp
->b_rptr
;
1356 if (usbmsioc
->ioc_state
== USBMS_GETSTRUCT
) {
1357 if (mp
->b_cont
== NULL
) {
1362 datap
= (mblk_t
*)mp
->b_cont
;
1363 if (err
= usbms_service_wheel_info(q
, datap
)) {
1367 if (err
= usbms_make_copyreq(mp
, 0, USBMS_GETRESULT
,
1368 sizeof (wheel_info
), 0, M_COPYOUT
)) {
1372 } else if (usbmsioc
->ioc_state
== USBMS_GETRESULT
) {
1374 usbms_ack_ioctl(mp
);
1378 case VUIDGWHEELSTATE
:
1379 ioctmp
= (mblk_t
*)copyresp
->cp_private
;
1380 usbmsioc
= (usbms_iocstate_t
*)ioctmp
->b_rptr
;
1381 if (usbmsioc
->ioc_state
== USBMS_GETSTRUCT
) {
1382 if (mp
->b_cont
== NULL
) {
1387 if (err
= usbms_service_wheel_state(q
, mp
->b_cont
,
1391 if (err
= usbms_make_copyreq(mp
, 0, USBMS_GETRESULT
,
1392 sizeof (wheel_state
), 0, M_COPYOUT
)) {
1396 } else if (usbmsioc
->ioc_state
== USBMS_GETRESULT
) {
1398 usbms_ack_ioctl(mp
);
1402 case VUIDSWHEELSTATE
:
1403 ioctmp
= (mblk_t
*)copyresp
->cp_private
;
1404 usbmsioc
= (usbms_iocstate_t
*)ioctmp
->b_rptr
;
1405 if (mp
->b_cont
== NULL
) {
1410 if (err
= usbms_service_wheel_state(q
, mp
->b_cont
,
1416 usbms_ack_ioctl(mp
);
1419 case MSIOSRESOLUTION
:
1420 ioctmp
= (mblk_t
*)copyresp
->cp_private
;
1421 usbmsioc
= (usbms_iocstate_t
*)ioctmp
->b_rptr
;
1422 if (mp
->b_cont
== NULL
) {
1427 if (err
= usbms_get_screen_parms(q
, mp
->b_cont
)) {
1432 usbms_ack_ioctl(mp
);
1442 mp
->b_datap
->db_type
= M_IOCNAK
;
1444 freemsg(mp
->b_cont
);
1447 if (copyresp
->cp_private
) {
1448 freemsg((mblk_t
*)copyresp
->cp_private
);
1449 copyresp
->cp_private
= NULL
;
1451 iocbp
->ioc_count
= 0;
1452 iocbp
->ioc_error
= err
;
1460 * This function is set up as call-back function should an ioctl fail.
1461 * It retries the ioctl.
1464 usbms_reioctl(void * usbms_addr
)
1466 usbms_state_t
*usbmsp
= (usbms_state_t
*)usbms_addr
;
1467 register queue_t
*q
;
1468 register mblk_t
*mp
;
1470 q
= usbmsp
->usbms_wq_ptr
;
1471 if ((mp
= usbmsp
->usbms_iocpending
) != NULL
) {
1472 usbmsp
->usbms_iocpending
= NULL
; /* not pending any more */
1478 * usbms_getparms() :
1479 * Called from MSIOGETPARMS ioctl to get the
1480 * current jitter_thesh, speed_law and speed_limit
1484 usbms_getparms(register Ms_parms
*data
,
1485 usbms_state_t
*usbmsp
)
1487 data
->jitter_thresh
= usbmsp
->usbms_jitter_thresh
;
1488 data
->speed_law
= usbmsp
->usbms_speedlaw
;
1489 data
->speed_limit
= usbmsp
->usbms_speedlimit
;
1496 * usbms_setparms() :
1497 * Called from MSIOSETPARMS ioctl to set the
1498 * current jitter_thesh, speed_law and speed_limit
1502 usbms_setparms(register Ms_parms
*data
,
1503 usbms_state_t
*usbmsp
)
1505 usbmsp
->usbms_jitter_thresh
= data
->jitter_thresh
;
1506 usbmsp
->usbms_speedlaw
= data
->speed_law
;
1507 usbmsp
->usbms_speedlimit
= data
->speed_limit
;
1514 * Resets the ms_softc structure to default values
1515 * and sends M_FLUSH above.
1518 usbms_flush(usbms_state_t
*usbmsp
)
1520 register struct ms_softc
*ms
= &usbmsp
->usbms_softc
;
1521 register queue_t
*q
;
1523 USB_DPRINTF_L3(PRINT_MASK_ALL
, usbms_log_handle
,
1524 "usbms_flush entering");
1527 ms
->ms_eventstate
= EVENT_BUT(usbmsp
->usbms_num_buttons
);
1528 usbmsp
->usbms_buf
->mb_off
= 0;
1529 ms
->ms_prevbuttons
= (char)USB_NO_BUT_PRESSED
;
1530 usbmsp
->usbms_oldbutt
= ms
->ms_prevbuttons
;
1531 if ((q
= usbmsp
->usbms_rq_ptr
) != NULL
&& q
->q_next
!= NULL
) {
1532 (void) putnextctl1(q
, M_FLUSH
, FLUSHR
);
1535 USB_DPRINTF_L3(PRINT_MASK_ALL
, usbms_log_handle
,
1536 "usbms_flush exiting");
1542 * Put procedure for input from driver end of stream (read queue).
1545 usbms_rput(queue_t
*q
,
1548 usbms_state_t
*usbmsp
= q
->q_ptr
;
1550 ushort_t limit
= (usbmsp
->usbms_idf
).tlen
;
1552 /* Maintain the original mp */
1556 freemsg(mp
); /* nobody's listening */
1561 switch (mp
->b_datap
->db_type
) {
1564 if (*mp
->b_rptr
& FLUSHW
)
1565 flushq(WR(q
), FLUSHDATA
);
1566 if (*mp
->b_rptr
& FLUSHR
)
1567 flushq(q
, FLUSHDATA
);
1574 * We don't have to handle this
1575 * because nothing is sent from the downstream
1583 if (!(usbmsp
->usbms_flags
& USBMS_OPEN
)) {
1584 freemsg(mp
); /* not ready to listen */
1591 usbms_mctl_receive(q
, mp
);
1596 usbmsp
->usbms_protoerr
= 1;
1597 usbmsp
->usbms_flags
&= ~USBMS_QWAIT
;
1598 if (*mp
->b_rptr
== ENODEV
) {
1612 * A data message, consisting of bytes from the mouse.
1613 * Make sure there are atleast "limit" number of bytes.
1615 if ((MBLKL(tmp_mp
) < limit
) || ((MBLKL(tmp_mp
) == limit
) &&
1616 (usbmsp
->usbms_rptid
!= HID_REPORT_ID_UNDEFINED
))) {
1621 if (usbmsp
->usbms_rptid
!= HID_REPORT_ID_UNDEFINED
) {
1622 if (*(tmp_mp
->b_rptr
) != usbmsp
->usbms_rptid
) {
1627 /* We skip the report id prefix. */
1632 usbms_input(usbmsp
, tmp_mp
);
1633 } while ((tmp_mp
= tmp_mp
->b_cont
) != NULL
); /* next block, if any */
1640 * usbms_mctl_receive() :
1641 * Handle M_CTL messages from hid. If
1642 * we don't understand the command, free message.
1645 usbms_mctl_receive(register queue_t
*q
,
1646 register mblk_t
*mp
)
1648 usbms_state_t
*usbmsd
= (usbms_state_t
*)q
->q_ptr
;
1649 struct iocblk
*iocp
;
1653 iocp
= (struct iocblk
*)mp
->b_rptr
;
1654 if (mp
->b_cont
!= NULL
)
1655 data
= (caddr_t
)mp
->b_cont
->b_rptr
;
1657 switch (iocp
->ioc_cmd
) {
1659 case HID_GET_PARSER_HANDLE
:
1660 if ((data
!= NULL
) &&
1661 (iocp
->ioc_count
== sizeof (hidparser_handle_t
)) &&
1662 (MBLKL(mp
->b_cont
) == iocp
->ioc_count
)) {
1663 usbmsd
->usbms_report_descr_handle
=
1664 *(hidparser_handle_t
*)data
;
1666 usbmsd
->usbms_report_descr_handle
= NULL
;
1669 usbmsd
->usbms_flags
&= ~USBMS_QWAIT
;
1671 case HID_SET_PROTOCOL
:
1672 usbmsd
->usbms_flags
&= ~USBMS_QWAIT
;
1685 * Mouse input routine; process a byte received from a mouse and
1686 * assemble into a mouseinfo message for the window system.
1688 * The USB mouse send a three-byte packet organized as
1690 * where dx and dy can be any signed byte value. The mouseinfo message
1692 * dx, dy, button, timestamp
1693 * Our strategy is to collect but, dx & dy three-byte packet, then
1694 * send the mouseinfo message up.
1696 * Basic algorithm: throw away bytes until we get a [potential]
1697 * button byte. Collect button; Collect dx; Collect dy; Send button,
1698 * dx, dy, timestamp.
1700 * Watch out for overflow!
1703 usbms_input(usbms_state_t
*usbmsp
,
1706 register struct usbmousebuf
*b
;
1707 register struct usbmouseinfo
*mi
;
1708 register int jitter_radius
;
1709 register int32_t nbutt
;
1713 nbutt
= usbmsp
->usbms_num_buttons
;
1714 b
= usbmsp
->usbms_buf
;
1716 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR
, usbms_log_handle
,
1717 "usbms_input entering");
1724 mi
= &b
->mb_info
[b
->mb_off
];
1727 * Lower 3 bits are middle, right, left.
1729 c
= mp
->b_rptr
[(usbmsp
->usbms_idf
).bpos
];
1730 mi
->mi_buttons
= (char)USB_NO_BUT_PRESSED
;
1731 if (c
& USBMS_BUT(1)) { /* left button is pressed */
1732 mi
->mi_buttons
= mi
->mi_buttons
& USB_LEFT_BUT_PRESSED
;
1733 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR
,
1735 "left button pressed");
1737 if (c
& USBMS_BUT(2)) { /* right button is pressed */
1738 mi
->mi_buttons
= mi
->mi_buttons
& USB_RIGHT_BUT_PRESSED
;
1739 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR
,
1741 "right button pressed");
1743 if (c
& USBMS_BUT(3)) { /* middle button is pressed */
1744 mi
->mi_buttons
= mi
->mi_buttons
&
1745 USB_MIDDLE_BUT_PRESSED
;
1746 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR
,
1748 "middle button pressed");
1752 for (i
= 4; i
< (nbutt
+ 1); i
++) {
1753 if (c
& USBMS_BUT(i
)) {
1754 mi
->mi_buttons
= mi
->mi_buttons
&
1756 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR
,
1758 "%d button pressed", i
);
1763 /* get the delta X and Y from the sample */
1764 mi
->mi_x
+= usbms_get_coordinate((usbmsp
->usbms_idf
).xpos
,
1765 (usbmsp
->usbms_idf
).xlen
, mp
);
1767 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR
,
1768 usbms_log_handle
, "x = %d", (int)mi
->mi_x
);
1770 uniqtime32(&mi
->mi_time
); /* record time when sample arrived */
1772 mi
->mi_y
+= usbms_get_coordinate((usbmsp
->usbms_idf
).ypos
,
1773 (usbmsp
->usbms_idf
).ylen
, mp
);
1775 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR
, usbms_log_handle
,
1776 "y = %d", (int)mi
->mi_y
);
1779 * Check the wheel data in the current event.
1780 * If it exists, the wheel data is got from the sample.
1783 if (usbmsp
->usbms_num_wheels
) {
1784 mi
->mi_z
+= usbms_get_coordinate((usbmsp
->usbms_idf
).zpos
,
1785 (usbmsp
->usbms_idf
).zlen
, mp
);
1787 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR
, usbms_log_handle
,
1788 "z = %d", (int)mi
->mi_z
);
1791 if (usbmsp
->usbms_jitter
) {
1792 (void) quntimeout(usbmsp
->usbms_rq_ptr
,
1793 (timeout_id_t
)usbmsp
->usbms_timeout_id
);
1794 usbmsp
->usbms_jitter
= 0;
1797 if (!usbmsp
->usbms_num_wheels
) {
1802 * If there is a wheel movement or a change in the button state,
1803 * send the data up immediately.
1805 if (!(mi
->mi_z
) && (mi
->mi_buttons
== usbmsp
->usbms_oldbutt
)) {
1807 * Buttons did not change; did position?
1809 if (mi
->mi_x
== 0 && mi
->mi_y
== 0) {
1810 /* no, position did not change */
1816 * Did the mouse move more than the jitter threshhold?
1818 jitter_radius
= usbmsp
->usbms_jitter_thresh
;
1819 if (USB_ABS((int)mi
->mi_x
) <= jitter_radius
&&
1820 USB_ABS((int)mi
->mi_y
) <= jitter_radius
) {
1822 * Mouse moved less than the jitter threshhold.
1823 * Don't indicate an event; keep accumulating motions.
1824 * After "jittertimeout" ticks expire, treat
1825 * the accumulated delta as the real delta.
1827 usbmsp
->usbms_jitter
= 1;
1828 usbmsp
->usbms_timeout_id
=
1829 qtimeout(usbmsp
->usbms_rq_ptr
,
1830 (void (*)())usbms_incr
,
1832 (clock_t)usbmsp
->usbms_jittertimeout
);
1837 usbmsp
->usbms_oldbutt
= mi
->mi_buttons
;
1840 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR
, usbms_log_handle
,
1841 "usbms_input exiting");
1846 * usbms_get_coordinate():
1847 * get the X, Y, WHEEL coordinate values
1850 usbms_get_coordinate(uint_t pos
, uint_t len
, mblk_t
*mp
)
1852 uint_t utmp
, bitval
, val
;
1855 /* get the unsigned int value from the bit stream */
1857 for (i
= (pos
+ len
- 1); i
>= (int)pos
; i
--) {
1858 bitval
= (mp
->b_rptr
[i
/8] & (1 << (i
%8))) >> (i
%8);
1859 utmp
= utmp
* 2 + bitval
;
1862 /* convert the unsigned int value into int value */
1863 val
= 1 << (len
- 1);
1864 xyz
= (int)(utmp
- val
);
1878 * Increment the mouse sample pointer.
1879 * Called either immediately after a sample or after a jitter timeout.
1882 usbms_incr(void *arg
)
1884 usbms_state_t
*usbmsp
= arg
;
1885 register struct ms_softc
*ms
= &usbmsp
->usbms_softc
;
1886 register struct usbmousebuf
*b
;
1887 register struct usbmouseinfo
*mi
;
1888 register int xc
, yc
, zc
;
1890 register int speedl
= usbmsp
->usbms_speedlimit
;
1891 register int xabs
, yabs
;
1894 * No longer waiting for jitter timeout
1896 usbmsp
->usbms_jitter
= 0;
1898 b
= usbmsp
->usbms_buf
;
1900 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR
, usbms_log_handle
,
1901 "usbms_incr entering");
1907 mi
= &b
->mb_info
[b
->mb_off
];
1908 if (usbmsp
->usbms_speedlaw
) {
1909 xabs
= USB_ABS((int)mi
->mi_x
);
1910 yabs
= USB_ABS((int)mi
->mi_y
);
1911 if (xabs
> speedl
|| yabs
> speedl
) {
1912 usbmsp
->usbms_speed_count
++;
1914 if (xabs
> speedl
) {
1917 if (yabs
> speedl
) {
1925 /* See if we need to wake up anyone waiting for input */
1926 wake
= b
->mb_off
== ms
->ms_oldoff
;
1928 /* Adjust circular buffer pointer */
1929 if (++b
->mb_off
>= b
->mb_size
) {
1937 * If over-took read index then flush buffer so that mouse state
1940 if (b
->mb_off
== ms
->ms_oldoff
) {
1942 USB_DPRINTF_L1(PRINT_MASK_ALL
, usbms_log_handle
,
1943 "Mouse buffer flushed when overrun.");
1945 usbms_flush(usbmsp
);
1950 /* Remember current buttons and fractional part of x & y */
1951 mi
->mi_buttons
= (char)USB_NO_BUT_PRESSED
;
1957 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR
, usbms_log_handle
,
1958 "usbms_incr run service");
1959 qenable(usbmsp
->usbms_rq_ptr
); /* run the service proc */
1961 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR
, usbms_log_handle
,
1962 "usbms_incr exiting");
1967 * usbms_check_for_wheels
1968 * return SUCCESS if wheel is found, else return FAILURE
1971 usbms_check_for_wheels(usbms_state_t
*usbmsp
)
1973 int rval
, report_id
;
1976 if (usbmsp
->usbms_report_descr_handle
) {
1977 /* Get the report id that has mouse data */
1978 if (hidparser_get_usage_attribute(
1979 usbmsp
->usbms_report_descr_handle
,
1980 0, /* Doesn't matter */
1981 HIDPARSER_ITEM_INPUT
,
1982 HID_GENERIC_DESKTOP
,
1984 HIDPARSER_ITEM_REPORT_ID
,
1985 &usbmsp
->usbms_rptid
) == HIDPARSER_NOT_FOUND
) {
1986 usbmsp
->usbms_rptid
= HID_REPORT_ID_UNDEFINED
;
1989 report_id
= usbmsp
->usbms_rptid
;
1992 /* find no. of wheels in this report */
1993 rval
= hidparser_get_usage_attribute(
1994 usbmsp
->usbms_report_descr_handle
,
1996 HIDPARSER_ITEM_INPUT
,
1997 HID_GENERIC_DESKTOP
,
1999 HIDPARSER_ITEM_REPORT_COUNT
,
2000 &usbmsp
->usbms_num_wheels
);
2001 if (rval
== HIDPARSER_SUCCESS
) {
2003 * Found wheel. By default enable the wheel.
2004 * Currently only enable only the first wheel.
2006 usbmsp
->usbms_wheel_state_bf
|=
2007 VUID_WHEEL_STATE_ENABLED
;
2009 return (USB_SUCCESS
);
2012 usbmsp
->usbms_num_wheels
= 0;
2014 return (USB_FAILURE
);
2019 * usbms_make_copyreq
2020 * helper function for usbms ioctls
2023 usbms_make_copyreq(mblk_t
*mp
,
2032 struct copyresp
*cr
;
2035 usbms_iocstate_t
*usbmsioc
;
2037 if ((!pvtsize
) && state
) {
2038 cr
= (struct copyresp
*)mp
->b_rptr
;
2039 ioctmp
= cr
->cp_private
;
2041 cq
= (struct copyreq
*)mp
->b_rptr
;
2042 if (mp
->b_cont
== NULL
) {
2046 cq
->cq_addr
= *((caddr_t
*)mp
->b_cont
->b_rptr
);
2047 cq
->cq_size
= reqsize
;
2050 ioctmp
= (mblk_t
*)allocb(pvtsize
, BPRI_MED
);
2051 if (ioctmp
== NULL
) {
2055 cq
->cq_private
= ioctmp
;
2056 ioctmp
= cq
->cq_private
;
2059 * Here we need to set cq_private even if there's
2060 * no private data, otherwise its value will be
2061 * TRANSPARENT (-1) on 64bit systems because it
2062 * overlaps iocp->ioc_count. If user address (cq_addr)
2063 * is invalid, it would cause panic later in
2065 * freemsg((mblk_t *)copyresp->cp_private);
2067 cq
->cq_private
= NULL
;
2070 usbmsioc
= (usbms_iocstate_t
*)ioctmp
->b_rptr
;
2071 usbmsioc
->ioc_state
= state
;
2072 if (pvtsize
) { /* M_COPYIN */
2073 usbmsioc
->u_addr
= cq
->cq_addr
;
2075 cq
->cq_addr
= usbmsioc
->u_addr
;
2076 cq
->cq_private
= ioctmp
;
2078 ioctmp
->b_wptr
= ioctmp
->b_rptr
+ sizeof (usbms_iocstate_t
);
2081 conttmp
= (mblk_t
*)allocb(contsize
, BPRI_MED
);
2082 if (conttmp
== NULL
) {
2087 freemsg(mp
->b_cont
);
2088 mp
->b_cont
= conttmp
;
2091 mp
->b_datap
->db_type
= (unsigned char)copytype
;
2092 mp
->b_wptr
= mp
->b_rptr
+ sizeof (struct copyreq
);
2094 return (USB_SUCCESS
);
2099 usbms_service_wheel_info(register queue_t
*q
, register mblk_t
*datap
)
2103 usbms_state_t
*usbmsp
= (usbms_state_t
*)q
->q_ptr
;
2106 wi
= (wheel_info
*)datap
->b_rptr
;
2107 if (wi
->vers
!= VUID_WHEEL_INFO_VERS
) {
2112 if (wi
->id
> (usbmsp
->usbms_num_wheels
- 1)) {
2117 wi
->format
= (usbmsp
->usbms_wheel_orient_bf
& (1 << wi
->id
)) ?
2118 VUID_WHEEL_FORMAT_HORIZONTAL
: VUID_WHEEL_FORMAT_VERTICAL
;
2120 return (USB_SUCCESS
);
2125 usbms_service_wheel_state(register queue_t
*q
,
2126 register mblk_t
*datap
,
2127 register uint_t cmd
)
2132 usbms_state_t
*usbmsp
= (usbms_state_t
*)q
->q_ptr
;
2134 ws
= (wheel_state
*)datap
->b_rptr
;
2135 if (ws
->vers
!= VUID_WHEEL_STATE_VERS
) {
2140 if (ws
->id
> (usbmsp
->usbms_num_wheels
- 1)) {
2147 case VUIDGWHEELSTATE
:
2148 ws
->stateflags
= (usbmsp
->usbms_wheel_state_bf
>> ws
->id
) &
2149 VUID_WHEEL_STATE_ENABLED
;
2152 case VUIDSWHEELSTATE
:
2153 usbmsp
->usbms_wheel_state_bf
= (ws
->stateflags
<< ws
->id
) |
2154 (~(1 << ws
->id
) & usbmsp
->usbms_wheel_state_bf
);
2163 return (USB_SUCCESS
);
2168 * usbms_get_screen_parms() :
2169 * Called from MSIOSRESOLUTION ioctl to get the
2170 * current screen height/width params from X.
2173 usbms_get_screen_parms(register queue_t
*q
,
2174 register mblk_t
*datap
)
2177 usbms_state_t
*usbmsp
= (usbms_state_t
*)q
->q_ptr
;
2178 Ms_screen_resolution
*res
= &(usbmsp
->usbms_resolution
);
2179 Ms_screen_resolution
*data
;
2181 data
= (Ms_screen_resolution
*)datap
->b_rptr
;
2182 res
->height
= data
->height
;
2183 res
->width
= data
->width
;
2185 return (USB_SUCCESS
);
2190 usbms_ack_ioctl(mblk_t
*mp
)
2193 struct iocblk
*iocbp
= (struct iocblk
*)mp
->b_rptr
;
2195 mp
->b_datap
->db_type
= M_IOCACK
;
2196 mp
->b_wptr
= mp
->b_rptr
+ sizeof (struct iocblk
);
2197 iocbp
->ioc_error
= 0;
2198 iocbp
->ioc_count
= 0;
2199 iocbp
->ioc_rval
= 0;
2200 if (mp
->b_cont
!= NULL
) {
2201 freemsg(mp
->b_cont
);
2208 * usbms_setup_abs_mouse_event() :
2209 * Called from MSIOSRESOLUTION ioctl to create
2210 * the absolute mouse type firm event.
2213 usbms_setup_abs_mouse_event()
2218 if ((mb
= allocb(sizeof (Firm_event
), BPRI_HI
)) != NULL
) {
2219 fep
= (Firm_event
*)mb
->b_wptr
;
2220 fep
->id
= MOUSE_TYPE_ABSOLUTE
;
2221 fep
->pair_type
= FE_PAIR_NONE
;
2224 mb
->b_wptr
+= sizeof (Firm_event
);
2226 USB_DPRINTF_L3(PRINT_MASK_ALL
, usbms_log_handle
,
2227 "No resource to report ABS mouse event");
2235 * usbms_read_input_data_format() :
2236 * Get the mouse packet length and usages' length.
2237 * Check whether X and Y are relative or absolute.
2239 * If they are absolute, the X and Y logical max values
2240 * will be got. A firm event will be created and sent
2241 * to the upper level.
2244 usbms_read_input_data_format(usbms_state_t
*usbmsp
)
2247 hidparser_rpt_t
*ms_rpt
;
2248 uint_t i
, button_page
;
2250 uint32_t rptcnt
, rptsz
;
2251 usbms_idf
*idf
= &(usbmsp
->usbms_idf
);
2252 Ms_screen_resolution
*res
= &(usbmsp
->usbms_resolution
);
2254 register queue_t
*q
;
2257 usbmsp
->usbms_rpt_abs
= B_FALSE
;
2259 /* allocate hidparser report structure */
2260 ms_rpt
= kmem_zalloc(sizeof (hidparser_rpt_t
), KM_SLEEP
);
2263 * Check what is the total length of the mouse packet
2264 * and get the usages and their lengths in order
2267 rval
= hidparser_get_usage_list_in_order(
2268 usbmsp
->usbms_report_descr_handle
,
2269 usbmsp
->usbms_rptid
,
2270 HIDPARSER_ITEM_INPUT
,
2273 if (rval
!= HIDPARSER_SUCCESS
) {
2275 kmem_free(ms_rpt
, sizeof (hidparser_rpt_t
));
2276 return (USB_FAILURE
);
2280 for (i
= 0; i
< ms_rpt
->no_of_usages
; i
++) {
2281 rptcnt
= ms_rpt
->usage_descr
[i
].rptcnt
;
2282 rptsz
= ms_rpt
->usage_descr
[i
].rptsz
;
2283 if ((ms_rpt
->usage_descr
[i
].usage_page
==
2284 HID_BUTTON_PAGE
) && (!button_page
)) {
2286 limit
+= (rptcnt
* rptsz
);
2291 switch (ms_rpt
->usage_descr
[i
].usage_id
) {
2305 * z-axis not yet supported, just skip it.
2307 * It would be ideal if the HID_GD_Z data would be
2308 * reported as horizontal wheel, and HID_GD_WHEEL
2309 * as vertical wheel.
2311 * We can not use the default case, because
2312 * that skips rptcnt*rptsz, but for an
2313 * "Apple Might Mouse" rptsz must be used.
2323 limit
+= rptcnt
* rptsz
;
2328 kmem_free(ms_rpt
, sizeof (hidparser_rpt_t
));
2330 /* get the length of sending data */
2331 idf
->tlen
= limit
/ 8;
2333 /* Check whether X and Y are relative or absolute */
2334 rval
= hidparser_get_main_item_data_descr(
2335 usbmsp
->usbms_report_descr_handle
,
2336 usbmsp
->usbms_rptid
,
2337 HIDPARSER_ITEM_INPUT
,
2338 HID_GENERIC_DESKTOP
,
2342 if (rval
!= HIDPARSER_SUCCESS
) {
2344 return (USB_FAILURE
);
2347 /* For the time being assume that Y also has the same attr */
2348 idf
->yattr
= idf
->xattr
;
2350 /* get the logical_maximum for X and Y respectively */
2351 if (!(idf
->xattr
& HID_MAIN_ITEM_RELATIVE
)) {
2353 /* the data format can't be parsed correctly */
2355 USB_DPRINTF_L3(PRINT_MASK_ALL
, usbms_log_handle
,
2356 "Wrong data packet include %d bits", limit
);
2358 return (USB_FAILURE
);
2360 if (hidparser_get_usage_attribute(
2361 usbmsp
->usbms_report_descr_handle
,
2362 usbmsp
->usbms_rptid
,
2363 HIDPARSER_ITEM_INPUT
,
2364 HID_GENERIC_DESKTOP
,
2366 HIDPARSER_ITEM_LOGICAL_MAXIMUM
,
2367 &usbmsp
->usbms_logical_Xmax
) != HIDPARSER_SUCCESS
) {
2369 USB_DPRINTF_L3(PRINT_MASK_ALL
, usbms_log_handle
,
2370 "fail to get X logical max.");
2372 return (USB_FAILURE
);
2374 if (hidparser_get_usage_attribute(
2375 usbmsp
->usbms_report_descr_handle
,
2376 usbmsp
->usbms_rptid
,
2377 HIDPARSER_ITEM_INPUT
,
2378 HID_GENERIC_DESKTOP
,
2380 HIDPARSER_ITEM_LOGICAL_MAXIMUM
,
2381 &usbmsp
->usbms_logical_Ymax
) != HIDPARSER_SUCCESS
) {
2383 USB_DPRINTF_L3(PRINT_MASK_ALL
, usbms_log_handle
,
2384 "fail to get Y logical max.");
2386 return (USB_FAILURE
);
2389 if (usbmsp
->usbms_logical_Xmax
== 0) {
2390 USB_DPRINTF_L3(PRINT_MASK_ALL
,
2392 "X logical max value is zero");
2394 return (USB_FAILURE
);
2397 if (usbmsp
->usbms_logical_Ymax
== 0) {
2398 USB_DPRINTF_L3(PRINT_MASK_ALL
,
2400 "Y logical max value is zero");
2402 return (USB_FAILURE
);
2405 res
->height
= USBMS_DEFAULT_RES_HEIGHT
;
2406 res
->width
= USBMS_DEFAULT_RES_WIDTH
;
2408 /* The wheel is not supported in current remote kvms. */
2409 usbmsp
->usbms_num_wheels
= 0;
2410 q
= usbmsp
->usbms_rq_ptr
;
2411 if ((mb
= usbms_setup_abs_mouse_event()) != NULL
) {
2415 return (USB_NO_RESOURCES
);
2419 return (USB_SUCCESS
);