9576 hid_attach is missing one mutex_exit in error path
[unleashed.git] / usr / src / uts / common / io / usb / clients / hid / hid.c
blob084fa7fedc4b2862e832dd97027cfb2364e590fe
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2016 Joyent, Inc.
29 * Human Interface Device driver (HID)
31 * The HID driver is a software driver which acts as a class
32 * driver for USB human input devices like keyboard, mouse,
33 * joystick etc and provides the class-specific interfaces
34 * between these client driver modules and the Universal Serial
35 * Bus Driver(USBA).
37 * NOTE: This driver is not DDI compliant in that it uses undocumented
38 * functions for logging (USB_DPRINTF_L*, usb_alloc_log_hdl, usb_free_log_hdl).
40 * Undocumented functions may go away in a future Solaris OS release.
42 * Please see the DDK for sample code of these functions, and for the usbskel
43 * skeleton template driver which contains scaled-down versions of these
44 * functions written in a DDI-compliant way.
47 #define USBDRV_MAJOR_VER 2
48 #define USBDRV_MINOR_VER 0
50 #include <sys/usb/usba.h>
51 #include <sys/usb/usba/genconsole.h>
52 #include <sys/usb/clients/hid/hid.h>
53 #include <sys/usb/clients/hid/hid_polled.h>
54 #include <sys/usb/clients/hidparser/hidparser.h>
55 #include <sys/usb/clients/hid/hidvar.h>
56 #include <sys/usb/clients/hid/hidminor.h>
57 #include <sys/usb/clients/hidparser/hid_parser_driver.h>
58 #include <sys/stropts.h>
59 #include <sys/sunddi.h>
60 #include <sys/stream.h>
61 #include <sys/strsun.h>
63 extern int ddi_create_internal_pathname(dev_info_t *, char *, int, minor_t);
65 /* Debugging support */
66 uint_t hid_errmask = (uint_t)PRINT_MASK_ALL;
67 uint_t hid_errlevel = USB_LOG_L4;
68 uint_t hid_instance_debug = (uint_t)-1;
70 /* tunables */
71 int hid_default_pipe_drain_timeout = HID_DEFAULT_PIPE_DRAIN_TIMEOUT;
72 int hid_pm_mouse = 1; /* enable remote_wakeup for USB mouse/keyboard */
74 /* soft state structures */
75 #define HID_INITIAL_SOFT_SPACE 4
76 static void *hid_statep;
78 /* Callbacks */
79 static void hid_interrupt_pipe_callback(usb_pipe_handle_t,
80 usb_intr_req_t *);
81 static void hid_default_pipe_callback(usb_pipe_handle_t, usb_ctrl_req_t *);
82 static void hid_interrupt_pipe_exception_callback(usb_pipe_handle_t,
83 usb_intr_req_t *);
84 static void hid_default_pipe_exception_callback(usb_pipe_handle_t,
85 usb_ctrl_req_t *);
86 static int hid_restore_state_event_callback(dev_info_t *);
87 static int hid_disconnect_event_callback(dev_info_t *);
88 static int hid_cpr_suspend(hid_state_t *hidp);
89 static void hid_cpr_resume(hid_state_t *hidp);
90 static void hid_power_change_callback(void *arg, int rval);
92 /* Supporting routines */
93 static size_t hid_parse_hid_descr(usb_hid_descr_t *, size_t,
94 usb_alt_if_data_t *, usb_ep_data_t *);
95 static int hid_parse_hid_descr_failure(hid_state_t *);
96 static int hid_handle_report_descriptor(hid_state_t *, int);
97 static void hid_set_idle(hid_state_t *);
98 static void hid_set_protocol(hid_state_t *, int);
99 static void hid_detach_cleanup(dev_info_t *, hid_state_t *);
101 static int hid_start_intr_polling(hid_state_t *);
102 static void hid_close_intr_pipe(hid_state_t *);
103 static int hid_mctl_execute_cmd(queue_t *, int, hid_req_t *,
104 mblk_t *);
105 static int hid_mctl_receive(queue_t *, mblk_t *);
106 static int hid_send_async_ctrl_request(hid_default_pipe_arg_t *, hid_req_t *,
107 uchar_t, int, ushort_t);
109 static void hid_create_pm_components(dev_info_t *, hid_state_t *);
110 static int hid_is_pm_enabled(dev_info_t *);
111 static void hid_restore_device_state(dev_info_t *, hid_state_t *);
112 static void hid_save_device_state(hid_state_t *);
114 static void hid_qreply_merror(queue_t *, mblk_t *, uchar_t);
115 static mblk_t *hid_data2mblk(uchar_t *, int);
116 static void hid_flush(queue_t *);
118 static int hid_pwrlvl0(hid_state_t *);
119 static int hid_pwrlvl1(hid_state_t *);
120 static int hid_pwrlvl2(hid_state_t *);
121 static int hid_pwrlvl3(hid_state_t *);
122 static void hid_pm_busy_component(hid_state_t *);
123 static void hid_pm_idle_component(hid_state_t *);
125 static int hid_polled_read(hid_polled_handle_t, uchar_t **);
126 static int hid_polled_input_enter(hid_polled_handle_t);
127 static int hid_polled_input_exit(hid_polled_handle_t);
128 static int hid_polled_input_init(hid_state_t *);
129 static int hid_polled_input_fini(hid_state_t *);
131 /* Streams entry points */
132 static int hid_open(queue_t *, dev_t *, int, int, cred_t *);
133 static int hid_close(queue_t *, int, cred_t *);
134 static int hid_wput(queue_t *, mblk_t *);
135 static int hid_wsrv(queue_t *);
137 /* dev_ops entry points */
138 static int hid_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
139 static int hid_attach(dev_info_t *, ddi_attach_cmd_t);
140 static int hid_detach(dev_info_t *, ddi_detach_cmd_t);
141 static int hid_power(dev_info_t *, int, int);
144 * Warlock is not aware of the automatic locking mechanisms for
145 * streams drivers. The hid streams enter points are protected by
146 * a per module perimeter. If the locking in hid is a bottleneck
147 * per queue pair or per queue locking may be used. Since warlock
148 * is not aware of the streams perimeters, these notes have been added.
150 * Note that the perimeters do not protect the driver from callbacks
151 * happening while a streams entry point is executing. So, the hid_mutex
152 * has been created to protect the data.
154 _NOTE(SCHEME_PROTECTS_DATA("unique per call", iocblk))
155 _NOTE(SCHEME_PROTECTS_DATA("unique per call", datab))
156 _NOTE(SCHEME_PROTECTS_DATA("unique per call", msgb))
157 _NOTE(SCHEME_PROTECTS_DATA("unique per call", queue))
158 _NOTE(SCHEME_PROTECTS_DATA("unique per call", usb_ctrl_req))
159 _NOTE(SCHEME_PROTECTS_DATA("unique per call", usb_intr_req))
161 /* module information */
162 static struct module_info hid_mod_info = {
163 0x0ffff, /* module id number */
164 "hid", /* module name */
165 0, /* min packet size accepted */
166 INFPSZ, /* max packet size accepted */
167 512, /* hi-water mark */
168 128 /* lo-water mark */
171 /* read queue information structure */
172 static struct qinit rinit = {
173 NULL, /* put procedure not needed */
174 NULL, /* service procedure not needed */
175 hid_open, /* called on startup */
176 hid_close, /* called on finish */
177 NULL, /* for future use */
178 &hid_mod_info, /* module information structure */
179 NULL /* module statistics structure */
182 /* write queue information structure */
183 static struct qinit winit = {
184 hid_wput, /* put procedure */
185 hid_wsrv, /* service procedure */
186 NULL, /* open not used on write side */
187 NULL, /* close not used on write side */
188 NULL, /* for future use */
189 &hid_mod_info, /* module information structure */
190 NULL /* module statistics structure */
193 struct streamtab hid_streamtab = {
194 &rinit,
195 &winit,
196 NULL, /* not a MUX */
197 NULL /* not a MUX */
200 struct cb_ops hid_cb_ops = {
201 nulldev, /* open */
202 nulldev, /* close */
203 nulldev, /* strategy */
204 nulldev, /* print */
205 nulldev, /* dump */
206 nulldev, /* read */
207 nulldev, /* write */
208 nulldev, /* ioctl */
209 nulldev, /* devmap */
210 nulldev, /* mmap */
211 nulldev, /* segmap */
212 nochpoll, /* poll */
213 ddi_prop_op, /* cb_prop_op */
214 &hid_streamtab, /* streamtab */
215 D_MP | D_MTPERQ
219 static struct dev_ops hid_ops = {
220 DEVO_REV, /* devo_rev, */
221 0, /* refcnt */
222 hid_info, /* info */
223 nulldev, /* identify */
224 nulldev, /* probe */
225 hid_attach, /* attach */
226 hid_detach, /* detach */
227 nodev, /* reset */
228 &hid_cb_ops, /* driver operations */
229 NULL, /* bus operations */
230 hid_power, /* power */
231 ddi_quiesce_not_needed, /* quiesce */
234 static struct modldrv hidmodldrv = {
235 &mod_driverops,
236 "USB HID Client Driver",
237 &hid_ops /* driver ops */
240 static struct modlinkage modlinkage = {
241 MODREV_1,
242 &hidmodldrv,
243 NULL,
246 static usb_event_t hid_events = {
247 hid_disconnect_event_callback,
248 hid_restore_state_event_callback,
249 NULL,
250 NULL,
255 _init(void)
257 int rval;
259 if (((rval = ddi_soft_state_init(&hid_statep, sizeof (hid_state_t),
260 HID_INITIAL_SOFT_SPACE)) != 0)) {
262 return (rval);
265 if ((rval = mod_install(&modlinkage)) != 0) {
266 ddi_soft_state_fini(&hid_statep);
269 return (rval);
274 _fini(void)
276 int rval;
278 if ((rval = mod_remove(&modlinkage)) != 0) {
280 return (rval);
283 ddi_soft_state_fini(&hid_statep);
285 return (rval);
290 _info(struct modinfo *modinfop)
292 return (mod_info(&modlinkage, modinfop));
297 * hid_info :
298 * Get minor number, soft state structure etc.
300 /*ARGSUSED*/
301 static int
302 hid_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
304 hid_state_t *hidp = NULL;
305 int error = DDI_FAILURE;
306 minor_t minor = getminor((dev_t)arg);
307 int instance = HID_MINOR_TO_INSTANCE(minor);
309 switch (infocmd) {
310 case DDI_INFO_DEVT2DEVINFO:
311 if ((hidp = ddi_get_soft_state(hid_statep, instance)) != NULL) {
312 *result = hidp->hid_dip;
313 if (*result != NULL) {
314 error = DDI_SUCCESS;
316 } else
317 *result = NULL;
318 break;
319 case DDI_INFO_DEVT2INSTANCE:
320 *result = (void *)(uintptr_t)instance;
321 error = DDI_SUCCESS;
322 break;
323 default:
324 break;
327 return (error);
332 * hid_attach :
333 * Gets called at the time of attach. Do allocation,
334 * and initialization of the software structure.
335 * Get all the descriptors, setup the
336 * report descriptor tree by calling hidparser
337 * function.
339 static int
340 hid_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
343 int instance = ddi_get_instance(dip);
344 int parse_hid_descr_error = 0;
345 hid_state_t *hidp = NULL;
346 uint32_t usage_page;
347 uint32_t usage;
348 usb_client_dev_data_t *dev_data;
349 usb_alt_if_data_t *altif_data;
350 char minor_name[HID_MINOR_NAME_LEN];
351 usb_ep_data_t *ep_data;
353 switch (cmd) {
354 case DDI_ATTACH:
355 break;
356 case DDI_RESUME:
357 hidp = ddi_get_soft_state(hid_statep, instance);
358 hid_cpr_resume(hidp);
359 return (DDI_SUCCESS);
360 default:
362 return (DDI_FAILURE);
366 * Allocate softstate information and get softstate pointer
368 if (ddi_soft_state_zalloc(hid_statep, instance) == DDI_SUCCESS) {
369 hidp = ddi_get_soft_state(hid_statep, instance);
371 if (hidp == NULL) {
373 goto fail;
376 hidp->hid_log_handle = usb_alloc_log_hdl(dip, NULL, &hid_errlevel,
377 &hid_errmask, &hid_instance_debug, 0);
379 hidp->hid_instance = instance;
380 hidp->hid_dip = dip;
383 * Register with USBA. Just retrieve interface descriptor
385 if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
386 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
387 "hid_attach: client attach failed");
389 goto fail;
392 if (usb_get_dev_data(dip, &dev_data, USB_PARSE_LVL_IF, 0) !=
393 USB_SUCCESS) {
395 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
396 "hid_attach: usb_get_dev_data() failed");
398 goto fail;
401 /* initialize mutex */
402 mutex_init(&hidp->hid_mutex, NULL, MUTEX_DRIVER,
403 dev_data->dev_iblock_cookie);
405 hidp->hid_attach_flags |= HID_LOCK_INIT;
407 /* get interface data for alternate 0 */
408 altif_data = &dev_data->dev_curr_cfg->
409 cfg_if[dev_data->dev_curr_if].if_alt[0];
411 mutex_enter(&hidp->hid_mutex);
412 hidp->hid_dev_data = dev_data;
413 hidp->hid_dev_descr = dev_data->dev_descr;
414 hidp->hid_interfaceno = dev_data->dev_curr_if;
415 hidp->hid_if_descr = altif_data->altif_descr;
417 * Make sure that the bInterfaceProtocol only has meaning to
418 * Boot Interface Subclass.
420 if (hidp->hid_if_descr.bInterfaceSubClass != BOOT_INTERFACE)
421 hidp->hid_if_descr.bInterfaceProtocol = NONE_PROTOCOL;
422 mutex_exit(&hidp->hid_mutex);
424 if ((ep_data = usb_lookup_ep_data(dip, dev_data,
425 hidp->hid_interfaceno, 0, 0,
426 (uint_t)USB_EP_ATTR_INTR, (uint_t)USB_EP_DIR_IN)) == NULL) {
428 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
429 "no interrupt IN endpoint found");
431 goto fail;
434 mutex_enter(&hidp->hid_mutex);
435 if (usb_ep_xdescr_fill(USB_EP_XDESCR_CURRENT_VERSION, dip, ep_data,
436 &hidp->hid_ep_intr_xdescr) != USB_SUCCESS) {
437 mutex_exit(&hidp->hid_mutex);
439 goto fail;
443 * Attempt to find the hid descriptor, it could be after interface
444 * or after endpoint descriptors
446 if (hid_parse_hid_descr(&hidp->hid_hid_descr, USB_HID_DESCR_SIZE,
447 altif_data, ep_data) != USB_HID_DESCR_SIZE) {
449 * If parsing of hid descriptor failed and
450 * the device is a keyboard or mouse, use predefined
451 * length and packet size.
453 if (hid_parse_hid_descr_failure(hidp) == USB_FAILURE) {
454 mutex_exit(&hidp->hid_mutex);
456 goto fail;
460 * hid descriptor was bad but since
461 * the device is a keyboard or mouse,
462 * we will use the default length
463 * and packet size.
465 parse_hid_descr_error = HID_BAD_DESCR;
466 } else {
467 /* Parse hid descriptor successful */
469 USB_DPRINTF_L3(PRINT_MASK_ATTA, hidp->hid_log_handle,
470 "Hid descriptor:\n\t"
471 "bLength = 0x%x bDescriptorType = 0x%x "
472 "bcdHID = 0x%x\n\t"
473 "bCountryCode = 0x%x bNumDescriptors = 0x%x\n\t"
474 "bReportDescriptorType = 0x%x\n\t"
475 "wReportDescriptorLength = 0x%x",
476 hidp->hid_hid_descr.bLength,
477 hidp->hid_hid_descr.bDescriptorType,
478 hidp->hid_hid_descr.bcdHID,
479 hidp->hid_hid_descr.bCountryCode,
480 hidp->hid_hid_descr.bNumDescriptors,
481 hidp->hid_hid_descr.bReportDescriptorType,
482 hidp->hid_hid_descr.wReportDescriptorLength);
486 * Save a copy of the default pipe for easy reference
488 hidp->hid_default_pipe = hidp->hid_dev_data->dev_default_ph;
490 /* we copied the descriptors we need, free the dev_data */
491 usb_free_dev_data(dip, dev_data);
492 hidp->hid_dev_data = NULL;
495 * Don't get the report descriptor if parsing hid descriptor earlier
496 * failed since device probably won't return valid report descriptor
497 * either. Though parsing of hid descriptor failed, we have reached
498 * this point because the device has been identified as a
499 * keyboard or a mouse successfully and the default packet
500 * size and layout(in case of keyboard only) will be used, so it
501 * is ok to go ahead even if parsing of hid descriptor failed and
502 * we will not try to get the report descriptor.
504 if (parse_hid_descr_error != HID_BAD_DESCR) {
506 * Sun mouse rev 105 is a bit slow in responding to this
507 * request and requires multiple retries
509 int retry;
512 * Get and parse the report descriptor.
513 * Set the packet size if parsing is successful.
514 * Note that we start retry at 1 to have a delay
515 * in the first iteration.
517 mutex_exit(&hidp->hid_mutex);
518 for (retry = 1; retry < HID_RETRY; retry++) {
519 if (hid_handle_report_descriptor(hidp,
520 hidp->hid_interfaceno) == USB_SUCCESS) {
521 break;
523 delay(retry * drv_usectohz(1000));
525 if (retry >= HID_RETRY) {
527 goto fail;
529 mutex_enter(&hidp->hid_mutex);
532 * If packet size is zero, but the device is identified
533 * as a mouse or a keyboard, use predefined packet
534 * size.
536 if (hidp->hid_packet_size == 0) {
537 if (hidp->hid_if_descr.bInterfaceProtocol ==
538 KEYBOARD_PROTOCOL) {
539 /* device is a keyboard */
540 hidp->hid_packet_size = USBKPSZ;
541 } else if (hidp->
542 hid_if_descr.bInterfaceProtocol ==
543 MOUSE_PROTOCOL) {
544 /* device is a mouse */
545 hidp->hid_packet_size = USBMSSZ;
546 } else {
547 USB_DPRINTF_L2(PRINT_MASK_ATTA,
548 hidp->hid_log_handle,
549 "Failed to find hid packet size");
550 mutex_exit(&hidp->hid_mutex);
552 goto fail;
558 * initialize the pipe policy for the interrupt pipe.
560 hidp->hid_intr_pipe_policy.pp_max_async_reqs = 1;
563 * Make a clas specific request to SET_IDLE
564 * In this case send no reports if state has not changed.
565 * See HID 7.2.4.
567 mutex_exit(&hidp->hid_mutex);
568 hid_set_idle(hidp);
570 /* always initialize to report protocol */
571 hid_set_protocol(hidp, SET_REPORT_PROTOCOL);
572 mutex_enter(&hidp->hid_mutex);
575 * Create minor node based on information from the
576 * descriptors
578 switch (hidp->hid_if_descr.bInterfaceProtocol) {
579 case KEYBOARD_PROTOCOL:
580 (void) strcpy(minor_name, "keyboard");
582 break;
583 case MOUSE_PROTOCOL:
584 (void) strcpy(minor_name, "mouse");
586 break;
587 default:
589 * If the report descriptor has the GD mouse collection in
590 * its multiple collection, create a minor node and support it.
591 * It is used on some advanced keyboard/mouse set.
593 if (hidparser_lookup_usage_collection(
594 hidp->hid_report_descr, HID_GENERIC_DESKTOP,
595 HID_GD_MOUSE) != HIDPARSER_FAILURE) {
596 (void) strcpy(minor_name, "mouse");
598 break;
601 if (hidparser_get_top_level_collection_usage(
602 hidp->hid_report_descr, &usage_page, &usage) !=
603 HIDPARSER_FAILURE) {
604 switch (usage_page) {
605 case HID_CONSUMER:
606 switch (usage) {
607 case HID_CONSUMER_CONTROL:
608 (void) strcpy(minor_name,
609 "consumer_control");
611 break;
612 default:
613 (void) sprintf(minor_name,
614 "hid_%d_%d", usage_page, usage);
616 break;
619 break;
620 case HID_GENERIC_DESKTOP:
621 switch (usage) {
622 case HID_GD_POINTER:
623 (void) strcpy(minor_name,
624 "pointer");
626 break;
627 case HID_GD_MOUSE:
628 (void) strcpy(minor_name,
629 "mouse");
631 break;
632 case HID_GD_KEYBOARD:
633 (void) strcpy(minor_name,
634 "keyboard");
636 break;
637 default:
638 (void) sprintf(minor_name,
639 "hid_%d_%d", usage_page, usage);
641 break;
644 break;
645 default:
646 (void) sprintf(minor_name,
647 "hid_%d_%d", usage_page, usage);
649 break;
651 } else {
652 USB_DPRINTF_L1(PRINT_MASK_ATTA, hidp->hid_log_handle,
653 "hid_attach: Unsupported HID device");
654 mutex_exit(&hidp->hid_mutex);
656 goto fail;
659 break;
662 mutex_exit(&hidp->hid_mutex);
664 if ((ddi_create_minor_node(dip, minor_name, S_IFCHR,
665 HID_CONSTRUCT_EXTERNAL_MINOR(instance),
666 DDI_PSEUDO, 0)) != DDI_SUCCESS) {
667 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
668 "hid_attach: Could not create minor node");
670 goto fail;
673 /* create internal path for virtual */
674 if (strcmp(minor_name, "mouse") == 0) {
675 if (ddi_create_internal_pathname(dip, "internal_mouse", S_IFCHR,
676 HID_CONSTRUCT_INTERNAL_MINOR(instance)) != DDI_SUCCESS) {
678 goto fail;
682 if (strcmp(minor_name, "keyboard") == 0) {
683 if (ddi_create_internal_pathname(dip, "internal_keyboard",
684 S_IFCHR, HID_CONSTRUCT_INTERNAL_MINOR(instance)) !=
685 DDI_SUCCESS) {
687 goto fail;
691 mutex_enter(&hidp->hid_mutex);
692 hidp->hid_attach_flags |= HID_MINOR_NODES;
693 hidp->hid_dev_state = USB_DEV_ONLINE;
694 mutex_exit(&hidp->hid_mutex);
696 /* register for all events */
697 if (usb_register_event_cbs(dip, &hid_events, 0) != USB_SUCCESS) {
698 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
699 "usb_register_event_cbs failed");
701 goto fail;
704 /* now create components to power manage this device */
705 hid_create_pm_components(dip, hidp);
706 hid_pm_busy_component(hidp);
707 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
708 hid_pm_idle_component(hidp);
710 hidp->hid_internal_rq = hidp->hid_external_rq = NULL;
711 hidp->hid_internal_flag = hidp->hid_external_flag = 0;
712 hidp->hid_inuse_rq = NULL;
715 * report device
717 ddi_report_dev(dip);
719 USB_DPRINTF_L4(PRINT_MASK_ATTA, hidp->hid_log_handle,
720 "hid_attach: End");
722 return (DDI_SUCCESS);
724 fail:
725 if (hidp) {
726 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
727 "hid_attach: fail");
728 hid_detach_cleanup(dip, hidp);
731 return (DDI_FAILURE);
736 * hid_detach :
737 * Gets called at the time of detach.
739 static int
740 hid_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
742 int instance = ddi_get_instance(dip);
743 hid_state_t *hidp;
744 int rval = DDI_FAILURE;
746 hidp = ddi_get_soft_state(hid_statep, instance);
748 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle, "hid_detach");
750 switch (cmd) {
751 case DDI_DETACH:
753 * Undo what we did in client_attach, freeing resources
754 * and removing things we installed. The system
755 * framework guarantees we are not active with this devinfo
756 * node in any other entry points at this time.
758 hid_detach_cleanup(dip, hidp);
760 return (DDI_SUCCESS);
761 case DDI_SUSPEND:
762 rval = hid_cpr_suspend(hidp);
764 return (rval == USB_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
765 default:
766 break;
769 return (rval);
773 * hid_open :
774 * Open entry point: Opens the interrupt pipe. Sets up queues.
776 /*ARGSUSED*/
777 static int
778 hid_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
780 int no_of_ep = 0;
781 int rval;
782 int instance;
783 hid_state_t *hidp;
784 minor_t minor = getminor(*devp);
786 instance = HID_MINOR_TO_INSTANCE(minor);
788 hidp = ddi_get_soft_state(hid_statep, instance);
789 if (hidp == NULL) {
791 return (ENXIO);
794 USB_DPRINTF_L4(PRINT_MASK_OPEN, hidp->hid_log_handle,
795 "hid_open: Begin");
797 if (sflag) {
798 /* clone open NOT supported here */
799 return (ENXIO);
802 if (!(flag & FREAD)) {
803 return (EIO);
807 * This is a workaround:
808 * Currently, if we open an already disconnected device, and send
809 * a CONSOPENPOLL ioctl to it, the system will panic, please refer
810 * to the processing HID_OPEN_POLLED_INPUT ioctl in the routine
811 * hid_mctl_receive().
812 * The consconfig_dacf module need this interface to detect if the
813 * device is already disconnnected.
815 mutex_enter(&hidp->hid_mutex);
816 if (HID_IS_INTERNAL_OPEN(minor) &&
817 (hidp->hid_dev_state == USB_DEV_DISCONNECTED)) {
818 mutex_exit(&hidp->hid_mutex);
819 return (ENODEV);
822 if (HID_IS_INTERNAL_OPEN(minor) &&
823 (hidp->hid_internal_rq != NULL)) {
824 ASSERT(hidp->hid_internal_rq == q);
826 mutex_exit(&hidp->hid_mutex);
827 return (0);
830 if ((!HID_IS_INTERNAL_OPEN(minor)) &&
831 (hidp->hid_external_rq != NULL)) {
832 ASSERT(hidp->hid_external_rq == q);
834 mutex_exit(&hidp->hid_mutex);
835 return (0);
838 mutex_exit(&hidp->hid_mutex);
840 q->q_ptr = hidp;
841 WR(q)->q_ptr = hidp;
843 mutex_enter(&hidp->hid_mutex);
844 if (hidp->hid_inuse_rq != NULL) {
845 /* Pipe has already been setup */
847 if (HID_IS_INTERNAL_OPEN(minor)) {
848 hidp->hid_internal_flag = HID_STREAMS_OPEN;
849 hidp->hid_inuse_rq = hidp->hid_internal_rq = q;
850 } else {
851 hidp->hid_external_flag = HID_STREAMS_OPEN;
852 hidp->hid_inuse_rq = hidp->hid_external_rq = q;
855 mutex_exit(&hidp->hid_mutex);
857 qprocson(q);
859 return (0);
862 /* Pipe only needs to be opened once */
863 hidp->hid_interrupt_pipe = NULL;
864 no_of_ep = hidp->hid_if_descr.bNumEndpoints;
865 mutex_exit(&hidp->hid_mutex);
867 /* Check if interrupt endpoint exists */
868 if (no_of_ep > 0) {
869 /* Open the interrupt pipe */
870 if (usb_pipe_xopen(hidp->hid_dip,
871 &hidp->hid_ep_intr_xdescr,
872 &hidp->hid_intr_pipe_policy, USB_FLAGS_SLEEP,
873 &hidp->hid_interrupt_pipe) !=
874 USB_SUCCESS) {
876 q->q_ptr = NULL;
877 WR(q)->q_ptr = NULL;
878 return (EIO);
882 hid_pm_busy_component(hidp);
883 (void) pm_raise_power(hidp->hid_dip, 0, USB_DEV_OS_FULL_PWR);
885 mutex_enter(&hidp->hid_mutex);
886 if (HID_IS_INTERNAL_OPEN(minor)) {
887 hidp->hid_internal_flag = HID_STREAMS_OPEN;
888 hidp->hid_inuse_rq = hidp->hid_internal_rq = q;
889 } else {
890 hidp->hid_external_flag = HID_STREAMS_OPEN;
891 hidp->hid_inuse_rq = hidp->hid_external_rq = q;
894 mutex_exit(&hidp->hid_mutex);
896 qprocson(q);
898 mutex_enter(&hidp->hid_mutex);
900 if ((rval = hid_start_intr_polling(hidp)) != USB_SUCCESS) {
901 USB_DPRINTF_L2(PRINT_MASK_OPEN, hidp->hid_log_handle,
902 "unable to start intr pipe polling. rval = %d", rval);
904 if (HID_IS_INTERNAL_OPEN(minor))
905 hidp->hid_internal_flag = HID_STREAMS_DISMANTLING;
906 else
907 hidp->hid_external_flag = HID_STREAMS_DISMANTLING;
908 mutex_exit(&hidp->hid_mutex);
910 usb_pipe_close(hidp->hid_dip, hidp->hid_interrupt_pipe,
911 USB_FLAGS_SLEEP, NULL, NULL);
913 mutex_enter(&hidp->hid_mutex);
914 hidp->hid_interrupt_pipe = NULL;
915 mutex_exit(&hidp->hid_mutex);
917 qprocsoff(q);
919 mutex_enter(&hidp->hid_mutex);
920 if (HID_IS_INTERNAL_OPEN(minor)) {
921 hidp->hid_internal_flag = 0;
922 hidp->hid_internal_rq = NULL;
923 if (hidp->hid_external_flag == HID_STREAMS_OPEN)
924 hidp->hid_inuse_rq = hidp->hid_external_rq;
925 else
926 hidp->hid_inuse_rq = NULL;
927 } else {
928 hidp->hid_external_flag = 0;
929 hidp->hid_external_rq = NULL;
930 if (hidp->hid_internal_flag == HID_STREAMS_OPEN)
931 hidp->hid_inuse_rq = hidp->hid_internal_rq;
932 else
933 hidp->hid_inuse_rq = NULL;
935 mutex_exit(&hidp->hid_mutex);
937 q->q_ptr = NULL;
938 WR(q)->q_ptr = NULL;
940 hid_pm_idle_component(hidp);
942 return (EIO);
944 mutex_exit(&hidp->hid_mutex);
946 USB_DPRINTF_L4(PRINT_MASK_OPEN, hidp->hid_log_handle, "hid_open: End");
949 * Keyboard and mouse is Power managed by device activity.
950 * All other devices go busy on open and idle on close.
952 switch (hidp->hid_pm->hid_pm_strategy) {
953 case HID_PM_ACTIVITY:
954 hid_pm_idle_component(hidp);
956 break;
957 default:
959 break;
962 return (0);
967 * hid_close :
968 * Close entry point.
970 /*ARGSUSED*/
971 static int
972 hid_close(queue_t *q, int flag, cred_t *credp)
974 hid_state_t *hidp = (hid_state_t *)q->q_ptr;
975 queue_t *wq;
976 mblk_t *mp;
978 USB_DPRINTF_L4(PRINT_MASK_CLOSE, hidp->hid_log_handle, "hid_close:");
980 mutex_enter(&hidp->hid_mutex);
982 ASSERT((hidp->hid_internal_rq == q) ||
983 (hidp->hid_external_rq == q));
985 if (hidp->hid_internal_rq == q)
986 hidp->hid_internal_flag = HID_STREAMS_DISMANTLING;
987 else
988 hidp->hid_external_flag = HID_STREAMS_DISMANTLING;
990 mutex_exit(&hidp->hid_mutex);
993 * In case there are any outstanding requests on
994 * the default pipe, wait forever for them to complete.
996 (void) usb_pipe_drain_reqs(hidp->hid_dip,
997 hidp->hid_default_pipe, 0, USB_FLAGS_SLEEP, NULL, 0);
999 mutex_enter(&hidp->hid_mutex);
1000 wq = WR(q);
1001 /* drain any M_CTLS on the WQ */
1002 while (mp = getq(wq)) {
1003 hid_qreply_merror(wq, mp, EIO);
1004 mutex_exit(&hidp->hid_mutex);
1005 hid_pm_idle_component(hidp);
1006 mutex_enter(&hidp->hid_mutex);
1008 mutex_exit(&hidp->hid_mutex);
1010 qprocsoff(q);
1012 q->q_ptr = NULL;
1013 wq->q_ptr = NULL;
1015 mutex_enter(&hidp->hid_mutex);
1017 if (hidp->hid_internal_rq == q) {
1018 hidp->hid_internal_rq = NULL;
1019 hidp->hid_internal_flag = 0;
1020 if (hidp->hid_inuse_rq == q) {
1021 /* We are closing the active stream */
1022 if (hidp->hid_external_flag == HID_STREAMS_OPEN)
1023 hidp->hid_inuse_rq = hidp->hid_external_rq;
1024 else
1025 hidp->hid_inuse_rq = NULL;
1027 } else {
1028 hidp->hid_external_rq = NULL;
1029 hidp->hid_external_flag = 0;
1030 if (hidp->hid_inuse_rq == q) {
1031 /* We are closing the active stream */
1032 if (hidp->hid_internal_flag == HID_STREAMS_OPEN)
1033 hidp->hid_inuse_rq = hidp->hid_internal_rq;
1034 else
1035 hidp->hid_inuse_rq = NULL;
1039 if (hidp->hid_inuse_rq != NULL) {
1040 mutex_exit(&hidp->hid_mutex);
1041 return (0);
1044 /* all queues are closed, close USB pipes */
1045 hid_close_intr_pipe(hidp);
1046 mutex_exit(&hidp->hid_mutex);
1049 * Devices other than keyboard/mouse go idle on close.
1051 switch (hidp->hid_pm->hid_pm_strategy) {
1052 case HID_PM_ACTIVITY:
1054 break;
1055 default:
1056 hid_pm_idle_component(hidp);
1058 break;
1060 USB_DPRINTF_L4(PRINT_MASK_CLOSE, hidp->hid_log_handle,
1061 "hid_close: End");
1063 return (0);
1068 * hid_wput :
1069 * write put routine for the hid module
1071 static int
1072 hid_wput(queue_t *q, mblk_t *mp)
1074 hid_state_t *hidp = (hid_state_t *)q->q_ptr;
1075 int error = USB_SUCCESS;
1076 struct iocblk *iocbp;
1077 mblk_t *datap;
1078 int direction;
1079 struct copyresp *crp;
1080 queue_t *tmpq;
1081 int flag;
1083 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
1084 "hid_wput: Begin");
1086 /* See if the upper module is passing the right thing */
1087 ASSERT(mp != NULL);
1088 ASSERT(mp->b_datap != NULL);
1090 switch (mp->b_datap->db_type) {
1091 case M_FLUSH: /* Canonical flush handling */
1092 if (*mp->b_rptr & FLUSHW) {
1093 flushq(q, FLUSHDATA);
1096 /* read queue not used so just send up */
1097 if (*mp->b_rptr & FLUSHR) {
1098 *mp->b_rptr &= ~FLUSHW;
1099 qreply(q, mp);
1100 } else {
1101 freemsg(mp);
1104 break;
1105 case M_IOCTL:
1106 iocbp = (struct iocblk *)mp->b_rptr;
1108 /* Only accept transparent ioctls */
1109 if (iocbp->ioc_count != TRANSPARENT) {
1110 miocnak(q, mp, 0, EINVAL);
1111 break;
1114 switch (iocbp->ioc_cmd) {
1115 case HIDIOCKMGDIRECT:
1117 mutex_enter(&hidp->hid_mutex);
1118 ASSERT(hidp->hid_inuse_rq != NULL);
1119 mutex_exit(&hidp->hid_mutex);
1121 if ((datap = allocb(sizeof (int), BPRI_MED)) == NULL) {
1122 miocnak(q, mp, 0, ENOMEM);
1123 break;
1126 mutex_enter(&hidp->hid_mutex);
1127 if (hidp->hid_inuse_rq == hidp->hid_internal_rq) {
1128 *(int *)datap->b_wptr = 0;
1129 datap->b_wptr += sizeof (int);
1130 } else {
1131 ASSERT(hidp->hid_inuse_rq ==
1132 hidp->hid_external_rq);
1133 *(int *)datap->b_wptr = 1;
1134 datap->b_wptr += sizeof (int);
1136 mutex_exit(&hidp->hid_mutex);
1138 mcopyout(mp, NULL, sizeof (int), NULL, datap);
1139 qreply(q, mp);
1140 break;
1142 case HIDIOCKMSDIRECT:
1143 mcopyin(mp, NULL, sizeof (int), NULL);
1144 qreply(q, mp);
1145 break;
1147 default:
1148 miocnak(q, mp, 0, ENOTTY);
1151 break;
1153 case M_IOCDATA:
1155 crp = (void *)mp->b_rptr;
1157 if (crp->cp_rval != 0) {
1158 miocnak(q, mp, 0, EIO);
1159 break;
1162 switch (crp->cp_cmd) {
1163 case HIDIOCKMGDIRECT:
1164 miocack(q, mp, 0, 0);
1165 break;
1167 case HIDIOCKMSDIRECT:
1168 direction = *(int *)mp->b_cont->b_rptr;
1170 if ((direction != 0) && (direction != 1)) {
1171 miocnak(q, mp, 0, EINVAL);
1172 break;
1175 mutex_enter(&hidp->hid_mutex);
1177 if (direction == 0) {
1178 /* The internal stream is made active */
1179 flag = hidp->hid_internal_flag;
1180 tmpq = hidp->hid_internal_rq;
1181 } else {
1182 /* The external stream is made active */
1183 flag = hidp->hid_external_flag;
1184 tmpq = hidp->hid_external_rq;
1187 if (flag != HID_STREAMS_OPEN) {
1188 mutex_exit(&hidp->hid_mutex);
1189 miocnak(q, mp, 0, EIO);
1190 break;
1193 hidp->hid_inuse_rq = tmpq;
1195 mutex_exit(&hidp->hid_mutex);
1196 miocack(q, mp, 0, 0);
1197 break;
1199 default:
1200 miocnak(q, mp, 0, ENOTTY);
1201 break;
1204 break;
1206 case M_CTL:
1207 /* we are busy now */
1208 hid_pm_busy_component(hidp);
1210 if (q->q_first) {
1211 (void) putq(q, mp);
1212 } else {
1213 error = hid_mctl_receive(q, mp);
1214 switch (error) {
1215 case HID_ENQUEUE:
1217 * put this mblk on the WQ for the wsrv to
1218 * process
1220 (void) putq(q, mp);
1222 break;
1223 case HID_INPROGRESS:
1224 /* request has been queued to the device */
1226 break;
1227 case HID_SUCCESS:
1229 * returned by M_CTLS that are processed
1230 * immediately
1233 /* FALLTHRU */
1234 case HID_FAILURE:
1235 default:
1236 hid_pm_idle_component(hidp);
1237 break;
1240 break;
1241 default:
1242 hid_qreply_merror(q, mp, EINVAL);
1243 error = USB_FAILURE;
1244 break;
1247 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
1248 "hid_wput: End");
1250 return (DDI_SUCCESS);
1255 * hid_wsrv :
1256 * Write service routine for hid. When a message arrives through
1257 * hid_wput(), it is kept in write queue to be serviced later.
1259 static int
1260 hid_wsrv(queue_t *q)
1262 hid_state_t *hidp = (hid_state_t *)q->q_ptr;
1263 int error;
1264 mblk_t *mp;
1266 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
1267 "hid_wsrv: Begin");
1269 mutex_enter(&hidp->hid_mutex);
1270 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
1271 "hid_wsrv: dev_state: %s",
1272 usb_str_dev_state(hidp->hid_dev_state));
1275 * raise power if we are powered down. It is OK to block here since
1276 * we have a separate thread to process this STREAM
1278 if (hidp->hid_dev_state == USB_DEV_PWRED_DOWN) {
1279 mutex_exit(&hidp->hid_mutex);
1280 (void) pm_raise_power(hidp->hid_dip, 0, USB_DEV_OS_FULL_PWR);
1281 mutex_enter(&hidp->hid_mutex);
1285 * continue servicing all the M_CTL's till the queue is empty
1286 * or the device gets disconnected or till a hid_close()
1288 while ((hidp->hid_dev_state == USB_DEV_ONLINE) &&
1289 (HID_STREAMS_FLAG(q, hidp) != HID_STREAMS_DISMANTLING) &&
1290 ((mp = getq(q)) != NULL)) {
1292 /* Send a message down */
1293 mutex_exit(&hidp->hid_mutex);
1294 error = hid_mctl_receive(q, mp);
1295 switch (error) {
1296 case HID_ENQUEUE:
1297 /* put this mblk back on q to preserve order */
1298 (void) putbq(q, mp);
1300 break;
1301 case HID_INPROGRESS:
1302 /* request has been queued to the device */
1304 break;
1305 case HID_SUCCESS:
1306 case HID_FAILURE:
1307 default:
1308 hid_pm_idle_component(hidp);
1310 break;
1312 mutex_enter(&hidp->hid_mutex);
1314 mutex_exit(&hidp->hid_mutex);
1315 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
1316 "hid_wsrv: End");
1318 return (DDI_SUCCESS);
1323 * hid_power:
1324 * power entry point
1326 static int
1327 hid_power(dev_info_t *dip, int comp, int level)
1329 int instance = ddi_get_instance(dip);
1330 hid_state_t *hidp;
1331 hid_power_t *hidpm;
1332 int retval;
1334 hidp = ddi_get_soft_state(hid_statep, instance);
1336 USB_DPRINTF_L3(PRINT_MASK_PM, hidp->hid_log_handle, "hid_power:"
1337 " hid_state: comp=%d level=%d", comp, level);
1339 /* check if we are transitioning to a legal power level */
1340 mutex_enter(&hidp->hid_mutex);
1341 hidpm = hidp->hid_pm;
1343 if (USB_DEV_PWRSTATE_OK(hidpm->hid_pwr_states, level)) {
1345 USB_DPRINTF_L2(PRINT_MASK_PM, hidp->hid_log_handle,
1346 "hid_power: illegal level=%d hid_pwr_states=%d",
1347 level, hidpm->hid_pwr_states);
1349 mutex_exit(&hidp->hid_mutex);
1351 return (DDI_FAILURE);
1354 switch (level) {
1355 case USB_DEV_OS_PWR_OFF:
1356 retval = hid_pwrlvl0(hidp);
1357 break;
1358 case USB_DEV_OS_PWR_1:
1359 retval = hid_pwrlvl1(hidp);
1360 break;
1361 case USB_DEV_OS_PWR_2:
1362 retval = hid_pwrlvl2(hidp);
1363 break;
1364 case USB_DEV_OS_FULL_PWR:
1365 retval = hid_pwrlvl3(hidp);
1366 break;
1367 default:
1368 retval = USB_FAILURE;
1369 break;
1372 mutex_exit(&hidp->hid_mutex);
1374 return ((retval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
1379 * hid_interrupt_pipe_callback:
1380 * Callback function for the hid intr pipe. This function is called by
1381 * USBA when a buffer has been filled. This driver does not cook the data,
1382 * it just sends the message up.
1384 static void
1385 hid_interrupt_pipe_callback(usb_pipe_handle_t pipe, usb_intr_req_t *req)
1387 hid_state_t *hidp = (hid_state_t *)req->intr_client_private;
1388 queue_t *q;
1390 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
1391 "hid_interrupt_pipe_callback: ph = 0x%p req = 0x%p",
1392 (void *)pipe, (void *)req);
1394 hid_pm_busy_component(hidp);
1396 mutex_enter(&hidp->hid_mutex);
1399 * If hid_close() is in progress, we shouldn't try accessing queue
1400 * Otherwise indicate that a putnext is going to happen, so
1401 * if close after this, that should wait for the putnext to finish.
1403 if (HID_STREAMS_FLAG(hidp->hid_inuse_rq, hidp) ==
1404 HID_STREAMS_OPEN) {
1406 * Check if data can be put to the next queue.
1408 if (!canputnext(hidp->hid_inuse_rq)) {
1409 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
1410 "Buffer flushed when overflowed.");
1412 /* Flush the queue above */
1413 hid_flush(hidp->hid_inuse_rq);
1414 mutex_exit(&hidp->hid_mutex);
1415 } else {
1416 q = hidp->hid_inuse_rq;
1417 mutex_exit(&hidp->hid_mutex);
1419 /* Put data upstream */
1420 putnext(q, req->intr_data);
1422 /* usb_free_intr_req should not free data */
1423 req->intr_data = NULL;
1425 } else {
1426 mutex_exit(&hidp->hid_mutex);
1429 /* free request and data */
1430 usb_free_intr_req(req);
1431 hid_pm_idle_component(hidp);
1436 * hid_default_pipe_callback :
1437 * Callback routine for the asynchronous control transfer
1438 * Called from hid_send_async_ctrl_request() where we open
1439 * the pipe in exclusive mode
1441 static void
1442 hid_default_pipe_callback(usb_pipe_handle_t pipe, usb_ctrl_req_t *req)
1444 hid_default_pipe_arg_t *hid_default_pipe_arg =
1445 (hid_default_pipe_arg_t *)req->ctrl_client_private;
1446 queue_t *wq = hid_default_pipe_arg->hid_default_pipe_arg_queue;
1447 queue_t *rq = RD(wq);
1448 hid_state_t *hidp = (hid_state_t *)rq->q_ptr;
1449 mblk_t *mctl_mp;
1450 mblk_t *data = NULL;
1452 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
1453 "hid_default_pipe_callback: "
1454 "ph = 0x%p, req = 0x%p, data= 0x%p",
1455 (void *)pipe, (void *)req, (void *)data);
1457 ASSERT((req->ctrl_cb_flags & USB_CB_INTR_CONTEXT) == 0);
1459 if (req->ctrl_data) {
1460 data = req->ctrl_data;
1461 req->ctrl_data = NULL;
1465 * Free the b_cont of the original message that was sent down.
1467 mctl_mp = hid_default_pipe_arg->hid_default_pipe_arg_mblk;
1468 freemsg(mctl_mp->b_cont);
1470 /* chain the mblk received to the original & send it up */
1471 mctl_mp->b_cont = data;
1473 if (canputnext(rq)) {
1474 putnext(rq, mctl_mp);
1475 } else {
1476 freemsg(mctl_mp); /* avoid leak */
1480 * Free the argument for the asynchronous callback
1482 kmem_free(hid_default_pipe_arg, sizeof (hid_default_pipe_arg_t));
1485 * Free the control pipe request structure.
1487 usb_free_ctrl_req(req);
1489 mutex_enter(&hidp->hid_mutex);
1490 hidp->hid_default_pipe_req--;
1491 ASSERT(hidp->hid_default_pipe_req >= 0);
1492 mutex_exit(&hidp->hid_mutex);
1494 hid_pm_idle_component(hidp);
1495 qenable(wq);
1500 * hid_interrupt_pipe_exception_callback:
1501 * Exception callback routine for interrupt pipe. If there is any data,
1502 * destroy it. No threads are waiting for the exception callback.
1504 /*ARGSUSED*/
1505 static void
1506 hid_interrupt_pipe_exception_callback(usb_pipe_handle_t pipe,
1507 usb_intr_req_t *req)
1509 hid_state_t *hidp = (hid_state_t *)req->intr_client_private;
1510 mblk_t *data = req->intr_data;
1511 usb_cb_flags_t flags = req->intr_cb_flags;
1512 int rval;
1514 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
1515 "hid_interrupt_pipe_exception_callback: "
1516 "completion_reason = 0x%x, data = 0x%p, flag = 0x%x",
1517 req->intr_completion_reason, (void *)data, req->intr_cb_flags);
1519 ASSERT((req->intr_cb_flags & USB_CB_INTR_CONTEXT) == 0);
1521 if (((flags & USB_CB_FUNCTIONAL_STALL) != 0) &&
1522 ((flags & USB_CB_STALL_CLEARED) == 0)) {
1523 USB_DPRINTF_L2(PRINT_MASK_ALL,
1524 hidp->hid_log_handle,
1525 "hid_interrupt_pipe_exception_callback: "
1526 "unable to clear stall. flags = 0x%x",
1527 req->intr_cb_flags);
1530 mutex_enter(&hidp->hid_mutex);
1532 switch (req->intr_completion_reason) {
1533 case USB_CR_STOPPED_POLLING:
1534 case USB_CR_PIPE_CLOSING:
1535 default:
1537 break;
1538 case USB_CR_PIPE_RESET:
1539 case USB_CR_NO_RESOURCES:
1540 if ((hidp->hid_dev_state == USB_DEV_ONLINE) &&
1541 ((rval = hid_start_intr_polling(hidp)) !=
1542 USB_SUCCESS)) {
1543 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
1544 "unable to restart interrupt poll. rval = %d",
1545 rval);
1548 break;
1551 mutex_exit(&hidp->hid_mutex);
1553 usb_free_intr_req(req);
1558 * hid_default_pipe_exception_callback:
1559 * Exception callback routine for default pipe.
1561 /*ARGSUSED*/
1562 static void
1563 hid_default_pipe_exception_callback(usb_pipe_handle_t pipe,
1564 usb_ctrl_req_t *req)
1566 hid_default_pipe_arg_t *hid_default_pipe_arg =
1567 (hid_default_pipe_arg_t *)req->ctrl_client_private;
1568 queue_t *wq = hid_default_pipe_arg->hid_default_pipe_arg_queue;
1569 queue_t *rq = RD(wq);
1570 hid_state_t *hidp = (hid_state_t *)rq->q_ptr;
1571 usb_cr_t ctrl_completion_reason = req->ctrl_completion_reason;
1572 mblk_t *mp, *data = NULL;
1574 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
1575 "hid_default_pipe_exception_callback: "
1576 "completion_reason = 0x%x, data = 0x%p, flag = 0x%x",
1577 ctrl_completion_reason, (void *)data, req->ctrl_cb_flags);
1579 ASSERT((req->ctrl_cb_flags & USB_CB_INTR_CONTEXT) == 0);
1581 mp = hid_default_pipe_arg->hid_default_pipe_arg_mblk;
1584 * Pass an error message up. Reuse existing mblk.
1586 if (canputnext(rq)) {
1587 mp->b_datap->db_type = M_ERROR;
1588 mp->b_rptr = mp->b_datap->db_base;
1589 mp->b_wptr = mp->b_rptr + sizeof (char);
1590 *mp->b_rptr = EIO;
1591 putnext(rq, mp);
1592 } else {
1593 freemsg(mp);
1596 kmem_free(hid_default_pipe_arg, sizeof (hid_default_pipe_arg_t));
1598 mutex_enter(&hidp->hid_mutex);
1599 hidp->hid_default_pipe_req--;
1600 ASSERT(hidp->hid_default_pipe_req >= 0);
1601 mutex_exit(&hidp->hid_mutex);
1603 qenable(wq);
1604 usb_free_ctrl_req(req);
1605 hid_pm_idle_component(hidp);
1610 * event handling:
1612 * hid_reconnect_event_callback:
1613 * the device was disconnected but this instance not detached, probably
1614 * because the device was busy
1616 * If the same device, continue with restoring state
1618 static int
1619 hid_restore_state_event_callback(dev_info_t *dip)
1621 hid_state_t *hidp = (hid_state_t *)ddi_get_soft_state(hid_statep,
1622 ddi_get_instance(dip));
1624 ASSERT(hidp != NULL);
1626 USB_DPRINTF_L3(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1627 "hid_restore_state_event_callback: dip=0x%p", (void *)dip);
1629 hid_restore_device_state(dip, hidp);
1631 return (USB_SUCCESS);
1636 * hid_cpr_suspend
1637 * Fail suspend if we can't finish outstanding i/o activity.
1639 static int
1640 hid_cpr_suspend(hid_state_t *hidp)
1642 int rval, prev_state;
1643 int retval = USB_FAILURE;
1645 USB_DPRINTF_L4(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1646 "hid_cpr_suspend: dip=0x%p", (void *)hidp->hid_dip);
1648 mutex_enter(&hidp->hid_mutex);
1649 switch (hidp->hid_dev_state) {
1650 case USB_DEV_ONLINE:
1651 case USB_DEV_PWRED_DOWN:
1652 prev_state = hidp->hid_dev_state;
1653 hidp->hid_dev_state = USB_DEV_SUSPENDED;
1654 mutex_exit(&hidp->hid_mutex);
1656 /* drain all request outstanding on the default control pipe */
1657 rval = usb_pipe_drain_reqs(hidp->hid_dip,
1658 hidp->hid_default_pipe, hid_default_pipe_drain_timeout,
1659 USB_FLAGS_SLEEP, NULL, 0);
1661 /* fail checkpoint if we haven't finished the job yet */
1662 mutex_enter(&hidp->hid_mutex);
1663 if ((rval != USB_SUCCESS) || (hidp->hid_default_pipe_req > 0)) {
1664 USB_DPRINTF_L2(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1665 "hid_cpr_suspend: "
1666 "device busy - can't checkpoint");
1668 /* fall back to previous state */
1669 hidp->hid_dev_state = prev_state;
1670 } else {
1671 retval = USB_SUCCESS;
1672 hid_save_device_state(hidp);
1675 break;
1676 case USB_DEV_DISCONNECTED:
1677 hidp->hid_dev_state = USB_DEV_SUSPENDED;
1678 hid_save_device_state(hidp);
1679 retval = USB_SUCCESS;
1680 break;
1681 case USB_DEV_SUSPENDED:
1682 default:
1683 USB_DPRINTF_L2(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1684 "hid_cpr_suspend: Illegal dev state: %d",
1685 hidp->hid_dev_state);
1687 break;
1689 mutex_exit(&hidp->hid_mutex);
1691 return (retval);
1695 static void
1696 hid_cpr_resume(hid_state_t *hidp)
1698 USB_DPRINTF_L4(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1699 "hid_cpr_resume: dip=0x%p", (void *)hidp->hid_dip);
1701 hid_restore_device_state(hidp->hid_dip, hidp);
1706 * hid_disconnect_event_callback:
1707 * The device has been disconnected. We either wait for
1708 * detach or a reconnect event. Close all pipes and timeouts.
1710 static int
1711 hid_disconnect_event_callback(dev_info_t *dip)
1713 hid_state_t *hidp;
1714 mblk_t *mp;
1716 hidp = (hid_state_t *)ddi_get_soft_state(hid_statep,
1717 ddi_get_instance(dip));
1718 ASSERT(hidp != NULL);
1720 USB_DPRINTF_L4(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1721 "hid_disconnect_event_callback: dip=0x%p", (void *)dip);
1723 mutex_enter(&hidp->hid_mutex);
1724 switch (hidp->hid_dev_state) {
1725 case USB_DEV_ONLINE:
1726 case USB_DEV_PWRED_DOWN:
1727 hidp->hid_dev_state = USB_DEV_DISCONNECTED;
1728 if (HID_IS_OPEN(hidp)) {
1730 USB_DPRINTF_L2(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1731 "busy device has been disconnected");
1733 hid_save_device_state(hidp);
1736 * Notify applications about device removal, this only
1737 * applies to an external (aka. physical) open. For an
1738 * internal open, consconfig_dacf closes the queue.
1740 if (hidp->hid_external_flag == HID_STREAMS_OPEN) {
1741 queue_t *q = hidp->hid_external_rq;
1742 mutex_exit(&hidp->hid_mutex);
1743 mp = allocb(sizeof (uchar_t), BPRI_HI);
1744 if (mp != NULL) {
1745 mp->b_datap->db_type = M_ERROR;
1746 mp->b_rptr = mp->b_datap->db_base;
1747 mp->b_wptr = mp->b_rptr + sizeof (char);
1748 *mp->b_rptr = ENODEV;
1749 putnext(q, mp);
1751 mutex_enter(&hidp->hid_mutex);
1754 break;
1755 case USB_DEV_SUSPENDED:
1756 /* we remain suspended */
1758 break;
1759 default:
1760 USB_DPRINTF_L2(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1761 "hid_disconnect_event_callback: Illegal dev state: %d",
1762 hidp->hid_dev_state);
1764 break;
1766 mutex_exit(&hidp->hid_mutex);
1768 return (USB_SUCCESS);
1773 * hid_power_change_callback:
1774 * Async callback function to notify pm_raise_power completion
1775 * after hid_power entry point is called.
1777 static void
1778 hid_power_change_callback(void *arg, int rval)
1780 hid_state_t *hidp;
1781 queue_t *wq;
1783 hidp = (hid_state_t *)arg;
1785 USB_DPRINTF_L4(PRINT_MASK_PM, hidp->hid_log_handle,
1786 "hid_power_change_callback - rval: %d", rval);
1788 mutex_enter(&hidp->hid_mutex);
1789 hidp->hid_pm->hid_raise_power = B_FALSE;
1791 if (hidp->hid_dev_state == USB_DEV_ONLINE) {
1792 wq = WR(hidp->hid_inuse_rq);
1793 mutex_exit(&hidp->hid_mutex);
1795 qenable(wq);
1797 } else {
1798 mutex_exit(&hidp->hid_mutex);
1804 * hid_parse_hid_descr:
1805 * Parse the hid descriptor, check after interface and after
1806 * endpoint descriptor
1808 static size_t
1809 hid_parse_hid_descr(usb_hid_descr_t *ret_descr, size_t ret_buf_len,
1810 usb_alt_if_data_t *altif_data, usb_ep_data_t *ep_data)
1812 usb_cvs_data_t *cvs;
1813 int which_cvs;
1815 for (which_cvs = 0; which_cvs < altif_data->altif_n_cvs; which_cvs++) {
1816 cvs = &altif_data->altif_cvs[which_cvs];
1817 if (cvs->cvs_buf == NULL) {
1818 continue;
1820 if (cvs->cvs_buf[1] == USB_DESCR_TYPE_HID) {
1821 return (usb_parse_data("ccscccs",
1822 cvs->cvs_buf, cvs->cvs_buf_len,
1823 (void *)ret_descr,
1824 (size_t)ret_buf_len));
1828 /* now try after endpoint */
1829 for (which_cvs = 0; which_cvs < ep_data->ep_n_cvs; which_cvs++) {
1830 cvs = &ep_data->ep_cvs[which_cvs];
1831 if (cvs->cvs_buf == NULL) {
1832 continue;
1834 if (cvs->cvs_buf[1] == USB_DESCR_TYPE_HID) {
1835 return (usb_parse_data("ccscccs",
1836 cvs->cvs_buf, cvs->cvs_buf_len,
1837 (void *)ret_descr,
1838 (size_t)ret_buf_len));
1842 return (USB_PARSE_ERROR);
1847 * hid_parse_hid_descr_failure:
1848 * If parsing of hid descriptor failed and the device is
1849 * a keyboard or mouse, use predefined length and packet size.
1851 static int
1852 hid_parse_hid_descr_failure(hid_state_t *hidp)
1855 * Parsing hid descriptor failed, probably because the
1856 * device did not return a valid hid descriptor. Check to
1857 * see if this is a keyboard or mouse. If so, use the
1858 * predefined hid descriptor length and packet size.
1859 * Otherwise, detach and return failure.
1861 USB_DPRINTF_L1(PRINT_MASK_ATTA, hidp->hid_log_handle,
1862 "Parsing of hid descriptor failed");
1864 if (hidp->hid_if_descr.bInterfaceProtocol == KEYBOARD_PROTOCOL) {
1865 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
1866 "Set hid descriptor length to predefined "
1867 "USB_KB_HID_DESCR_LENGTH for keyboard.");
1869 /* device is a keyboard */
1870 hidp->hid_hid_descr.wReportDescriptorLength =
1871 USB_KB_HID_DESCR_LENGTH;
1873 hidp->hid_packet_size = USBKPSZ;
1875 } else if (hidp->hid_if_descr.bInterfaceProtocol ==
1876 MOUSE_PROTOCOL) {
1877 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
1878 "Set hid descriptor length to predefined "
1879 "USB_MS_HID_DESCR_LENGTH for mouse.");
1881 /* device is a mouse */
1882 hidp->hid_hid_descr.wReportDescriptorLength =
1883 USB_MS_HID_DESCR_LENGTH;
1885 hidp->hid_packet_size = USBMSSZ;
1886 } else {
1888 return (USB_FAILURE);
1891 return (USB_SUCCESS);
1896 * hid_handle_report_descriptor:
1897 * Get the report descriptor, call hidparser routine to parse
1898 * it and query the hidparser tree to get the packet size
1900 static int
1901 hid_handle_report_descriptor(hid_state_t *hidp, int interface)
1903 usb_cr_t completion_reason;
1904 usb_cb_flags_t cb_flags;
1905 mblk_t *data = NULL;
1906 hidparser_packet_info_t hpack;
1907 int i;
1908 usb_ctrl_setup_t setup = {
1909 USB_DEV_REQ_DEV_TO_HOST | /* bmRequestType */
1910 USB_DEV_REQ_RCPT_IF,
1911 USB_REQ_GET_DESCR, /* bRequest */
1912 USB_CLASS_DESCR_TYPE_REPORT, /* wValue */
1913 0, /* wIndex: interface, fill in later */
1914 0, /* wLength, fill in later */
1915 0 /* attributes */
1919 * Parsing hid desciptor was successful earlier.
1920 * Get Report Descriptor
1922 setup.wIndex = (uint16_t)interface;
1923 setup.wLength = hidp->hid_hid_descr.wReportDescriptorLength;
1924 if (usb_pipe_ctrl_xfer_wait(hidp->hid_default_pipe,
1925 &setup,
1926 &data, /* data */
1927 &completion_reason, &cb_flags, 0) != USB_SUCCESS) {
1929 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
1930 "Failed to receive the Report Descriptor");
1931 freemsg(data);
1933 return (USB_FAILURE);
1935 } else {
1936 int n = hidp->hid_hid_descr.wReportDescriptorLength;
1938 ASSERT(data);
1940 /* Print the report descriptor */
1941 for (i = 0; i < n; i++) {
1942 USB_DPRINTF_L3(PRINT_MASK_ATTA, hidp->hid_log_handle,
1943 "Index = %d\tvalue =0x%x", i,
1944 (int)(data->b_rptr[i]));
1947 /* Get Report Descriptor was successful */
1948 if (hidparser_parse_report_descriptor(
1949 data->b_rptr,
1950 hidp->hid_hid_descr.wReportDescriptorLength,
1951 &hidp->hid_hid_descr,
1952 &hidp->hid_report_descr) == HIDPARSER_SUCCESS) {
1954 /* find max intr-in xfer length */
1955 hidparser_find_max_packet_size_from_report_descriptor(
1956 hidp->hid_report_descr, &hpack);
1957 /* round up to the nearest byte */
1958 hidp->hid_packet_size = (hpack.max_packet_size + 7) / 8;
1960 /* if report id is used, add more more byte for it */
1961 if (hpack.report_id != HID_REPORT_ID_UNDEFINED) {
1962 hidp->hid_packet_size++;
1964 } else {
1965 USB_DPRINTF_L1(PRINT_MASK_ATTA, hidp->hid_log_handle,
1966 "Invalid Report Descriptor");
1967 freemsg(data);
1969 return (USB_FAILURE);
1972 freemsg(data);
1974 return (USB_SUCCESS);
1980 * hid_set_idle:
1981 * Make a clas specific request to SET_IDLE.
1982 * In this case send no reports if state has not changed.
1983 * See HID 7.2.4.
1985 /*ARGSUSED*/
1986 static void
1987 hid_set_idle(hid_state_t *hidp)
1989 usb_cr_t completion_reason;
1990 usb_cb_flags_t cb_flags;
1991 usb_ctrl_setup_t setup = {
1992 USB_DEV_REQ_HOST_TO_DEV | /* bmRequestType */
1993 USB_DEV_REQ_TYPE_CLASS |
1994 USB_DEV_REQ_RCPT_IF,
1995 SET_IDLE, /* bRequest */
1996 DURATION, /* wValue */
1997 0, /* wIndex: interface, fill in later */
1998 0, /* wLength */
1999 0 /* attributes */
2002 USB_DPRINTF_L4(PRINT_MASK_ATTA, hidp->hid_log_handle,
2003 "hid_set_idle: Begin");
2005 setup.wIndex = hidp->hid_if_descr.bInterfaceNumber;
2006 if (usb_pipe_ctrl_xfer_wait(
2007 hidp->hid_default_pipe,
2008 &setup,
2009 NULL, /* no data to send. */
2010 &completion_reason, &cb_flags, 0) != USB_SUCCESS) {
2012 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
2013 "Failed while trying to set idle,"
2014 "cr = %d, cb_flags = 0x%x\n",
2015 completion_reason, cb_flags);
2017 USB_DPRINTF_L4(PRINT_MASK_ATTA, hidp->hid_log_handle,
2018 "hid_set_idle: End");
2023 * hid_set_protocol:
2024 * Initialize the device to set the preferred protocol
2026 /*ARGSUSED*/
2027 static void
2028 hid_set_protocol(hid_state_t *hidp, int protocol)
2030 usb_cr_t completion_reason;
2031 usb_cb_flags_t cb_flags;
2032 usb_ctrl_setup_t setup;
2034 USB_DPRINTF_L4(PRINT_MASK_ATTA, hidp->hid_log_handle,
2035 "hid_set_protocol(%d): Begin", protocol);
2037 /* initialize the setup request */
2038 setup.bmRequestType = USB_DEV_REQ_HOST_TO_DEV |
2039 USB_DEV_REQ_TYPE_CLASS | USB_DEV_REQ_RCPT_IF;
2040 setup.bRequest = SET_PROTOCOL;
2041 setup.wValue = (uint16_t)protocol;
2042 setup.wIndex = hidp->hid_if_descr.bInterfaceNumber;
2043 setup.wLength = 0;
2044 setup.attrs = 0;
2045 if (usb_pipe_ctrl_xfer_wait(
2046 hidp->hid_default_pipe, /* bmRequestType */
2047 &setup,
2048 NULL, /* no data to send */
2049 &completion_reason, &cb_flags, 0) != USB_SUCCESS) {
2051 * Some devices fail to follow the specification
2052 * and instead of STALLing, they continously
2053 * NAK the SET_IDLE command. We need to reset
2054 * the pipe then, so that ohci doesn't panic.
2056 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
2057 "Failed while trying to set protocol:%d,"
2058 "cr = %d cb_flags = 0x%x\n",
2059 completion_reason, cb_flags, protocol);
2062 USB_DPRINTF_L4(PRINT_MASK_ATTA, hidp->hid_log_handle,
2063 "hid_set_protocol: End");
2068 * hid_detach_cleanup:
2069 * called by attach and detach for cleanup.
2071 static void
2072 hid_detach_cleanup(dev_info_t *dip, hid_state_t *hidp)
2074 int flags = hidp->hid_attach_flags;
2075 int rval;
2076 hid_power_t *hidpm;
2078 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
2079 "hid_detach_cleanup: Begin");
2081 if ((hidp->hid_attach_flags & HID_LOCK_INIT) == 0) {
2083 goto done;
2087 * Disable the event callbacks first, after this point, event
2088 * callbacks will never get called. Note we shouldn't hold
2089 * mutex while unregistering events because there may be a
2090 * competing event callback thread. Event callbacks are done
2091 * with ndi mutex held and this can cause a potential deadlock.
2093 usb_unregister_event_cbs(dip, &hid_events);
2095 mutex_enter(&hidp->hid_mutex);
2097 hidpm = hidp->hid_pm;
2099 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
2100 "hid_detach_cleanup: hidpm=0x%p", (void *)hidpm);
2102 if (hidpm && (hidp->hid_dev_state != USB_DEV_DISCONNECTED)) {
2104 mutex_exit(&hidp->hid_mutex);
2105 hid_pm_busy_component(hidp);
2106 if (hid_is_pm_enabled(dip) == USB_SUCCESS) {
2108 if (hidpm->hid_wakeup_enabled) {
2110 /* First bring the device to full power */
2111 (void) pm_raise_power(dip, 0,
2112 USB_DEV_OS_FULL_PWR);
2114 /* Disable remote wakeup */
2115 rval = usb_handle_remote_wakeup(dip,
2116 USB_REMOTE_WAKEUP_DISABLE);
2118 if (rval != DDI_SUCCESS) {
2119 USB_DPRINTF_L2(PRINT_MASK_ALL,
2120 hidp->hid_log_handle,
2121 "hid_detach_cleanup: "
2122 "disble remote wakeup failed, "
2123 "rval= %d", rval);
2127 (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
2129 hid_pm_idle_component(hidp);
2130 mutex_enter(&hidp->hid_mutex);
2133 if (hidpm) {
2134 freemsg(hidpm->hid_pm_pwrup);
2135 kmem_free(hidpm, sizeof (hid_power_t));
2136 hidp->hid_pm = NULL;
2139 mutex_exit(&hidp->hid_mutex);
2141 if (hidp->hid_report_descr != NULL) {
2142 (void) hidparser_free_report_descriptor_handle(
2143 hidp->hid_report_descr);
2146 if (flags & HID_MINOR_NODES) {
2147 ddi_remove_minor_node(dip, NULL);
2150 mutex_destroy(&hidp->hid_mutex);
2152 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
2153 "hid_detach_cleanup: End");
2155 done:
2156 usb_client_detach(dip, hidp->hid_dev_data);
2157 usb_free_log_hdl(hidp->hid_log_handle);
2158 ddi_soft_state_free(hid_statep, hidp->hid_instance);
2160 ddi_prop_remove_all(dip);
2165 * hid_start_intr_polling:
2166 * Allocate an interrupt request structure, initialize,
2167 * and start interrupt transfers.
2169 static int
2170 hid_start_intr_polling(hid_state_t *hidp)
2172 usb_intr_req_t *req;
2173 int rval = USB_SUCCESS;
2175 USB_DPRINTF_L4(PRINT_MASK_PM, hidp->hid_log_handle,
2176 "hid_start_intr_polling: "
2177 "dev_state=%s internal_str_flag=%d external_str_flag=%d ph=0x%p",
2178 usb_str_dev_state(hidp->hid_dev_state), hidp->hid_internal_flag,
2179 hidp->hid_external_flag, (void *)hidp->hid_interrupt_pipe);
2181 if (HID_IS_OPEN(hidp) && (hidp->hid_interrupt_pipe != NULL)) {
2183 * initialize interrupt pipe request structure
2185 req = usb_alloc_intr_req(hidp->hid_dip, 0, USB_FLAGS_SLEEP);
2186 req->intr_client_private = (usb_opaque_t)hidp;
2187 req->intr_attributes = USB_ATTRS_SHORT_XFER_OK |
2188 USB_ATTRS_AUTOCLEARING;
2189 req->intr_len = hidp->hid_packet_size;
2190 req->intr_cb = hid_interrupt_pipe_callback;
2191 req->intr_exc_cb = hid_interrupt_pipe_exception_callback;
2194 * Start polling on the interrupt pipe.
2196 mutex_exit(&hidp->hid_mutex);
2198 if ((rval = usb_pipe_intr_xfer(hidp->hid_interrupt_pipe, req,
2199 USB_FLAGS_SLEEP)) != USB_SUCCESS) {
2200 USB_DPRINTF_L2(PRINT_MASK_PM, hidp->hid_log_handle,
2201 "hid_start_intr_polling failed: rval = %d",
2202 rval);
2203 usb_free_intr_req(req);
2206 mutex_enter(&hidp->hid_mutex);
2209 USB_DPRINTF_L4(PRINT_MASK_PM, hidp->hid_log_handle,
2210 "hid_start_intr_polling: done, rval = %d", rval);
2212 return (rval);
2217 * hid_close_intr_pipe:
2218 * close the interrupt pipe after draining all callbacks
2220 static void
2221 hid_close_intr_pipe(hid_state_t *hidp)
2223 USB_DPRINTF_L4(PRINT_MASK_CLOSE, hidp->hid_log_handle,
2224 "hid_close_intr_pipe: Begin");
2226 if (hidp->hid_interrupt_pipe) {
2228 * Close the interrupt pipe
2230 mutex_exit(&hidp->hid_mutex);
2231 usb_pipe_close(hidp->hid_dip, hidp->hid_interrupt_pipe,
2232 USB_FLAGS_SLEEP, NULL, NULL);
2233 mutex_enter(&hidp->hid_mutex);
2234 hidp->hid_interrupt_pipe = NULL;
2236 USB_DPRINTF_L4(PRINT_MASK_CLOSE, hidp->hid_log_handle,
2237 "hid_close_intr_pipe: End");
2242 * hid_mctl_receive:
2243 * Handle M_CTL messages from upper stream. If
2244 * we don't understand the command, free message.
2246 static int
2247 hid_mctl_receive(register queue_t *q, register mblk_t *mp)
2249 hid_state_t *hidp = (hid_state_t *)q->q_ptr;
2250 struct iocblk *iocp;
2251 int error = HID_FAILURE;
2252 uchar_t request_type;
2253 hid_req_t *hid_req_data = NULL;
2254 hid_polled_input_callback_t hid_polled_input;
2255 hid_vid_pid_t hid_vid_pid;
2257 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
2258 "hid_mctl_receive");
2260 iocp = (struct iocblk *)mp->b_rptr;
2262 switch (iocp->ioc_cmd) {
2263 case HID_SET_REPORT:
2264 /* FALLTHRU */
2265 case HID_SET_IDLE:
2266 /* FALLTHRU */
2267 case HID_SET_PROTOCOL:
2268 request_type = USB_DEV_REQ_HOST_TO_DEV |
2269 USB_DEV_REQ_RCPT_IF | USB_DEV_REQ_TYPE_CLASS;
2271 break;
2272 case HID_GET_REPORT:
2273 /* FALLTHRU */
2274 case HID_GET_IDLE:
2275 /* FALLTHRU */
2276 case HID_GET_PROTOCOL:
2277 request_type = USB_DEV_REQ_DEV_TO_HOST |
2278 USB_DEV_REQ_RCPT_IF | USB_DEV_REQ_TYPE_CLASS;
2280 break;
2281 case HID_GET_PARSER_HANDLE:
2282 if (canputnext(RD(q))) {
2283 freemsg(mp->b_cont);
2284 mp->b_cont = hid_data2mblk(
2285 (uchar_t *)&hidp->hid_report_descr,
2286 sizeof (hidp->hid_report_descr));
2287 if (mp->b_cont == NULL) {
2289 * can't allocate mblk, indicate
2290 * that nothing is returned
2292 iocp->ioc_count = 0;
2293 } else {
2294 iocp->ioc_count =
2295 sizeof (hidp->hid_report_descr);
2297 qreply(q, mp);
2299 return (HID_SUCCESS);
2300 } else {
2302 /* retry */
2303 return (HID_ENQUEUE);
2305 case HID_GET_VID_PID:
2306 if (canputnext(RD(q))) {
2307 freemsg(mp->b_cont);
2309 hid_vid_pid.VendorId =
2310 hidp->hid_dev_descr->idVendor;
2311 hid_vid_pid.ProductId =
2312 hidp->hid_dev_descr->idProduct;
2314 mp->b_cont = hid_data2mblk(
2315 (uchar_t *)&hid_vid_pid, sizeof (hid_vid_pid_t));
2316 if (mp->b_cont == NULL) {
2318 * can't allocate mblk, indicate that nothing
2319 * is being returned.
2321 iocp->ioc_count = 0;
2322 } else {
2323 iocp->ioc_count =
2324 sizeof (hid_vid_pid_t);
2326 qreply(q, mp);
2328 return (HID_SUCCESS);
2329 } else {
2331 /* retry */
2332 return (HID_ENQUEUE);
2334 case HID_OPEN_POLLED_INPUT:
2335 if (canputnext(RD(q))) {
2336 freemsg(mp->b_cont);
2338 /* Initialize the structure */
2339 hid_polled_input.hid_polled_version =
2340 HID_POLLED_INPUT_V0;
2341 hid_polled_input.hid_polled_read = hid_polled_read;
2342 hid_polled_input.hid_polled_input_enter =
2343 hid_polled_input_enter;
2344 hid_polled_input.hid_polled_input_exit =
2345 hid_polled_input_exit;
2346 hid_polled_input.hid_polled_input_handle =
2347 (hid_polled_handle_t)hidp;
2349 mp->b_cont = hid_data2mblk(
2350 (uchar_t *)&hid_polled_input,
2351 sizeof (hid_polled_input_callback_t));
2352 if (mp->b_cont == NULL) {
2354 * can't allocate mblk, indicate that nothing
2355 * is being returned.
2357 iocp->ioc_count = 0;
2358 } else {
2359 /* Call down into USBA */
2360 (void) hid_polled_input_init(hidp);
2362 iocp->ioc_count =
2363 sizeof (hid_polled_input_callback_t);
2365 qreply(q, mp);
2367 return (HID_SUCCESS);
2368 } else {
2370 /* retry */
2371 return (HID_ENQUEUE);
2373 case HID_CLOSE_POLLED_INPUT:
2374 /* Call down into USBA */
2375 (void) hid_polled_input_fini(hidp);
2377 iocp->ioc_count = 0;
2378 qreply(q, mp);
2380 return (HID_SUCCESS);
2381 default:
2382 hid_qreply_merror(q, mp, EINVAL);
2384 return (HID_FAILURE);
2388 * These (device executable) commands require a hid_req_t.
2389 * Make sure one is present
2391 if (mp->b_cont == NULL) {
2392 hid_qreply_merror(q, mp, EINVAL);
2394 return (error);
2395 } else {
2396 hid_req_data = (hid_req_t *)mp->b_cont->b_rptr;
2397 if ((iocp->ioc_cmd == HID_SET_REPORT) &&
2398 (hid_req_data->hid_req_wLength == 0)) {
2399 hid_qreply_merror(q, mp, EINVAL);
2401 return (error);
2406 * Check is version no. is correct. This
2407 * is coming from the user
2409 if (hid_req_data->hid_req_version_no != HID_VERSION_V_0) {
2410 hid_qreply_merror(q, mp, EINVAL);
2412 return (error);
2415 mutex_enter(&hidp->hid_mutex);
2416 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
2417 "hid_mctl_receive: dev_state=%s",
2418 usb_str_dev_state(hidp->hid_dev_state));
2420 switch (hidp->hid_dev_state) {
2421 case USB_DEV_PWRED_DOWN:
2423 * get the device full powered. We get a callback
2424 * which enables the WQ and kicks off IO
2426 hidp->hid_dev_state = USB_DEV_HID_POWER_CHANGE;
2427 mutex_exit(&hidp->hid_mutex);
2428 if (usb_req_raise_power(hidp->hid_dip, 0,
2429 USB_DEV_OS_FULL_PWR, hid_power_change_callback,
2430 hidp, 0) != USB_SUCCESS) {
2431 /* we retry raising power in wsrv */
2432 mutex_enter(&hidp->hid_mutex);
2433 hidp->hid_dev_state = USB_DEV_PWRED_DOWN;
2434 mutex_exit(&hidp->hid_mutex);
2436 error = HID_ENQUEUE;
2438 break;
2439 case USB_DEV_HID_POWER_CHANGE:
2440 mutex_exit(&hidp->hid_mutex);
2441 error = HID_ENQUEUE;
2443 break;
2444 case USB_DEV_ONLINE:
2445 if (HID_STREAMS_FLAG(q, hidp) != HID_STREAMS_DISMANTLING) {
2446 /* Send a message down */
2447 mutex_exit(&hidp->hid_mutex);
2448 error = hid_mctl_execute_cmd(q, request_type,
2449 hid_req_data, mp);
2450 if (error == HID_FAILURE) {
2451 hid_qreply_merror(q, mp, EIO);
2453 } else {
2454 mutex_exit(&hidp->hid_mutex);
2455 hid_qreply_merror(q, mp, EIO);
2458 break;
2459 default:
2460 mutex_exit(&hidp->hid_mutex);
2461 hid_qreply_merror(q, mp, EIO);
2463 break;
2466 return (error);
2471 * hid_mctl_execute_cmd:
2472 * Send the command to the device.
2474 static int
2475 hid_mctl_execute_cmd(queue_t *q, int request_type, hid_req_t *hid_req_data,
2476 mblk_t *mp)
2478 int request_index;
2479 struct iocblk *iocp;
2480 hid_default_pipe_arg_t *def_pipe_arg;
2481 hid_state_t *hidp = (hid_state_t *)q->q_ptr;
2483 iocp = (struct iocblk *)mp->b_rptr;
2484 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
2485 "hid_mctl_execute_cmd: iocp=0x%p", (void *)iocp);
2487 request_index = hidp->hid_if_descr.bInterfaceNumber;
2490 * Set up the argument to be passed back to hid
2491 * when the asynchronous control callback is
2492 * executed.
2494 def_pipe_arg = kmem_zalloc(sizeof (hid_default_pipe_arg_t), 0);
2496 if (def_pipe_arg == NULL) {
2498 return (HID_FAILURE);
2501 def_pipe_arg->hid_default_pipe_arg_queue = q;
2502 def_pipe_arg->hid_default_pipe_arg_mctlmsg.ioc_cmd = iocp->ioc_cmd;
2503 def_pipe_arg->hid_default_pipe_arg_mctlmsg.ioc_count = 0;
2504 def_pipe_arg->hid_default_pipe_arg_mblk = mp;
2507 * Send the command down to USBA through default
2508 * pipe.
2510 if (hid_send_async_ctrl_request(def_pipe_arg, hid_req_data,
2511 request_type, iocp->ioc_cmd, request_index) != USB_SUCCESS) {
2513 kmem_free(def_pipe_arg, sizeof (hid_default_pipe_arg_t));
2515 return (HID_FAILURE);
2518 return (HID_INPROGRESS);
2523 * hid_send_async_ctrl_request:
2524 * Send an asynchronous control request to USBA. Since hid is a STREAMS
2525 * driver, it is not allowed to wait in its entry points except for the
2526 * open and close entry points. Therefore, hid must use the asynchronous
2527 * USBA calls.
2529 static int
2530 hid_send_async_ctrl_request(hid_default_pipe_arg_t *hid_default_pipe_arg,
2531 hid_req_t *hid_request, uchar_t request_type, int request_request,
2532 ushort_t request_index)
2534 queue_t *q = hid_default_pipe_arg->hid_default_pipe_arg_queue;
2535 hid_state_t *hidp = (hid_state_t *)q->q_ptr;
2536 usb_ctrl_req_t *ctrl_req;
2537 int rval;
2538 size_t length = 0;
2540 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
2541 "hid_send_async_ctrl_request: "
2542 "rq_type=%d rq_rq=%d index=%d",
2543 request_type, request_request, request_index);
2545 mutex_enter(&hidp->hid_mutex);
2546 hidp->hid_default_pipe_req++;
2547 mutex_exit(&hidp->hid_mutex);
2550 * Note that ctrl_req->ctrl_data should be allocated by usba
2551 * only for IN requests. OUT request(e.g SET_REPORT) can have a
2552 * non-zero wLength value but ctrl_data would be allocated by
2553 * client for them.
2555 if (hid_request->hid_req_wLength >= MAX_REPORT_DATA) {
2556 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
2557 "hid_req_wLength is exceeded");
2558 return (USB_FAILURE);
2560 if ((request_type & USB_DEV_REQ_DIR_MASK) == USB_DEV_REQ_DEV_TO_HOST) {
2561 length = hid_request->hid_req_wLength;
2564 if ((ctrl_req = usb_alloc_ctrl_req(hidp->hid_dip, length, 0)) == NULL) {
2565 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
2566 "unable to alloc ctrl req. async trans failed");
2567 mutex_enter(&hidp->hid_mutex);
2568 hidp->hid_default_pipe_req--;
2569 ASSERT(hidp->hid_default_pipe_req >= 0);
2570 mutex_exit(&hidp->hid_mutex);
2572 return (USB_FAILURE);
2575 if ((request_type & USB_DEV_REQ_DIR_MASK) == USB_DEV_REQ_HOST_TO_DEV) {
2576 ASSERT((length == 0) && (ctrl_req->ctrl_data == NULL));
2579 ctrl_req->ctrl_bmRequestType = request_type;
2580 ctrl_req->ctrl_bRequest = (uint8_t)request_request;
2581 ctrl_req->ctrl_wValue = hid_request->hid_req_wValue;
2582 ctrl_req->ctrl_wIndex = request_index;
2583 ctrl_req->ctrl_wLength = hid_request->hid_req_wLength;
2584 /* host to device: create a msg from hid_req_data */
2585 if ((request_type & USB_DEV_REQ_DIR_MASK) == USB_DEV_REQ_HOST_TO_DEV) {
2586 mblk_t *pblk = allocb(hid_request->hid_req_wLength, BPRI_HI);
2587 if (pblk == NULL) {
2588 usb_free_ctrl_req(ctrl_req);
2589 return (USB_FAILURE);
2591 bcopy(hid_request->hid_req_data, pblk->b_wptr,
2592 hid_request->hid_req_wLength);
2593 pblk->b_wptr += hid_request->hid_req_wLength;
2594 ctrl_req->ctrl_data = pblk;
2596 ctrl_req->ctrl_attributes = USB_ATTRS_AUTOCLEARING;
2597 ctrl_req->ctrl_client_private = (usb_opaque_t)hid_default_pipe_arg;
2598 ctrl_req->ctrl_cb = hid_default_pipe_callback;
2599 ctrl_req->ctrl_exc_cb = hid_default_pipe_exception_callback;
2601 if ((rval = usb_pipe_ctrl_xfer(hidp->hid_default_pipe,
2602 ctrl_req, 0)) != USB_SUCCESS) {
2603 mutex_enter(&hidp->hid_mutex);
2604 hidp->hid_default_pipe_req--;
2605 ASSERT(hidp->hid_default_pipe_req >= 0);
2606 mutex_exit(&hidp->hid_mutex);
2608 usb_free_ctrl_req(ctrl_req);
2609 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
2610 "usb_pipe_ctrl_xfer() failed. rval = %d", rval);
2612 return (USB_FAILURE);
2615 return (USB_SUCCESS);
2619 * hid_create_pm_components:
2620 * Create the pm components required for power management.
2621 * For keyboard/mouse, the components is created only if the device
2622 * supports a remote wakeup.
2623 * For other hid devices they are created unconditionally.
2625 static void
2626 hid_create_pm_components(dev_info_t *dip, hid_state_t *hidp)
2628 hid_power_t *hidpm;
2629 uint_t pwr_states;
2631 USB_DPRINTF_L4(PRINT_MASK_PM, hidp->hid_log_handle,
2632 "hid_create_pm_components: Begin");
2634 /* Allocate the state structure */
2635 hidpm = kmem_zalloc(sizeof (hid_power_t), KM_SLEEP);
2636 hidp->hid_pm = hidpm;
2637 hidpm->hid_state = hidp;
2638 hidpm->hid_raise_power = B_FALSE;
2639 hidpm->hid_pm_capabilities = 0;
2640 hidpm->hid_current_power = USB_DEV_OS_FULL_PWR;
2642 switch (hidp->hid_if_descr.bInterfaceProtocol) {
2643 case KEYBOARD_PROTOCOL:
2644 case MOUSE_PROTOCOL:
2645 hidpm->hid_pm_strategy = HID_PM_ACTIVITY;
2646 if ((hid_is_pm_enabled(dip) == USB_SUCCESS) &&
2647 (usb_handle_remote_wakeup(dip, USB_REMOTE_WAKEUP_ENABLE) ==
2648 USB_SUCCESS)) {
2650 USB_DPRINTF_L3(PRINT_MASK_PM, hidp->hid_log_handle,
2651 "hid_create_pm_components: Remote Wakeup Enabled");
2653 if (usb_create_pm_components(dip, &pwr_states) ==
2654 USB_SUCCESS) {
2655 hidpm->hid_wakeup_enabled = 1;
2656 hidpm->hid_pwr_states = (uint8_t)pwr_states;
2660 break;
2661 default:
2662 hidpm->hid_pm_strategy = HID_PM_OPEN_CLOSE;
2663 if ((hid_is_pm_enabled(dip) == USB_SUCCESS) &&
2664 (usb_create_pm_components(dip, &pwr_states) ==
2665 USB_SUCCESS)) {
2666 hidpm->hid_wakeup_enabled = 0;
2667 hidpm->hid_pwr_states = (uint8_t)pwr_states;
2670 break;
2673 USB_DPRINTF_L4(PRINT_MASK_PM, hidp->hid_log_handle,
2674 "hid_create_pm_components: END");
2679 * hid_is_pm_enabled
2680 * Check if the device is pm enabled. Always enable
2681 * pm on the new SUN mouse
2683 static int
2684 hid_is_pm_enabled(dev_info_t *dip)
2686 hid_state_t *hidp = ddi_get_soft_state(hid_statep,
2687 ddi_get_instance(dip));
2689 if (strcmp(ddi_node_name(dip), "mouse") == 0) {
2690 /* check for overrides first */
2691 if (hid_pm_mouse ||
2692 (ddi_prop_exists(DDI_DEV_T_ANY, dip,
2693 (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
2694 "hid-mouse-pm-enable") == 1)) {
2696 return (USB_SUCCESS);
2700 * Always enable PM for 1.05 or greater SUN mouse
2701 * hidp->hid_dev_descr won't be NULL.
2703 if ((hidp->hid_dev_descr->idVendor ==
2704 HID_SUN_MOUSE_VENDOR_ID) &&
2705 (hidp->hid_dev_descr->idProduct ==
2706 HID_SUN_MOUSE_PROD_ID) &&
2707 (hidp->hid_dev_descr->bcdDevice >=
2708 HID_SUN_MOUSE_BCDDEVICE)) {
2710 return (USB_SUCCESS);
2712 } else {
2714 return (USB_SUCCESS);
2717 return (USB_FAILURE);
2722 * hid_save_device_state
2723 * Save the current device/driver state.
2725 static void
2726 hid_save_device_state(hid_state_t *hidp)
2728 struct iocblk *mctlmsg;
2729 mblk_t *mp;
2730 queue_t *q;
2732 USB_DPRINTF_L4(PRINT_MASK_EVENTS, hidp->hid_log_handle,
2733 "hid_save_device_state");
2735 if (!(HID_IS_OPEN(hidp)))
2736 return;
2738 if (hidp->hid_internal_flag == HID_STREAMS_OPEN) {
2740 * Send MCTLs up indicating that the device
2741 * will loose its state
2743 q = hidp->hid_internal_rq;
2745 mutex_exit(&hidp->hid_mutex);
2746 if (canputnext(q)) {
2747 mp = allocb(sizeof (struct iocblk), BPRI_HI);
2748 if (mp != NULL) {
2749 mp->b_datap->db_type = M_CTL;
2750 mctlmsg = (struct iocblk *)
2751 mp->b_datap->db_base;
2752 mctlmsg->ioc_cmd = HID_DISCONNECT_EVENT;
2753 mctlmsg->ioc_count = 0;
2754 putnext(q, mp);
2757 mutex_enter(&hidp->hid_mutex);
2760 if (hidp->hid_external_flag == HID_STREAMS_OPEN) {
2762 * Send MCTLs up indicating that the device
2763 * will loose its state
2765 q = hidp->hid_external_rq;
2767 mutex_exit(&hidp->hid_mutex);
2768 if (canputnext(q)) {
2769 mp = allocb(sizeof (struct iocblk), BPRI_HI);
2770 if (mp != NULL) {
2771 mp->b_datap->db_type = M_CTL;
2772 mctlmsg = (struct iocblk *)
2773 mp->b_datap->db_base;
2774 mctlmsg->ioc_cmd = HID_DISCONNECT_EVENT;
2775 mctlmsg->ioc_count = 0;
2776 putnext(q, mp);
2779 mutex_enter(&hidp->hid_mutex);
2782 mutex_exit(&hidp->hid_mutex);
2783 /* stop polling on the intr pipe */
2784 usb_pipe_stop_intr_polling(hidp->hid_interrupt_pipe, USB_FLAGS_SLEEP);
2785 mutex_enter(&hidp->hid_mutex);
2790 * hid_restore_device_state:
2791 * Set original configuration of the device.
2792 * Reopen intr pipe.
2793 * Enable wrq - this starts new transactions on the control pipe.
2795 static void
2796 hid_restore_device_state(dev_info_t *dip, hid_state_t *hidp)
2798 int rval;
2799 hid_power_t *hidpm;
2800 struct iocblk *mctlmsg;
2801 mblk_t *mp;
2802 queue_t *q;
2804 hid_pm_busy_component(hidp);
2805 mutex_enter(&hidp->hid_mutex);
2807 USB_DPRINTF_L4(PRINT_MASK_ATTA, hidp->hid_log_handle,
2808 "hid_restore_device_state: %s",
2809 usb_str_dev_state(hidp->hid_dev_state));
2811 hidpm = hidp->hid_pm;
2812 mutex_exit(&hidp->hid_mutex);
2814 /* First bring the device to full power */
2815 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
2817 mutex_enter(&hidp->hid_mutex);
2818 if (hidp->hid_dev_state == USB_DEV_ONLINE) {
2820 * We failed the checkpoint, there is no need to restore
2821 * the device state
2823 mutex_exit(&hidp->hid_mutex);
2824 hid_pm_idle_component(hidp);
2826 return;
2828 mutex_exit(&hidp->hid_mutex);
2831 /* Check if we are talking to the same device */
2832 if (usb_check_same_device(dip, hidp->hid_log_handle, USB_LOG_L2,
2833 PRINT_MASK_ALL, USB_CHK_BASIC|USB_CHK_CFG, NULL) != USB_SUCCESS) {
2835 /* change the device state from suspended to disconnected */
2836 mutex_enter(&hidp->hid_mutex);
2837 hidp->hid_dev_state = USB_DEV_DISCONNECTED;
2838 mutex_exit(&hidp->hid_mutex);
2839 hid_pm_idle_component(hidp);
2840 goto nodev;
2843 hid_set_idle(hidp);
2844 hid_set_protocol(hidp, SET_REPORT_PROTOCOL);
2846 mutex_enter(&hidp->hid_mutex);
2847 /* if the device had remote wakeup earlier, enable it again */
2848 if (hidpm->hid_wakeup_enabled) {
2849 mutex_exit(&hidp->hid_mutex);
2851 if ((rval = usb_handle_remote_wakeup(hidp->hid_dip,
2852 USB_REMOTE_WAKEUP_ENABLE)) != USB_SUCCESS) {
2853 USB_DPRINTF_L2(PRINT_MASK_ATTA,
2854 hidp->hid_log_handle,
2855 "usb_handle_remote_wakeup failed (%d)", rval);
2858 mutex_enter(&hidp->hid_mutex);
2862 * restart polling on the interrupt pipe only if the device
2863 * was previously operational (open)
2865 if (HID_IS_OPEN(hidp)) {
2866 if ((rval = hid_start_intr_polling(hidp)) != USB_SUCCESS) {
2867 USB_DPRINTF_L3(PRINT_MASK_ATTA, hidp->hid_log_handle,
2868 "hid_restore_device_state:"
2869 "unable to restart intr pipe poll"
2870 " rval = %d ", rval);
2872 * change the device state from
2873 * suspended to disconnected
2875 hidp->hid_dev_state = USB_DEV_DISCONNECTED;
2876 mutex_exit(&hidp->hid_mutex);
2877 hid_pm_idle_component(hidp);
2878 goto nodev;
2881 if (hidp->hid_dev_state == USB_DEV_DISCONNECTED) {
2882 USB_DPRINTF_L2(PRINT_MASK_EVENTS, hidp->hid_log_handle,
2883 "device is being re-connected");
2886 /* set the device state ONLINE */
2887 hidp->hid_dev_state = USB_DEV_ONLINE;
2889 /* inform upstream modules that the device is back */
2890 if (hidp->hid_internal_flag == HID_STREAMS_OPEN) {
2891 q = hidp->hid_internal_rq;
2893 mutex_exit(&hidp->hid_mutex);
2894 if (canputnext(q)) {
2895 mp = allocb(sizeof (struct iocblk), BPRI_HI);
2896 if (mp != NULL) {
2897 mp->b_datap->db_type = M_CTL;
2898 mctlmsg = (struct iocblk *)
2899 mp->b_datap->db_base;
2900 mctlmsg->ioc_cmd = HID_CONNECT_EVENT;
2901 mctlmsg->ioc_count = 0;
2902 putnext(q, mp);
2905 /* enable write side q */
2906 qenable(WR(q));
2907 mutex_enter(&hidp->hid_mutex);
2910 if (hidp->hid_external_flag == HID_STREAMS_OPEN) {
2911 q = hidp->hid_external_rq;
2913 mutex_exit(&hidp->hid_mutex);
2914 if (canputnext(q)) {
2915 mp = allocb(sizeof (struct iocblk), BPRI_HI);
2916 if (mp != NULL) {
2917 mp->b_datap->db_type = M_CTL;
2918 mctlmsg = (struct iocblk *)
2919 mp->b_datap->db_base;
2920 mctlmsg->ioc_cmd = HID_CONNECT_EVENT;
2921 mctlmsg->ioc_count = 0;
2922 putnext(q, mp);
2925 /* enable write side q */
2926 qenable(WR(q));
2927 mutex_enter(&hidp->hid_mutex);
2929 } else {
2930 /* set the device state ONLINE */
2931 hidp->hid_dev_state = USB_DEV_ONLINE;
2934 mutex_exit(&hidp->hid_mutex);
2935 hid_pm_idle_component(hidp);
2936 return;
2938 nodev:
2940 * Notify applications about device removal. This only
2941 * applies to an external (aka. physical) open. Not sure how to
2942 * notify consconfig to close the internal minor node.
2944 mutex_enter(&hidp->hid_mutex);
2946 if ((q = hidp->hid_external_rq) == NULL) {
2947 mutex_exit(&hidp->hid_mutex);
2948 return;
2951 mutex_exit(&hidp->hid_mutex);
2952 mp = allocb(sizeof (uchar_t), BPRI_HI);
2953 if (mp != NULL) {
2954 mp->b_datap->db_type = M_ERROR;
2955 mp->b_rptr = mp->b_datap->db_base;
2956 mp->b_wptr = mp->b_rptr + sizeof (char);
2957 *mp->b_rptr = ENODEV;
2958 putnext(q, mp);
2964 * hid_qreply_merror:
2965 * Pass an error message up.
2967 static void
2968 hid_qreply_merror(queue_t *q, mblk_t *mp, uchar_t errval)
2970 mp->b_datap->db_type = M_ERROR;
2971 if (mp->b_cont) {
2972 freemsg(mp->b_cont);
2973 mp->b_cont = NULL;
2975 mp->b_rptr = mp->b_datap->db_base;
2976 mp->b_wptr = mp->b_rptr + sizeof (char);
2977 *mp->b_rptr = errval;
2979 qreply(q, mp);
2984 * hid_data2mblk:
2985 * Form an mblk from the given data
2987 static mblk_t *
2988 hid_data2mblk(uchar_t *buf, int len)
2990 mblk_t *mp = NULL;
2992 if (len >= 0) {
2993 mp = allocb(len, BPRI_HI);
2994 if (mp) {
2995 bcopy(buf, mp->b_datap->db_base, len);
2996 mp->b_wptr += len;
3000 return (mp);
3005 * hid_flush :
3006 * Flush data already sent upstreams to client module.
3008 static void
3009 hid_flush(queue_t *q)
3012 * Flush pending data already sent upstream
3014 if ((q != NULL) && (q->q_next != NULL)) {
3015 (void) putnextctl1(q, M_FLUSH, FLUSHR);
3020 static void
3021 hid_pm_busy_component(hid_state_t *hid_statep)
3023 ASSERT(!mutex_owned(&hid_statep->hid_mutex));
3025 if (hid_statep->hid_pm != NULL) {
3026 mutex_enter(&hid_statep->hid_mutex);
3027 hid_statep->hid_pm->hid_pm_busy++;
3029 USB_DPRINTF_L4(PRINT_MASK_PM, hid_statep->hid_log_handle,
3030 "hid_pm_busy_component: %d",
3031 hid_statep->hid_pm->hid_pm_busy);
3033 mutex_exit(&hid_statep->hid_mutex);
3034 if (pm_busy_component(hid_statep->hid_dip, 0) != DDI_SUCCESS) {
3035 mutex_enter(&hid_statep->hid_mutex);
3036 hid_statep->hid_pm->hid_pm_busy--;
3038 USB_DPRINTF_L2(PRINT_MASK_PM,
3039 hid_statep->hid_log_handle,
3040 "hid_pm_busy_component failed: %d",
3041 hid_statep->hid_pm->hid_pm_busy);
3043 mutex_exit(&hid_statep->hid_mutex);
3050 static void
3051 hid_pm_idle_component(hid_state_t *hid_statep)
3053 ASSERT(!mutex_owned(&hid_statep->hid_mutex));
3055 if (hid_statep->hid_pm != NULL) {
3056 if (pm_idle_component(hid_statep->hid_dip, 0) == DDI_SUCCESS) {
3057 mutex_enter(&hid_statep->hid_mutex);
3058 ASSERT(hid_statep->hid_pm->hid_pm_busy > 0);
3059 hid_statep->hid_pm->hid_pm_busy--;
3061 USB_DPRINTF_L4(PRINT_MASK_PM,
3062 hid_statep->hid_log_handle,
3063 "hid_pm_idle_component: %d",
3064 hid_statep->hid_pm->hid_pm_busy);
3066 mutex_exit(&hid_statep->hid_mutex);
3073 * hid_pwrlvl0:
3074 * Functions to handle power transition for various levels
3075 * These functions act as place holders to issue USB commands
3076 * to the devices to change their power levels
3078 static int
3079 hid_pwrlvl0(hid_state_t *hidp)
3081 hid_power_t *hidpm;
3082 int rval;
3083 struct iocblk *mctlmsg;
3084 mblk_t *mp_lowpwr, *mp_fullpwr;
3085 queue_t *q;
3087 hidpm = hidp->hid_pm;
3089 switch (hidp->hid_dev_state) {
3090 case USB_DEV_ONLINE:
3091 /* Deny the powerdown request if the device is busy */
3092 if (hidpm->hid_pm_busy != 0) {
3094 return (USB_FAILURE);
3097 if (HID_IS_OPEN(hidp)) {
3098 q = hidp->hid_inuse_rq;
3099 mutex_exit(&hidp->hid_mutex);
3100 if (canputnext(q)) {
3101 /* try to preallocate mblks */
3102 mp_lowpwr = allocb(
3103 (int)sizeof (struct iocblk), BPRI_HI);
3104 mp_fullpwr = allocb(
3105 (int)sizeof (struct iocblk), BPRI_HI);
3106 if ((mp_lowpwr != NULL) &&
3107 (mp_fullpwr != NULL)) {
3108 /* stop polling */
3109 usb_pipe_stop_intr_polling(
3110 hidp->hid_interrupt_pipe,
3111 USB_FLAGS_SLEEP);
3114 * Send an MCTL up indicating that
3115 * we are powering off
3117 mp_lowpwr->b_datap->db_type = M_CTL;
3118 mctlmsg = (struct iocblk *)
3119 mp_lowpwr->b_datap->db_base;
3120 mctlmsg->ioc_cmd = HID_POWER_OFF;
3121 mctlmsg->ioc_count = 0;
3122 putnext(q, mp_lowpwr);
3124 /* save the full powr mblk */
3125 mutex_enter(&hidp->hid_mutex);
3126 hidpm->hid_pm_pwrup = mp_fullpwr;
3127 } else {
3129 * Since we failed to allocate one
3130 * or more mblks, we fail attempt
3131 * to go into low power this time
3133 freemsg(mp_lowpwr);
3134 freemsg(mp_fullpwr);
3135 mutex_enter(&hidp->hid_mutex);
3137 return (USB_FAILURE);
3139 } else {
3141 * Since we can't send an mblk up,
3142 * we fail this attempt to go to low power
3144 mutex_enter(&hidp->hid_mutex);
3146 return (USB_FAILURE);
3150 mutex_exit(&hidp->hid_mutex);
3151 /* Issue USB D3 command to the device here */
3152 rval = usb_set_device_pwrlvl3(hidp->hid_dip);
3153 ASSERT(rval == USB_SUCCESS);
3155 mutex_enter(&hidp->hid_mutex);
3156 hidp->hid_dev_state = USB_DEV_PWRED_DOWN;
3157 hidpm->hid_current_power = USB_DEV_OS_PWR_OFF;
3159 /* FALLTHRU */
3160 case USB_DEV_DISCONNECTED:
3161 case USB_DEV_SUSPENDED:
3162 case USB_DEV_PWRED_DOWN:
3163 default:
3164 break;
3167 return (USB_SUCCESS);
3171 /* ARGSUSED */
3172 static int
3173 hid_pwrlvl1(hid_state_t *hidp)
3175 int rval;
3177 /* Issue USB D2 command to the device here */
3178 rval = usb_set_device_pwrlvl2(hidp->hid_dip);
3179 ASSERT(rval == USB_SUCCESS);
3181 return (USB_FAILURE);
3185 /* ARGSUSED */
3186 static int
3187 hid_pwrlvl2(hid_state_t *hidp)
3189 int rval;
3191 rval = usb_set_device_pwrlvl1(hidp->hid_dip);
3192 ASSERT(rval == USB_SUCCESS);
3194 return (USB_FAILURE);
3198 static int
3199 hid_pwrlvl3(hid_state_t *hidp)
3201 hid_power_t *hidpm;
3202 int rval;
3203 struct iocblk *mctlmsg;
3204 mblk_t *mp;
3205 queue_t *q;
3207 hidpm = hidp->hid_pm;
3209 switch (hidp->hid_dev_state) {
3210 case USB_DEV_HID_POWER_CHANGE:
3211 case USB_DEV_PWRED_DOWN:
3212 /* Issue USB D0 command to the device here */
3213 rval = usb_set_device_pwrlvl0(hidp->hid_dip);
3214 ASSERT(rval == USB_SUCCESS);
3216 if (HID_IS_OPEN(hidp)) {
3217 /* restart polling on intr pipe */
3218 rval = hid_start_intr_polling(hidp);
3219 if (rval != USB_SUCCESS) {
3220 USB_DPRINTF_L2(PRINT_MASK_EVENTS,
3221 hidp->hid_log_handle,
3222 "unable to restart intr polling rval = %d",
3223 rval);
3225 return (USB_FAILURE);
3228 /* Send an MCTL up indicating device in full power */
3229 q = hidp->hid_inuse_rq;
3230 mp = hidpm->hid_pm_pwrup;
3231 hidpm->hid_pm_pwrup = NULL;
3232 mutex_exit(&hidp->hid_mutex);
3233 if (canputnext(q)) {
3234 mp->b_datap->db_type = M_CTL;
3235 mctlmsg = (struct iocblk *)
3236 mp->b_datap->db_base;
3237 mctlmsg->ioc_cmd = HID_FULL_POWER;
3238 mctlmsg->ioc_count = 0;
3239 putnext(q, mp);
3240 } else {
3241 freemsg(mp);
3243 mutex_enter(&hidp->hid_mutex);
3246 hidp->hid_dev_state = USB_DEV_ONLINE;
3247 hidpm->hid_current_power = USB_DEV_OS_FULL_PWR;
3249 /* FALLTHRU */
3250 case USB_DEV_DISCONNECTED:
3251 case USB_DEV_SUSPENDED:
3252 case USB_DEV_ONLINE:
3254 return (USB_SUCCESS);
3255 default:
3256 USB_DPRINTF_L2(PRINT_MASK_EVENTS, hidp->hid_log_handle,
3257 "hid_pwrlvl3: Improper State");
3259 return (USB_FAILURE);
3265 * hid_polled_input_init :
3266 * This routine calls down to the lower layers to initialize any state
3267 * information. This routine initializes the lower layers for input.
3269 static int
3270 hid_polled_input_init(hid_state_t *hidp)
3272 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
3273 "hid_polled_input_init");
3276 * Call the lower layers to intialize any state information
3277 * that they will need to provide the polled characters.
3279 if (usb_console_input_init(hidp->hid_dip, hidp->hid_interrupt_pipe,
3280 &hidp->hid_polled_raw_buf,
3281 &hidp->hid_polled_console_info) != USB_SUCCESS) {
3283 * If for some reason the lower layers cannot initialized, then
3284 * bail.
3286 (void) hid_polled_input_fini(hidp);
3288 return (USB_FAILURE);
3291 return (USB_SUCCESS);
3296 * hid_polled_input_fini:
3297 * This routine is called when we are done using this device as an input
3298 * device.
3300 static int
3301 hid_polled_input_fini(hid_state_t *hidp)
3303 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
3304 "hid_polled_input_fini");
3307 * Call the lower layers to free any state information
3308 * only if polled input has been initialised.
3310 if ((hidp->hid_polled_console_info) &&
3311 (usb_console_input_fini(hidp->hid_polled_console_info) !=
3312 USB_SUCCESS)) {
3314 return (USB_FAILURE);
3316 hidp->hid_polled_console_info = NULL;
3318 return (USB_SUCCESS);
3323 * hid_polled_input_enter:
3324 * This is the routine that is called in polled mode to save the USB
3325 * state information before using the USB keyboard as an input device.
3326 * This routine, and all of the routines that it calls, are responsible
3327 * for saving any state information so that it can be restored when
3328 * polling mode is over.
3330 static int
3331 /* ARGSUSED */
3332 hid_polled_input_enter(hid_polled_handle_t hid_polled_inputp)
3334 hid_state_t *hidp = (hid_state_t *)hid_polled_inputp;
3337 * Call the lower layers to tell them to save any state information.
3339 (void) usb_console_input_enter(hidp->hid_polled_console_info);
3341 return (USB_SUCCESS);
3346 * hid_polled_read :
3347 * This is the routine that is called in polled mode when it wants to read
3348 * a character. We will call to the lower layers to see if there is any
3349 * input data available. If there is USB scancodes available, we will
3350 * give them back.
3352 static int
3353 hid_polled_read(hid_polled_handle_t hid_polled_input, uchar_t **buffer)
3355 hid_state_t *hidp = (hid_state_t *)hid_polled_input;
3356 uint_t num_bytes;
3359 * Call the lower layers to get the character from the controller.
3360 * The lower layers will return the number of characters that
3361 * were put in the raw buffer. The address of the raw buffer
3362 * was passed down to the lower layers during hid_polled_init.
3364 if (usb_console_read(hidp->hid_polled_console_info,
3365 &num_bytes) != USB_SUCCESS) {
3367 return (0);
3370 _NOTE(NO_COMPETING_THREADS_NOW);
3372 *buffer = hidp->hid_polled_raw_buf;
3374 _NOTE(COMPETING_THREADS_NOW);
3377 * Return the number of characters that were copied into the
3378 * polled buffer.
3380 return (num_bytes);
3385 * hid_polled_input_exit :
3386 * This is the routine that is called in polled mode when it is giving up
3387 * control of the USB keyboard. This routine, and the lower layer routines
3388 * that it calls, are responsible for restoring the controller state to the
3389 * state it was in before polled mode.
3391 static int
3392 hid_polled_input_exit(hid_polled_handle_t hid_polled_inputp)
3394 hid_state_t *hidp = (hid_state_t *)hid_polled_inputp;
3397 * Call the lower layers to restore any state information.
3399 (void) usb_console_input_exit(hidp->hid_polled_console_info);
3401 return (0);