10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51584Sdanmcd * Common Development and Distribution License (the "License").
61584Sdanmcd * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*12425SFei.Feng@Sun.COM * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <sys/usb/usba/usbai_version.h>
270Sstevel@tonic-gate #include <sys/usb/usba.h>
280Sstevel@tonic-gate #include <sys/usb/clients/hid/hid.h>
290Sstevel@tonic-gate #include <sys/usb/clients/hidparser/hidparser.h>
300Sstevel@tonic-gate
310Sstevel@tonic-gate #include <sys/stropts.h>
320Sstevel@tonic-gate #include <sys/strsun.h>
330Sstevel@tonic-gate #include <sys/vuid_event.h>
340Sstevel@tonic-gate #include <sys/vuid_wheel.h>
350Sstevel@tonic-gate #include <sys/termios.h>
360Sstevel@tonic-gate #include <sys/termio.h>
370Sstevel@tonic-gate #include <sys/strtty.h>
380Sstevel@tonic-gate #include <sys/msreg.h>
390Sstevel@tonic-gate #include <sys/msio.h>
400Sstevel@tonic-gate
410Sstevel@tonic-gate #include <sys/usb/clients/usbms/usbms.h>
420Sstevel@tonic-gate
430Sstevel@tonic-gate /* debugging information */
44880Sfrits uint_t usbms_errmask = (uint_t)PRINT_MASK_ALL;
45880Sfrits uint_t usbms_errlevel = USB_LOG_L2;
460Sstevel@tonic-gate static usb_log_handle_t usbms_log_handle;
470Sstevel@tonic-gate
480Sstevel@tonic-gate static struct streamtab usbms_streamtab;
490Sstevel@tonic-gate
500Sstevel@tonic-gate static struct fmodsw fsw = {
510Sstevel@tonic-gate "usbms",
520Sstevel@tonic-gate &usbms_streamtab,
530Sstevel@tonic-gate D_MP | D_MTPERMOD
540Sstevel@tonic-gate };
550Sstevel@tonic-gate
560Sstevel@tonic-gate /*
570Sstevel@tonic-gate * Module linkage information for the kernel.
580Sstevel@tonic-gate */
590Sstevel@tonic-gate static struct modlstrmod modlstrmod = {
600Sstevel@tonic-gate &mod_strmodops,
617425SGongtian.Zhao@Sun.COM "USB mouse streams",
620Sstevel@tonic-gate &fsw
630Sstevel@tonic-gate };
640Sstevel@tonic-gate
650Sstevel@tonic-gate static struct modlinkage modlinkage = {
660Sstevel@tonic-gate MODREV_1,
670Sstevel@tonic-gate (void *)&modlstrmod,
680Sstevel@tonic-gate NULL
690Sstevel@tonic-gate };
700Sstevel@tonic-gate
710Sstevel@tonic-gate
720Sstevel@tonic-gate int
_init(void)730Sstevel@tonic-gate _init(void)
740Sstevel@tonic-gate {
750Sstevel@tonic-gate int rval = mod_install(&modlinkage);
760Sstevel@tonic-gate
770Sstevel@tonic-gate if (rval == 0) {
780Sstevel@tonic-gate usbms_log_handle = usb_alloc_log_hdl(NULL, "usbms",
796710Syz224750 &usbms_errlevel, &usbms_errmask, NULL, 0);
800Sstevel@tonic-gate }
810Sstevel@tonic-gate
820Sstevel@tonic-gate return (rval);
830Sstevel@tonic-gate }
840Sstevel@tonic-gate
850Sstevel@tonic-gate int
_fini(void)860Sstevel@tonic-gate _fini(void)
870Sstevel@tonic-gate {
880Sstevel@tonic-gate int rval = mod_remove(&modlinkage);
890Sstevel@tonic-gate
900Sstevel@tonic-gate if (rval == 0) {
910Sstevel@tonic-gate usb_free_log_hdl(usbms_log_handle);
920Sstevel@tonic-gate }
930Sstevel@tonic-gate
940Sstevel@tonic-gate return (rval);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate
970Sstevel@tonic-gate
980Sstevel@tonic-gate int
_info(struct modinfo * modinfop)990Sstevel@tonic-gate _info(struct modinfo *modinfop)
1000Sstevel@tonic-gate {
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate /* Function prototypes */
1070Sstevel@tonic-gate static void usbms_reioctl(void *);
1080Sstevel@tonic-gate static void usbms_ioctl(queue_t *, mblk_t *);
1090Sstevel@tonic-gate static int usbms_open();
1100Sstevel@tonic-gate static int usbms_close();
1110Sstevel@tonic-gate static int usbms_wput();
1120Sstevel@tonic-gate static void usbms_rput();
1130Sstevel@tonic-gate static void usbms_mctl_receive(
1140Sstevel@tonic-gate register queue_t *q,
1150Sstevel@tonic-gate register mblk_t *mp);
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate static void usbms_rserv(queue_t *q);
1180Sstevel@tonic-gate static void usbms_miocdata(
1190Sstevel@tonic-gate register queue_t *q,
1200Sstevel@tonic-gate register mblk_t *mp);
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate static void usbms_resched(void *);
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate static int usbms_getparms(
1250Sstevel@tonic-gate register Ms_parms *data,
1260Sstevel@tonic-gate usbms_state_t *usbmsp);
1270Sstevel@tonic-gate
1280Sstevel@tonic-gate static int usbms_setparms(
1290Sstevel@tonic-gate register Ms_parms *data,
1300Sstevel@tonic-gate usbms_state_t *usbmsp);
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate static int usbms_get_screen_parms(
1330Sstevel@tonic-gate register queue_t *q,
1340Sstevel@tonic-gate register mblk_t *datap);
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate static void usbms_flush(usbms_state_t *usbmsp);
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate static void usbms_incr(void *);
1390Sstevel@tonic-gate static void usbms_input(
1400Sstevel@tonic-gate usbms_state_t *usbmsp,
1410Sstevel@tonic-gate mblk_t *mp);
1420Sstevel@tonic-gate static void usbms_rserv_vuid_button(
1430Sstevel@tonic-gate queue_t *q,
1440Sstevel@tonic-gate struct usbmouseinfo *mi,
1450Sstevel@tonic-gate mblk_t **bpaddr);
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate static void usbms_rserv_vuid_event_y(
1480Sstevel@tonic-gate queue_t *q,
1490Sstevel@tonic-gate struct usbmouseinfo *mi,
1500Sstevel@tonic-gate mblk_t **bpaddr);
1510Sstevel@tonic-gate static void usbms_rserv_vuid_event_x(
1520Sstevel@tonic-gate queue_t *q,
1530Sstevel@tonic-gate struct usbmouseinfo *mi,
1540Sstevel@tonic-gate mblk_t **bpaddr);
1550Sstevel@tonic-gate static void usbms_rserv_vuid_event_wheel(
1560Sstevel@tonic-gate queue_t *,
1570Sstevel@tonic-gate struct usbmouseinfo *,
1580Sstevel@tonic-gate mblk_t **,
1590Sstevel@tonic-gate ushort_t id);
1600Sstevel@tonic-gate static int usbms_check_for_wheels(usbms_state_t *);
1610Sstevel@tonic-gate static int usbms_make_copyreq(
1620Sstevel@tonic-gate mblk_t *,
1630Sstevel@tonic-gate uint_t pvtsize,
1640Sstevel@tonic-gate uint_t state,
1650Sstevel@tonic-gate uint_t reqsize,
1660Sstevel@tonic-gate uint_t contsize,
1670Sstevel@tonic-gate uint_t copytype);
1680Sstevel@tonic-gate static int usbms_service_wheel_info(
1690Sstevel@tonic-gate queue_t *,
1700Sstevel@tonic-gate mblk_t *);
1710Sstevel@tonic-gate static int usbms_service_wheel_state(
1720Sstevel@tonic-gate queue_t *,
1730Sstevel@tonic-gate mblk_t *,
1740Sstevel@tonic-gate uint_t cmd);
1750Sstevel@tonic-gate static void usbms_ack_ioctl(mblk_t *);
1760Sstevel@tonic-gate static int usbms_read_input_data_format(usbms_state_t *);
1771662Sqz150045 static mblk_t *usbms_setup_abs_mouse_event();
1781418Sqz150045 static int usbms_get_coordinate(
1791418Sqz150045 uint_t pos,
1801418Sqz150045 uint_t len,
1811418Sqz150045 mblk_t *mp);
1820Sstevel@tonic-gate extern void uniqtime32();
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate /*
1850Sstevel@tonic-gate * Device driver qinit functions
1860Sstevel@tonic-gate */
1870Sstevel@tonic-gate static struct module_info usbms_mod_info = {
1880Sstevel@tonic-gate 0x0ffff, /* module id number */
1890Sstevel@tonic-gate "usbms", /* module name */
1900Sstevel@tonic-gate 0, /* min packet size accepted */
1910Sstevel@tonic-gate INFPSZ, /* max packet size accepted */
1920Sstevel@tonic-gate 512, /* hi-water mark */
1930Sstevel@tonic-gate 128 /* lo-water mark */
1940Sstevel@tonic-gate };
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate /* read side queue information structure */
1970Sstevel@tonic-gate static struct qinit rinit = {
1980Sstevel@tonic-gate (int (*)())usbms_rput, /* put procedure not needed */
1990Sstevel@tonic-gate (int (*)())usbms_rserv, /* service procedure */
2000Sstevel@tonic-gate usbms_open, /* called on startup */
2010Sstevel@tonic-gate usbms_close, /* called on finish */
2020Sstevel@tonic-gate NULL, /* for future use */
2030Sstevel@tonic-gate &usbms_mod_info, /* module information structure */
2040Sstevel@tonic-gate NULL /* module statistics structure */
2050Sstevel@tonic-gate };
2060Sstevel@tonic-gate
2070Sstevel@tonic-gate /* write side queue information structure */
2080Sstevel@tonic-gate static struct qinit winit = {
2090Sstevel@tonic-gate usbms_wput, /* put procedure */
2100Sstevel@tonic-gate NULL, /* no service proecedure needed */
2110Sstevel@tonic-gate NULL, /* open not used on write side */
2120Sstevel@tonic-gate NULL, /* close not used on write side */
2130Sstevel@tonic-gate NULL, /* for future use */
2140Sstevel@tonic-gate &usbms_mod_info, /* module information structure */
2150Sstevel@tonic-gate NULL /* module statistics structure */
2160Sstevel@tonic-gate };
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate static struct streamtab usbms_streamtab = {
2190Sstevel@tonic-gate &rinit,
2200Sstevel@tonic-gate &winit,
2210Sstevel@tonic-gate NULL, /* not a MUX */
2220Sstevel@tonic-gate NULL /* not a MUX */
2230Sstevel@tonic-gate };
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate /*
2260Sstevel@tonic-gate * Message when overrun circular buffer
2270Sstevel@tonic-gate */
2280Sstevel@tonic-gate static int overrun_msg;
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate /* Increment when overrun circular buffer */
2310Sstevel@tonic-gate static int overrun_cnt;
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate extern int hz;
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate /*
2360Sstevel@tonic-gate * Mouse buffer size in bytes. Place here as variable so that one could
2370Sstevel@tonic-gate * massage it using adb if it turns out to be too small.
2380Sstevel@tonic-gate */
2390Sstevel@tonic-gate static uint16_t usbms_buf_bytes = USBMS_BUF_BYTES;
2400Sstevel@tonic-gate
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate /*
2430Sstevel@tonic-gate * Regular STREAMS Entry points
2440Sstevel@tonic-gate */
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate /*
2470Sstevel@tonic-gate * usbms_open() :
2480Sstevel@tonic-gate * open() entry point for the USB mouse module.
2490Sstevel@tonic-gate */
2500Sstevel@tonic-gate /*ARGSUSED*/
2510Sstevel@tonic-gate static int
usbms_open(queue_t * q,dev_t * devp,int flag,int sflag,cred_t * credp)2520Sstevel@tonic-gate usbms_open(queue_t *q,
2530Sstevel@tonic-gate dev_t *devp,
2540Sstevel@tonic-gate int flag,
2550Sstevel@tonic-gate int sflag,
2560Sstevel@tonic-gate cred_t *credp)
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate {
2590Sstevel@tonic-gate register struct usbmousebuf *mousebufp;
2600Sstevel@tonic-gate register struct ms_softc *msd_soft;
2610Sstevel@tonic-gate usbms_state_t *usbmsp;
2620Sstevel@tonic-gate struct iocblk mctlmsg;
2630Sstevel@tonic-gate mblk_t *mctl_ptr;
2640Sstevel@tonic-gate
2650Sstevel@tonic-gate
2660Sstevel@tonic-gate /* Clone opens are not allowed */
2670Sstevel@tonic-gate if (sflag != MODOPEN)
2680Sstevel@tonic-gate return (EINVAL);
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate /* If the module is already open, just return */
2710Sstevel@tonic-gate if (q->q_ptr) {
2720Sstevel@tonic-gate return (0);
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate
2750Sstevel@tonic-gate /* allocate usbms state structure */
2760Sstevel@tonic-gate usbmsp = kmem_zalloc(sizeof (usbms_state_t), KM_SLEEP);
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate q->q_ptr = usbmsp;
2790Sstevel@tonic-gate WR(q)->q_ptr = usbmsp;
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate usbmsp->usbms_rq_ptr = q;
2820Sstevel@tonic-gate usbmsp->usbms_wq_ptr = WR(q);
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate qprocson(q);
2850Sstevel@tonic-gate
2860Sstevel@tonic-gate /*
2870Sstevel@tonic-gate * Set up private data.
2880Sstevel@tonic-gate */
2890Sstevel@tonic-gate usbmsp->usbms_state = USBMS_WAIT_BUTN;
2900Sstevel@tonic-gate usbmsp->usbms_iocpending = NULL;
2910Sstevel@tonic-gate usbmsp->usbms_jitter_thresh = USBMS_JITTER_THRESH;
2920Sstevel@tonic-gate usbmsp->usbms_speedlimit = USBMS_SPEEDLIMIT;
2930Sstevel@tonic-gate usbmsp->usbms_speedlaw = USBMS_SPEEDLAW;
2940Sstevel@tonic-gate usbmsp->usbms_speed_count = USBMS_SPEED_COUNT;
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate msd_soft = &usbmsp->usbms_softc;
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate /*
2990Sstevel@tonic-gate * Initially set the format to MS_VUID_FORMAT
3000Sstevel@tonic-gate */
3010Sstevel@tonic-gate msd_soft->ms_readformat = MS_VUID_FORMAT;
3020Sstevel@tonic-gate
3030Sstevel@tonic-gate /*
3040Sstevel@tonic-gate * Allocate buffer and initialize data.
3050Sstevel@tonic-gate */
3060Sstevel@tonic-gate msd_soft->ms_bufbytes = usbms_buf_bytes;
3070Sstevel@tonic-gate mousebufp = kmem_zalloc((uint_t)msd_soft->ms_bufbytes,
3080Sstevel@tonic-gate KM_SLEEP);
3090Sstevel@tonic-gate
3100Sstevel@tonic-gate /* Truncation will happen */
3110Sstevel@tonic-gate mousebufp->mb_size = (uint16_t)((msd_soft->ms_bufbytes -
3120Sstevel@tonic-gate sizeof (struct usbmousebuf)) /
3130Sstevel@tonic-gate sizeof (struct usbmouseinfo));
3140Sstevel@tonic-gate mousebufp->mb_info = (struct usbmouseinfo *)((char *)mousebufp +
3150Sstevel@tonic-gate sizeof (struct usbmousebuf));
3160Sstevel@tonic-gate usbmsp->usbms_buf = mousebufp;
3170Sstevel@tonic-gate msd_soft->ms_vuidaddr = VKEY_FIRST;
3180Sstevel@tonic-gate usbmsp->usbms_jittertimeout = JITTER_TIMEOUT;
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate /* request hid report descriptor from HID */
3210Sstevel@tonic-gate mctlmsg.ioc_cmd = HID_GET_PARSER_HANDLE;
3220Sstevel@tonic-gate mctlmsg.ioc_count = 0;
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0);
3250Sstevel@tonic-gate if (mctl_ptr == NULL) {
3260Sstevel@tonic-gate qprocsoff(q);
3270Sstevel@tonic-gate kmem_free(usbmsp->usbms_buf, msd_soft->ms_bufbytes);
3280Sstevel@tonic-gate kmem_free(usbmsp, sizeof (usbms_state_t));
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate return (ENOMEM);
3310Sstevel@tonic-gate }
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate usbmsp->usbms_flags |= USBMS_QWAIT;
3340Sstevel@tonic-gate putnext(usbmsp->usbms_wq_ptr, mctl_ptr);
3350Sstevel@tonic-gate
3360Sstevel@tonic-gate /*
3370Sstevel@tonic-gate * Now that signal has been sent, wait for report descriptor. Cleanup
3380Sstevel@tonic-gate * if user signals in the mean time (as when this gets opened in an
3390Sstevel@tonic-gate * inappropriate context and the user types a ^C).
3400Sstevel@tonic-gate */
3410Sstevel@tonic-gate while (usbmsp->usbms_flags & USBMS_QWAIT) {
3420Sstevel@tonic-gate
3430Sstevel@tonic-gate if (qwait_sig(q) == 0) {
3440Sstevel@tonic-gate qprocsoff(q);
3450Sstevel@tonic-gate kmem_free(usbmsp->usbms_buf, msd_soft->ms_bufbytes);
3460Sstevel@tonic-gate kmem_free(usbmsp, sizeof (usbms_state_t));
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate return (EINTR);
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate }
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate if (usbmsp->usbms_report_descr_handle != NULL) {
3530Sstevel@tonic-gate if (hidparser_get_usage_attribute(
3540Sstevel@tonic-gate usbmsp->usbms_report_descr_handle,
3550Sstevel@tonic-gate 0,
3560Sstevel@tonic-gate HIDPARSER_ITEM_INPUT,
3570Sstevel@tonic-gate USBMS_USAGE_PAGE_BUTTON,
3580Sstevel@tonic-gate 0,
3590Sstevel@tonic-gate HIDPARSER_ITEM_REPORT_COUNT,
3600Sstevel@tonic-gate (int32_t *)&usbmsp->usbms_num_buttons) ==
3610Sstevel@tonic-gate HIDPARSER_SUCCESS) {
3621418Sqz150045 if (usbmsp->usbms_num_buttons > USB_MS_MAX_BUTTON_NO)
3631418Sqz150045 usbmsp->usbms_num_buttons =
3641418Sqz150045 USB_MS_MAX_BUTTON_NO;
3650Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL,
3660Sstevel@tonic-gate usbms_log_handle, "Num of buttons is : %d",
3670Sstevel@tonic-gate usbmsp->usbms_num_buttons);
3680Sstevel@tonic-gate } else {
3690Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN,
3700Sstevel@tonic-gate usbms_log_handle,
3710Sstevel@tonic-gate "hidparser_get_usage_attribute failed : "
3720Sstevel@tonic-gate "Set to default number of buttons(3).");
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate usbmsp->usbms_num_buttons = USB_MS_DEFAULT_BUTTON_NO;
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate } else {
3770Sstevel@tonic-gate USB_DPRINTF_L1(PRINT_MASK_ALL,
378978Sfrits usbms_log_handle, "Invalid HID "
3790Sstevel@tonic-gate "Descriptor Tree. Set to default value(3 buttons).");
3800Sstevel@tonic-gate usbmsp->usbms_num_buttons = USB_MS_DEFAULT_BUTTON_NO;
3810Sstevel@tonic-gate }
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate /* check if this mouse has wheel */
3840Sstevel@tonic-gate if (usbms_check_for_wheels(usbmsp) == USB_FAILURE) {
3850Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbms_log_handle,
3860Sstevel@tonic-gate "No wheels detected");
3870Sstevel@tonic-gate } else {
3880Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbms_log_handle,
3890Sstevel@tonic-gate "Wheel detected");
3900Sstevel@tonic-gate }
3910Sstevel@tonic-gate
3920Sstevel@tonic-gate usbms_flush(usbmsp);
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate /* get the data format from the hid descriptor */
3950Sstevel@tonic-gate if (usbms_read_input_data_format(usbmsp) != USB_SUCCESS) {
3960Sstevel@tonic-gate
3970Sstevel@tonic-gate qprocsoff(q);
3980Sstevel@tonic-gate kmem_free(usbmsp->usbms_buf, msd_soft->ms_bufbytes);
3990Sstevel@tonic-gate kmem_free(usbmsp, sizeof (usbms_state_t));
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate return (EINVAL);
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate
4040Sstevel@tonic-gate usbmsp->usbms_flags |= USBMS_OPEN;
4050Sstevel@tonic-gate
4060Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_OPEN, usbms_log_handle,
4070Sstevel@tonic-gate "usbms_open exiting");
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate return (0);
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate /*
4140Sstevel@tonic-gate * usbms_close() :
4150Sstevel@tonic-gate * close() entry point for the USB mouse module.
4160Sstevel@tonic-gate */
4170Sstevel@tonic-gate /*ARGSUSED*/
4180Sstevel@tonic-gate static int
usbms_close(queue_t * q,int flag,cred_t * credp)4190Sstevel@tonic-gate usbms_close(queue_t *q,
4200Sstevel@tonic-gate int flag,
4210Sstevel@tonic-gate cred_t *credp)
4220Sstevel@tonic-gate {
4230Sstevel@tonic-gate usbms_state_t *usbmsp = q->q_ptr;
4240Sstevel@tonic-gate register struct ms_softc *ms = &usbmsp->usbms_softc;
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_CLOSE, usbms_log_handle,
4276710Syz224750 "usbms_close entering");
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate qprocsoff(q);
4300Sstevel@tonic-gate
4310Sstevel@tonic-gate if (usbmsp->usbms_jitter) {
4320Sstevel@tonic-gate (void) quntimeout(q,
4336710Syz224750 (timeout_id_t)(long)usbmsp->usbms_timeout_id);
4340Sstevel@tonic-gate usbmsp->usbms_jitter = 0;
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate if (usbmsp->usbms_reioctl_id) {
4370Sstevel@tonic-gate qunbufcall(q, (bufcall_id_t)(long)usbmsp->usbms_reioctl_id);
4380Sstevel@tonic-gate usbmsp->usbms_reioctl_id = 0;
4390Sstevel@tonic-gate }
4400Sstevel@tonic-gate if (usbmsp->usbms_resched_id) {
4410Sstevel@tonic-gate qunbufcall(q, (bufcall_id_t)usbmsp->usbms_resched_id);
4420Sstevel@tonic-gate usbmsp->usbms_resched_id = 0;
4430Sstevel@tonic-gate }
4440Sstevel@tonic-gate if (usbmsp->usbms_iocpending != NULL) {
4450Sstevel@tonic-gate /*
4460Sstevel@tonic-gate * We were holding an "ioctl" response pending the
4470Sstevel@tonic-gate * availability of an "mblk" to hold data to be passed up;
4480Sstevel@tonic-gate * another "ioctl" came through, which means that "ioctl"
4490Sstevel@tonic-gate * must have timed out or been aborted.
4500Sstevel@tonic-gate */
4510Sstevel@tonic-gate freemsg(usbmsp->usbms_iocpending);
4520Sstevel@tonic-gate usbmsp->usbms_iocpending = NULL;
4530Sstevel@tonic-gate }
4540Sstevel@tonic-gate
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate /* Free mouse buffer */
4570Sstevel@tonic-gate if (usbmsp->usbms_buf != NULL) {
4580Sstevel@tonic-gate kmem_free(usbmsp->usbms_buf, ms->ms_bufbytes);
4590Sstevel@tonic-gate }
4600Sstevel@tonic-gate
4610Sstevel@tonic-gate kmem_free(usbmsp, sizeof (usbms_state_t));
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate q->q_ptr = NULL;
4640Sstevel@tonic-gate WR(q)->q_ptr = NULL;
4650Sstevel@tonic-gate
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_CLOSE, usbms_log_handle,
4686710Syz224750 "usbms_close exiting");
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate return (0);
4710Sstevel@tonic-gate }
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate /*
4750Sstevel@tonic-gate * usbms_rserv() :
4760Sstevel@tonic-gate * Read queue service routine.
4770Sstevel@tonic-gate * Turn buffered mouse events into stream messages.
4780Sstevel@tonic-gate */
4790Sstevel@tonic-gate static void
usbms_rserv(queue_t * q)4800Sstevel@tonic-gate usbms_rserv(queue_t *q)
4810Sstevel@tonic-gate {
4820Sstevel@tonic-gate usbms_state_t *usbmsp = q->q_ptr;
4830Sstevel@tonic-gate struct ms_softc *ms;
4840Sstevel@tonic-gate struct usbmousebuf *b;
4850Sstevel@tonic-gate struct usbmouseinfo *mi;
4860Sstevel@tonic-gate mblk_t *bp;
4870Sstevel@tonic-gate ushort_t i, loop;
4880Sstevel@tonic-gate uchar_t nbutt = (uchar_t)usbmsp->usbms_num_buttons;
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate ms = &usbmsp->usbms_softc;
4910Sstevel@tonic-gate b = usbmsp->usbms_buf;
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_SERV, usbms_log_handle,
4946710Syz224750 "usbms_rserv entering");
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate while (canputnext(q) && ms->ms_oldoff != b->mb_off) {
4970Sstevel@tonic-gate mi = &b->mb_info[ms->ms_oldoff];
4980Sstevel@tonic-gate switch (ms->ms_readformat) {
4990Sstevel@tonic-gate
5000Sstevel@tonic-gate case MS_3BYTE_FORMAT: {
5010Sstevel@tonic-gate register char *cp;
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate if ((usbmsp->usbms_idf).xlen != 1) {
5040Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_SERV,
5050Sstevel@tonic-gate usbms_log_handle,
5060Sstevel@tonic-gate "Can't set to 3 byte format. Length != 1");
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate return;
5090Sstevel@tonic-gate }
5100Sstevel@tonic-gate if ((bp = allocb(3, BPRI_HI)) != NULL) {
5110Sstevel@tonic-gate cp = (char *)bp->b_wptr;
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate *cp++ = 0x80 | (mi->mi_buttons & 0xFF);
5140Sstevel@tonic-gate /* Update read buttons */
5150Sstevel@tonic-gate ms->ms_prevbuttons = mi->mi_buttons;
5160Sstevel@tonic-gate
5170Sstevel@tonic-gate *cp++ = (mi->mi_x & 0xFF);
5180Sstevel@tonic-gate *cp++ = ((-mi->mi_y) & 0xFF);
5190Sstevel@tonic-gate /* lower pri to avoid mouse droppings */
5200Sstevel@tonic-gate bp->b_wptr = (uchar_t *)cp;
5210Sstevel@tonic-gate putnext(q, bp);
5220Sstevel@tonic-gate } else {
5230Sstevel@tonic-gate if (usbmsp->usbms_resched_id) {
5240Sstevel@tonic-gate qunbufcall(q,
5256710Syz224750 (bufcall_id_t)usbmsp->
5266710Syz224750 usbms_resched_id);
5270Sstevel@tonic-gate }
5280Sstevel@tonic-gate usbmsp->usbms_resched_id = qbufcall(q,
5296710Syz224750 (size_t)3,
5306710Syz224750 (uint_t)BPRI_HI,
5316710Syz224750 (void (*)())usbms_resched,
5326710Syz224750 (void *) usbmsp);
5330Sstevel@tonic-gate if (usbmsp->usbms_resched_id == 0)
5340Sstevel@tonic-gate
5350Sstevel@tonic-gate return; /* try again later */
5360Sstevel@tonic-gate /* bufcall failed; just pitch this event */
5370Sstevel@tonic-gate /* or maybe flush queue? */
5380Sstevel@tonic-gate }
5390Sstevel@tonic-gate ms->ms_oldoff++; /* next event */
5400Sstevel@tonic-gate
5410Sstevel@tonic-gate /* circular buffer wraparound */
5420Sstevel@tonic-gate if (ms->ms_oldoff >= b->mb_size) {
5430Sstevel@tonic-gate ms->ms_oldoff = 0;
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate break;
5460Sstevel@tonic-gate }
5470Sstevel@tonic-gate
5480Sstevel@tonic-gate case MS_VUID_FORMAT:
5490Sstevel@tonic-gate default: {
5500Sstevel@tonic-gate
5510Sstevel@tonic-gate do {
5520Sstevel@tonic-gate bp = NULL;
5530Sstevel@tonic-gate
5540Sstevel@tonic-gate switch (ms->ms_eventstate) {
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate case EVENT_WHEEL:
5570Sstevel@tonic-gate loop = (usbmsp->usbms_num_wheels ?
5586710Syz224750 1 : 0);
5590Sstevel@tonic-gate
5600Sstevel@tonic-gate if (usbmsp->usbms_num_wheels) {
5610Sstevel@tonic-gate for (i = 0; i < loop; i++) {
5626710Syz224750 usbms_rserv_vuid_event_wheel
5636710Syz224750 (q, mi, &bp, i);
5640Sstevel@tonic-gate }
5650Sstevel@tonic-gate }
5660Sstevel@tonic-gate
5670Sstevel@tonic-gate break;
5680Sstevel@tonic-gate case EVENT_BUT8:
5690Sstevel@tonic-gate case EVENT_BUT7:
5700Sstevel@tonic-gate case EVENT_BUT6:
5710Sstevel@tonic-gate case EVENT_BUT5:
5720Sstevel@tonic-gate case EVENT_BUT4:
5730Sstevel@tonic-gate case EVENT_BUT3: /* Send right button */
5740Sstevel@tonic-gate case EVENT_BUT2: /* Send middle button */
5750Sstevel@tonic-gate case EVENT_BUT1: /* Send left button */
5760Sstevel@tonic-gate usbms_rserv_vuid_button(q, mi, &bp);
5770Sstevel@tonic-gate
5780Sstevel@tonic-gate break;
5790Sstevel@tonic-gate case EVENT_Y:
5800Sstevel@tonic-gate usbms_rserv_vuid_event_y(q, mi, &bp);
5810Sstevel@tonic-gate
5820Sstevel@tonic-gate break;
5830Sstevel@tonic-gate case EVENT_X:
5840Sstevel@tonic-gate usbms_rserv_vuid_event_x(q, mi, &bp);
5850Sstevel@tonic-gate
5860Sstevel@tonic-gate break;
5870Sstevel@tonic-gate default:
5880Sstevel@tonic-gate /* start again */
5890Sstevel@tonic-gate ms->ms_eventstate = EVENT_WHEEL;
5900Sstevel@tonic-gate
5910Sstevel@tonic-gate break;
5920Sstevel@tonic-gate }
5930Sstevel@tonic-gate if (bp != NULL) {
5940Sstevel@tonic-gate /* lower pri to avoid mouse droppings */
5950Sstevel@tonic-gate bp->b_wptr += sizeof (Firm_event);
5960Sstevel@tonic-gate putnext(q, bp);
5970Sstevel@tonic-gate }
5980Sstevel@tonic-gate if (ms->ms_eventstate == EVENT_X) {
5990Sstevel@tonic-gate ms->ms_eventstate = EVENT_WHEEL;
6000Sstevel@tonic-gate } else if (ms->ms_eventstate == EVENT_WHEEL) {
6010Sstevel@tonic-gate ms->ms_oldoff++; /* next event */
6020Sstevel@tonic-gate /* circular buffer wraparound */
6030Sstevel@tonic-gate if (ms->ms_oldoff >= b->mb_size) {
6040Sstevel@tonic-gate ms->ms_oldoff = 0;
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate ms->ms_eventstate = EVENT_BUT(nbutt);
6070Sstevel@tonic-gate } else
6080Sstevel@tonic-gate ms->ms_eventstate--;
6090Sstevel@tonic-gate } while (ms->ms_eventstate != EVENT_BUT(nbutt));
6100Sstevel@tonic-gate }
6110Sstevel@tonic-gate }
6120Sstevel@tonic-gate }
6130Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_SERV, usbms_log_handle,
6146710Syz224750 "usbms_rserv exiting");
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate
6170Sstevel@tonic-gate
6180Sstevel@tonic-gate /*
6190Sstevel@tonic-gate * usbms_rserv_vuid_event_wheel
6200Sstevel@tonic-gate * convert wheel data to firm events
6210Sstevel@tonic-gate */
6220Sstevel@tonic-gate static void
usbms_rserv_vuid_event_wheel(queue_t * q,struct usbmouseinfo * mi,mblk_t ** bpaddr,ushort_t id)6230Sstevel@tonic-gate usbms_rserv_vuid_event_wheel(queue_t *q,
6240Sstevel@tonic-gate struct usbmouseinfo *mi,
6250Sstevel@tonic-gate mblk_t **bpaddr,
6260Sstevel@tonic-gate ushort_t id)
6270Sstevel@tonic-gate {
6280Sstevel@tonic-gate Firm_event *fep;
6290Sstevel@tonic-gate mblk_t *tmp;
6300Sstevel@tonic-gate struct ms_softc *ms;
6310Sstevel@tonic-gate usbms_state_t *usbmsp = (usbms_state_t *)q->q_ptr;
6320Sstevel@tonic-gate
6330Sstevel@tonic-gate if (!(usbmsp->usbms_wheel_state_bf & (1 << id))) {
6340Sstevel@tonic-gate
6350Sstevel@tonic-gate return;
6360Sstevel@tonic-gate }
6370Sstevel@tonic-gate ms = &usbmsp->usbms_softc;
6380Sstevel@tonic-gate if (mi->mi_z) {
6390Sstevel@tonic-gate if ((tmp = allocb(sizeof (Firm_event), BPRI_HI)) != NULL) {
6400Sstevel@tonic-gate fep = (Firm_event *)tmp->b_wptr;
6410Sstevel@tonic-gate fep->id = vuid_id_addr(vuid_first(VUID_WHEEL)) |
6420Sstevel@tonic-gate vuid_id_offset(id);
6430Sstevel@tonic-gate fep->pair_type = FE_PAIR_NONE;
6440Sstevel@tonic-gate fep->pair = NULL;
6450Sstevel@tonic-gate fep->value = mi->mi_z;
6460Sstevel@tonic-gate fep->time = mi->mi_time;
6470Sstevel@tonic-gate *bpaddr = tmp;
6480Sstevel@tonic-gate } else {
6490Sstevel@tonic-gate if (usbmsp->usbms_resched_id) {
6500Sstevel@tonic-gate qunbufcall(q,
6516710Syz224750 (bufcall_id_t)usbmsp->usbms_resched_id);
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate usbmsp->usbms_resched_id =
6540Sstevel@tonic-gate qbufcall(q, sizeof (Firm_event), BPRI_HI,
6550Sstevel@tonic-gate (void (*)())usbms_resched, (void *) usbmsp);
6560Sstevel@tonic-gate if (usbmsp->usbms_resched_id == 0) {
6570Sstevel@tonic-gate /* try again later */
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate return;
6600Sstevel@tonic-gate }
6610Sstevel@tonic-gate
6620Sstevel@tonic-gate /* flush the queue */
6630Sstevel@tonic-gate ms->ms_eventstate = EVENT_WHEEL;
6640Sstevel@tonic-gate }
6650Sstevel@tonic-gate }
6660Sstevel@tonic-gate }
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate
6690Sstevel@tonic-gate /*
6700Sstevel@tonic-gate * usbms_rserv_vuid_button() :
6710Sstevel@tonic-gate * Process a VUID button event
6720Sstevel@tonic-gate */
6730Sstevel@tonic-gate static void
usbms_rserv_vuid_button(queue_t * q,struct usbmouseinfo * mi,mblk_t ** bpaddr)6740Sstevel@tonic-gate usbms_rserv_vuid_button(queue_t *q,
6750Sstevel@tonic-gate struct usbmouseinfo *mi,
6760Sstevel@tonic-gate mblk_t **bpaddr)
6770Sstevel@tonic-gate {
6780Sstevel@tonic-gate usbms_state_t *usbmsp = q->q_ptr;
6790Sstevel@tonic-gate struct ms_softc *ms;
6800Sstevel@tonic-gate int button_number;
6810Sstevel@tonic-gate uchar_t hwbit = 0x0;
6820Sstevel@tonic-gate Firm_event *fep;
6830Sstevel@tonic-gate mblk_t *bp;
6840Sstevel@tonic-gate uchar_t nbutt;
6850Sstevel@tonic-gate
6860Sstevel@tonic-gate ms = &usbmsp->usbms_softc;
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate /* Test button. Send an event if it changed. */
6890Sstevel@tonic-gate nbutt = (uchar_t)usbmsp->usbms_num_buttons;
6900Sstevel@tonic-gate button_number = nbutt - (EVENT_BUT(nbutt) - ms->ms_eventstate) - 1;
6910Sstevel@tonic-gate switch (button_number) {
6920Sstevel@tonic-gate case 2:
6930Sstevel@tonic-gate /* Right button */
6940Sstevel@tonic-gate hwbit = 0x01;
6950Sstevel@tonic-gate
6960Sstevel@tonic-gate break;
6970Sstevel@tonic-gate case 1:
6981584Sdanmcd /*
6991584Sdanmcd * On two-button mice, the second button is the "right"
7001584Sdanmcd * button. There is no "middle". The vuidps2.c file has
7011584Sdanmcd * a bmap[] array in sendButtonEvent(). We do something
7021584Sdanmcd * equivalent here ONLY in the case of two-button mice.
7031584Sdanmcd */
7041584Sdanmcd if (nbutt == 2) {
7051584Sdanmcd hwbit = 0x01;
7061584Sdanmcd /*
7071584Sdanmcd * Trick the vuid message into thinking it's a
7081584Sdanmcd * right-button click also.
7091584Sdanmcd */
7101584Sdanmcd button_number = 2;
7111584Sdanmcd } else {
7121584Sdanmcd /* ... otherwise, it's just the middle button */
7131584Sdanmcd hwbit = 0x02;
7141584Sdanmcd }
7150Sstevel@tonic-gate break;
7160Sstevel@tonic-gate case 0:
7170Sstevel@tonic-gate /* Left button */
7180Sstevel@tonic-gate hwbit = 0x04;
7190Sstevel@tonic-gate
7200Sstevel@tonic-gate break;
7210Sstevel@tonic-gate default :
7220Sstevel@tonic-gate /* Any other button */
7230Sstevel@tonic-gate hwbit = USBMS_BUT(nbutt) >> (EVENT_BUT(nbutt) -
7240Sstevel@tonic-gate ms->ms_eventstate);
7250Sstevel@tonic-gate
7260Sstevel@tonic-gate break;
7270Sstevel@tonic-gate }
7280Sstevel@tonic-gate
7290Sstevel@tonic-gate if ((ms->ms_prevbuttons & hwbit) !=
7306710Syz224750 (mi->mi_buttons & hwbit)) {
7310Sstevel@tonic-gate if ((bp = allocb(sizeof (Firm_event),
7326710Syz224750 BPRI_HI)) != NULL) {
7330Sstevel@tonic-gate *bpaddr = bp;
7340Sstevel@tonic-gate fep = (Firm_event *)bp->b_wptr;
7350Sstevel@tonic-gate fep->id = vuid_id_addr(
7366710Syz224750 ms->ms_vuidaddr) |
7376710Syz224750 vuid_id_offset(BUT(1)
7386710Syz224750 + button_number);
7390Sstevel@tonic-gate fep->pair_type = FE_PAIR_NONE;
7400Sstevel@tonic-gate fep->pair = 0;
7410Sstevel@tonic-gate
7420Sstevel@tonic-gate /*
7430Sstevel@tonic-gate * Update read buttons and set
7440Sstevel@tonic-gate * value
7450Sstevel@tonic-gate */
7460Sstevel@tonic-gate if (mi->mi_buttons & hwbit) {
7470Sstevel@tonic-gate fep->value = 0;
7480Sstevel@tonic-gate ms->ms_prevbuttons |=
7496710Syz224750 hwbit;
7500Sstevel@tonic-gate } else {
7510Sstevel@tonic-gate fep->value = 1;
7520Sstevel@tonic-gate ms->ms_prevbuttons &=
7536710Syz224750 ~hwbit;
7540Sstevel@tonic-gate }
7550Sstevel@tonic-gate fep->time = mi->mi_time;
7560Sstevel@tonic-gate } else {
7570Sstevel@tonic-gate if (usbmsp->usbms_resched_id) {
7580Sstevel@tonic-gate qunbufcall(q,
7596710Syz224750 (bufcall_id_t)usbmsp->usbms_resched_id);
7600Sstevel@tonic-gate }
7610Sstevel@tonic-gate usbmsp->usbms_resched_id =
7626710Syz224750 qbufcall(q,
7636710Syz224750 sizeof (Firm_event),
7646710Syz224750 BPRI_HI,
7656710Syz224750 (void (*)())usbms_resched,
7666710Syz224750 (void *) usbmsp);
7670Sstevel@tonic-gate if (usbmsp->usbms_resched_id == 0)
7680Sstevel@tonic-gate /* try again later */
7690Sstevel@tonic-gate return;
7700Sstevel@tonic-gate /*
7710Sstevel@tonic-gate * bufcall failed; just pitch
7720Sstevel@tonic-gate * this event
7730Sstevel@tonic-gate */
7740Sstevel@tonic-gate /* or maybe flush queue? */
7750Sstevel@tonic-gate ms->ms_eventstate = EVENT_WHEEL;
7760Sstevel@tonic-gate }
7770Sstevel@tonic-gate }
7780Sstevel@tonic-gate }
7790Sstevel@tonic-gate
7800Sstevel@tonic-gate /*
7810Sstevel@tonic-gate * usbms_rserv_vuid_event_y() :
7820Sstevel@tonic-gate * Process a VUID y-event
7830Sstevel@tonic-gate */
7840Sstevel@tonic-gate static void
usbms_rserv_vuid_event_y(register queue_t * q,register struct usbmouseinfo * mi,mblk_t ** bpaddr)7850Sstevel@tonic-gate usbms_rserv_vuid_event_y(register queue_t *q,
7860Sstevel@tonic-gate register struct usbmouseinfo *mi,
7870Sstevel@tonic-gate mblk_t **bpaddr)
7880Sstevel@tonic-gate {
7890Sstevel@tonic-gate usbms_state_t *usbmsp = q->q_ptr;
7900Sstevel@tonic-gate register struct ms_softc *ms;
7910Sstevel@tonic-gate register Firm_event *fep;
7920Sstevel@tonic-gate mblk_t *bp;
7930Sstevel@tonic-gate
7940Sstevel@tonic-gate ms = &usbmsp->usbms_softc;
7950Sstevel@tonic-gate
7960Sstevel@tonic-gate /*
7970Sstevel@tonic-gate * The (max, 0) message and (0, max) message are always sent before
7980Sstevel@tonic-gate * the button click message is sent on the IBM Bladecenter. Stop
7990Sstevel@tonic-gate * their sending may prevent the coordinate from moving to the
8000Sstevel@tonic-gate * (max, max).
8010Sstevel@tonic-gate */
8020Sstevel@tonic-gate if (!(((usbmsp->usbms_idf).yattr) & HID_MAIN_ITEM_RELATIVE)) {
8030Sstevel@tonic-gate if ((mi->mi_x == 0) &&
8040Sstevel@tonic-gate (mi->mi_y == usbmsp->usbms_logical_Ymax)) {
8050Sstevel@tonic-gate
8060Sstevel@tonic-gate return;
8070Sstevel@tonic-gate }
8080Sstevel@tonic-gate }
8090Sstevel@tonic-gate
8100Sstevel@tonic-gate /* Send y if changed. */
8110Sstevel@tonic-gate if (mi->mi_y != 0) {
8120Sstevel@tonic-gate if ((bp = allocb(sizeof (Firm_event),
8136710Syz224750 BPRI_HI)) != NULL) {
8140Sstevel@tonic-gate *bpaddr = bp;
8150Sstevel@tonic-gate fep = (Firm_event *)bp->b_wptr;
8160Sstevel@tonic-gate if (((usbmsp->usbms_idf).yattr) &
8170Sstevel@tonic-gate HID_MAIN_ITEM_RELATIVE) {
8180Sstevel@tonic-gate fep->id = vuid_id_addr(
8196710Syz224750 ms->ms_vuidaddr) |
8206710Syz224750 vuid_id_offset(
8216710Syz224750 LOC_Y_DELTA);
8220Sstevel@tonic-gate fep->pair_type =
8236710Syz224750 FE_PAIR_ABSOLUTE;
8240Sstevel@tonic-gate fep->pair =
8256710Syz224750 (uchar_t)LOC_Y_ABSOLUTE;
8260Sstevel@tonic-gate fep->value = -(mi->mi_y);
8270Sstevel@tonic-gate } else {
8280Sstevel@tonic-gate fep->id = vuid_id_addr(
8296710Syz224750 ms->ms_vuidaddr) |
8306710Syz224750 vuid_id_offset(
8316710Syz224750 LOC_Y_ABSOLUTE);
8320Sstevel@tonic-gate fep->pair_type = FE_PAIR_DELTA;
8330Sstevel@tonic-gate fep->pair = (uchar_t)LOC_Y_DELTA;
8340Sstevel@tonic-gate fep->value = (mi->mi_y *
8350Sstevel@tonic-gate ((usbmsp->usbms_resolution).height) /
8360Sstevel@tonic-gate usbmsp->usbms_logical_Ymax);
8370Sstevel@tonic-gate if ((mi->mi_y *
8380Sstevel@tonic-gate ((usbmsp->usbms_resolution).height) %
8390Sstevel@tonic-gate usbmsp->usbms_logical_Ymax) >=
8400Sstevel@tonic-gate (usbmsp->usbms_logical_Ymax / 2)) {
8410Sstevel@tonic-gate fep->value ++;
8420Sstevel@tonic-gate }
8430Sstevel@tonic-gate }
8440Sstevel@tonic-gate fep->time = mi->mi_time;
8450Sstevel@tonic-gate } else {
8460Sstevel@tonic-gate if (usbmsp->usbms_resched_id) {
8470Sstevel@tonic-gate qunbufcall(q,
8486710Syz224750 (bufcall_id_t)usbmsp->usbms_resched_id);
8490Sstevel@tonic-gate }
8500Sstevel@tonic-gate usbmsp->usbms_resched_id =
8516710Syz224750 qbufcall(q,
8526710Syz224750 sizeof (Firm_event),
8536710Syz224750 BPRI_HI,
8546710Syz224750 (void (*)())usbms_resched,
8556710Syz224750 (void *)usbmsp);
8560Sstevel@tonic-gate if (usbmsp->usbms_resched_id == 0) {
8570Sstevel@tonic-gate /* try again later */
8580Sstevel@tonic-gate return;
8590Sstevel@tonic-gate }
8600Sstevel@tonic-gate
8610Sstevel@tonic-gate /*
8620Sstevel@tonic-gate * bufcall failed; just pitch
8630Sstevel@tonic-gate * this event
8640Sstevel@tonic-gate */
8650Sstevel@tonic-gate /* or maybe flush queue? */
8660Sstevel@tonic-gate ms->ms_eventstate = EVENT_WHEEL;
8670Sstevel@tonic-gate }
8680Sstevel@tonic-gate }
8690Sstevel@tonic-gate }
8700Sstevel@tonic-gate
8710Sstevel@tonic-gate /*
8720Sstevel@tonic-gate * usbms_rserv_vuid_event_x() :
8730Sstevel@tonic-gate * Process a VUID x-event
8740Sstevel@tonic-gate */
8750Sstevel@tonic-gate static void
usbms_rserv_vuid_event_x(register queue_t * q,register struct usbmouseinfo * mi,mblk_t ** bpaddr)8760Sstevel@tonic-gate usbms_rserv_vuid_event_x(register queue_t *q,
8770Sstevel@tonic-gate register struct usbmouseinfo *mi,
8780Sstevel@tonic-gate mblk_t **bpaddr)
8790Sstevel@tonic-gate {
8800Sstevel@tonic-gate usbms_state_t *usbmsp = q->q_ptr;
8810Sstevel@tonic-gate register struct ms_softc *ms;
8820Sstevel@tonic-gate register Firm_event *fep;
8830Sstevel@tonic-gate mblk_t *bp;
8840Sstevel@tonic-gate
8850Sstevel@tonic-gate ms = &usbmsp->usbms_softc;
8860Sstevel@tonic-gate
8870Sstevel@tonic-gate /*
8880Sstevel@tonic-gate * The (max, 0) message and (0, max) message are always sent before
8890Sstevel@tonic-gate * the button click message is sent on the IBM Bladecenter. Stop
8900Sstevel@tonic-gate * their sending may prevent the coordinate from moving to the
8910Sstevel@tonic-gate * (max, max).
8920Sstevel@tonic-gate */
8930Sstevel@tonic-gate if (!(((usbmsp->usbms_idf).xattr) & HID_MAIN_ITEM_RELATIVE)) {
8940Sstevel@tonic-gate if ((mi->mi_y == 0) &&
8950Sstevel@tonic-gate (mi->mi_x == usbmsp->usbms_logical_Xmax)) {
8960Sstevel@tonic-gate
8970Sstevel@tonic-gate return;
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate }
9000Sstevel@tonic-gate
9010Sstevel@tonic-gate /* Send x if changed. */
9020Sstevel@tonic-gate if (mi->mi_x != 0) {
9030Sstevel@tonic-gate if ((bp = allocb(sizeof (Firm_event),
9046710Syz224750 BPRI_HI)) != NULL) {
9050Sstevel@tonic-gate *bpaddr = bp;
9060Sstevel@tonic-gate fep = (Firm_event *)bp->b_wptr;
9070Sstevel@tonic-gate if (((usbmsp->usbms_idf).xattr) &
9080Sstevel@tonic-gate HID_MAIN_ITEM_RELATIVE) {
9090Sstevel@tonic-gate fep->id = vuid_id_addr(
9106710Syz224750 ms->ms_vuidaddr) |
9116710Syz224750 vuid_id_offset(LOC_X_DELTA);
9120Sstevel@tonic-gate fep->pair_type =
9136710Syz224750 FE_PAIR_ABSOLUTE;
9140Sstevel@tonic-gate fep->pair =
9156710Syz224750 (uchar_t)LOC_X_ABSOLUTE;
9160Sstevel@tonic-gate fep->value = mi->mi_x;
9170Sstevel@tonic-gate } else {
9180Sstevel@tonic-gate fep->id = vuid_id_addr(ms->ms_vuidaddr) |
9196710Syz224750 vuid_id_offset(LOC_X_ABSOLUTE);
9200Sstevel@tonic-gate fep->pair_type = FE_PAIR_DELTA;
9210Sstevel@tonic-gate fep->pair = (uchar_t)LOC_X_DELTA;
9220Sstevel@tonic-gate fep->value = (mi->mi_x *
9230Sstevel@tonic-gate ((usbmsp->usbms_resolution).width) /
9240Sstevel@tonic-gate usbmsp->usbms_logical_Xmax);
9250Sstevel@tonic-gate if ((mi->mi_x *
9260Sstevel@tonic-gate ((usbmsp->usbms_resolution).width) %
9270Sstevel@tonic-gate usbmsp->usbms_logical_Xmax) >=
9280Sstevel@tonic-gate (usbmsp->usbms_logical_Xmax / 2)) {
9290Sstevel@tonic-gate fep->value ++;
9300Sstevel@tonic-gate }
9310Sstevel@tonic-gate }
9320Sstevel@tonic-gate fep->time = mi->mi_time;
9330Sstevel@tonic-gate } else {
9340Sstevel@tonic-gate if (usbmsp->usbms_resched_id)
9350Sstevel@tonic-gate qunbufcall(q,
9366710Syz224750 (bufcall_id_t)usbmsp->usbms_resched_id);
9370Sstevel@tonic-gate usbmsp->usbms_resched_id =
9386710Syz224750 qbufcall(q,
9396710Syz224750 sizeof (Firm_event),
9406710Syz224750 BPRI_HI,
9416710Syz224750 (void (*)())usbms_resched,
9426710Syz224750 (void *) usbmsp);
9430Sstevel@tonic-gate if (usbmsp->usbms_resched_id == 0)
9440Sstevel@tonic-gate /* try again later */
9450Sstevel@tonic-gate return;
9460Sstevel@tonic-gate
9470Sstevel@tonic-gate /*
9480Sstevel@tonic-gate * bufcall failed; just
9490Sstevel@tonic-gate * pitch this event
9500Sstevel@tonic-gate */
9510Sstevel@tonic-gate /* or maybe flush queue? */
9520Sstevel@tonic-gate ms->ms_eventstate = EVENT_WHEEL;
9530Sstevel@tonic-gate }
9540Sstevel@tonic-gate }
9550Sstevel@tonic-gate }
9560Sstevel@tonic-gate
9570Sstevel@tonic-gate /*
9580Sstevel@tonic-gate * usbms_resched() :
9590Sstevel@tonic-gate * Callback routine for the qbufcall() in case
9600Sstevel@tonic-gate * of allocb() failure. When buffer becomes
9610Sstevel@tonic-gate * available, this function is called and
9620Sstevel@tonic-gate * enables the queue.
9630Sstevel@tonic-gate */
9640Sstevel@tonic-gate static void
usbms_resched(void * usbmsp)9650Sstevel@tonic-gate usbms_resched(void * usbmsp)
9660Sstevel@tonic-gate {
9670Sstevel@tonic-gate register queue_t *q;
9680Sstevel@tonic-gate register usbms_state_t *tmp_usbmsp = (usbms_state_t *)usbmsp;
9690Sstevel@tonic-gate
9700Sstevel@tonic-gate tmp_usbmsp->usbms_resched_id = 0;
9710Sstevel@tonic-gate if ((q = tmp_usbmsp->usbms_rq_ptr) != 0)
9720Sstevel@tonic-gate qenable(q); /* run the service procedure */
9730Sstevel@tonic-gate }
9740Sstevel@tonic-gate
9750Sstevel@tonic-gate /*
9760Sstevel@tonic-gate * usbms_wput() :
9770Sstevel@tonic-gate * wput() routine for the mouse module.
9780Sstevel@tonic-gate * Module below : hid, module above : consms
9790Sstevel@tonic-gate */
9800Sstevel@tonic-gate static int
usbms_wput(queue_t * q,mblk_t * mp)9810Sstevel@tonic-gate usbms_wput(queue_t *q,
9820Sstevel@tonic-gate mblk_t *mp)
9830Sstevel@tonic-gate {
9840Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
9856710Syz224750 "usbms_wput entering");
9860Sstevel@tonic-gate switch (mp->b_datap->db_type) {
9870Sstevel@tonic-gate
9880Sstevel@tonic-gate case M_FLUSH: /* Canonical flush handling */
9890Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) {
9900Sstevel@tonic-gate flushq(q, FLUSHDATA);
9910Sstevel@tonic-gate }
9920Sstevel@tonic-gate
9930Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) {
9940Sstevel@tonic-gate flushq(RD(q), FLUSHDATA);
9950Sstevel@tonic-gate }
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate putnext(q, mp); /* pass it down the line. */
9980Sstevel@tonic-gate break;
9990Sstevel@tonic-gate
10000Sstevel@tonic-gate case M_IOCTL:
10010Sstevel@tonic-gate usbms_ioctl(q, mp);
10020Sstevel@tonic-gate break;
10030Sstevel@tonic-gate
10040Sstevel@tonic-gate case M_IOCDATA:
10050Sstevel@tonic-gate usbms_miocdata(q, mp);
10060Sstevel@tonic-gate
10070Sstevel@tonic-gate break;
10080Sstevel@tonic-gate default:
10090Sstevel@tonic-gate putnext(q, mp); /* pass it down the line. */
10100Sstevel@tonic-gate }
10110Sstevel@tonic-gate
10120Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
10136710Syz224750 "usbms_wput exiting");
10140Sstevel@tonic-gate
10150Sstevel@tonic-gate return (0);
10160Sstevel@tonic-gate }
10170Sstevel@tonic-gate
10180Sstevel@tonic-gate
10190Sstevel@tonic-gate /*
10200Sstevel@tonic-gate * usbms_ioctl() :
10210Sstevel@tonic-gate * Process ioctls we recognize and own. Otherwise, NAK.
10220Sstevel@tonic-gate */
10230Sstevel@tonic-gate static void
usbms_ioctl(register queue_t * q,register mblk_t * mp)10240Sstevel@tonic-gate usbms_ioctl(register queue_t *q,
10250Sstevel@tonic-gate register mblk_t *mp)
10260Sstevel@tonic-gate {
10270Sstevel@tonic-gate usbms_state_t *usbmsp = (usbms_state_t *)q->q_ptr;
10280Sstevel@tonic-gate register struct ms_softc *ms;
10290Sstevel@tonic-gate register struct iocblk *iocp;
10300Sstevel@tonic-gate Vuid_addr_probe *addr_probe;
10310Sstevel@tonic-gate uint_t ioctlrespsize;
10320Sstevel@tonic-gate int err = 0;
10330Sstevel@tonic-gate mblk_t *datap;
10340Sstevel@tonic-gate ushort_t transparent = 0;
10351662Sqz150045 boolean_t report_abs = B_FALSE;
10361662Sqz150045 mblk_t *mb;
10370Sstevel@tonic-gate
10380Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbms_log_handle,
10396710Syz224750 "usbms_ioctl entering");
10400Sstevel@tonic-gate
10410Sstevel@tonic-gate if (usbmsp == NULL) {
10420Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL);
10430Sstevel@tonic-gate
10440Sstevel@tonic-gate return;
10450Sstevel@tonic-gate }
10460Sstevel@tonic-gate ms = &usbmsp->usbms_softc;
10470Sstevel@tonic-gate
10480Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr;
10490Sstevel@tonic-gate switch (iocp->ioc_cmd) {
10500Sstevel@tonic-gate
10510Sstevel@tonic-gate case VUIDSFORMAT:
10520Sstevel@tonic-gate err = miocpullup(mp, sizeof (int));
10530Sstevel@tonic-gate if (err != 0)
10540Sstevel@tonic-gate break;
10550Sstevel@tonic-gate
10560Sstevel@tonic-gate if (*(int *)mp->b_cont->b_rptr == ms->ms_readformat) {
10570Sstevel@tonic-gate break;
10580Sstevel@tonic-gate }
10590Sstevel@tonic-gate ms->ms_readformat = *(int *)mp->b_cont->b_rptr;
10600Sstevel@tonic-gate /*
10610Sstevel@tonic-gate * Flush mouse buffer because the messages upstream of us
10620Sstevel@tonic-gate * are in the old format.
10630Sstevel@tonic-gate */
10640Sstevel@tonic-gate
10650Sstevel@tonic-gate usbms_flush(usbmsp);
10660Sstevel@tonic-gate break;
10670Sstevel@tonic-gate
10680Sstevel@tonic-gate case VUIDGFORMAT:
10690Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
10700Sstevel@tonic-gate ioctlrespsize = sizeof (int);
10710Sstevel@tonic-gate goto allocfailure;
10720Sstevel@tonic-gate }
10730Sstevel@tonic-gate *(int *)datap->b_wptr = ms->ms_readformat;
10740Sstevel@tonic-gate datap->b_wptr += sizeof (int);
10750Sstevel@tonic-gate freemsg(mp->b_cont);
10760Sstevel@tonic-gate mp->b_cont = datap;
10770Sstevel@tonic-gate iocp->ioc_count = sizeof (int);
10780Sstevel@tonic-gate break;
10790Sstevel@tonic-gate
10800Sstevel@tonic-gate case VUIDGADDR:
10810Sstevel@tonic-gate case VUIDSADDR:
10820Sstevel@tonic-gate err = miocpullup(mp, sizeof (Vuid_addr_probe));
10830Sstevel@tonic-gate if (err != 0)
10840Sstevel@tonic-gate break;
10850Sstevel@tonic-gate
10860Sstevel@tonic-gate addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
10870Sstevel@tonic-gate if (addr_probe->base != VKEY_FIRST) {
10880Sstevel@tonic-gate err = ENODEV;
10890Sstevel@tonic-gate break;
10900Sstevel@tonic-gate }
10910Sstevel@tonic-gate if (iocp->ioc_cmd == VUIDSADDR)
10920Sstevel@tonic-gate ms->ms_vuidaddr = addr_probe->data.next;
10930Sstevel@tonic-gate else
10940Sstevel@tonic-gate addr_probe->data.current = ms->ms_vuidaddr;
10950Sstevel@tonic-gate break;
10960Sstevel@tonic-gate
10970Sstevel@tonic-gate case MSIOGETPARMS:
10980Sstevel@tonic-gate if ((datap = allocb(sizeof (Ms_parms), BPRI_HI)) == NULL) {
10990Sstevel@tonic-gate ioctlrespsize = sizeof (Ms_parms);
11000Sstevel@tonic-gate goto allocfailure;
11010Sstevel@tonic-gate }
11020Sstevel@tonic-gate err = usbms_getparms((Ms_parms *)datap->b_wptr, usbmsp);
11030Sstevel@tonic-gate datap->b_wptr += sizeof (Ms_parms);
11040Sstevel@tonic-gate freemsg(mp->b_cont);
11050Sstevel@tonic-gate mp->b_cont = datap;
11060Sstevel@tonic-gate iocp->ioc_count = sizeof (Ms_parms);
11070Sstevel@tonic-gate break;
11080Sstevel@tonic-gate
11090Sstevel@tonic-gate case MSIOSETPARMS:
11100Sstevel@tonic-gate err = miocpullup(mp, sizeof (Ms_parms));
11110Sstevel@tonic-gate if (err != 0)
11120Sstevel@tonic-gate break;
11130Sstevel@tonic-gate err = usbms_setparms((Ms_parms *)mp->b_cont->b_rptr, usbmsp);
11140Sstevel@tonic-gate break;
11150Sstevel@tonic-gate
11160Sstevel@tonic-gate case MSIOBUTTONS:
11170Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
11180Sstevel@tonic-gate ioctlrespsize = sizeof (int);
11190Sstevel@tonic-gate goto allocfailure;
11200Sstevel@tonic-gate }
11210Sstevel@tonic-gate *(int *)datap->b_wptr = (int)usbmsp->usbms_num_buttons;
11220Sstevel@tonic-gate datap->b_wptr += sizeof (int);
11230Sstevel@tonic-gate freemsg(mp->b_cont);
11240Sstevel@tonic-gate mp->b_cont = datap;
11250Sstevel@tonic-gate iocp->ioc_count = sizeof (int);
11260Sstevel@tonic-gate
11270Sstevel@tonic-gate break;
11280Sstevel@tonic-gate case VUIDGWHEELCOUNT:
11290Sstevel@tonic-gate /*
11300Sstevel@tonic-gate * New IOCTL support. Since it's explicitly mentioned that
11310Sstevel@tonic-gate * you can't add more ioctls to stream head's hard coded
11320Sstevel@tonic-gate * list, we have to do the transparent ioctl processing
11330Sstevel@tonic-gate * which is heavy.
11340Sstevel@tonic-gate */
11350Sstevel@tonic-gate
11360Sstevel@tonic-gate /* Currently support for only one wheel */
11370Sstevel@tonic-gate
11380Sstevel@tonic-gate if (iocp->ioc_count == TRANSPARENT) {
11390Sstevel@tonic-gate transparent = 1;
11400Sstevel@tonic-gate if (err = usbms_make_copyreq(mp, 0, 0, sizeof (int),
11410Sstevel@tonic-gate 0, M_COPYOUT)) {
11420Sstevel@tonic-gate
11430Sstevel@tonic-gate break;
11440Sstevel@tonic-gate }
11450Sstevel@tonic-gate }
11460Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
11470Sstevel@tonic-gate ioctlrespsize = sizeof (int);
11480Sstevel@tonic-gate
11490Sstevel@tonic-gate goto allocfailure;
11500Sstevel@tonic-gate }
11510Sstevel@tonic-gate *((int *)datap->b_wptr) = (usbmsp->usbms_num_wheels ? 1 : 0);
11520Sstevel@tonic-gate datap->b_wptr += sizeof (int);
11530Sstevel@tonic-gate if (mp->b_cont) {
11540Sstevel@tonic-gate freemsg(mp->b_cont);
11550Sstevel@tonic-gate mp->b_cont = NULL;
11560Sstevel@tonic-gate }
11570Sstevel@tonic-gate mp->b_cont = datap;
11580Sstevel@tonic-gate if (transparent) {
11590Sstevel@tonic-gate qreply(q, mp);
11600Sstevel@tonic-gate
11610Sstevel@tonic-gate return;
11620Sstevel@tonic-gate }
11630Sstevel@tonic-gate
11640Sstevel@tonic-gate break;
11650Sstevel@tonic-gate case VUIDGWHEELINFO:
11660Sstevel@tonic-gate if (iocp->ioc_count == TRANSPARENT) {
11670Sstevel@tonic-gate if (err = usbms_make_copyreq(mp,
11680Sstevel@tonic-gate sizeof (usbms_iocstate_t),
11690Sstevel@tonic-gate USBMS_GETSTRUCT,
11700Sstevel@tonic-gate sizeof (wheel_info),
11710Sstevel@tonic-gate 0,
11720Sstevel@tonic-gate M_COPYIN)) {
11730Sstevel@tonic-gate
11740Sstevel@tonic-gate break;
11750Sstevel@tonic-gate }
11760Sstevel@tonic-gate /*
11770Sstevel@tonic-gate * If there is no b_cont the earlier func. will fail.
11780Sstevel@tonic-gate * Hence there is no need for an explicit check here.
11790Sstevel@tonic-gate */
11800Sstevel@tonic-gate freemsg(mp->b_cont);
11810Sstevel@tonic-gate mp->b_cont = (mblk_t *)NULL;
11820Sstevel@tonic-gate qreply(q, mp);
11830Sstevel@tonic-gate
11840Sstevel@tonic-gate return;
11850Sstevel@tonic-gate }
11860Sstevel@tonic-gate if (mp->b_cont == NULL || iocp->ioc_count !=
11876710Syz224750 sizeof (wheel_info)) {
11880Sstevel@tonic-gate err = EINVAL;
11890Sstevel@tonic-gate break;
11900Sstevel@tonic-gate }
11910Sstevel@tonic-gate datap = mp->b_cont;
11920Sstevel@tonic-gate err = usbms_service_wheel_info(q, datap);
11930Sstevel@tonic-gate
11940Sstevel@tonic-gate break;
11950Sstevel@tonic-gate case VUIDGWHEELSTATE:
11960Sstevel@tonic-gate if (iocp->ioc_count == TRANSPARENT) {
11970Sstevel@tonic-gate if (err = usbms_make_copyreq(mp,
11980Sstevel@tonic-gate sizeof (usbms_iocstate_t),
11990Sstevel@tonic-gate USBMS_GETSTRUCT,
12000Sstevel@tonic-gate sizeof (wheel_state),
12010Sstevel@tonic-gate 0,
12020Sstevel@tonic-gate M_COPYIN)) {
12030Sstevel@tonic-gate
12040Sstevel@tonic-gate break;
12050Sstevel@tonic-gate }
12060Sstevel@tonic-gate freemsg(mp->b_cont);
12070Sstevel@tonic-gate mp->b_cont = (mblk_t *)NULL;
12080Sstevel@tonic-gate qreply(q, mp);
12090Sstevel@tonic-gate
12100Sstevel@tonic-gate return;
12110Sstevel@tonic-gate }
12120Sstevel@tonic-gate if ((mp->b_cont == NULL) ||
12130Sstevel@tonic-gate (iocp->ioc_count != sizeof (wheel_state))) {
12140Sstevel@tonic-gate err = EINVAL;
12150Sstevel@tonic-gate
12160Sstevel@tonic-gate break;
12170Sstevel@tonic-gate }
12180Sstevel@tonic-gate datap = mp->b_cont;
12190Sstevel@tonic-gate err = usbms_service_wheel_state(q, datap, VUIDGWHEELSTATE);
12200Sstevel@tonic-gate
12210Sstevel@tonic-gate break;
12220Sstevel@tonic-gate case VUIDSWHEELSTATE:
12230Sstevel@tonic-gate if (iocp->ioc_count == TRANSPARENT) {
12240Sstevel@tonic-gate if (err = usbms_make_copyreq(mp,
12250Sstevel@tonic-gate sizeof (usbms_iocstate_t),
12260Sstevel@tonic-gate USBMS_GETSTRUCT,
12270Sstevel@tonic-gate sizeof (wheel_state),
12280Sstevel@tonic-gate 0,
12290Sstevel@tonic-gate M_COPYIN)) {
12300Sstevel@tonic-gate
12310Sstevel@tonic-gate break;
12320Sstevel@tonic-gate }
12330Sstevel@tonic-gate freemsg(mp->b_cont);
12340Sstevel@tonic-gate mp->b_cont = (mblk_t *)NULL;
12350Sstevel@tonic-gate qreply(q, mp);
12360Sstevel@tonic-gate
12370Sstevel@tonic-gate return;
12380Sstevel@tonic-gate }
12390Sstevel@tonic-gate if (mp->b_cont == NULL) {
12400Sstevel@tonic-gate err = EINVAL;
12410Sstevel@tonic-gate
12420Sstevel@tonic-gate break;
12430Sstevel@tonic-gate }
12440Sstevel@tonic-gate datap = mp->b_cont;
12450Sstevel@tonic-gate err = usbms_service_wheel_state(q, datap, VUIDSWHEELSTATE);
12460Sstevel@tonic-gate
12470Sstevel@tonic-gate break;
12480Sstevel@tonic-gate case MSIOSRESOLUTION:
12490Sstevel@tonic-gate if (iocp->ioc_count == TRANSPARENT) {
12500Sstevel@tonic-gate if (err = usbms_make_copyreq(mp,
12510Sstevel@tonic-gate sizeof (usbms_iocstate_t),
12520Sstevel@tonic-gate USBMS_GETSTRUCT,
12530Sstevel@tonic-gate sizeof (Ms_screen_resolution),
12540Sstevel@tonic-gate 0,
12550Sstevel@tonic-gate M_COPYIN)) {
12560Sstevel@tonic-gate
12570Sstevel@tonic-gate break;
12580Sstevel@tonic-gate }
12590Sstevel@tonic-gate
12600Sstevel@tonic-gate freemsg(mp->b_cont);
12610Sstevel@tonic-gate mp->b_cont = (mblk_t *)NULL;
12620Sstevel@tonic-gate qreply(q, mp);
12630Sstevel@tonic-gate
12640Sstevel@tonic-gate return;
12650Sstevel@tonic-gate }
12660Sstevel@tonic-gate if (mp->b_cont == NULL) {
12670Sstevel@tonic-gate err = EINVAL;
12680Sstevel@tonic-gate
12690Sstevel@tonic-gate break;
12700Sstevel@tonic-gate }
12710Sstevel@tonic-gate datap = mp->b_cont;
12720Sstevel@tonic-gate err = usbms_get_screen_parms(q, datap);
12731662Sqz150045 /*
12741662Sqz150045 * Create the absolute mouse type event.
12751662Sqz150045 * It is used for the hotplug absolute mouse.
12761662Sqz150045 */
12771662Sqz150045 if ((!((usbmsp->usbms_idf).xattr & HID_MAIN_ITEM_RELATIVE)) &&
12781662Sqz150045 (usbmsp->usbms_rpt_abs == B_FALSE)) {
12791662Sqz150045 report_abs = B_TRUE;
12801662Sqz150045 }
12811662Sqz150045
12820Sstevel@tonic-gate break;
12830Sstevel@tonic-gate
12840Sstevel@tonic-gate default:
12850Sstevel@tonic-gate putnext(q, mp); /* pass it down the line */
12860Sstevel@tonic-gate
12870Sstevel@tonic-gate return;
12880Sstevel@tonic-gate } /* switch */
12890Sstevel@tonic-gate
12900Sstevel@tonic-gate if (err != 0)
12910Sstevel@tonic-gate miocnak(q, mp, 0, err);
12920Sstevel@tonic-gate else {
12930Sstevel@tonic-gate iocp->ioc_rval = 0;
12940Sstevel@tonic-gate iocp->ioc_error = 0;
12950Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK;
12960Sstevel@tonic-gate qreply(q, mp);
12971662Sqz150045
12981662Sqz150045 if (report_abs == B_TRUE) {
12991662Sqz150045 /* send the abs mouse type event to the upper level */
13001662Sqz150045 if ((mb = usbms_setup_abs_mouse_event()) != NULL) {
13011662Sqz150045 usbmsp->usbms_rpt_abs = B_TRUE;
13021662Sqz150045 qreply(q, mb);
13031662Sqz150045 }
13041662Sqz150045 }
13050Sstevel@tonic-gate }
13060Sstevel@tonic-gate
13070Sstevel@tonic-gate return;
13080Sstevel@tonic-gate
13090Sstevel@tonic-gate allocfailure:
13100Sstevel@tonic-gate /*
13110Sstevel@tonic-gate * We needed to allocate something to handle this "ioctl", but
13120Sstevel@tonic-gate * couldn't; save this "ioctl" and arrange to get called back when
13130Sstevel@tonic-gate * it's more likely that we can get what we need.
13140Sstevel@tonic-gate * If there's already one being saved, throw it out, since it
13150Sstevel@tonic-gate * must have timed out.
13160Sstevel@tonic-gate */
13170Sstevel@tonic-gate freemsg(usbmsp->usbms_iocpending);
13180Sstevel@tonic-gate usbmsp->usbms_iocpending = mp;
13190Sstevel@tonic-gate if (usbmsp->usbms_reioctl_id) {
13200Sstevel@tonic-gate qunbufcall(q, (bufcall_id_t)usbmsp->usbms_reioctl_id);
13210Sstevel@tonic-gate }
13220Sstevel@tonic-gate usbmsp->usbms_reioctl_id = qbufcall(q, ioctlrespsize, BPRI_HI,
13236710Syz224750 (void (*)())usbms_reioctl,
13246710Syz224750 (void *)usbmsp);
13250Sstevel@tonic-gate }
13260Sstevel@tonic-gate
13270Sstevel@tonic-gate
13280Sstevel@tonic-gate /*
13290Sstevel@tonic-gate * M_IOCDATA processing for IOCTL's: VUIDGWHEELCOUNT, VUIDGWHEELINFO,
13300Sstevel@tonic-gate * VUIDGWHEELSTATE, VUIDSWHEELSTATE & MSIOSRESOLUTION.
13310Sstevel@tonic-gate */
13320Sstevel@tonic-gate static void
usbms_miocdata(register queue_t * q,register mblk_t * mp)13330Sstevel@tonic-gate usbms_miocdata(register queue_t *q,
13340Sstevel@tonic-gate register mblk_t *mp)
13350Sstevel@tonic-gate {
13360Sstevel@tonic-gate struct copyresp *copyresp;
13370Sstevel@tonic-gate struct iocblk *iocbp;
13380Sstevel@tonic-gate mblk_t *datap;
13390Sstevel@tonic-gate mblk_t *ioctmp;
13400Sstevel@tonic-gate usbms_iocstate_t *usbmsioc;
13410Sstevel@tonic-gate int err = 0;
13420Sstevel@tonic-gate
13430Sstevel@tonic-gate copyresp = (struct copyresp *)mp->b_rptr;
13440Sstevel@tonic-gate iocbp = (struct iocblk *)mp->b_rptr;
13450Sstevel@tonic-gate if (copyresp->cp_rval) {
13460Sstevel@tonic-gate err = EAGAIN;
13470Sstevel@tonic-gate
13480Sstevel@tonic-gate goto err;
13490Sstevel@tonic-gate }
13500Sstevel@tonic-gate switch (copyresp->cp_cmd) {
13510Sstevel@tonic-gate
13520Sstevel@tonic-gate case VUIDGWHEELCOUNT:
13530Sstevel@tonic-gate usbms_ack_ioctl(mp);
13540Sstevel@tonic-gate
13550Sstevel@tonic-gate break;
13560Sstevel@tonic-gate case VUIDGWHEELINFO:
13570Sstevel@tonic-gate ioctmp = copyresp->cp_private;
13580Sstevel@tonic-gate usbmsioc = (usbms_iocstate_t *)ioctmp->b_rptr;
13590Sstevel@tonic-gate if (usbmsioc->ioc_state == USBMS_GETSTRUCT) {
13600Sstevel@tonic-gate if (mp->b_cont == NULL) {
13610Sstevel@tonic-gate err = EINVAL;
13620Sstevel@tonic-gate
13630Sstevel@tonic-gate break;
13640Sstevel@tonic-gate }
13650Sstevel@tonic-gate datap = (mblk_t *)mp->b_cont;
13660Sstevel@tonic-gate if (err = usbms_service_wheel_info(q, datap)) {
13670Sstevel@tonic-gate
13680Sstevel@tonic-gate goto err;
13690Sstevel@tonic-gate }
13700Sstevel@tonic-gate if (err = usbms_make_copyreq(mp, 0, USBMS_GETRESULT,
13710Sstevel@tonic-gate sizeof (wheel_info), 0, M_COPYOUT)) {
13720Sstevel@tonic-gate
13730Sstevel@tonic-gate goto err;
13740Sstevel@tonic-gate }
13750Sstevel@tonic-gate } else if (usbmsioc->ioc_state == USBMS_GETRESULT) {
13760Sstevel@tonic-gate freemsg(ioctmp);
13770Sstevel@tonic-gate usbms_ack_ioctl(mp);
13780Sstevel@tonic-gate }
13790Sstevel@tonic-gate
13800Sstevel@tonic-gate break;
13810Sstevel@tonic-gate case VUIDGWHEELSTATE:
13820Sstevel@tonic-gate ioctmp = (mblk_t *)copyresp->cp_private;
13830Sstevel@tonic-gate usbmsioc = (usbms_iocstate_t *)ioctmp->b_rptr;
13840Sstevel@tonic-gate if (usbmsioc->ioc_state == USBMS_GETSTRUCT) {
13850Sstevel@tonic-gate if (mp->b_cont == NULL) {
13860Sstevel@tonic-gate err = EINVAL;
13870Sstevel@tonic-gate
13880Sstevel@tonic-gate break;
13890Sstevel@tonic-gate }
13900Sstevel@tonic-gate if (err = usbms_service_wheel_state(q, mp->b_cont,
13910Sstevel@tonic-gate VUIDGWHEELSTATE)) {
13920Sstevel@tonic-gate goto err;
13930Sstevel@tonic-gate }
13940Sstevel@tonic-gate if (err = usbms_make_copyreq(mp, 0, USBMS_GETRESULT,
13950Sstevel@tonic-gate sizeof (wheel_state), 0, M_COPYOUT)) {
13960Sstevel@tonic-gate
13970Sstevel@tonic-gate goto err;
13980Sstevel@tonic-gate }
13990Sstevel@tonic-gate } else if (usbmsioc->ioc_state == USBMS_GETRESULT) {
14000Sstevel@tonic-gate freemsg(ioctmp);
14010Sstevel@tonic-gate usbms_ack_ioctl(mp);
14020Sstevel@tonic-gate }
14030Sstevel@tonic-gate
14040Sstevel@tonic-gate break;
14050Sstevel@tonic-gate case VUIDSWHEELSTATE:
14060Sstevel@tonic-gate ioctmp = (mblk_t *)copyresp->cp_private;
14070Sstevel@tonic-gate usbmsioc = (usbms_iocstate_t *)ioctmp->b_rptr;
14080Sstevel@tonic-gate if (mp->b_cont == NULL) {
14090Sstevel@tonic-gate err = EINVAL;
14100Sstevel@tonic-gate
14110Sstevel@tonic-gate break;
14120Sstevel@tonic-gate }
14130Sstevel@tonic-gate if (err = usbms_service_wheel_state(q, mp->b_cont,
14140Sstevel@tonic-gate VUIDSWHEELSTATE)) {
14150Sstevel@tonic-gate
14160Sstevel@tonic-gate goto err;
14170Sstevel@tonic-gate }
14180Sstevel@tonic-gate freemsg(ioctmp);
14190Sstevel@tonic-gate usbms_ack_ioctl(mp);
14200Sstevel@tonic-gate
14210Sstevel@tonic-gate break;
14220Sstevel@tonic-gate case MSIOSRESOLUTION:
14230Sstevel@tonic-gate ioctmp = (mblk_t *)copyresp->cp_private;
14240Sstevel@tonic-gate usbmsioc = (usbms_iocstate_t *)ioctmp->b_rptr;
14250Sstevel@tonic-gate if (mp->b_cont == NULL) {
14260Sstevel@tonic-gate err = EINVAL;
14270Sstevel@tonic-gate
14280Sstevel@tonic-gate break;
14290Sstevel@tonic-gate }
14300Sstevel@tonic-gate if (err = usbms_get_screen_parms(q, mp->b_cont)) {
14310Sstevel@tonic-gate
14320Sstevel@tonic-gate goto err;
14330Sstevel@tonic-gate }
14340Sstevel@tonic-gate freemsg(ioctmp);
14350Sstevel@tonic-gate usbms_ack_ioctl(mp);
14360Sstevel@tonic-gate
14370Sstevel@tonic-gate break;
14380Sstevel@tonic-gate default:
14390Sstevel@tonic-gate err = EINVAL;
14400Sstevel@tonic-gate break;
14410Sstevel@tonic-gate }
14420Sstevel@tonic-gate
14430Sstevel@tonic-gate err:
14440Sstevel@tonic-gate if (err) {
14450Sstevel@tonic-gate mp->b_datap->db_type = M_IOCNAK;
14460Sstevel@tonic-gate if (mp->b_cont) {
14470Sstevel@tonic-gate freemsg(mp->b_cont);
14480Sstevel@tonic-gate mp->b_cont = (mblk_t *)NULL;
14490Sstevel@tonic-gate }
14500Sstevel@tonic-gate if (copyresp->cp_private) {
14510Sstevel@tonic-gate freemsg((mblk_t *)copyresp->cp_private);
14520Sstevel@tonic-gate copyresp->cp_private = (mblk_t *)NULL;
14530Sstevel@tonic-gate }
14540Sstevel@tonic-gate iocbp->ioc_count = 0;
14550Sstevel@tonic-gate iocbp->ioc_error = err;
14560Sstevel@tonic-gate }
14570Sstevel@tonic-gate qreply(q, mp);
14580Sstevel@tonic-gate }
14590Sstevel@tonic-gate
14600Sstevel@tonic-gate
14610Sstevel@tonic-gate /*
14620Sstevel@tonic-gate * usbms_reioctl() :
14630Sstevel@tonic-gate * This function is set up as call-back function should an ioctl fail.
14640Sstevel@tonic-gate * It retries the ioctl.
14650Sstevel@tonic-gate */
14660Sstevel@tonic-gate static void
usbms_reioctl(void * usbms_addr)14670Sstevel@tonic-gate usbms_reioctl(void * usbms_addr)
14680Sstevel@tonic-gate {
14690Sstevel@tonic-gate usbms_state_t *usbmsp = (usbms_state_t *)usbms_addr;
14700Sstevel@tonic-gate register queue_t *q;
14710Sstevel@tonic-gate register mblk_t *mp;
14720Sstevel@tonic-gate
14730Sstevel@tonic-gate q = usbmsp->usbms_wq_ptr;
14740Sstevel@tonic-gate if ((mp = usbmsp->usbms_iocpending) != NULL) {
14750Sstevel@tonic-gate usbmsp->usbms_iocpending = NULL; /* not pending any more */
14760Sstevel@tonic-gate usbms_ioctl(q, mp);
14770Sstevel@tonic-gate }
14780Sstevel@tonic-gate }
14790Sstevel@tonic-gate
14800Sstevel@tonic-gate /*
14810Sstevel@tonic-gate * usbms_getparms() :
14820Sstevel@tonic-gate * Called from MSIOGETPARMS ioctl to get the
14830Sstevel@tonic-gate * current jitter_thesh, speed_law and speed_limit
14840Sstevel@tonic-gate * values.
14850Sstevel@tonic-gate */
14860Sstevel@tonic-gate static int
usbms_getparms(register Ms_parms * data,usbms_state_t * usbmsp)14870Sstevel@tonic-gate usbms_getparms(register Ms_parms *data,
14880Sstevel@tonic-gate usbms_state_t *usbmsp)
14890Sstevel@tonic-gate {
14900Sstevel@tonic-gate data->jitter_thresh = usbmsp->usbms_jitter_thresh;
14910Sstevel@tonic-gate data->speed_law = usbmsp->usbms_speedlaw;
14920Sstevel@tonic-gate data->speed_limit = usbmsp->usbms_speedlimit;
14930Sstevel@tonic-gate
14940Sstevel@tonic-gate return (0);
14950Sstevel@tonic-gate }
14960Sstevel@tonic-gate
14970Sstevel@tonic-gate
14980Sstevel@tonic-gate /*
14990Sstevel@tonic-gate * usbms_setparms() :
15000Sstevel@tonic-gate * Called from MSIOSETPARMS ioctl to set the
15010Sstevel@tonic-gate * current jitter_thesh, speed_law and speed_limit
15020Sstevel@tonic-gate * values.
15030Sstevel@tonic-gate */
15040Sstevel@tonic-gate static int
usbms_setparms(register Ms_parms * data,usbms_state_t * usbmsp)15050Sstevel@tonic-gate usbms_setparms(register Ms_parms *data,
15060Sstevel@tonic-gate usbms_state_t *usbmsp)
15070Sstevel@tonic-gate {
15080Sstevel@tonic-gate usbmsp->usbms_jitter_thresh = data->jitter_thresh;
15090Sstevel@tonic-gate usbmsp->usbms_speedlaw = data->speed_law;
15100Sstevel@tonic-gate usbmsp->usbms_speedlimit = data->speed_limit;
15110Sstevel@tonic-gate
15120Sstevel@tonic-gate return (0);
15130Sstevel@tonic-gate }
15140Sstevel@tonic-gate
15150Sstevel@tonic-gate /*
15160Sstevel@tonic-gate * usbms_flush() :
15170Sstevel@tonic-gate * Resets the ms_softc structure to default values
15180Sstevel@tonic-gate * and sends M_FLUSH above.
15190Sstevel@tonic-gate */
15200Sstevel@tonic-gate static void
usbms_flush(usbms_state_t * usbmsp)15210Sstevel@tonic-gate usbms_flush(usbms_state_t *usbmsp)
15220Sstevel@tonic-gate {
15230Sstevel@tonic-gate register struct ms_softc *ms = &usbmsp->usbms_softc;
15240Sstevel@tonic-gate register queue_t *q;
15250Sstevel@tonic-gate
15260Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
15276710Syz224750 "usbms_flush entering");
15280Sstevel@tonic-gate
15290Sstevel@tonic-gate ms->ms_oldoff = 0;
15300Sstevel@tonic-gate ms->ms_eventstate = EVENT_BUT(usbmsp->usbms_num_buttons);
15310Sstevel@tonic-gate usbmsp->usbms_buf->mb_off = 0;
15320Sstevel@tonic-gate ms->ms_prevbuttons = (char)USB_NO_BUT_PRESSED;
15330Sstevel@tonic-gate usbmsp->usbms_oldbutt = ms->ms_prevbuttons;
15340Sstevel@tonic-gate if ((q = usbmsp->usbms_rq_ptr) != NULL && q->q_next != NULL) {
15350Sstevel@tonic-gate (void) putnextctl1(q, M_FLUSH, FLUSHR);
15360Sstevel@tonic-gate }
15370Sstevel@tonic-gate
15380Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
15396710Syz224750 "usbms_flush exiting");
15400Sstevel@tonic-gate }
15410Sstevel@tonic-gate
15420Sstevel@tonic-gate
15430Sstevel@tonic-gate /*
15440Sstevel@tonic-gate * usbms_rput() :
15450Sstevel@tonic-gate * Put procedure for input from driver end of stream (read queue).
15460Sstevel@tonic-gate */
15470Sstevel@tonic-gate static void
usbms_rput(queue_t * q,mblk_t * mp)15480Sstevel@tonic-gate usbms_rput(queue_t *q,
15490Sstevel@tonic-gate mblk_t *mp)
15500Sstevel@tonic-gate {
15510Sstevel@tonic-gate usbms_state_t *usbmsp = q->q_ptr;
15520Sstevel@tonic-gate mblk_t *tmp_mp;
15530Sstevel@tonic-gate ushort_t limit = (usbmsp->usbms_idf).tlen;
15540Sstevel@tonic-gate
15550Sstevel@tonic-gate /* Maintain the original mp */
15560Sstevel@tonic-gate tmp_mp = mp;
15570Sstevel@tonic-gate
15580Sstevel@tonic-gate if (usbmsp == 0) {
15590Sstevel@tonic-gate freemsg(mp); /* nobody's listening */
15600Sstevel@tonic-gate
15610Sstevel@tonic-gate return;
15620Sstevel@tonic-gate }
15630Sstevel@tonic-gate
15640Sstevel@tonic-gate switch (mp->b_datap->db_type) {
15650Sstevel@tonic-gate
15660Sstevel@tonic-gate case M_FLUSH:
15670Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW)
15680Sstevel@tonic-gate flushq(WR(q), FLUSHDATA);
15690Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR)
15700Sstevel@tonic-gate flushq(q, FLUSHDATA);
15710Sstevel@tonic-gate freemsg(mp);
15720Sstevel@tonic-gate
15730Sstevel@tonic-gate return;
15740Sstevel@tonic-gate
15750Sstevel@tonic-gate case M_BREAK:
15760Sstevel@tonic-gate /*
15770Sstevel@tonic-gate * We don't have to handle this
15780Sstevel@tonic-gate * because nothing is sent from the downstream
15790Sstevel@tonic-gate */
15800Sstevel@tonic-gate
15810Sstevel@tonic-gate freemsg(mp);
15820Sstevel@tonic-gate
15830Sstevel@tonic-gate return;
15840Sstevel@tonic-gate
15850Sstevel@tonic-gate case M_DATA:
15860Sstevel@tonic-gate if (!(usbmsp->usbms_flags & USBMS_OPEN)) {
15870Sstevel@tonic-gate freemsg(mp); /* not ready to listen */
15880Sstevel@tonic-gate
15890Sstevel@tonic-gate return;
15900Sstevel@tonic-gate }
15910Sstevel@tonic-gate break;
15920Sstevel@tonic-gate
15930Sstevel@tonic-gate case M_CTL:
15940Sstevel@tonic-gate usbms_mctl_receive(q, mp);
15950Sstevel@tonic-gate
15960Sstevel@tonic-gate return;
15970Sstevel@tonic-gate
15980Sstevel@tonic-gate case M_ERROR:
15990Sstevel@tonic-gate usbmsp->usbms_protoerr = 1;
16000Sstevel@tonic-gate usbmsp->usbms_flags &= ~USBMS_QWAIT;
1601*12425SFei.Feng@Sun.COM if (*mp->b_rptr == ENODEV) {
1602*12425SFei.Feng@Sun.COM putnext(q, mp);
1603*12425SFei.Feng@Sun.COM } else {
1604*12425SFei.Feng@Sun.COM freemsg(mp);
1605*12425SFei.Feng@Sun.COM }
16060Sstevel@tonic-gate
16070Sstevel@tonic-gate return;
16080Sstevel@tonic-gate default:
16090Sstevel@tonic-gate putnext(q, mp);
16100Sstevel@tonic-gate
16110Sstevel@tonic-gate return;
16120Sstevel@tonic-gate }
16130Sstevel@tonic-gate
16140Sstevel@tonic-gate /*
16150Sstevel@tonic-gate * A data message, consisting of bytes from the mouse.
16160Sstevel@tonic-gate * Make sure there are atleast "limit" number of bytes.
16170Sstevel@tonic-gate */
16187492SZhigang.Lu@Sun.COM if ((MBLKL(tmp_mp) < limit) || ((MBLKL(tmp_mp) == limit) &&
16190Sstevel@tonic-gate (usbmsp->usbms_rptid != HID_REPORT_ID_UNDEFINED))) {
16200Sstevel@tonic-gate freemsg(mp);
16210Sstevel@tonic-gate return;
16220Sstevel@tonic-gate }
16230Sstevel@tonic-gate do {
16240Sstevel@tonic-gate if (usbmsp->usbms_rptid != HID_REPORT_ID_UNDEFINED) {
16250Sstevel@tonic-gate if (*(tmp_mp->b_rptr) != usbmsp->usbms_rptid) {
16260Sstevel@tonic-gate freemsg(mp);
16270Sstevel@tonic-gate
16280Sstevel@tonic-gate return;
16290Sstevel@tonic-gate } else {
16300Sstevel@tonic-gate /* We skip the report id prefix. */
16310Sstevel@tonic-gate tmp_mp->b_rptr++;
16320Sstevel@tonic-gate }
16330Sstevel@tonic-gate }
16340Sstevel@tonic-gate
16350Sstevel@tonic-gate usbms_input(usbmsp, tmp_mp);
16360Sstevel@tonic-gate } while ((tmp_mp = tmp_mp->b_cont) != NULL); /* next block, if any */
16370Sstevel@tonic-gate
16380Sstevel@tonic-gate freemsg(mp);
16390Sstevel@tonic-gate }
16400Sstevel@tonic-gate
16410Sstevel@tonic-gate
16420Sstevel@tonic-gate /*
16430Sstevel@tonic-gate * usbms_mctl_receive() :
16440Sstevel@tonic-gate * Handle M_CTL messages from hid. If
16450Sstevel@tonic-gate * we don't understand the command, free message.
16460Sstevel@tonic-gate */
16470Sstevel@tonic-gate static void
usbms_mctl_receive(register queue_t * q,register mblk_t * mp)16480Sstevel@tonic-gate usbms_mctl_receive(register queue_t *q,
16490Sstevel@tonic-gate register mblk_t *mp)
16500Sstevel@tonic-gate {
16510Sstevel@tonic-gate usbms_state_t *usbmsd = (usbms_state_t *)q->q_ptr;
16520Sstevel@tonic-gate struct iocblk *iocp;
16530Sstevel@tonic-gate caddr_t data;
16540Sstevel@tonic-gate
16550Sstevel@tonic-gate
16560Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr;
16570Sstevel@tonic-gate if (mp->b_cont != NULL)
16580Sstevel@tonic-gate data = (caddr_t)mp->b_cont->b_rptr;
16590Sstevel@tonic-gate
16600Sstevel@tonic-gate switch (iocp->ioc_cmd) {
16610Sstevel@tonic-gate
16620Sstevel@tonic-gate case HID_GET_PARSER_HANDLE:
16630Sstevel@tonic-gate if ((data != NULL) &&
16640Sstevel@tonic-gate (iocp->ioc_count == sizeof (hidparser_handle_t)) &&
16657492SZhigang.Lu@Sun.COM (MBLKL(mp->b_cont) == iocp->ioc_count)) {
16660Sstevel@tonic-gate usbmsd->usbms_report_descr_handle =
16670Sstevel@tonic-gate *(hidparser_handle_t *)data;
16680Sstevel@tonic-gate } else {
16690Sstevel@tonic-gate usbmsd->usbms_report_descr_handle = NULL;
16700Sstevel@tonic-gate }
16710Sstevel@tonic-gate freemsg(mp);
16720Sstevel@tonic-gate usbmsd->usbms_flags &= ~USBMS_QWAIT;
16730Sstevel@tonic-gate break;
16740Sstevel@tonic-gate case HID_SET_PROTOCOL:
16750Sstevel@tonic-gate usbmsd->usbms_flags &= ~USBMS_QWAIT;
16760Sstevel@tonic-gate
16770Sstevel@tonic-gate /* FALLTHRU */
16780Sstevel@tonic-gate default:
16796710Syz224750 freemsg(mp);
16806710Syz224750 break;
16810Sstevel@tonic-gate }
16820Sstevel@tonic-gate }
16830Sstevel@tonic-gate
16840Sstevel@tonic-gate
16850Sstevel@tonic-gate /*
16860Sstevel@tonic-gate * usbms_input() :
16870Sstevel@tonic-gate *
16880Sstevel@tonic-gate * Mouse input routine; process a byte received from a mouse and
16890Sstevel@tonic-gate * assemble into a mouseinfo message for the window system.
16900Sstevel@tonic-gate *
16910Sstevel@tonic-gate * The USB mouse send a three-byte packet organized as
16920Sstevel@tonic-gate * button, dx, dy
16930Sstevel@tonic-gate * where dx and dy can be any signed byte value. The mouseinfo message
16940Sstevel@tonic-gate * is organized as
16950Sstevel@tonic-gate * dx, dy, button, timestamp
16960Sstevel@tonic-gate * Our strategy is to collect but, dx & dy three-byte packet, then
16970Sstevel@tonic-gate * send the mouseinfo message up.
16980Sstevel@tonic-gate *
16990Sstevel@tonic-gate * Basic algorithm: throw away bytes until we get a [potential]
17000Sstevel@tonic-gate * button byte. Collect button; Collect dx; Collect dy; Send button,
17010Sstevel@tonic-gate * dx, dy, timestamp.
17020Sstevel@tonic-gate *
17030Sstevel@tonic-gate * Watch out for overflow!
17040Sstevel@tonic-gate */
17050Sstevel@tonic-gate static void
usbms_input(usbms_state_t * usbmsp,mblk_t * mp)17060Sstevel@tonic-gate usbms_input(usbms_state_t *usbmsp,
17070Sstevel@tonic-gate mblk_t *mp)
17080Sstevel@tonic-gate {
17090Sstevel@tonic-gate register struct usbmousebuf *b;
17100Sstevel@tonic-gate register struct usbmouseinfo *mi;
17110Sstevel@tonic-gate register int jitter_radius;
17120Sstevel@tonic-gate register int32_t nbutt;
17130Sstevel@tonic-gate ushort_t i;
17140Sstevel@tonic-gate char c;
17150Sstevel@tonic-gate
17160Sstevel@tonic-gate nbutt = usbmsp->usbms_num_buttons;
17170Sstevel@tonic-gate b = usbmsp->usbms_buf;
17180Sstevel@tonic-gate
17190Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle,
17206710Syz224750 "usbms_input entering");
17210Sstevel@tonic-gate
17220Sstevel@tonic-gate if (b == NULL) {
17230Sstevel@tonic-gate
17240Sstevel@tonic-gate return;
17250Sstevel@tonic-gate }
17260Sstevel@tonic-gate
17270Sstevel@tonic-gate mi = &b->mb_info[b->mb_off];
17280Sstevel@tonic-gate
17290Sstevel@tonic-gate /*
17300Sstevel@tonic-gate * Lower 3 bits are middle, right, left.
17310Sstevel@tonic-gate */
17320Sstevel@tonic-gate c = mp->b_rptr[(usbmsp->usbms_idf).bpos];
17330Sstevel@tonic-gate mi->mi_buttons = (char)USB_NO_BUT_PRESSED;
17340Sstevel@tonic-gate if (c & USBMS_BUT(1)) { /* left button is pressed */
17350Sstevel@tonic-gate mi->mi_buttons = mi->mi_buttons & USB_LEFT_BUT_PRESSED;
17360Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR,
17376710Syz224750 usbms_log_handle,
17386710Syz224750 "left button pressed");
17390Sstevel@tonic-gate }
17400Sstevel@tonic-gate if (c & USBMS_BUT(2)) { /* right button is pressed */
17410Sstevel@tonic-gate mi->mi_buttons = mi->mi_buttons & USB_RIGHT_BUT_PRESSED;
17420Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR,
17436710Syz224750 usbms_log_handle,
17446710Syz224750 "right button pressed");
17450Sstevel@tonic-gate }
17460Sstevel@tonic-gate if (c & USBMS_BUT(3)) { /* middle button is pressed */
17470Sstevel@tonic-gate mi->mi_buttons = mi->mi_buttons &
17486710Syz224750 USB_MIDDLE_BUT_PRESSED;
17490Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR,
17506710Syz224750 usbms_log_handle,
17516710Syz224750 "middle button pressed");
17520Sstevel@tonic-gate }
17530Sstevel@tonic-gate
17540Sstevel@tonic-gate if (nbutt > 3) {
17550Sstevel@tonic-gate for (i = 4; i < (nbutt + 1); i++) {
17560Sstevel@tonic-gate if (c & USBMS_BUT(i)) {
17570Sstevel@tonic-gate mi->mi_buttons = mi->mi_buttons &
17586710Syz224750 USB_BUT_PRESSED(i);
17590Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR,
17606710Syz224750 usbms_log_handle,
17616710Syz224750 "%d button pressed", i);
17620Sstevel@tonic-gate }
17630Sstevel@tonic-gate }
17640Sstevel@tonic-gate }
17650Sstevel@tonic-gate
17661418Sqz150045 /* get the delta X and Y from the sample */
17671418Sqz150045 mi->mi_x += usbms_get_coordinate((usbmsp->usbms_idf).xpos,
17686710Syz224750 (usbmsp->usbms_idf).xlen, mp);
17690Sstevel@tonic-gate
17700Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR,
17716710Syz224750 usbms_log_handle, "x = %d", (int)mi->mi_x);
17720Sstevel@tonic-gate
17730Sstevel@tonic-gate uniqtime32(&mi->mi_time); /* record time when sample arrived */
17740Sstevel@tonic-gate
17751418Sqz150045 mi->mi_y += usbms_get_coordinate((usbmsp->usbms_idf).ypos,
17766710Syz224750 (usbmsp->usbms_idf).ylen, mp);
17770Sstevel@tonic-gate
17780Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle,
17796710Syz224750 "y = %d", (int)mi->mi_y);
17800Sstevel@tonic-gate
17810Sstevel@tonic-gate /*
17820Sstevel@tonic-gate * Check the wheel data in the current event.
17830Sstevel@tonic-gate * If it exists, the wheel data is got from the sample.
17840Sstevel@tonic-gate */
17850Sstevel@tonic-gate
17860Sstevel@tonic-gate if (usbmsp->usbms_num_wheels) {
17871418Sqz150045 mi->mi_z += usbms_get_coordinate((usbmsp->usbms_idf).zpos,
17886710Syz224750 (usbmsp->usbms_idf).zlen, mp);
17890Sstevel@tonic-gate
17900Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle,
17916710Syz224750 "z = %d", (int)mi->mi_z);
17920Sstevel@tonic-gate }
17930Sstevel@tonic-gate
17940Sstevel@tonic-gate if (usbmsp->usbms_jitter) {
17950Sstevel@tonic-gate (void) quntimeout(usbmsp->usbms_rq_ptr,
17966710Syz224750 (timeout_id_t)usbmsp->usbms_timeout_id);
17970Sstevel@tonic-gate usbmsp->usbms_jitter = 0;
17980Sstevel@tonic-gate }
17990Sstevel@tonic-gate
18000Sstevel@tonic-gate if (!usbmsp->usbms_num_wheels) {
18010Sstevel@tonic-gate mi->mi_z = 0;
18020Sstevel@tonic-gate }
18030Sstevel@tonic-gate
18040Sstevel@tonic-gate /*
18050Sstevel@tonic-gate * If there is a wheel movement or a change in the button state,
18060Sstevel@tonic-gate * send the data up immediately.
18070Sstevel@tonic-gate */
18080Sstevel@tonic-gate if (!(mi->mi_z) && (mi->mi_buttons == usbmsp->usbms_oldbutt)) {
18090Sstevel@tonic-gate /*
18100Sstevel@tonic-gate * Buttons did not change; did position?
18110Sstevel@tonic-gate */
18120Sstevel@tonic-gate if (mi->mi_x == 0 && mi->mi_y == 0) {
18130Sstevel@tonic-gate /* no, position did not change */
18140Sstevel@tonic-gate
18150Sstevel@tonic-gate return;
18160Sstevel@tonic-gate }
18170Sstevel@tonic-gate
18180Sstevel@tonic-gate /*
18190Sstevel@tonic-gate * Did the mouse move more than the jitter threshhold?
18200Sstevel@tonic-gate */
18210Sstevel@tonic-gate jitter_radius = usbmsp->usbms_jitter_thresh;
18220Sstevel@tonic-gate if (USB_ABS((int)mi->mi_x) <= jitter_radius &&
18236710Syz224750 USB_ABS((int)mi->mi_y) <= jitter_radius) {
18240Sstevel@tonic-gate /*
18250Sstevel@tonic-gate * Mouse moved less than the jitter threshhold.
18260Sstevel@tonic-gate * Don't indicate an event; keep accumulating motions.
18270Sstevel@tonic-gate * After "jittertimeout" ticks expire, treat
18280Sstevel@tonic-gate * the accumulated delta as the real delta.
18290Sstevel@tonic-gate */
18300Sstevel@tonic-gate usbmsp->usbms_jitter = 1;
18310Sstevel@tonic-gate usbmsp->usbms_timeout_id =
18326710Syz224750 qtimeout(usbmsp->usbms_rq_ptr,
18336710Syz224750 (void (*)())usbms_incr,
18346710Syz224750 (void *)usbmsp,
18356710Syz224750 (clock_t)usbmsp->usbms_jittertimeout);
18360Sstevel@tonic-gate
18370Sstevel@tonic-gate return;
18380Sstevel@tonic-gate }
18390Sstevel@tonic-gate }
18400Sstevel@tonic-gate usbmsp->usbms_oldbutt = mi->mi_buttons;
18410Sstevel@tonic-gate usbms_incr(usbmsp);
18420Sstevel@tonic-gate
18430Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle,
18446710Syz224750 "usbms_input exiting");
18450Sstevel@tonic-gate }
18460Sstevel@tonic-gate
18470Sstevel@tonic-gate
18480Sstevel@tonic-gate /*
18491418Sqz150045 * usbms_get_coordinate():
18501418Sqz150045 * get the X, Y, WHEEL coordinate values
18511418Sqz150045 */
18521418Sqz150045 static int
usbms_get_coordinate(uint_t pos,uint_t len,mblk_t * mp)18531418Sqz150045 usbms_get_coordinate(uint_t pos, uint_t len, mblk_t *mp)
18541418Sqz150045 {
18551418Sqz150045 uint_t utmp, bitval, val;
18561418Sqz150045 int i, xyz;
18571418Sqz150045
18581418Sqz150045 /* get the unsigned int value from the bit stream */
18591418Sqz150045 utmp = 0;
186010060SPengcheng.Chen@Sun.COM for (i = (pos + len - 1); i >= (int)pos; i--) {
18611418Sqz150045 bitval = (mp->b_rptr[i/8] & (1 << (i%8))) >> (i%8);
18621418Sqz150045 utmp = utmp * 2 + bitval;
18631418Sqz150045 }
18641418Sqz150045
18651418Sqz150045 /* convert the unsigned int value into int value */
18661418Sqz150045 val = 1 << (len - 1);
18671418Sqz150045 xyz = (int)(utmp - val);
18681418Sqz150045 if (xyz < 0)
18691418Sqz150045 xyz += val;
18701418Sqz150045 else if (xyz == 0)
18711418Sqz150045 xyz = -(val - 1);
18721418Sqz150045 else
18731418Sqz150045 xyz -= val;
18741418Sqz150045
18751418Sqz150045 return (xyz);
18761418Sqz150045 }
18771418Sqz150045
18781418Sqz150045
18791418Sqz150045 /*
18800Sstevel@tonic-gate * usbms_incr() :
18810Sstevel@tonic-gate * Increment the mouse sample pointer.
18820Sstevel@tonic-gate * Called either immediately after a sample or after a jitter timeout.
18830Sstevel@tonic-gate */
18840Sstevel@tonic-gate static void
usbms_incr(void * arg)18850Sstevel@tonic-gate usbms_incr(void *arg)
18860Sstevel@tonic-gate {
18870Sstevel@tonic-gate usbms_state_t *usbmsp = arg;
18880Sstevel@tonic-gate register struct ms_softc *ms = &usbmsp->usbms_softc;
18890Sstevel@tonic-gate register struct usbmousebuf *b;
18900Sstevel@tonic-gate register struct usbmouseinfo *mi;
18910Sstevel@tonic-gate register int xc, yc, zc;
18920Sstevel@tonic-gate register int wake;
18930Sstevel@tonic-gate register int speedl = usbmsp->usbms_speedlimit;
18940Sstevel@tonic-gate register int xabs, yabs;
18950Sstevel@tonic-gate
18960Sstevel@tonic-gate /*
18970Sstevel@tonic-gate * No longer waiting for jitter timeout
18980Sstevel@tonic-gate */
18990Sstevel@tonic-gate usbmsp->usbms_jitter = 0;
19000Sstevel@tonic-gate
19010Sstevel@tonic-gate b = usbmsp->usbms_buf;
19020Sstevel@tonic-gate
19030Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle,
19046710Syz224750 "usbms_incr entering");
19050Sstevel@tonic-gate
19060Sstevel@tonic-gate if (b == NULL) {
19070Sstevel@tonic-gate
19080Sstevel@tonic-gate return;
19090Sstevel@tonic-gate }
19100Sstevel@tonic-gate mi = &b->mb_info[b->mb_off];
19110Sstevel@tonic-gate if (usbmsp->usbms_speedlaw) {
19120Sstevel@tonic-gate xabs = USB_ABS((int)mi->mi_x);
19130Sstevel@tonic-gate yabs = USB_ABS((int)mi->mi_y);
19140Sstevel@tonic-gate if (xabs > speedl || yabs > speedl) {
19150Sstevel@tonic-gate usbmsp->usbms_speed_count++;
19160Sstevel@tonic-gate }
19170Sstevel@tonic-gate if (xabs > speedl) {
19180Sstevel@tonic-gate mi->mi_x = 0;
19190Sstevel@tonic-gate }
19200Sstevel@tonic-gate if (yabs > speedl) {
19210Sstevel@tonic-gate mi->mi_y = 0;
19220Sstevel@tonic-gate }
19230Sstevel@tonic-gate }
19240Sstevel@tonic-gate
19250Sstevel@tonic-gate
19260Sstevel@tonic-gate xc = yc = zc = 0;
19270Sstevel@tonic-gate
19280Sstevel@tonic-gate /* See if we need to wake up anyone waiting for input */
19290Sstevel@tonic-gate wake = b->mb_off == ms->ms_oldoff;
19300Sstevel@tonic-gate
19310Sstevel@tonic-gate /* Adjust circular buffer pointer */
19320Sstevel@tonic-gate if (++b->mb_off >= b->mb_size) {
19330Sstevel@tonic-gate b->mb_off = 0;
19340Sstevel@tonic-gate mi = b->mb_info;
19350Sstevel@tonic-gate } else {
19360Sstevel@tonic-gate mi++;
19370Sstevel@tonic-gate }
19380Sstevel@tonic-gate
19390Sstevel@tonic-gate /*
19400Sstevel@tonic-gate * If over-took read index then flush buffer so that mouse state
19410Sstevel@tonic-gate * is consistent.
19420Sstevel@tonic-gate */
19430Sstevel@tonic-gate if (b->mb_off == ms->ms_oldoff) {
19440Sstevel@tonic-gate if (overrun_msg) {
19450Sstevel@tonic-gate USB_DPRINTF_L1(PRINT_MASK_ALL, usbms_log_handle,
19466710Syz224750 "Mouse buffer flushed when overrun.");
19470Sstevel@tonic-gate }
19480Sstevel@tonic-gate usbms_flush(usbmsp);
19490Sstevel@tonic-gate overrun_cnt++;
19500Sstevel@tonic-gate mi = b->mb_info;
19510Sstevel@tonic-gate }
19520Sstevel@tonic-gate
19530Sstevel@tonic-gate /* Remember current buttons and fractional part of x & y */
19540Sstevel@tonic-gate mi->mi_buttons = (char)USB_NO_BUT_PRESSED;
19550Sstevel@tonic-gate mi->mi_x = xc;
19560Sstevel@tonic-gate mi->mi_y = yc;
19570Sstevel@tonic-gate mi->mi_z = zc;
19580Sstevel@tonic-gate
19590Sstevel@tonic-gate if (wake) {
19600Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle,
19616710Syz224750 "usbms_incr run service");
19620Sstevel@tonic-gate qenable(usbmsp->usbms_rq_ptr); /* run the service proc */
19630Sstevel@tonic-gate }
19640Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle,
19656710Syz224750 "usbms_incr exiting");
19660Sstevel@tonic-gate }
19670Sstevel@tonic-gate
19680Sstevel@tonic-gate
19690Sstevel@tonic-gate /*
19700Sstevel@tonic-gate * usbms_check_for_wheels
19710Sstevel@tonic-gate * return SUCCESS if wheel is found, else return FAILURE
19720Sstevel@tonic-gate */
19730Sstevel@tonic-gate static int
usbms_check_for_wheels(usbms_state_t * usbmsp)19740Sstevel@tonic-gate usbms_check_for_wheels(usbms_state_t *usbmsp)
19750Sstevel@tonic-gate {
19760Sstevel@tonic-gate int rval, report_id;
19770Sstevel@tonic-gate
19780Sstevel@tonic-gate
19790Sstevel@tonic-gate if (usbmsp->usbms_report_descr_handle) {
19800Sstevel@tonic-gate /* Get the report id that has mouse data */
19810Sstevel@tonic-gate if (hidparser_get_usage_attribute(
19820Sstevel@tonic-gate usbmsp->usbms_report_descr_handle,
19830Sstevel@tonic-gate 0, /* Doesn't matter */
19840Sstevel@tonic-gate HIDPARSER_ITEM_INPUT,
19850Sstevel@tonic-gate HID_GENERIC_DESKTOP,
19860Sstevel@tonic-gate HID_GD_X,
19870Sstevel@tonic-gate HIDPARSER_ITEM_REPORT_ID,
19880Sstevel@tonic-gate &usbmsp->usbms_rptid) == HIDPARSER_NOT_FOUND) {
19890Sstevel@tonic-gate usbmsp->usbms_rptid = HID_REPORT_ID_UNDEFINED;
19900Sstevel@tonic-gate report_id = 0;
19910Sstevel@tonic-gate } else {
19920Sstevel@tonic-gate report_id = usbmsp->usbms_rptid;
19930Sstevel@tonic-gate }
19940Sstevel@tonic-gate
19950Sstevel@tonic-gate /* find no. of wheels in this report */
19960Sstevel@tonic-gate rval = hidparser_get_usage_attribute(
19976710Syz224750 usbmsp->usbms_report_descr_handle,
19986710Syz224750 report_id,
19996710Syz224750 HIDPARSER_ITEM_INPUT,
20006710Syz224750 HID_GENERIC_DESKTOP,
20016710Syz224750 HID_GD_WHEEL,
20026710Syz224750 HIDPARSER_ITEM_REPORT_COUNT,
20036710Syz224750 &usbmsp->usbms_num_wheels);
20040Sstevel@tonic-gate if (rval == HIDPARSER_SUCCESS) {
20050Sstevel@tonic-gate /*
20060Sstevel@tonic-gate * Found wheel. By default enable the wheel.
20070Sstevel@tonic-gate * Currently only enable only the first wheel.
20080Sstevel@tonic-gate */
20090Sstevel@tonic-gate usbmsp->usbms_wheel_state_bf |=
20106710Syz224750 VUID_WHEEL_STATE_ENABLED;
20110Sstevel@tonic-gate
20120Sstevel@tonic-gate return (USB_SUCCESS);
20130Sstevel@tonic-gate }
20140Sstevel@tonic-gate }
20150Sstevel@tonic-gate usbmsp->usbms_num_wheels = 0;
20160Sstevel@tonic-gate
20170Sstevel@tonic-gate return (USB_FAILURE);
20180Sstevel@tonic-gate }
20190Sstevel@tonic-gate
20200Sstevel@tonic-gate
20210Sstevel@tonic-gate /*
20220Sstevel@tonic-gate * usbms_make_copyreq
20230Sstevel@tonic-gate * helper function for usbms ioctls
20240Sstevel@tonic-gate */
20250Sstevel@tonic-gate static int
usbms_make_copyreq(mblk_t * mp,uint_t pvtsize,uint_t state,uint_t reqsize,uint_t contsize,uint_t copytype)20260Sstevel@tonic-gate usbms_make_copyreq(mblk_t *mp,
20270Sstevel@tonic-gate uint_t pvtsize,
20280Sstevel@tonic-gate uint_t state,
20290Sstevel@tonic-gate uint_t reqsize,
20300Sstevel@tonic-gate uint_t contsize,
20310Sstevel@tonic-gate uint_t copytype)
20320Sstevel@tonic-gate {
20330Sstevel@tonic-gate
20340Sstevel@tonic-gate struct copyreq *cq;
20350Sstevel@tonic-gate struct copyresp *cr;
20360Sstevel@tonic-gate mblk_t *ioctmp;
20370Sstevel@tonic-gate mblk_t *conttmp;
20380Sstevel@tonic-gate usbms_iocstate_t *usbmsioc;
20390Sstevel@tonic-gate
20400Sstevel@tonic-gate if ((!pvtsize) && state) {
20410Sstevel@tonic-gate cr = (struct copyresp *)mp->b_rptr;
20420Sstevel@tonic-gate ioctmp = cr->cp_private;
20430Sstevel@tonic-gate }
20440Sstevel@tonic-gate cq = (struct copyreq *)mp->b_rptr;
20450Sstevel@tonic-gate if (mp->b_cont == NULL) {
20460Sstevel@tonic-gate
20470Sstevel@tonic-gate return (EINVAL);
20480Sstevel@tonic-gate }
20490Sstevel@tonic-gate cq->cq_addr = *((caddr_t *)mp->b_cont->b_rptr);
20500Sstevel@tonic-gate cq->cq_size = reqsize;
20510Sstevel@tonic-gate cq->cq_flag = 0;
20520Sstevel@tonic-gate if (pvtsize) {
20530Sstevel@tonic-gate ioctmp = (mblk_t *)allocb(pvtsize, BPRI_MED);
20540Sstevel@tonic-gate if (ioctmp == NULL) {
20550Sstevel@tonic-gate
20560Sstevel@tonic-gate return (EAGAIN);
20570Sstevel@tonic-gate }
20580Sstevel@tonic-gate cq->cq_private = ioctmp;
20590Sstevel@tonic-gate ioctmp = cq->cq_private;
20606710Syz224750 } else {
20616710Syz224750 /*
20626710Syz224750 * Here we need to set cq_private even if there's
20636710Syz224750 * no private data, otherwise its value will be
20646710Syz224750 * TRANSPARENT (-1) on 64bit systems because it
20656710Syz224750 * overlaps iocp->ioc_count. If user address (cq_addr)
20666710Syz224750 * is invalid, it would cause panic later in
20676710Syz224750 * usbms_miocdata:
20686710Syz224750 * freemsg((mblk_t *)copyresp->cp_private);
20696710Syz224750 */
20706710Syz224750 cq->cq_private = NULL;
20716710Syz224750 }
20720Sstevel@tonic-gate if (state) {
20730Sstevel@tonic-gate usbmsioc = (usbms_iocstate_t *)ioctmp->b_rptr;
20740Sstevel@tonic-gate usbmsioc->ioc_state = state;
20756710Syz224750 if (pvtsize) { /* M_COPYIN */
20760Sstevel@tonic-gate usbmsioc->u_addr = cq->cq_addr;
20770Sstevel@tonic-gate } else {
20780Sstevel@tonic-gate cq->cq_addr = usbmsioc->u_addr;
20790Sstevel@tonic-gate cq->cq_private = ioctmp;
20800Sstevel@tonic-gate }
20810Sstevel@tonic-gate ioctmp->b_wptr = ioctmp->b_rptr + sizeof (usbms_iocstate_t);
20820Sstevel@tonic-gate }
20830Sstevel@tonic-gate if (contsize) {
20840Sstevel@tonic-gate conttmp = (mblk_t *)allocb(contsize, BPRI_MED);
20850Sstevel@tonic-gate if (conttmp == NULL) {
20860Sstevel@tonic-gate
20870Sstevel@tonic-gate return (EAGAIN);
20880Sstevel@tonic-gate }
20890Sstevel@tonic-gate if (mp->b_cont) {
20900Sstevel@tonic-gate freemsg(mp->b_cont);
20910Sstevel@tonic-gate mp->b_cont = conttmp;
20920Sstevel@tonic-gate }
20930Sstevel@tonic-gate }
20947492SZhigang.Lu@Sun.COM mp->b_datap->db_type = (unsigned char)copytype;
20950Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (struct copyreq);
20960Sstevel@tonic-gate
20970Sstevel@tonic-gate return (USB_SUCCESS);
20980Sstevel@tonic-gate }
20990Sstevel@tonic-gate
21000Sstevel@tonic-gate
21010Sstevel@tonic-gate static int
usbms_service_wheel_info(register queue_t * q,register mblk_t * datap)21020Sstevel@tonic-gate usbms_service_wheel_info(register queue_t *q, register mblk_t *datap)
21030Sstevel@tonic-gate {
21040Sstevel@tonic-gate
21050Sstevel@tonic-gate wheel_info *wi;
21060Sstevel@tonic-gate usbms_state_t *usbmsp = (usbms_state_t *)q->q_ptr;
21070Sstevel@tonic-gate uint_t err;
21080Sstevel@tonic-gate
21090Sstevel@tonic-gate wi = (wheel_info *)datap->b_rptr;
21100Sstevel@tonic-gate if (wi->vers != VUID_WHEEL_INFO_VERS) {
21110Sstevel@tonic-gate err = EINVAL;
21120Sstevel@tonic-gate
21130Sstevel@tonic-gate return (err);
21140Sstevel@tonic-gate }
21150Sstevel@tonic-gate if (wi->id > (usbmsp->usbms_num_wheels - 1)) {
21160Sstevel@tonic-gate err = EINVAL;
21170Sstevel@tonic-gate
21180Sstevel@tonic-gate return (err);
21190Sstevel@tonic-gate }
21200Sstevel@tonic-gate wi->format = (usbmsp->usbms_wheel_orient_bf & (1 << wi->id)) ?
21210Sstevel@tonic-gate VUID_WHEEL_FORMAT_HORIZONTAL : VUID_WHEEL_FORMAT_VERTICAL;
21220Sstevel@tonic-gate
21230Sstevel@tonic-gate return (USB_SUCCESS);
21240Sstevel@tonic-gate }
21250Sstevel@tonic-gate
21260Sstevel@tonic-gate
21270Sstevel@tonic-gate static int
usbms_service_wheel_state(register queue_t * q,register mblk_t * datap,register uint_t cmd)21280Sstevel@tonic-gate usbms_service_wheel_state(register queue_t *q,
21290Sstevel@tonic-gate register mblk_t *datap,
21300Sstevel@tonic-gate register uint_t cmd)
21310Sstevel@tonic-gate {
21320Sstevel@tonic-gate
21330Sstevel@tonic-gate wheel_state *ws;
21340Sstevel@tonic-gate uint_t err;
21350Sstevel@tonic-gate usbms_state_t *usbmsp = (usbms_state_t *)q->q_ptr;
21360Sstevel@tonic-gate
21370Sstevel@tonic-gate ws = (wheel_state *)datap->b_rptr;
21380Sstevel@tonic-gate if (ws->vers != VUID_WHEEL_STATE_VERS) {
21390Sstevel@tonic-gate err = EINVAL;
21400Sstevel@tonic-gate
21410Sstevel@tonic-gate return (err);
21420Sstevel@tonic-gate }
21430Sstevel@tonic-gate if (ws->id > (usbmsp->usbms_num_wheels - 1)) {
21440Sstevel@tonic-gate err = EINVAL;
21450Sstevel@tonic-gate
21460Sstevel@tonic-gate return (err);
21470Sstevel@tonic-gate }
21480Sstevel@tonic-gate
21490Sstevel@tonic-gate switch (cmd) {
21500Sstevel@tonic-gate case VUIDGWHEELSTATE:
21510Sstevel@tonic-gate ws->stateflags = (usbmsp->usbms_wheel_state_bf >> ws->id) &
21520Sstevel@tonic-gate VUID_WHEEL_STATE_ENABLED;
21530Sstevel@tonic-gate
21540Sstevel@tonic-gate break;
21550Sstevel@tonic-gate case VUIDSWHEELSTATE:
21560Sstevel@tonic-gate usbmsp->usbms_wheel_state_bf = (ws->stateflags << ws->id) |
21570Sstevel@tonic-gate (~(1 << ws->id) & usbmsp->usbms_wheel_state_bf);
21580Sstevel@tonic-gate
21590Sstevel@tonic-gate break;
21600Sstevel@tonic-gate default:
21610Sstevel@tonic-gate err = EINVAL;
21620Sstevel@tonic-gate
21630Sstevel@tonic-gate return (err);
21640Sstevel@tonic-gate }
21650Sstevel@tonic-gate
21660Sstevel@tonic-gate return (USB_SUCCESS);
21670Sstevel@tonic-gate }
21680Sstevel@tonic-gate
21690Sstevel@tonic-gate
21700Sstevel@tonic-gate /*
21710Sstevel@tonic-gate * usbms_get_screen_parms() :
21720Sstevel@tonic-gate * Called from MSIOSRESOLUTION ioctl to get the
21730Sstevel@tonic-gate * current screen height/width params from X.
21740Sstevel@tonic-gate */
21750Sstevel@tonic-gate static int
usbms_get_screen_parms(register queue_t * q,register mblk_t * datap)21760Sstevel@tonic-gate usbms_get_screen_parms(register queue_t *q,
21770Sstevel@tonic-gate register mblk_t *datap)
21780Sstevel@tonic-gate {
21790Sstevel@tonic-gate
21800Sstevel@tonic-gate usbms_state_t *usbmsp = (usbms_state_t *)q->q_ptr;
21810Sstevel@tonic-gate Ms_screen_resolution *res = &(usbmsp->usbms_resolution);
21820Sstevel@tonic-gate Ms_screen_resolution *data;
21830Sstevel@tonic-gate
21840Sstevel@tonic-gate data = (Ms_screen_resolution *)datap->b_rptr;
21850Sstevel@tonic-gate res->height = data->height;
21860Sstevel@tonic-gate res->width = data->width;
21870Sstevel@tonic-gate
21880Sstevel@tonic-gate return (USB_SUCCESS);
21890Sstevel@tonic-gate }
21900Sstevel@tonic-gate
21910Sstevel@tonic-gate
21920Sstevel@tonic-gate static void
usbms_ack_ioctl(mblk_t * mp)21930Sstevel@tonic-gate usbms_ack_ioctl(mblk_t *mp)
21940Sstevel@tonic-gate {
21950Sstevel@tonic-gate
21960Sstevel@tonic-gate struct iocblk *iocbp = (struct iocblk *)mp->b_rptr;
21970Sstevel@tonic-gate
21980Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK;
21990Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (struct iocblk);
22000Sstevel@tonic-gate iocbp->ioc_error = 0;
22010Sstevel@tonic-gate iocbp->ioc_count = 0;
22020Sstevel@tonic-gate iocbp->ioc_rval = 0;
22030Sstevel@tonic-gate if (mp->b_cont != NULL) {
22040Sstevel@tonic-gate freemsg(mp->b_cont);
22050Sstevel@tonic-gate mp->b_cont = NULL;
22060Sstevel@tonic-gate }
22070Sstevel@tonic-gate }
22080Sstevel@tonic-gate
22090Sstevel@tonic-gate
22100Sstevel@tonic-gate /*
22111662Sqz150045 * usbms_setup_abs_mouse_event() :
22121662Sqz150045 * Called from MSIOSRESOLUTION ioctl to create
22131662Sqz150045 * the absolute mouse type firm event.
22141662Sqz150045 */
22151662Sqz150045 static mblk_t *
usbms_setup_abs_mouse_event()22161662Sqz150045 usbms_setup_abs_mouse_event()
22171662Sqz150045 {
22181662Sqz150045 mblk_t *mb;
22191662Sqz150045 Firm_event *fep;
22201662Sqz150045
22211662Sqz150045 if ((mb = allocb(sizeof (Firm_event), BPRI_HI)) != NULL) {
22221662Sqz150045 fep = (Firm_event *)mb->b_wptr;
22231662Sqz150045 fep->id = MOUSE_TYPE_ABSOLUTE;
22241662Sqz150045 fep->pair_type = FE_PAIR_NONE;
22251662Sqz150045 fep->pair = NULL;
22261662Sqz150045 fep->value = NULL;
22271662Sqz150045 mb->b_wptr += sizeof (Firm_event);
22281662Sqz150045 } else {
22291662Sqz150045 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
22301662Sqz150045 "No resource to report ABS mouse event");
22311662Sqz150045 }
22321662Sqz150045
22331662Sqz150045 return (mb);
22341662Sqz150045 }
22351662Sqz150045
22361662Sqz150045
22371662Sqz150045 /*
22380Sstevel@tonic-gate * usbms_read_input_data_format() :
22390Sstevel@tonic-gate * Get the mouse packet length and usages' length.
22400Sstevel@tonic-gate * Check whether X and Y are relative or absolute.
22410Sstevel@tonic-gate *
22420Sstevel@tonic-gate * If they are absolute, the X and Y logical max values
22430Sstevel@tonic-gate * will be got. A firm event will be created and sent
22440Sstevel@tonic-gate * to the upper level.
22450Sstevel@tonic-gate */
22460Sstevel@tonic-gate int
usbms_read_input_data_format(usbms_state_t * usbmsp)22470Sstevel@tonic-gate usbms_read_input_data_format(usbms_state_t *usbmsp)
22480Sstevel@tonic-gate {
22490Sstevel@tonic-gate
22500Sstevel@tonic-gate hidparser_rpt_t *ms_rpt;
22511418Sqz150045 uint_t i, button_page;
22520Sstevel@tonic-gate uint_t limit = 0;
22530Sstevel@tonic-gate uint32_t rptcnt, rptsz;
22540Sstevel@tonic-gate usbms_idf *idf = &(usbmsp->usbms_idf);
22550Sstevel@tonic-gate Ms_screen_resolution *res = &(usbmsp->usbms_resolution);
22560Sstevel@tonic-gate mblk_t *mb;
22570Sstevel@tonic-gate register queue_t *q;
22580Sstevel@tonic-gate int rval;
22590Sstevel@tonic-gate
22601662Sqz150045 usbmsp->usbms_rpt_abs = B_FALSE;
22611662Sqz150045
22620Sstevel@tonic-gate /* allocate hidparser report structure */
22630Sstevel@tonic-gate ms_rpt = kmem_zalloc(sizeof (hidparser_rpt_t), KM_SLEEP);
22640Sstevel@tonic-gate
22650Sstevel@tonic-gate /*
22660Sstevel@tonic-gate * Check what is the total length of the mouse packet
22670Sstevel@tonic-gate * and get the usages and their lengths in order
22680Sstevel@tonic-gate */
22690Sstevel@tonic-gate
22700Sstevel@tonic-gate rval = hidparser_get_usage_list_in_order(
22716710Syz224750 usbmsp->usbms_report_descr_handle,
22726710Syz224750 usbmsp->usbms_rptid,
22736710Syz224750 HIDPARSER_ITEM_INPUT,
22746710Syz224750 ms_rpt);
22750Sstevel@tonic-gate
22760Sstevel@tonic-gate if (rval != HIDPARSER_SUCCESS) {
22770Sstevel@tonic-gate
22780Sstevel@tonic-gate kmem_free(ms_rpt, sizeof (hidparser_rpt_t));
22790Sstevel@tonic-gate return (USB_FAILURE);
22800Sstevel@tonic-gate }
22810Sstevel@tonic-gate
22821418Sqz150045 button_page = 0;
22830Sstevel@tonic-gate for (i = 0; i < ms_rpt->no_of_usages; i++) {
22840Sstevel@tonic-gate rptcnt = ms_rpt->usage_descr[i].rptcnt;
22850Sstevel@tonic-gate rptsz = ms_rpt->usage_descr[i].rptsz;
22861418Sqz150045 if ((ms_rpt->usage_descr[i].usage_page ==
22876710Syz224750 HID_BUTTON_PAGE) && (!button_page)) {
22881418Sqz150045 idf->bpos = limit;
22891418Sqz150045 limit += (rptcnt * rptsz);
22901418Sqz150045 button_page = 1;
229131Sqz150045 continue;
229231Sqz150045 }
22931418Sqz150045
22941418Sqz150045 switch (ms_rpt->usage_descr[i].usage_id) {
22951418Sqz150045
22961418Sqz150045 case HID_GD_X:
22971418Sqz150045 idf->xpos = limit;
22981418Sqz150045 idf->xlen = rptsz;
22991418Sqz150045 limit += rptsz;
23001418Sqz150045 break;
23011418Sqz150045 case HID_GD_Y:
23021418Sqz150045 idf->ypos = limit;
23031418Sqz150045 idf->ylen = rptsz;
23041418Sqz150045 limit += rptsz;
23051418Sqz150045 break;
23062542Ssetje case HID_GD_Z:
23072542Ssetje /*
23082542Ssetje * z-axis not yet supported, just skip it.
23092542Ssetje *
23102542Ssetje * It would be ideal if the HID_GD_Z data would be
23112542Ssetje * reported as horizontal wheel, and HID_GD_WHEEL
23122542Ssetje * as vertical wheel.
23132542Ssetje *
23142542Ssetje * We can not use the default case, because
23152542Ssetje * that skips rptcnt*rptsz, but for an
23162542Ssetje * "Apple Might Mouse" rptsz must be used.
23172542Ssetje */
23182542Ssetje limit += rptsz;
23192542Ssetje break;
23201418Sqz150045 case HID_GD_WHEEL:
23211418Sqz150045 idf->zpos = limit;
23221418Sqz150045 idf->zlen = rptsz;
23231418Sqz150045 limit += rptsz;
23241418Sqz150045 break;
23251418Sqz150045 default:
23261418Sqz150045 limit += rptcnt * rptsz;
23271418Sqz150045 break;
23280Sstevel@tonic-gate }
23290Sstevel@tonic-gate }
23300Sstevel@tonic-gate
23310Sstevel@tonic-gate kmem_free(ms_rpt, sizeof (hidparser_rpt_t));
23320Sstevel@tonic-gate
233331Sqz150045 /* get the length of sending data */
233431Sqz150045 idf->tlen = limit / 8;
23350Sstevel@tonic-gate
23360Sstevel@tonic-gate /* Check whether X and Y are relative or absolute */
23370Sstevel@tonic-gate rval = hidparser_get_main_item_data_descr(
23386710Syz224750 usbmsp->usbms_report_descr_handle,
23396710Syz224750 usbmsp->usbms_rptid,
23406710Syz224750 HIDPARSER_ITEM_INPUT,
23416710Syz224750 HID_GENERIC_DESKTOP,
23426710Syz224750 HID_GD_X,
23436710Syz224750 &idf->xattr);
23440Sstevel@tonic-gate
23450Sstevel@tonic-gate if (rval != HIDPARSER_SUCCESS) {
23460Sstevel@tonic-gate
23470Sstevel@tonic-gate return (USB_FAILURE);
23480Sstevel@tonic-gate }
23490Sstevel@tonic-gate
23500Sstevel@tonic-gate /* For the time being assume that Y also has the same attr */
23510Sstevel@tonic-gate idf->yattr = idf->xattr;
23520Sstevel@tonic-gate
23530Sstevel@tonic-gate /* get the logical_maximum for X and Y respectively */
23540Sstevel@tonic-gate if (!(idf->xattr & HID_MAIN_ITEM_RELATIVE)) {
235531Sqz150045
235631Sqz150045 /* the data format can't be parsed correctly */
235731Sqz150045 if (limit % 8) {
235831Sqz150045 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
235931Sqz150045 "Wrong data packet include %d bits", limit);
236031Sqz150045
236131Sqz150045 return (USB_FAILURE);
236231Sqz150045 }
23630Sstevel@tonic-gate if (hidparser_get_usage_attribute(
23646710Syz224750 usbmsp->usbms_report_descr_handle,
23656710Syz224750 usbmsp->usbms_rptid,
23666710Syz224750 HIDPARSER_ITEM_INPUT,
23676710Syz224750 HID_GENERIC_DESKTOP,
23686710Syz224750 HID_GD_X,
23696710Syz224750 HIDPARSER_ITEM_LOGICAL_MAXIMUM,
23706710Syz224750 &usbmsp->usbms_logical_Xmax) != HIDPARSER_SUCCESS) {
23710Sstevel@tonic-gate
23720Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
23730Sstevel@tonic-gate "fail to get X logical max.");
23740Sstevel@tonic-gate
23750Sstevel@tonic-gate return (USB_FAILURE);
23760Sstevel@tonic-gate }
23770Sstevel@tonic-gate if (hidparser_get_usage_attribute(
23786710Syz224750 usbmsp->usbms_report_descr_handle,
23796710Syz224750 usbmsp->usbms_rptid,
23806710Syz224750 HIDPARSER_ITEM_INPUT,
23816710Syz224750 HID_GENERIC_DESKTOP,
23826710Syz224750 HID_GD_Y,
23836710Syz224750 HIDPARSER_ITEM_LOGICAL_MAXIMUM,
23846710Syz224750 &usbmsp->usbms_logical_Ymax) != HIDPARSER_SUCCESS) {
23850Sstevel@tonic-gate
23860Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle,
23870Sstevel@tonic-gate "fail to get Y logical max.");
23880Sstevel@tonic-gate
23890Sstevel@tonic-gate return (USB_FAILURE);
23900Sstevel@tonic-gate }
23910Sstevel@tonic-gate
23920Sstevel@tonic-gate if (usbmsp->usbms_logical_Xmax == 0) {
23930Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL,
23940Sstevel@tonic-gate usbms_log_handle,
239531Sqz150045 "X logical max value is zero");
23960Sstevel@tonic-gate
23970Sstevel@tonic-gate return (USB_FAILURE);
23980Sstevel@tonic-gate }
23990Sstevel@tonic-gate
24000Sstevel@tonic-gate if (usbmsp->usbms_logical_Ymax == 0) {
24010Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL,
24020Sstevel@tonic-gate usbms_log_handle,
240331Sqz150045 "Y logical max value is zero");
24040Sstevel@tonic-gate
24050Sstevel@tonic-gate return (USB_FAILURE);
24060Sstevel@tonic-gate }
24070Sstevel@tonic-gate
24080Sstevel@tonic-gate res->height = USBMS_DEFAULT_RES_HEIGHT;
24090Sstevel@tonic-gate res->width = USBMS_DEFAULT_RES_WIDTH;
24100Sstevel@tonic-gate
24110Sstevel@tonic-gate /* The wheel is not supported in current remote kvms. */
24120Sstevel@tonic-gate usbmsp->usbms_num_wheels = 0;
24131662Sqz150045 q = usbmsp->usbms_rq_ptr;
24141662Sqz150045 if ((mb = usbms_setup_abs_mouse_event()) != NULL) {
24151662Sqz150045 putnext(q, mb);
24161662Sqz150045 } else {
24170Sstevel@tonic-gate
24180Sstevel@tonic-gate return (USB_NO_RESOURCES);
24190Sstevel@tonic-gate }
24200Sstevel@tonic-gate }
24210Sstevel@tonic-gate
24220Sstevel@tonic-gate return (USB_SUCCESS);
24230Sstevel@tonic-gate }
2424