1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2017 Joyent, Inc.
25 */
26
27
28 /*
29 * Human Interface Device driver (HID)
30 *
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).
36 *
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).
39 *
40 * Undocumented functions may go away in a future Solaris OS release.
41 *
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.
45 */
46
47 #define USBDRV_MAJOR_VER 2
48 #define USBDRV_MINOR_VER 0
49
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>
62
63 extern int ddi_create_internal_pathname(dev_info_t *, char *, int, minor_t);
64
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;
69
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 */
73
74 /* soft state structures */
75 #define HID_INITIAL_SOFT_SPACE 4
76 static void *hid_statep;
77
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);
91
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 *);
100
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);
108
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 *);
113
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 *);
117
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 *);
124
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 *);
130
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 *);
136
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);
142 /* These are to enable ugen support: */
143 static int hid_chropen(dev_t *, int, int, cred_t *);
144 static int hid_chrclose(dev_t, int, int, cred_t *);
145 static int hid_read(dev_t, struct uio *, cred_t *);
146 static int hid_write(dev_t, struct uio *, cred_t *);
147 static int hid_poll(dev_t, short, int, short *, struct pollhead **);
148
149 /*
150 * Warlock is not aware of the automatic locking mechanisms for
151 * streams drivers. The hid streams enter points are protected by
152 * a per module perimeter. If the locking in hid is a bottleneck
153 * per queue pair or per queue locking may be used. Since warlock
154 * is not aware of the streams perimeters, these notes have been added.
155 *
156 * Note that the perimeters do not protect the driver from callbacks
157 * happening while a streams entry point is executing. So, the hid_mutex
158 * has been created to protect the data.
159 */
160 _NOTE(SCHEME_PROTECTS_DATA("unique per call", iocblk))
161 _NOTE(SCHEME_PROTECTS_DATA("unique per call", datab))
162 _NOTE(SCHEME_PROTECTS_DATA("unique per call", msgb))
163 _NOTE(SCHEME_PROTECTS_DATA("unique per call", queue))
164 _NOTE(SCHEME_PROTECTS_DATA("unique per call", usb_ctrl_req))
165 _NOTE(SCHEME_PROTECTS_DATA("unique per call", usb_intr_req))
166
167 /* module information */
168 static struct module_info hid_mod_info = {
169 0x0ffff, /* module id number */
170 "hid", /* module name */
171 0, /* min packet size accepted */
172 INFPSZ, /* max packet size accepted */
173 512, /* hi-water mark */
174 128 /* lo-water mark */
175 };
176
177 /* read queue information structure */
178 static struct qinit rinit = {
179 NULL, /* put procedure not needed */
180 NULL, /* service procedure not needed */
181 hid_open, /* called on startup */
182 hid_close, /* called on finish */
183 NULL, /* for future use */
184 &hid_mod_info, /* module information structure */
185 NULL /* module statistics structure */
186 };
187
188 /* write queue information structure */
189 static struct qinit winit = {
190 hid_wput, /* put procedure */
191 hid_wsrv, /* service procedure */
192 NULL, /* open not used on write side */
193 NULL, /* close not used on write side */
194 NULL, /* for future use */
195 &hid_mod_info, /* module information structure */
196 NULL /* module statistics structure */
197 };
198
199 struct streamtab hid_streamtab = {
200 &rinit,
201 &winit,
202 NULL, /* not a MUX */
203 NULL /* not a MUX */
204 };
205
206 struct cb_ops hid_cb_ops = {
207 hid_chropen, /* open */
208 hid_chrclose, /* close */
209 nulldev, /* strategy */
210 nulldev, /* print */
211 nulldev, /* dump */
212 hid_read, /* read */
213 hid_write, /* write */
214 nulldev, /* ioctl */
215 nulldev, /* devmap */
216 nulldev, /* mmap */
217 nulldev, /* segmap */
218 hid_poll, /* poll */
219 ddi_prop_op, /* cb_prop_op */
220 &hid_streamtab, /* streamtab */
221 D_MP | D_MTPERQ
222 };
223
224
225 static struct dev_ops hid_ops = {
226 DEVO_REV, /* devo_rev, */
227 0, /* refcnt */
228 hid_info, /* info */
229 nulldev, /* identify */
230 nulldev, /* probe */
231 hid_attach, /* attach */
232 hid_detach, /* detach */
233 nodev, /* reset */
234 &hid_cb_ops, /* driver operations */
235 NULL, /* bus operations */
236 hid_power, /* power */
237 ddi_quiesce_not_needed, /* quiesce */
238 };
239
240 static struct modldrv hidmodldrv = {
241 &mod_driverops,
242 "USB HID Client Driver",
243 &hid_ops /* driver ops */
244 };
245
246 static struct modlinkage modlinkage = {
247 MODREV_1,
248 &hidmodldrv,
249 NULL,
250 };
251
252 static usb_event_t hid_events = {
253 hid_disconnect_event_callback,
254 hid_restore_state_event_callback,
255 NULL,
256 NULL,
257 };
258
259
260 int
_init(void)261 _init(void)
262 {
263 int rval;
264
265 if (((rval = ddi_soft_state_init(&hid_statep, sizeof (hid_state_t),
266 HID_INITIAL_SOFT_SPACE)) != 0)) {
267
268 return (rval);
269 }
270
271 if ((rval = mod_install(&modlinkage)) != 0) {
272 ddi_soft_state_fini(&hid_statep);
273 }
274
275 return (rval);
276 }
277
278
279 int
_fini(void)280 _fini(void)
281 {
282 int rval;
283
284 if ((rval = mod_remove(&modlinkage)) != 0) {
285
286 return (rval);
287 }
288
289 ddi_soft_state_fini(&hid_statep);
290
291 return (rval);
292 }
293
294
295 int
_info(struct modinfo * modinfop)296 _info(struct modinfo *modinfop)
297 {
298 return (mod_info(&modlinkage, modinfop));
299 }
300
301
302 /*
303 * hid_info :
304 * Get minor number, soft state structure etc.
305 */
306 /*ARGSUSED*/
307 static int
hid_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)308 hid_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
309 {
310 hid_state_t *hidp = NULL;
311 int error = DDI_FAILURE;
312 minor_t minor = getminor((dev_t)arg);
313 int instance = HID_MINOR_TO_INSTANCE(minor);
314
315 switch (infocmd) {
316 case DDI_INFO_DEVT2DEVINFO:
317 if ((hidp = ddi_get_soft_state(hid_statep, instance)) != NULL) {
318 *result = hidp->hid_dip;
319 if (*result != NULL) {
320 error = DDI_SUCCESS;
321 }
322 } else
323 *result = NULL;
324 break;
325 case DDI_INFO_DEVT2INSTANCE:
326 *result = (void *)(uintptr_t)instance;
327 error = DDI_SUCCESS;
328 break;
329 default:
330 break;
331 }
332
333 return (error);
334 }
335
336
337 /*
338 * hid_attach :
339 * Gets called at the time of attach. Do allocation,
340 * and initialization of the software structure.
341 * Get all the descriptors, setup the
342 * report descriptor tree by calling hidparser
343 * function.
344 */
345 static int
hid_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)346 hid_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
347 {
348
349 int instance = ddi_get_instance(dip);
350 int parse_hid_descr_error = 0;
351 hid_state_t *hidp = NULL;
352 uint32_t usage_page;
353 uint32_t usage;
354 usb_client_dev_data_t *dev_data;
355 usb_alt_if_data_t *altif_data;
356 char minor_name[HID_MINOR_NAME_LEN];
357 usb_ep_data_t *ep_data;
358 usb_ugen_info_t usb_ugen_info;
359
360 switch (cmd) {
361 case DDI_ATTACH:
362 break;
363 case DDI_RESUME:
364 hidp = ddi_get_soft_state(hid_statep, instance);
365 hid_cpr_resume(hidp);
366 return (DDI_SUCCESS);
367 default:
368
369 return (DDI_FAILURE);
370 }
371
372 /*
373 * Allocate softstate information and get softstate pointer
374 */
375 if (ddi_soft_state_zalloc(hid_statep, instance) == DDI_SUCCESS) {
376 hidp = ddi_get_soft_state(hid_statep, instance);
377 }
378 if (hidp == NULL) {
379
380 goto fail;
381 }
382
383 hidp->hid_log_handle = usb_alloc_log_hdl(dip, NULL, &hid_errlevel,
384 &hid_errmask, &hid_instance_debug, 0);
385
386 hidp->hid_instance = instance;
387 hidp->hid_dip = dip;
388
389 /*
390 * Register with USBA. Just retrieve interface descriptor
391 */
392 if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
393 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
394 "hid_attach: client attach failed");
395
396 goto fail;
397 }
398
399 if (usb_get_dev_data(dip, &dev_data, USB_PARSE_LVL_IF, 0) !=
400 USB_SUCCESS) {
401
402 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
403 "hid_attach: usb_get_dev_data() failed");
404
405 goto fail;
406 }
407
408 /* initialize mutex */
409 mutex_init(&hidp->hid_mutex, NULL, MUTEX_DRIVER,
410 dev_data->dev_iblock_cookie);
411
412 hidp->hid_attach_flags |= HID_LOCK_INIT;
413
414 /* get interface data for alternate 0 */
415 altif_data = &dev_data->dev_curr_cfg->
416 cfg_if[dev_data->dev_curr_if].if_alt[0];
417
418 mutex_enter(&hidp->hid_mutex);
419 hidp->hid_dev_data = dev_data;
420 hidp->hid_dev_descr = dev_data->dev_descr;
421 hidp->hid_interfaceno = dev_data->dev_curr_if;
422 hidp->hid_if_descr = altif_data->altif_descr;
423 /*
424 * Make sure that the bInterfaceProtocol only has meaning to
425 * Boot Interface Subclass.
426 */
427 if (hidp->hid_if_descr.bInterfaceSubClass != BOOT_INTERFACE)
428 hidp->hid_if_descr.bInterfaceProtocol = NONE_PROTOCOL;
429 mutex_exit(&hidp->hid_mutex);
430
431 if ((ep_data = usb_lookup_ep_data(dip, dev_data,
432 hidp->hid_interfaceno, 0, 0,
433 (uint_t)USB_EP_ATTR_INTR, (uint_t)USB_EP_DIR_IN)) == NULL) {
434
435 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
436 "no interrupt IN endpoint found");
437
438 goto fail;
439 }
440
441 mutex_enter(&hidp->hid_mutex);
442 if (usb_ep_xdescr_fill(USB_EP_XDESCR_CURRENT_VERSION, dip, ep_data,
443 &hidp->hid_ep_intr_xdescr) != USB_SUCCESS) {
444 mutex_exit(&hidp->hid_mutex);
445
446 goto fail;
447 }
448
449 /*
450 * Attempt to find the hid descriptor, it could be after interface
451 * or after endpoint descriptors
452 */
453 if (hid_parse_hid_descr(&hidp->hid_hid_descr, USB_HID_DESCR_SIZE,
454 altif_data, ep_data) != USB_HID_DESCR_SIZE) {
455 /*
456 * If parsing of hid descriptor failed and
457 * the device is a keyboard or mouse, use predefined
458 * length and packet size.
459 */
460 if (hid_parse_hid_descr_failure(hidp) == USB_FAILURE) {
461 mutex_exit(&hidp->hid_mutex);
462
463 goto fail;
464 }
465
466 /*
467 * hid descriptor was bad but since
468 * the device is a keyboard or mouse,
469 * we will use the default length
470 * and packet size.
471 */
472 parse_hid_descr_error = HID_BAD_DESCR;
473 } else {
474 /* Parse hid descriptor successful */
475
476 USB_DPRINTF_L3(PRINT_MASK_ATTA, hidp->hid_log_handle,
477 "Hid descriptor:\n\t"
478 "bLength = 0x%x bDescriptorType = 0x%x "
479 "bcdHID = 0x%x\n\t"
480 "bCountryCode = 0x%x bNumDescriptors = 0x%x\n\t"
481 "bReportDescriptorType = 0x%x\n\t"
482 "wReportDescriptorLength = 0x%x",
483 hidp->hid_hid_descr.bLength,
484 hidp->hid_hid_descr.bDescriptorType,
485 hidp->hid_hid_descr.bcdHID,
486 hidp->hid_hid_descr.bCountryCode,
487 hidp->hid_hid_descr.bNumDescriptors,
488 hidp->hid_hid_descr.bReportDescriptorType,
489 hidp->hid_hid_descr.wReportDescriptorLength);
490 }
491
492 /*
493 * Save a copy of the default pipe for easy reference
494 */
495 hidp->hid_default_pipe = hidp->hid_dev_data->dev_default_ph;
496
497 /* we copied the descriptors we need, free the dev_data */
498 usb_free_dev_data(dip, dev_data);
499 hidp->hid_dev_data = NULL;
500
501 if (usb_owns_device(dip)) {
502 /* Get a ugen handle. */
503 bzero(&usb_ugen_info, sizeof (usb_ugen_info));
504
505 usb_ugen_info.usb_ugen_flags = 0;
506 usb_ugen_info.usb_ugen_minor_node_ugen_bits_mask =
507 (dev_t)HID_MINOR_UGEN_BITS_MASK;
508 usb_ugen_info.usb_ugen_minor_node_instance_mask =
509 (dev_t)HID_MINOR_INSTANCE_MASK;
510 hidp->hid_ugen_hdl = usb_ugen_get_hdl(dip, &usb_ugen_info);
511
512 if (usb_ugen_attach(hidp->hid_ugen_hdl, cmd) !=
513 USB_SUCCESS) {
514 USB_DPRINTF_L2(PRINT_MASK_ATTA,
515 hidp->hid_log_handle,
516 "usb_ugen_attach failed");
517
518 usb_ugen_release_hdl(hidp->hid_ugen_hdl);
519 hidp->hid_ugen_hdl = NULL;
520 }
521 }
522
523 /*
524 * Don't get the report descriptor if parsing hid descriptor earlier
525 * failed since device probably won't return valid report descriptor
526 * either. Though parsing of hid descriptor failed, we have reached
527 * this point because the device has been identified as a
528 * keyboard or a mouse successfully and the default packet
529 * size and layout(in case of keyboard only) will be used, so it
530 * is ok to go ahead even if parsing of hid descriptor failed and
531 * we will not try to get the report descriptor.
532 */
533 if (parse_hid_descr_error != HID_BAD_DESCR) {
534 /*
535 * Sun mouse rev 105 is a bit slow in responding to this
536 * request and requires multiple retries
537 */
538 int retry;
539
540 /*
541 * Get and parse the report descriptor.
542 * Set the packet size if parsing is successful.
543 * Note that we start retry at 1 to have a delay
544 * in the first iteration.
545 */
546 mutex_exit(&hidp->hid_mutex);
547 for (retry = 1; retry < HID_RETRY; retry++) {
548 if (hid_handle_report_descriptor(hidp,
549 hidp->hid_interfaceno) == USB_SUCCESS) {
550 break;
551 }
552 delay(retry * drv_usectohz(1000));
553 }
554 if (retry >= HID_RETRY) {
555
556 goto fail;
557 }
558 mutex_enter(&hidp->hid_mutex);
559
560 /*
561 * If packet size is zero, but the device is identified
562 * as a mouse or a keyboard, use predefined packet
563 * size.
564 */
565 if (hidp->hid_packet_size == 0) {
566 if (hidp->hid_if_descr.bInterfaceProtocol ==
567 KEYBOARD_PROTOCOL) {
568 /* device is a keyboard */
569 hidp->hid_packet_size = USBKPSZ;
570 } else if (hidp->
571 hid_if_descr.bInterfaceProtocol ==
572 MOUSE_PROTOCOL) {
573 /* device is a mouse */
574 hidp->hid_packet_size = USBMSSZ;
575 } else {
576 USB_DPRINTF_L2(PRINT_MASK_ATTA,
577 hidp->hid_log_handle,
578 "Failed to find hid packet size");
579 mutex_exit(&hidp->hid_mutex);
580
581 goto fail;
582 }
583 }
584 }
585
586 /*
587 * initialize the pipe policy for the interrupt pipe.
588 */
589 hidp->hid_intr_pipe_policy.pp_max_async_reqs = 1;
590
591 /*
592 * Make a clas specific request to SET_IDLE
593 * In this case send no reports if state has not changed.
594 * See HID 7.2.4.
595 */
596 mutex_exit(&hidp->hid_mutex);
597 hid_set_idle(hidp);
598
599 /* always initialize to report protocol */
600 hid_set_protocol(hidp, SET_REPORT_PROTOCOL);
601 mutex_enter(&hidp->hid_mutex);
602
603 /*
604 * Create minor node based on information from the
605 * descriptors
606 */
607 switch (hidp->hid_if_descr.bInterfaceProtocol) {
608 case KEYBOARD_PROTOCOL:
609 (void) strcpy(minor_name, "keyboard");
610
611 break;
612 case MOUSE_PROTOCOL:
613 (void) strcpy(minor_name, "mouse");
614
615 break;
616 default:
617 /*
618 * If the report descriptor has the GD mouse collection in
619 * its multiple collection, create a minor node and support it.
620 * It is used on some advanced keyboard/mouse set.
621 */
622 if (hidparser_lookup_usage_collection(
623 hidp->hid_report_descr, HID_GENERIC_DESKTOP,
624 HID_GD_MOUSE) != HIDPARSER_FAILURE) {
625 (void) strcpy(minor_name, "mouse");
626
627 break;
628 }
629
630 if (hidparser_get_top_level_collection_usage(
631 hidp->hid_report_descr, &usage_page, &usage) !=
632 HIDPARSER_FAILURE) {
633 switch (usage_page) {
634 case HID_CONSUMER:
635 switch (usage) {
636 case HID_CONSUMER_CONTROL:
637 (void) strcpy(minor_name,
638 "consumer_control");
639
640 break;
641 default:
642 (void) sprintf(minor_name,
643 "hid_%d_%d", usage_page, usage);
644
645 break;
646 }
647
648 break;
649 case HID_GENERIC_DESKTOP:
650 switch (usage) {
651 case HID_GD_POINTER:
652 (void) strcpy(minor_name,
653 "pointer");
654
655 break;
656 case HID_GD_MOUSE:
657 (void) strcpy(minor_name,
658 "mouse");
659
660 break;
661 case HID_GD_KEYBOARD:
662 (void) strcpy(minor_name,
663 "keyboard");
664
665 break;
666 default:
667 (void) sprintf(minor_name,
668 "hid_%d_%d", usage_page, usage);
669
670 break;
671 }
672
673 break;
674 default:
675 (void) sprintf(minor_name,
676 "hid_%d_%d", usage_page, usage);
677
678 break;
679 }
680 } else {
681 USB_DPRINTF_L1(PRINT_MASK_ATTA, hidp->hid_log_handle,
682 "hid_attach: Unsupported HID device");
683 mutex_exit(&hidp->hid_mutex);
684
685 goto fail;
686 }
687
688 break;
689 }
690
691 mutex_exit(&hidp->hid_mutex);
692
693 if ((ddi_create_minor_node(dip, minor_name, S_IFCHR,
694 HID_CONSTRUCT_EXTERNAL_MINOR(instance),
695 DDI_PSEUDO, 0)) != DDI_SUCCESS) {
696 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
697 "hid_attach: Could not create minor node");
698
699 goto fail;
700 }
701
702 /* create internal path for virtual */
703 if (strcmp(minor_name, "mouse") == 0) {
704 if (ddi_create_internal_pathname(dip, "internal_mouse", S_IFCHR,
705 HID_CONSTRUCT_INTERNAL_MINOR(instance)) != DDI_SUCCESS) {
706
707 goto fail;
708 }
709 }
710
711 if (strcmp(minor_name, "keyboard") == 0) {
712 if (ddi_create_internal_pathname(dip, "internal_keyboard",
713 S_IFCHR, HID_CONSTRUCT_INTERNAL_MINOR(instance)) !=
714 DDI_SUCCESS) {
715
716 goto fail;
717 }
718 }
719
720 mutex_enter(&hidp->hid_mutex);
721 hidp->hid_attach_flags |= HID_MINOR_NODES;
722 hidp->hid_dev_state = USB_DEV_ONLINE;
723 mutex_exit(&hidp->hid_mutex);
724
725 /* register for all events */
726 if (usb_register_event_cbs(dip, &hid_events, 0) != USB_SUCCESS) {
727 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
728 "usb_register_event_cbs failed");
729
730 goto fail;
731 }
732
733 /* now create components to power manage this device */
734 hid_create_pm_components(dip, hidp);
735 hid_pm_busy_component(hidp);
736 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
737 hid_pm_idle_component(hidp);
738
739 hidp->hid_internal_rq = hidp->hid_external_rq = NULL;
740 hidp->hid_internal_flag = hidp->hid_external_flag = 0;
741 hidp->hid_inuse_rq = NULL;
742
743 /*
744 * report device
745 */
746 ddi_report_dev(dip);
747
748 USB_DPRINTF_L4(PRINT_MASK_ATTA, hidp->hid_log_handle,
749 "hid_attach: End");
750
751 return (DDI_SUCCESS);
752
753 fail:
754 if (hidp) {
755 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
756 "hid_attach: fail");
757 hid_detach_cleanup(dip, hidp);
758 }
759
760 return (DDI_FAILURE);
761 }
762
763
764 /*
765 * hid_detach :
766 * Gets called at the time of detach.
767 */
768 static int
hid_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)769 hid_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
770 {
771 int instance = ddi_get_instance(dip);
772 hid_state_t *hidp;
773 int rval = DDI_FAILURE;
774
775 hidp = ddi_get_soft_state(hid_statep, instance);
776
777 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle, "hid_detach");
778
779 switch (cmd) {
780 case DDI_DETACH:
781 /*
782 * Undo what we did in client_attach, freeing resources
783 * and removing things we installed. The system
784 * framework guarantees we are not active with this devinfo
785 * node in any other entry points at this time.
786 */
787 hid_detach_cleanup(dip, hidp);
788
789 return (DDI_SUCCESS);
790 case DDI_SUSPEND:
791 rval = hid_cpr_suspend(hidp);
792
793 return (rval == USB_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
794 default:
795 break;
796 }
797
798 return (rval);
799 }
800
801 static int
hid_chropen(dev_t * devp,int flag,int sflag,cred_t * credp)802 hid_chropen(dev_t *devp, int flag, int sflag, cred_t *credp)
803 {
804 int rval;
805 minor_t minor = getminor(*devp);
806 int instance;
807 hid_state_t *hidp;
808
809 instance = HID_MINOR_TO_INSTANCE(minor);
810
811 hidp = ddi_get_soft_state(hid_statep, instance);
812 if (hidp == NULL) {
813 return (ENXIO);
814 }
815
816 if (!HID_IS_UGEN_OPEN(minor)) {
817 return (ENXIO);
818 }
819
820 hid_pm_busy_component(hidp);
821 (void) pm_raise_power(hidp->hid_dip, 0, USB_DEV_OS_FULL_PWR);
822
823 mutex_enter(&hidp->hid_mutex);
824
825 rval = usb_ugen_open(hidp->hid_ugen_hdl, devp, flag,
826 sflag, credp);
827
828 mutex_exit(&hidp->hid_mutex);
829
830 if (rval != 0) {
831 hid_pm_idle_component(hidp);
832 }
833
834 return (rval);
835 }
836
837 static int
hid_chrclose(dev_t dev,int flag,int otyp,cred_t * credp)838 hid_chrclose(dev_t dev, int flag, int otyp, cred_t *credp)
839 {
840 int rval;
841 minor_t minor = getminor(dev);
842 int instance;
843 hid_state_t *hidp;
844
845 instance = HID_MINOR_TO_INSTANCE(minor);
846
847 hidp = ddi_get_soft_state(hid_statep, instance);
848 if (hidp == NULL) {
849 return (ENXIO);
850 }
851
852 if (!HID_IS_UGEN_OPEN(minor)) {
853 return (ENXIO);
854 }
855
856 mutex_enter(&hidp->hid_mutex);
857
858 rval = usb_ugen_close(hidp->hid_ugen_hdl, dev, flag,
859 otyp, credp);
860
861 mutex_exit(&hidp->hid_mutex);
862
863 if (rval == 0) {
864 hid_pm_idle_component(hidp);
865 }
866
867 return (rval);
868 }
869
870 static int
hid_read(dev_t dev,struct uio * uiop,cred_t * credp)871 hid_read(dev_t dev, struct uio *uiop, cred_t *credp)
872 {
873 int rval;
874 minor_t minor = getminor(dev);
875 int instance;
876 hid_state_t *hidp;
877
878 instance = HID_MINOR_TO_INSTANCE(minor);
879
880 hidp = ddi_get_soft_state(hid_statep, instance);
881 if (hidp == NULL) {
882 return (ENXIO);
883 }
884
885 if (!HID_IS_UGEN_OPEN(minor)) {
886 return (ENXIO);
887 }
888
889 rval = usb_ugen_read(hidp->hid_ugen_hdl, dev, uiop, credp);
890
891 return (rval);
892 }
893
894 static int
hid_write(dev_t dev,struct uio * uiop,cred_t * credp)895 hid_write(dev_t dev, struct uio *uiop, cred_t *credp)
896 {
897 int rval;
898 minor_t minor = getminor(dev);
899 int instance;
900 hid_state_t *hidp;
901
902 instance = HID_MINOR_TO_INSTANCE(minor);
903
904 hidp = ddi_get_soft_state(hid_statep, instance);
905 if (hidp == NULL) {
906 return (ENXIO);
907 }
908
909 if (!HID_IS_UGEN_OPEN(minor)) {
910 return (ENXIO);
911 }
912
913 rval = usb_ugen_write(hidp->hid_ugen_hdl, dev, uiop, credp);
914
915 return (rval);
916 }
917
918 static int
hid_poll(dev_t dev,short events,int anyyet,short * reventsp,struct pollhead ** phpp)919 hid_poll(dev_t dev, short events, int anyyet, short *reventsp,
920 struct pollhead **phpp)
921 {
922 int rval;
923 minor_t minor = getminor(dev);
924 int instance;
925 hid_state_t *hidp;
926
927 instance = HID_MINOR_TO_INSTANCE(minor);
928
929 hidp = ddi_get_soft_state(hid_statep, instance);
930 if (hidp == NULL) {
931 return (ENXIO);
932 }
933
934 if (!HID_IS_UGEN_OPEN(minor)) {
935 return (ENXIO);
936 }
937
938 rval = usb_ugen_poll(hidp->hid_ugen_hdl, dev, events, anyyet,
939 reventsp, phpp);
940
941 return (rval);
942 }
943
944 /*
945 * hid_open :
946 * Open entry point: Opens the interrupt pipe. Sets up queues.
947 */
948 /*ARGSUSED*/
949 static int
hid_open(queue_t * q,dev_t * devp,int flag,int sflag,cred_t * credp)950 hid_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
951 {
952 int no_of_ep = 0;
953 int rval;
954 int instance;
955 hid_state_t *hidp;
956 minor_t minor = getminor(*devp);
957
958 instance = HID_MINOR_TO_INSTANCE(minor);
959
960 hidp = ddi_get_soft_state(hid_statep, instance);
961 if (hidp == NULL) {
962 return (ENXIO);
963 }
964
965 USB_DPRINTF_L4(PRINT_MASK_OPEN, hidp->hid_log_handle,
966 "hid_open: Begin");
967
968 /*
969 * If this is a ugen device, return ENOSTR (no streams). This will
970 * cause spec_open to try hid_chropen from our regular ops_cb instead
971 * (and thus treat us as a plain character device).
972 */
973 if (HID_IS_UGEN_OPEN(minor)) {
974 return (ENOSTR);
975 }
976
977 if (sflag) {
978 /* clone open NOT supported here */
979 return (ENXIO);
980 }
981
982 if (!(flag & FREAD)) {
983 return (EIO);
984 }
985
986 mutex_enter(&hidp->hid_mutex);
987
988 /*
989 * This is a workaround:
990 * Currently, if we open an already disconnected device, and send
991 * a CONSOPENPOLL ioctl to it, the system will panic, please refer
992 * to the processing HID_OPEN_POLLED_INPUT ioctl in the routine
993 * hid_mctl_receive().
994 * The consconfig_dacf module need this interface to detect if the
995 * device is already disconnnected.
996 */
997 if (HID_IS_INTERNAL_OPEN(minor) &&
998 (hidp->hid_dev_state == USB_DEV_DISCONNECTED)) {
999 mutex_exit(&hidp->hid_mutex);
1000 return (ENODEV);
1001 }
1002
1003 if (HID_IS_INTERNAL_OPEN(minor) &&
1004 (hidp->hid_internal_rq != NULL)) {
1005 ASSERT(hidp->hid_internal_rq == q);
1006
1007 mutex_exit(&hidp->hid_mutex);
1008 return (0);
1009 }
1010
1011 if ((!HID_IS_INTERNAL_OPEN(minor)) &&
1012 (hidp->hid_external_rq != NULL)) {
1013 ASSERT(hidp->hid_external_rq == q);
1014
1015 mutex_exit(&hidp->hid_mutex);
1016 return (0);
1017 }
1018
1019 mutex_exit(&hidp->hid_mutex);
1020
1021 q->q_ptr = hidp;
1022 WR(q)->q_ptr = hidp;
1023
1024 mutex_enter(&hidp->hid_mutex);
1025 if (hidp->hid_inuse_rq != NULL) {
1026 /* Pipe has already been setup */
1027
1028 if (HID_IS_INTERNAL_OPEN(minor)) {
1029 hidp->hid_internal_flag = HID_STREAMS_OPEN;
1030 hidp->hid_inuse_rq = hidp->hid_internal_rq = q;
1031 } else {
1032 hidp->hid_external_flag = HID_STREAMS_OPEN;
1033 hidp->hid_inuse_rq = hidp->hid_external_rq = q;
1034 }
1035
1036 mutex_exit(&hidp->hid_mutex);
1037
1038 qprocson(q);
1039
1040 return (0);
1041 }
1042
1043 /* Pipe only needs to be opened once */
1044 hidp->hid_interrupt_pipe = NULL;
1045 no_of_ep = hidp->hid_if_descr.bNumEndpoints;
1046 mutex_exit(&hidp->hid_mutex);
1047
1048 /* Check if interrupt endpoint exists */
1049 if (no_of_ep > 0) {
1050 /* Open the interrupt pipe */
1051 if (usb_pipe_xopen(hidp->hid_dip,
1052 &hidp->hid_ep_intr_xdescr,
1053 &hidp->hid_intr_pipe_policy, USB_FLAGS_SLEEP,
1054 &hidp->hid_interrupt_pipe) !=
1055 USB_SUCCESS) {
1056
1057 q->q_ptr = NULL;
1058 WR(q)->q_ptr = NULL;
1059 return (EIO);
1060 }
1061 }
1062
1063 hid_pm_busy_component(hidp);
1064 (void) pm_raise_power(hidp->hid_dip, 0, USB_DEV_OS_FULL_PWR);
1065
1066 mutex_enter(&hidp->hid_mutex);
1067 if (HID_IS_INTERNAL_OPEN(minor)) {
1068 hidp->hid_internal_flag = HID_STREAMS_OPEN;
1069 hidp->hid_inuse_rq = hidp->hid_internal_rq = q;
1070 } else {
1071 hidp->hid_external_flag = HID_STREAMS_OPEN;
1072 hidp->hid_inuse_rq = hidp->hid_external_rq = q;
1073 }
1074
1075 mutex_exit(&hidp->hid_mutex);
1076
1077 qprocson(q);
1078
1079 mutex_enter(&hidp->hid_mutex);
1080
1081 if ((rval = hid_start_intr_polling(hidp)) != USB_SUCCESS) {
1082 USB_DPRINTF_L2(PRINT_MASK_OPEN, hidp->hid_log_handle,
1083 "unable to start intr pipe polling. rval = %d", rval);
1084
1085 if (HID_IS_INTERNAL_OPEN(minor))
1086 hidp->hid_internal_flag = HID_STREAMS_DISMANTLING;
1087 else
1088 hidp->hid_external_flag = HID_STREAMS_DISMANTLING;
1089 mutex_exit(&hidp->hid_mutex);
1090
1091 usb_pipe_close(hidp->hid_dip, hidp->hid_interrupt_pipe,
1092 USB_FLAGS_SLEEP, NULL, NULL);
1093
1094 mutex_enter(&hidp->hid_mutex);
1095 hidp->hid_interrupt_pipe = NULL;
1096 mutex_exit(&hidp->hid_mutex);
1097
1098 qprocsoff(q);
1099
1100 mutex_enter(&hidp->hid_mutex);
1101 if (HID_IS_INTERNAL_OPEN(minor)) {
1102 hidp->hid_internal_flag = 0;
1103 hidp->hid_internal_rq = NULL;
1104 if (hidp->hid_external_flag == HID_STREAMS_OPEN)
1105 hidp->hid_inuse_rq = hidp->hid_external_rq;
1106 else
1107 hidp->hid_inuse_rq = NULL;
1108 } else {
1109 hidp->hid_external_flag = 0;
1110 hidp->hid_external_rq = NULL;
1111 if (hidp->hid_internal_flag == HID_STREAMS_OPEN)
1112 hidp->hid_inuse_rq = hidp->hid_internal_rq;
1113 else
1114 hidp->hid_inuse_rq = NULL;
1115 }
1116 mutex_exit(&hidp->hid_mutex);
1117
1118 q->q_ptr = NULL;
1119 WR(q)->q_ptr = NULL;
1120
1121 hid_pm_idle_component(hidp);
1122
1123 return (EIO);
1124 }
1125 mutex_exit(&hidp->hid_mutex);
1126
1127 USB_DPRINTF_L4(PRINT_MASK_OPEN, hidp->hid_log_handle, "hid_open: End");
1128
1129 /*
1130 * Keyboard and mouse is Power managed by device activity.
1131 * All other devices go busy on open and idle on close.
1132 */
1133 switch (hidp->hid_pm->hid_pm_strategy) {
1134 case HID_PM_ACTIVITY:
1135 hid_pm_idle_component(hidp);
1136
1137 break;
1138 default:
1139
1140 break;
1141 }
1142
1143 return (0);
1144 }
1145
1146
1147 /*
1148 * hid_close :
1149 * Close entry point.
1150 */
1151 /*ARGSUSED*/
1152 static int
hid_close(queue_t * q,int flag,cred_t * credp)1153 hid_close(queue_t *q, int flag, cred_t *credp)
1154 {
1155 hid_state_t *hidp = (hid_state_t *)q->q_ptr;
1156 queue_t *wq;
1157 mblk_t *mp;
1158
1159 USB_DPRINTF_L4(PRINT_MASK_CLOSE, hidp->hid_log_handle, "hid_close:");
1160
1161 mutex_enter(&hidp->hid_mutex);
1162
1163 ASSERT((hidp->hid_internal_rq == q) ||
1164 (hidp->hid_external_rq == q));
1165
1166 if (hidp->hid_internal_rq == q)
1167 hidp->hid_internal_flag = HID_STREAMS_DISMANTLING;
1168 else
1169 hidp->hid_external_flag = HID_STREAMS_DISMANTLING;
1170
1171 mutex_exit(&hidp->hid_mutex);
1172
1173 /*
1174 * In case there are any outstanding requests on
1175 * the default pipe, wait forever for them to complete.
1176 */
1177 (void) usb_pipe_drain_reqs(hidp->hid_dip,
1178 hidp->hid_default_pipe, 0, USB_FLAGS_SLEEP, NULL, 0);
1179
1180 mutex_enter(&hidp->hid_mutex);
1181 wq = WR(q);
1182 /* drain any M_CTLS on the WQ */
1183 while (mp = getq(wq)) {
1184 hid_qreply_merror(wq, mp, EIO);
1185 mutex_exit(&hidp->hid_mutex);
1186 hid_pm_idle_component(hidp);
1187 mutex_enter(&hidp->hid_mutex);
1188 }
1189 mutex_exit(&hidp->hid_mutex);
1190
1191 qprocsoff(q);
1192
1193 q->q_ptr = NULL;
1194 wq->q_ptr = NULL;
1195
1196 mutex_enter(&hidp->hid_mutex);
1197
1198 if (hidp->hid_internal_rq == q) {
1199 hidp->hid_internal_rq = NULL;
1200 hidp->hid_internal_flag = 0;
1201 if (hidp->hid_inuse_rq == q) {
1202 /* We are closing the active stream */
1203 if (hidp->hid_external_flag == HID_STREAMS_OPEN)
1204 hidp->hid_inuse_rq = hidp->hid_external_rq;
1205 else
1206 hidp->hid_inuse_rq = NULL;
1207 }
1208 } else {
1209 hidp->hid_external_rq = NULL;
1210 hidp->hid_external_flag = 0;
1211 if (hidp->hid_inuse_rq == q) {
1212 /* We are closing the active stream */
1213 if (hidp->hid_internal_flag == HID_STREAMS_OPEN)
1214 hidp->hid_inuse_rq = hidp->hid_internal_rq;
1215 else
1216 hidp->hid_inuse_rq = NULL;
1217 }
1218 }
1219
1220 if (hidp->hid_inuse_rq != NULL) {
1221 mutex_exit(&hidp->hid_mutex);
1222 return (0);
1223 }
1224
1225 /* all queues are closed, close USB pipes */
1226 hid_close_intr_pipe(hidp);
1227 mutex_exit(&hidp->hid_mutex);
1228
1229 /*
1230 * Devices other than keyboard/mouse go idle on close.
1231 */
1232 switch (hidp->hid_pm->hid_pm_strategy) {
1233 case HID_PM_ACTIVITY:
1234
1235 break;
1236 default:
1237 hid_pm_idle_component(hidp);
1238
1239 break;
1240 }
1241 USB_DPRINTF_L4(PRINT_MASK_CLOSE, hidp->hid_log_handle,
1242 "hid_close: End");
1243
1244 return (0);
1245 }
1246
1247
1248 /*
1249 * hid_wput :
1250 * write put routine for the hid module
1251 */
1252 static int
hid_wput(queue_t * q,mblk_t * mp)1253 hid_wput(queue_t *q, mblk_t *mp)
1254 {
1255 hid_state_t *hidp = (hid_state_t *)q->q_ptr;
1256 int error = USB_SUCCESS;
1257 struct iocblk *iocbp;
1258 mblk_t *datap;
1259 int direction;
1260 struct copyresp *crp;
1261 queue_t *tmpq;
1262 int flag;
1263
1264 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
1265 "hid_wput: Begin");
1266
1267 /* See if the upper module is passing the right thing */
1268 ASSERT(mp != NULL);
1269 ASSERT(mp->b_datap != NULL);
1270
1271 switch (mp->b_datap->db_type) {
1272 case M_FLUSH: /* Canonical flush handling */
1273 if (*mp->b_rptr & FLUSHW) {
1274 flushq(q, FLUSHDATA);
1275 }
1276
1277 /* read queue not used so just send up */
1278 if (*mp->b_rptr & FLUSHR) {
1279 *mp->b_rptr &= ~FLUSHW;
1280 qreply(q, mp);
1281 } else {
1282 freemsg(mp);
1283 }
1284
1285 break;
1286 case M_IOCTL:
1287 iocbp = (struct iocblk *)mp->b_rptr;
1288
1289 /* Only accept transparent ioctls */
1290 if (iocbp->ioc_count != TRANSPARENT) {
1291 miocnak(q, mp, 0, EINVAL);
1292 break;
1293 }
1294
1295 switch (iocbp->ioc_cmd) {
1296 case HIDIOCKMGDIRECT:
1297
1298 mutex_enter(&hidp->hid_mutex);
1299 ASSERT(hidp->hid_inuse_rq != NULL);
1300 mutex_exit(&hidp->hid_mutex);
1301
1302 if ((datap = allocb(sizeof (int), BPRI_MED)) == NULL) {
1303 miocnak(q, mp, 0, ENOMEM);
1304 break;
1305 }
1306
1307 mutex_enter(&hidp->hid_mutex);
1308 if (hidp->hid_inuse_rq == hidp->hid_internal_rq) {
1309 *(int *)datap->b_wptr = 0;
1310 datap->b_wptr += sizeof (int);
1311 } else {
1312 ASSERT(hidp->hid_inuse_rq ==
1313 hidp->hid_external_rq);
1314 *(int *)datap->b_wptr = 1;
1315 datap->b_wptr += sizeof (int);
1316 }
1317 mutex_exit(&hidp->hid_mutex);
1318
1319 mcopyout(mp, NULL, sizeof (int), NULL, datap);
1320 qreply(q, mp);
1321 break;
1322
1323 case HIDIOCKMSDIRECT:
1324 mcopyin(mp, NULL, sizeof (int), NULL);
1325 qreply(q, mp);
1326 break;
1327
1328 default:
1329 miocnak(q, mp, 0, ENOTTY);
1330 }
1331
1332 break;
1333
1334 case M_IOCDATA:
1335
1336 crp = (void *)mp->b_rptr;
1337
1338 if (crp->cp_rval != 0) {
1339 miocnak(q, mp, 0, EIO);
1340 break;
1341 }
1342
1343 switch (crp->cp_cmd) {
1344 case HIDIOCKMGDIRECT:
1345 miocack(q, mp, 0, 0);
1346 break;
1347
1348 case HIDIOCKMSDIRECT:
1349 direction = *(int *)mp->b_cont->b_rptr;
1350
1351 if ((direction != 0) && (direction != 1)) {
1352 miocnak(q, mp, 0, EINVAL);
1353 break;
1354 }
1355
1356 mutex_enter(&hidp->hid_mutex);
1357
1358 if (direction == 0) {
1359 /* The internal stream is made active */
1360 flag = hidp->hid_internal_flag;
1361 tmpq = hidp->hid_internal_rq;
1362 } else {
1363 /* The external stream is made active */
1364 flag = hidp->hid_external_flag;
1365 tmpq = hidp->hid_external_rq;
1366 }
1367
1368 if (flag != HID_STREAMS_OPEN) {
1369 mutex_exit(&hidp->hid_mutex);
1370 miocnak(q, mp, 0, EIO);
1371 break;
1372 }
1373
1374 hidp->hid_inuse_rq = tmpq;
1375
1376 mutex_exit(&hidp->hid_mutex);
1377 miocack(q, mp, 0, 0);
1378 break;
1379
1380 default:
1381 miocnak(q, mp, 0, ENOTTY);
1382 break;
1383 }
1384
1385 break;
1386
1387 case M_CTL:
1388 /* we are busy now */
1389 hid_pm_busy_component(hidp);
1390
1391 if (q->q_first) {
1392 (void) putq(q, mp);
1393 } else {
1394 error = hid_mctl_receive(q, mp);
1395 switch (error) {
1396 case HID_ENQUEUE:
1397 /*
1398 * put this mblk on the WQ for the wsrv to
1399 * process
1400 */
1401 (void) putq(q, mp);
1402
1403 break;
1404 case HID_INPROGRESS:
1405 /* request has been queued to the device */
1406
1407 break;
1408 case HID_SUCCESS:
1409 /*
1410 * returned by M_CTLS that are processed
1411 * immediately
1412 */
1413
1414 /* FALLTHRU */
1415 case HID_FAILURE:
1416 default:
1417 hid_pm_idle_component(hidp);
1418 break;
1419 }
1420 }
1421 break;
1422 default:
1423 hid_qreply_merror(q, mp, EINVAL);
1424 error = USB_FAILURE;
1425 break;
1426 }
1427
1428 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
1429 "hid_wput: End");
1430
1431 return (DDI_SUCCESS);
1432 }
1433
1434
1435 /*
1436 * hid_wsrv :
1437 * Write service routine for hid. When a message arrives through
1438 * hid_wput(), it is kept in write queue to be serviced later.
1439 */
1440 static int
hid_wsrv(queue_t * q)1441 hid_wsrv(queue_t *q)
1442 {
1443 hid_state_t *hidp = (hid_state_t *)q->q_ptr;
1444 int error;
1445 mblk_t *mp;
1446
1447 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
1448 "hid_wsrv: Begin");
1449
1450 mutex_enter(&hidp->hid_mutex);
1451 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
1452 "hid_wsrv: dev_state: %s",
1453 usb_str_dev_state(hidp->hid_dev_state));
1454
1455 /*
1456 * raise power if we are powered down. It is OK to block here since
1457 * we have a separate thread to process this STREAM
1458 */
1459 if (hidp->hid_dev_state == USB_DEV_PWRED_DOWN) {
1460 mutex_exit(&hidp->hid_mutex);
1461 (void) pm_raise_power(hidp->hid_dip, 0, USB_DEV_OS_FULL_PWR);
1462 mutex_enter(&hidp->hid_mutex);
1463 }
1464
1465 /*
1466 * continue servicing all the M_CTL's till the queue is empty
1467 * or the device gets disconnected or till a hid_close()
1468 */
1469 while ((hidp->hid_dev_state == USB_DEV_ONLINE) &&
1470 (HID_STREAMS_FLAG(q, hidp) != HID_STREAMS_DISMANTLING) &&
1471 ((mp = getq(q)) != NULL)) {
1472
1473 /* Send a message down */
1474 mutex_exit(&hidp->hid_mutex);
1475 error = hid_mctl_receive(q, mp);
1476 switch (error) {
1477 case HID_ENQUEUE:
1478 /* put this mblk back on q to preserve order */
1479 (void) putbq(q, mp);
1480
1481 break;
1482 case HID_INPROGRESS:
1483 /* request has been queued to the device */
1484
1485 break;
1486 case HID_SUCCESS:
1487 case HID_FAILURE:
1488 default:
1489 hid_pm_idle_component(hidp);
1490
1491 break;
1492 }
1493 mutex_enter(&hidp->hid_mutex);
1494 }
1495 mutex_exit(&hidp->hid_mutex);
1496 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
1497 "hid_wsrv: End");
1498
1499 return (DDI_SUCCESS);
1500 }
1501
1502
1503 /*
1504 * hid_power:
1505 * power entry point
1506 */
1507 static int
hid_power(dev_info_t * dip,int comp,int level)1508 hid_power(dev_info_t *dip, int comp, int level)
1509 {
1510 int instance = ddi_get_instance(dip);
1511 hid_state_t *hidp;
1512 hid_power_t *hidpm;
1513 int retval;
1514
1515 hidp = ddi_get_soft_state(hid_statep, instance);
1516
1517 USB_DPRINTF_L3(PRINT_MASK_PM, hidp->hid_log_handle, "hid_power:"
1518 " hid_state: comp=%d level=%d", comp, level);
1519
1520 /* check if we are transitioning to a legal power level */
1521 mutex_enter(&hidp->hid_mutex);
1522 hidpm = hidp->hid_pm;
1523
1524 if (USB_DEV_PWRSTATE_OK(hidpm->hid_pwr_states, level)) {
1525
1526 USB_DPRINTF_L2(PRINT_MASK_PM, hidp->hid_log_handle,
1527 "hid_power: illegal level=%d hid_pwr_states=%d",
1528 level, hidpm->hid_pwr_states);
1529
1530 mutex_exit(&hidp->hid_mutex);
1531
1532 return (DDI_FAILURE);
1533 }
1534
1535 switch (level) {
1536 case USB_DEV_OS_PWR_OFF:
1537 retval = hid_pwrlvl0(hidp);
1538 break;
1539 case USB_DEV_OS_PWR_1:
1540 retval = hid_pwrlvl1(hidp);
1541 break;
1542 case USB_DEV_OS_PWR_2:
1543 retval = hid_pwrlvl2(hidp);
1544 break;
1545 case USB_DEV_OS_FULL_PWR:
1546 retval = hid_pwrlvl3(hidp);
1547 break;
1548 default:
1549 retval = USB_FAILURE;
1550 break;
1551 }
1552
1553 mutex_exit(&hidp->hid_mutex);
1554
1555 return ((retval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
1556 }
1557
1558
1559 /*
1560 * hid_interrupt_pipe_callback:
1561 * Callback function for the hid intr pipe. This function is called by
1562 * USBA when a buffer has been filled. This driver does not cook the data,
1563 * it just sends the message up.
1564 */
1565 static void
hid_interrupt_pipe_callback(usb_pipe_handle_t pipe,usb_intr_req_t * req)1566 hid_interrupt_pipe_callback(usb_pipe_handle_t pipe, usb_intr_req_t *req)
1567 {
1568 hid_state_t *hidp = (hid_state_t *)req->intr_client_private;
1569 queue_t *q;
1570
1571 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
1572 "hid_interrupt_pipe_callback: ph = 0x%p req = 0x%p",
1573 (void *)pipe, (void *)req);
1574
1575 hid_pm_busy_component(hidp);
1576
1577 mutex_enter(&hidp->hid_mutex);
1578
1579 /*
1580 * If hid_close() is in progress, we shouldn't try accessing queue
1581 * Otherwise indicate that a putnext is going to happen, so
1582 * if close after this, that should wait for the putnext to finish.
1583 */
1584 if (HID_STREAMS_FLAG(hidp->hid_inuse_rq, hidp) ==
1585 HID_STREAMS_OPEN) {
1586 /*
1587 * Check if data can be put to the next queue.
1588 */
1589 if (!canputnext(hidp->hid_inuse_rq)) {
1590 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
1591 "Buffer flushed when overflowed.");
1592
1593 /* Flush the queue above */
1594 hid_flush(hidp->hid_inuse_rq);
1595 mutex_exit(&hidp->hid_mutex);
1596 } else {
1597 q = hidp->hid_inuse_rq;
1598 mutex_exit(&hidp->hid_mutex);
1599
1600 /* Put data upstream */
1601 putnext(q, req->intr_data);
1602
1603 /* usb_free_intr_req should not free data */
1604 req->intr_data = NULL;
1605 }
1606 } else {
1607 mutex_exit(&hidp->hid_mutex);
1608 }
1609
1610 /* free request and data */
1611 usb_free_intr_req(req);
1612 hid_pm_idle_component(hidp);
1613 }
1614
1615
1616 /*
1617 * hid_default_pipe_callback :
1618 * Callback routine for the asynchronous control transfer
1619 * Called from hid_send_async_ctrl_request() where we open
1620 * the pipe in exclusive mode
1621 */
1622 static void
hid_default_pipe_callback(usb_pipe_handle_t pipe,usb_ctrl_req_t * req)1623 hid_default_pipe_callback(usb_pipe_handle_t pipe, usb_ctrl_req_t *req)
1624 {
1625 hid_default_pipe_arg_t *hid_default_pipe_arg =
1626 (hid_default_pipe_arg_t *)req->ctrl_client_private;
1627 queue_t *wq = hid_default_pipe_arg->hid_default_pipe_arg_queue;
1628 queue_t *rq = RD(wq);
1629 hid_state_t *hidp = (hid_state_t *)rq->q_ptr;
1630 mblk_t *mctl_mp;
1631 mblk_t *data = NULL;
1632
1633 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
1634 "hid_default_pipe_callback: "
1635 "ph = 0x%p, req = 0x%p, data= 0x%p",
1636 (void *)pipe, (void *)req, (void *)data);
1637
1638 ASSERT((req->ctrl_cb_flags & USB_CB_INTR_CONTEXT) == 0);
1639
1640 if (req->ctrl_data) {
1641 data = req->ctrl_data;
1642 req->ctrl_data = NULL;
1643 }
1644
1645 /*
1646 * Free the b_cont of the original message that was sent down.
1647 */
1648 mctl_mp = hid_default_pipe_arg->hid_default_pipe_arg_mblk;
1649 freemsg(mctl_mp->b_cont);
1650
1651 /* chain the mblk received to the original & send it up */
1652 mctl_mp->b_cont = data;
1653
1654 if (canputnext(rq)) {
1655 putnext(rq, mctl_mp);
1656 } else {
1657 freemsg(mctl_mp); /* avoid leak */
1658 }
1659
1660 /*
1661 * Free the argument for the asynchronous callback
1662 */
1663 kmem_free(hid_default_pipe_arg, sizeof (hid_default_pipe_arg_t));
1664
1665 /*
1666 * Free the control pipe request structure.
1667 */
1668 usb_free_ctrl_req(req);
1669
1670 mutex_enter(&hidp->hid_mutex);
1671 hidp->hid_default_pipe_req--;
1672 ASSERT(hidp->hid_default_pipe_req >= 0);
1673 mutex_exit(&hidp->hid_mutex);
1674
1675 hid_pm_idle_component(hidp);
1676 qenable(wq);
1677 }
1678
1679
1680 /*
1681 * hid_interrupt_pipe_exception_callback:
1682 * Exception callback routine for interrupt pipe. If there is any data,
1683 * destroy it. No threads are waiting for the exception callback.
1684 */
1685 /*ARGSUSED*/
1686 static void
hid_interrupt_pipe_exception_callback(usb_pipe_handle_t pipe,usb_intr_req_t * req)1687 hid_interrupt_pipe_exception_callback(usb_pipe_handle_t pipe,
1688 usb_intr_req_t *req)
1689 {
1690 hid_state_t *hidp = (hid_state_t *)req->intr_client_private;
1691 mblk_t *data = req->intr_data;
1692 usb_cb_flags_t flags = req->intr_cb_flags;
1693 int rval;
1694
1695 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
1696 "hid_interrupt_pipe_exception_callback: "
1697 "completion_reason = 0x%x, data = 0x%p, flag = 0x%x",
1698 req->intr_completion_reason, (void *)data, req->intr_cb_flags);
1699
1700 ASSERT((req->intr_cb_flags & USB_CB_INTR_CONTEXT) == 0);
1701
1702 if (((flags & USB_CB_FUNCTIONAL_STALL) != 0) &&
1703 ((flags & USB_CB_STALL_CLEARED) == 0)) {
1704 USB_DPRINTF_L2(PRINT_MASK_ALL,
1705 hidp->hid_log_handle,
1706 "hid_interrupt_pipe_exception_callback: "
1707 "unable to clear stall. flags = 0x%x",
1708 req->intr_cb_flags);
1709 }
1710
1711 mutex_enter(&hidp->hid_mutex);
1712
1713 switch (req->intr_completion_reason) {
1714 case USB_CR_STOPPED_POLLING:
1715 case USB_CR_PIPE_CLOSING:
1716 default:
1717
1718 break;
1719 case USB_CR_PIPE_RESET:
1720 case USB_CR_NO_RESOURCES:
1721 if ((hidp->hid_dev_state == USB_DEV_ONLINE) &&
1722 ((rval = hid_start_intr_polling(hidp)) !=
1723 USB_SUCCESS)) {
1724 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
1725 "unable to restart interrupt poll. rval = %d",
1726 rval);
1727 }
1728
1729 break;
1730 }
1731
1732 mutex_exit(&hidp->hid_mutex);
1733
1734 usb_free_intr_req(req);
1735 }
1736
1737
1738 /*
1739 * hid_default_pipe_exception_callback:
1740 * Exception callback routine for default pipe.
1741 */
1742 /*ARGSUSED*/
1743 static void
hid_default_pipe_exception_callback(usb_pipe_handle_t pipe,usb_ctrl_req_t * req)1744 hid_default_pipe_exception_callback(usb_pipe_handle_t pipe,
1745 usb_ctrl_req_t *req)
1746 {
1747 hid_default_pipe_arg_t *hid_default_pipe_arg =
1748 (hid_default_pipe_arg_t *)req->ctrl_client_private;
1749 queue_t *wq = hid_default_pipe_arg->hid_default_pipe_arg_queue;
1750 queue_t *rq = RD(wq);
1751 hid_state_t *hidp = (hid_state_t *)rq->q_ptr;
1752 usb_cr_t ctrl_completion_reason = req->ctrl_completion_reason;
1753 mblk_t *mp, *data = NULL;
1754
1755 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
1756 "hid_default_pipe_exception_callback: "
1757 "completion_reason = 0x%x, data = 0x%p, flag = 0x%x",
1758 ctrl_completion_reason, (void *)data, req->ctrl_cb_flags);
1759
1760 ASSERT((req->ctrl_cb_flags & USB_CB_INTR_CONTEXT) == 0);
1761
1762 mp = hid_default_pipe_arg->hid_default_pipe_arg_mblk;
1763
1764 /*
1765 * Pass an error message up. Reuse existing mblk.
1766 */
1767 if (canputnext(rq)) {
1768 mp->b_datap->db_type = M_ERROR;
1769 mp->b_rptr = mp->b_datap->db_base;
1770 mp->b_wptr = mp->b_rptr + sizeof (char);
1771 *mp->b_rptr = EIO;
1772 putnext(rq, mp);
1773 } else {
1774 freemsg(mp);
1775 }
1776
1777 kmem_free(hid_default_pipe_arg, sizeof (hid_default_pipe_arg_t));
1778
1779 mutex_enter(&hidp->hid_mutex);
1780 hidp->hid_default_pipe_req--;
1781 ASSERT(hidp->hid_default_pipe_req >= 0);
1782 mutex_exit(&hidp->hid_mutex);
1783
1784 qenable(wq);
1785 usb_free_ctrl_req(req);
1786 hid_pm_idle_component(hidp);
1787 }
1788
1789
1790 /*
1791 * event handling:
1792 *
1793 * hid_reconnect_event_callback:
1794 * the device was disconnected but this instance not detached, probably
1795 * because the device was busy
1796 *
1797 * If the same device, continue with restoring state
1798 */
1799 static int
hid_restore_state_event_callback(dev_info_t * dip)1800 hid_restore_state_event_callback(dev_info_t *dip)
1801 {
1802 hid_state_t *hidp = (hid_state_t *)ddi_get_soft_state(hid_statep,
1803 ddi_get_instance(dip));
1804
1805 ASSERT(hidp != NULL);
1806
1807 USB_DPRINTF_L3(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1808 "hid_restore_state_event_callback: dip=0x%p", (void *)dip);
1809
1810 hid_restore_device_state(dip, hidp);
1811
1812 return (USB_SUCCESS);
1813 }
1814
1815
1816 /*
1817 * hid_cpr_suspend
1818 * Fail suspend if we can't finish outstanding i/o activity.
1819 */
1820 static int
hid_cpr_suspend(hid_state_t * hidp)1821 hid_cpr_suspend(hid_state_t *hidp)
1822 {
1823 int rval, prev_state;
1824 int retval = USB_FAILURE;
1825
1826 USB_DPRINTF_L4(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1827 "hid_cpr_suspend: dip=0x%p", (void *)hidp->hid_dip);
1828
1829 mutex_enter(&hidp->hid_mutex);
1830 switch (hidp->hid_dev_state) {
1831 case USB_DEV_ONLINE:
1832 case USB_DEV_PWRED_DOWN:
1833 prev_state = hidp->hid_dev_state;
1834 hidp->hid_dev_state = USB_DEV_SUSPENDED;
1835 mutex_exit(&hidp->hid_mutex);
1836
1837 /* drain all request outstanding on the default control pipe */
1838 rval = usb_pipe_drain_reqs(hidp->hid_dip,
1839 hidp->hid_default_pipe, hid_default_pipe_drain_timeout,
1840 USB_FLAGS_SLEEP, NULL, 0);
1841
1842 /* fail checkpoint if we haven't finished the job yet */
1843 mutex_enter(&hidp->hid_mutex);
1844 if ((rval != USB_SUCCESS) || (hidp->hid_default_pipe_req > 0)) {
1845 USB_DPRINTF_L2(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1846 "hid_cpr_suspend: "
1847 "device busy - can't checkpoint");
1848
1849 /* fall back to previous state */
1850 hidp->hid_dev_state = prev_state;
1851 } else {
1852 retval = USB_SUCCESS;
1853 hid_save_device_state(hidp);
1854 }
1855
1856 break;
1857 case USB_DEV_DISCONNECTED:
1858 hidp->hid_dev_state = USB_DEV_SUSPENDED;
1859 hid_save_device_state(hidp);
1860 retval = USB_SUCCESS;
1861 break;
1862 case USB_DEV_SUSPENDED:
1863 default:
1864 USB_DPRINTF_L2(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1865 "hid_cpr_suspend: Illegal dev state: %d",
1866 hidp->hid_dev_state);
1867
1868 break;
1869 }
1870 mutex_exit(&hidp->hid_mutex);
1871
1872 if ((retval == USB_SUCCESS) && hidp->hid_ugen_hdl != NULL) {
1873 retval = usb_ugen_detach(hidp->hid_ugen_hdl,
1874 DDI_SUSPEND);
1875 }
1876
1877 return (retval);
1878 }
1879
1880
1881 static void
hid_cpr_resume(hid_state_t * hidp)1882 hid_cpr_resume(hid_state_t *hidp)
1883 {
1884 USB_DPRINTF_L4(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1885 "hid_cpr_resume: dip=0x%p", (void *)hidp->hid_dip);
1886
1887 hid_restore_device_state(hidp->hid_dip, hidp);
1888
1889 if (hidp->hid_ugen_hdl != NULL) {
1890 (void) usb_ugen_attach(hidp->hid_ugen_hdl, DDI_RESUME);
1891 }
1892 }
1893
1894
1895 /*
1896 * hid_disconnect_event_callback:
1897 * The device has been disconnected. We either wait for
1898 * detach or a reconnect event. Close all pipes and timeouts.
1899 */
1900 static int
hid_disconnect_event_callback(dev_info_t * dip)1901 hid_disconnect_event_callback(dev_info_t *dip)
1902 {
1903 hid_state_t *hidp;
1904 mblk_t *mp;
1905
1906 hidp = (hid_state_t *)ddi_get_soft_state(hid_statep,
1907 ddi_get_instance(dip));
1908 ASSERT(hidp != NULL);
1909
1910 USB_DPRINTF_L4(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1911 "hid_disconnect_event_callback: dip=0x%p", (void *)dip);
1912
1913 mutex_enter(&hidp->hid_mutex);
1914 switch (hidp->hid_dev_state) {
1915 case USB_DEV_ONLINE:
1916 case USB_DEV_PWRED_DOWN:
1917 hidp->hid_dev_state = USB_DEV_DISCONNECTED;
1918 if (HID_IS_OPEN(hidp)) {
1919
1920 USB_DPRINTF_L2(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1921 "busy device has been disconnected");
1922 }
1923 hid_save_device_state(hidp);
1924
1925 /*
1926 * Notify applications about device removal, this only
1927 * applies to an external (aka. physical) open. For an
1928 * internal open, consconfig_dacf closes the queue.
1929 */
1930 if (hidp->hid_external_flag == HID_STREAMS_OPEN) {
1931 queue_t *q = hidp->hid_external_rq;
1932 mutex_exit(&hidp->hid_mutex);
1933 mp = allocb(sizeof (uchar_t), BPRI_HI);
1934 if (mp != NULL) {
1935 mp->b_datap->db_type = M_ERROR;
1936 mp->b_rptr = mp->b_datap->db_base;
1937 mp->b_wptr = mp->b_rptr + sizeof (char);
1938 *mp->b_rptr = ENODEV;
1939 putnext(q, mp);
1940 }
1941 mutex_enter(&hidp->hid_mutex);
1942 }
1943
1944 break;
1945 case USB_DEV_SUSPENDED:
1946 /* we remain suspended */
1947
1948 break;
1949 default:
1950 USB_DPRINTF_L2(PRINT_MASK_EVENTS, hidp->hid_log_handle,
1951 "hid_disconnect_event_callback: Illegal dev state: %d",
1952 hidp->hid_dev_state);
1953
1954 break;
1955 }
1956 mutex_exit(&hidp->hid_mutex);
1957
1958 return (USB_SUCCESS);
1959 }
1960
1961
1962 /*
1963 * hid_power_change_callback:
1964 * Async callback function to notify pm_raise_power completion
1965 * after hid_power entry point is called.
1966 */
1967 static void
hid_power_change_callback(void * arg,int rval)1968 hid_power_change_callback(void *arg, int rval)
1969 {
1970 hid_state_t *hidp;
1971 queue_t *wq;
1972
1973 hidp = (hid_state_t *)arg;
1974
1975 USB_DPRINTF_L4(PRINT_MASK_PM, hidp->hid_log_handle,
1976 "hid_power_change_callback - rval: %d", rval);
1977
1978 mutex_enter(&hidp->hid_mutex);
1979 hidp->hid_pm->hid_raise_power = B_FALSE;
1980
1981 if (hidp->hid_dev_state == USB_DEV_ONLINE) {
1982 wq = WR(hidp->hid_inuse_rq);
1983 mutex_exit(&hidp->hid_mutex);
1984
1985 qenable(wq);
1986
1987 } else {
1988 mutex_exit(&hidp->hid_mutex);
1989 }
1990 }
1991
1992
1993 /*
1994 * hid_parse_hid_descr:
1995 * Parse the hid descriptor, check after interface and after
1996 * endpoint descriptor
1997 */
1998 static size_t
hid_parse_hid_descr(usb_hid_descr_t * ret_descr,size_t ret_buf_len,usb_alt_if_data_t * altif_data,usb_ep_data_t * ep_data)1999 hid_parse_hid_descr(usb_hid_descr_t *ret_descr, size_t ret_buf_len,
2000 usb_alt_if_data_t *altif_data, usb_ep_data_t *ep_data)
2001 {
2002 usb_cvs_data_t *cvs;
2003 int which_cvs;
2004
2005 for (which_cvs = 0; which_cvs < altif_data->altif_n_cvs; which_cvs++) {
2006 cvs = &altif_data->altif_cvs[which_cvs];
2007 if (cvs->cvs_buf == NULL) {
2008 continue;
2009 }
2010 if (cvs->cvs_buf[1] == USB_DESCR_TYPE_HID) {
2011 return (usb_parse_data("ccscccs",
2012 cvs->cvs_buf, cvs->cvs_buf_len,
2013 (void *)ret_descr,
2014 (size_t)ret_buf_len));
2015 }
2016 }
2017
2018 /* now try after endpoint */
2019 for (which_cvs = 0; which_cvs < ep_data->ep_n_cvs; which_cvs++) {
2020 cvs = &ep_data->ep_cvs[which_cvs];
2021 if (cvs->cvs_buf == NULL) {
2022 continue;
2023 }
2024 if (cvs->cvs_buf[1] == USB_DESCR_TYPE_HID) {
2025 return (usb_parse_data("ccscccs",
2026 cvs->cvs_buf, cvs->cvs_buf_len,
2027 (void *)ret_descr,
2028 (size_t)ret_buf_len));
2029 }
2030 }
2031
2032 return (USB_PARSE_ERROR);
2033 }
2034
2035
2036 /*
2037 * hid_parse_hid_descr_failure:
2038 * If parsing of hid descriptor failed and the device is
2039 * a keyboard or mouse, use predefined length and packet size.
2040 */
2041 static int
hid_parse_hid_descr_failure(hid_state_t * hidp)2042 hid_parse_hid_descr_failure(hid_state_t *hidp)
2043 {
2044 /*
2045 * Parsing hid descriptor failed, probably because the
2046 * device did not return a valid hid descriptor. Check to
2047 * see if this is a keyboard or mouse. If so, use the
2048 * predefined hid descriptor length and packet size.
2049 * Otherwise, detach and return failure.
2050 */
2051 USB_DPRINTF_L1(PRINT_MASK_ATTA, hidp->hid_log_handle,
2052 "Parsing of hid descriptor failed");
2053
2054 if (hidp->hid_if_descr.bInterfaceProtocol == KEYBOARD_PROTOCOL) {
2055 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
2056 "Set hid descriptor length to predefined "
2057 "USB_KB_HID_DESCR_LENGTH for keyboard.");
2058
2059 /* device is a keyboard */
2060 hidp->hid_hid_descr.wReportDescriptorLength =
2061 USB_KB_HID_DESCR_LENGTH;
2062
2063 hidp->hid_packet_size = USBKPSZ;
2064
2065 } else if (hidp->hid_if_descr.bInterfaceProtocol ==
2066 MOUSE_PROTOCOL) {
2067 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
2068 "Set hid descriptor length to predefined "
2069 "USB_MS_HID_DESCR_LENGTH for mouse.");
2070
2071 /* device is a mouse */
2072 hidp->hid_hid_descr.wReportDescriptorLength =
2073 USB_MS_HID_DESCR_LENGTH;
2074
2075 hidp->hid_packet_size = USBMSSZ;
2076 } else {
2077
2078 return (USB_FAILURE);
2079 }
2080
2081 return (USB_SUCCESS);
2082 }
2083
2084
2085 /*
2086 * hid_handle_report_descriptor:
2087 * Get the report descriptor, call hidparser routine to parse
2088 * it and query the hidparser tree to get the packet size
2089 */
2090 static int
hid_handle_report_descriptor(hid_state_t * hidp,int interface)2091 hid_handle_report_descriptor(hid_state_t *hidp, int interface)
2092 {
2093 usb_cr_t completion_reason;
2094 usb_cb_flags_t cb_flags;
2095 mblk_t *data = NULL;
2096 hidparser_packet_info_t hpack;
2097 int i;
2098 usb_ctrl_setup_t setup = {
2099 USB_DEV_REQ_DEV_TO_HOST | /* bmRequestType */
2100 USB_DEV_REQ_RCPT_IF,
2101 USB_REQ_GET_DESCR, /* bRequest */
2102 USB_CLASS_DESCR_TYPE_REPORT, /* wValue */
2103 0, /* wIndex: interface, fill in later */
2104 0, /* wLength, fill in later */
2105 0 /* attributes */
2106 };
2107
2108 /*
2109 * Parsing hid desciptor was successful earlier.
2110 * Get Report Descriptor
2111 */
2112 setup.wIndex = (uint16_t)interface;
2113 setup.wLength = hidp->hid_hid_descr.wReportDescriptorLength;
2114 if (usb_pipe_ctrl_xfer_wait(hidp->hid_default_pipe,
2115 &setup,
2116 &data, /* data */
2117 &completion_reason, &cb_flags, 0) != USB_SUCCESS) {
2118
2119 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
2120 "Failed to receive the Report Descriptor");
2121 freemsg(data);
2122
2123 return (USB_FAILURE);
2124
2125 } else {
2126 int n = hidp->hid_hid_descr.wReportDescriptorLength;
2127
2128 ASSERT(data);
2129
2130 /* Print the report descriptor */
2131 for (i = 0; i < n; i++) {
2132 USB_DPRINTF_L3(PRINT_MASK_ATTA, hidp->hid_log_handle,
2133 "Index = %d\tvalue =0x%x", i,
2134 (int)(data->b_rptr[i]));
2135 }
2136
2137 /* Get Report Descriptor was successful */
2138 if (hidparser_parse_report_descriptor(
2139 data->b_rptr,
2140 hidp->hid_hid_descr.wReportDescriptorLength,
2141 &hidp->hid_hid_descr,
2142 &hidp->hid_report_descr) == HIDPARSER_SUCCESS) {
2143
2144 /* find max intr-in xfer length */
2145 hidparser_find_max_packet_size_from_report_descriptor(
2146 hidp->hid_report_descr, &hpack);
2147 /* round up to the nearest byte */
2148 hidp->hid_packet_size = (hpack.max_packet_size + 7) / 8;
2149
2150 /* if report id is used, add more more byte for it */
2151 if (hpack.report_id != HID_REPORT_ID_UNDEFINED) {
2152 hidp->hid_packet_size++;
2153 }
2154 } else {
2155 USB_DPRINTF_L1(PRINT_MASK_ATTA, hidp->hid_log_handle,
2156 "Invalid Report Descriptor");
2157 freemsg(data);
2158
2159 return (USB_FAILURE);
2160 }
2161
2162 freemsg(data);
2163
2164 return (USB_SUCCESS);
2165 }
2166 }
2167
2168
2169 /*
2170 * hid_set_idle:
2171 * Make a clas specific request to SET_IDLE.
2172 * In this case send no reports if state has not changed.
2173 * See HID 7.2.4.
2174 */
2175 /*ARGSUSED*/
2176 static void
hid_set_idle(hid_state_t * hidp)2177 hid_set_idle(hid_state_t *hidp)
2178 {
2179 usb_cr_t completion_reason;
2180 usb_cb_flags_t cb_flags;
2181 usb_ctrl_setup_t setup = {
2182 USB_DEV_REQ_HOST_TO_DEV | /* bmRequestType */
2183 USB_DEV_REQ_TYPE_CLASS |
2184 USB_DEV_REQ_RCPT_IF,
2185 SET_IDLE, /* bRequest */
2186 DURATION, /* wValue */
2187 0, /* wIndex: interface, fill in later */
2188 0, /* wLength */
2189 0 /* attributes */
2190 };
2191
2192 USB_DPRINTF_L4(PRINT_MASK_ATTA, hidp->hid_log_handle,
2193 "hid_set_idle: Begin");
2194
2195 setup.wIndex = hidp->hid_if_descr.bInterfaceNumber;
2196 if (usb_pipe_ctrl_xfer_wait(
2197 hidp->hid_default_pipe,
2198 &setup,
2199 NULL, /* no data to send. */
2200 &completion_reason, &cb_flags, 0) != USB_SUCCESS) {
2201
2202 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
2203 "Failed while trying to set idle,"
2204 "cr = %d, cb_flags = 0x%x\n",
2205 completion_reason, cb_flags);
2206 }
2207 USB_DPRINTF_L4(PRINT_MASK_ATTA, hidp->hid_log_handle,
2208 "hid_set_idle: End");
2209 }
2210
2211
2212 /*
2213 * hid_set_protocol:
2214 * Initialize the device to set the preferred protocol
2215 */
2216 /*ARGSUSED*/
2217 static void
hid_set_protocol(hid_state_t * hidp,int protocol)2218 hid_set_protocol(hid_state_t *hidp, int protocol)
2219 {
2220 usb_cr_t completion_reason;
2221 usb_cb_flags_t cb_flags;
2222 usb_ctrl_setup_t setup;
2223
2224 USB_DPRINTF_L4(PRINT_MASK_ATTA, hidp->hid_log_handle,
2225 "hid_set_protocol(%d): Begin", protocol);
2226
2227 /* initialize the setup request */
2228 setup.bmRequestType = USB_DEV_REQ_HOST_TO_DEV |
2229 USB_DEV_REQ_TYPE_CLASS | USB_DEV_REQ_RCPT_IF;
2230 setup.bRequest = SET_PROTOCOL;
2231 setup.wValue = (uint16_t)protocol;
2232 setup.wIndex = hidp->hid_if_descr.bInterfaceNumber;
2233 setup.wLength = 0;
2234 setup.attrs = 0;
2235 if (usb_pipe_ctrl_xfer_wait(
2236 hidp->hid_default_pipe, /* bmRequestType */
2237 &setup,
2238 NULL, /* no data to send */
2239 &completion_reason, &cb_flags, 0) != USB_SUCCESS) {
2240 /*
2241 * Some devices fail to follow the specification
2242 * and instead of STALLing, they continously
2243 * NAK the SET_IDLE command. We need to reset
2244 * the pipe then, so that ohci doesn't panic.
2245 */
2246 USB_DPRINTF_L2(PRINT_MASK_ATTA, hidp->hid_log_handle,
2247 "Failed while trying to set protocol:%d,"
2248 "cr = %d cb_flags = 0x%x\n",
2249 completion_reason, cb_flags, protocol);
2250 }
2251
2252 USB_DPRINTF_L4(PRINT_MASK_ATTA, hidp->hid_log_handle,
2253 "hid_set_protocol: End");
2254 }
2255
2256
2257 /*
2258 * hid_detach_cleanup:
2259 * called by attach and detach for cleanup.
2260 */
2261 static void
hid_detach_cleanup(dev_info_t * dip,hid_state_t * hidp)2262 hid_detach_cleanup(dev_info_t *dip, hid_state_t *hidp)
2263 {
2264 int flags = hidp->hid_attach_flags;
2265 int rval;
2266 hid_power_t *hidpm;
2267
2268 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
2269 "hid_detach_cleanup: Begin");
2270
2271 if ((hidp->hid_attach_flags & HID_LOCK_INIT) == 0) {
2272
2273 goto done;
2274 }
2275
2276 /*
2277 * Disable the event callbacks first, after this point, event
2278 * callbacks will never get called. Note we shouldn't hold
2279 * mutex while unregistering events because there may be a
2280 * competing event callback thread. Event callbacks are done
2281 * with ndi mutex held and this can cause a potential deadlock.
2282 */
2283 usb_unregister_event_cbs(dip, &hid_events);
2284
2285 mutex_enter(&hidp->hid_mutex);
2286
2287 hidpm = hidp->hid_pm;
2288
2289 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
2290 "hid_detach_cleanup: hidpm=0x%p", (void *)hidpm);
2291
2292 if (hidpm && (hidp->hid_dev_state != USB_DEV_DISCONNECTED)) {
2293
2294 mutex_exit(&hidp->hid_mutex);
2295 hid_pm_busy_component(hidp);
2296 if (hid_is_pm_enabled(dip) == USB_SUCCESS) {
2297
2298 if (hidpm->hid_wakeup_enabled) {
2299
2300 /* First bring the device to full power */
2301 (void) pm_raise_power(dip, 0,
2302 USB_DEV_OS_FULL_PWR);
2303
2304 /* Disable remote wakeup */
2305 rval = usb_handle_remote_wakeup(dip,
2306 USB_REMOTE_WAKEUP_DISABLE);
2307
2308 if (rval != DDI_SUCCESS) {
2309 USB_DPRINTF_L2(PRINT_MASK_ALL,
2310 hidp->hid_log_handle,
2311 "hid_detach_cleanup: "
2312 "disble remote wakeup failed, "
2313 "rval= %d", rval);
2314 }
2315 }
2316
2317 (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
2318 }
2319 hid_pm_idle_component(hidp);
2320 mutex_enter(&hidp->hid_mutex);
2321 }
2322
2323 if (hidpm) {
2324 freemsg(hidpm->hid_pm_pwrup);
2325 kmem_free(hidpm, sizeof (hid_power_t));
2326 hidp->hid_pm = NULL;
2327 }
2328
2329 if (hidp->hid_ugen_hdl != NULL) {
2330 rval = usb_ugen_detach(hidp->hid_ugen_hdl, DDI_DETACH);
2331 VERIFY0(rval);
2332 usb_ugen_release_hdl(hidp->hid_ugen_hdl);
2333 }
2334
2335 mutex_exit(&hidp->hid_mutex);
2336
2337 if (hidp->hid_report_descr != NULL) {
2338 (void) hidparser_free_report_descriptor_handle(
2339 hidp->hid_report_descr);
2340 }
2341
2342 if (flags & HID_MINOR_NODES) {
2343 ddi_remove_minor_node(dip, NULL);
2344 }
2345
2346 mutex_destroy(&hidp->hid_mutex);
2347
2348 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
2349 "hid_detach_cleanup: End");
2350
2351 done:
2352 usb_client_detach(dip, hidp->hid_dev_data);
2353 usb_free_log_hdl(hidp->hid_log_handle);
2354 ddi_soft_state_free(hid_statep, hidp->hid_instance);
2355
2356 ddi_prop_remove_all(dip);
2357 }
2358
2359
2360 /*
2361 * hid_start_intr_polling:
2362 * Allocate an interrupt request structure, initialize,
2363 * and start interrupt transfers.
2364 */
2365 static int
hid_start_intr_polling(hid_state_t * hidp)2366 hid_start_intr_polling(hid_state_t *hidp)
2367 {
2368 usb_intr_req_t *req;
2369 int rval = USB_SUCCESS;
2370
2371 USB_DPRINTF_L4(PRINT_MASK_PM, hidp->hid_log_handle,
2372 "hid_start_intr_polling: "
2373 "dev_state=%s internal_str_flag=%d external_str_flag=%d ph=0x%p",
2374 usb_str_dev_state(hidp->hid_dev_state), hidp->hid_internal_flag,
2375 hidp->hid_external_flag, (void *)hidp->hid_interrupt_pipe);
2376
2377 if (HID_IS_OPEN(hidp) && (hidp->hid_interrupt_pipe != NULL)) {
2378 /*
2379 * initialize interrupt pipe request structure
2380 */
2381 req = usb_alloc_intr_req(hidp->hid_dip, 0, USB_FLAGS_SLEEP);
2382 req->intr_client_private = (usb_opaque_t)hidp;
2383 req->intr_attributes = USB_ATTRS_SHORT_XFER_OK |
2384 USB_ATTRS_AUTOCLEARING;
2385 req->intr_len = hidp->hid_packet_size;
2386 req->intr_cb = hid_interrupt_pipe_callback;
2387 req->intr_exc_cb = hid_interrupt_pipe_exception_callback;
2388
2389 /*
2390 * Start polling on the interrupt pipe.
2391 */
2392 mutex_exit(&hidp->hid_mutex);
2393
2394 if ((rval = usb_pipe_intr_xfer(hidp->hid_interrupt_pipe, req,
2395 USB_FLAGS_SLEEP)) != USB_SUCCESS) {
2396 USB_DPRINTF_L2(PRINT_MASK_PM, hidp->hid_log_handle,
2397 "hid_start_intr_polling failed: rval = %d",
2398 rval);
2399 usb_free_intr_req(req);
2400 }
2401
2402 mutex_enter(&hidp->hid_mutex);
2403 }
2404
2405 USB_DPRINTF_L4(PRINT_MASK_PM, hidp->hid_log_handle,
2406 "hid_start_intr_polling: done, rval = %d", rval);
2407
2408 return (rval);
2409 }
2410
2411
2412 /*
2413 * hid_close_intr_pipe:
2414 * close the interrupt pipe after draining all callbacks
2415 */
2416 static void
hid_close_intr_pipe(hid_state_t * hidp)2417 hid_close_intr_pipe(hid_state_t *hidp)
2418 {
2419 USB_DPRINTF_L4(PRINT_MASK_CLOSE, hidp->hid_log_handle,
2420 "hid_close_intr_pipe: Begin");
2421
2422 if (hidp->hid_interrupt_pipe) {
2423 /*
2424 * Close the interrupt pipe
2425 */
2426 mutex_exit(&hidp->hid_mutex);
2427 usb_pipe_close(hidp->hid_dip, hidp->hid_interrupt_pipe,
2428 USB_FLAGS_SLEEP, NULL, NULL);
2429 mutex_enter(&hidp->hid_mutex);
2430 hidp->hid_interrupt_pipe = NULL;
2431 }
2432 USB_DPRINTF_L4(PRINT_MASK_CLOSE, hidp->hid_log_handle,
2433 "hid_close_intr_pipe: End");
2434 }
2435
2436
2437 /*
2438 * hid_mctl_receive:
2439 * Handle M_CTL messages from upper stream. If
2440 * we don't understand the command, free message.
2441 */
2442 static int
hid_mctl_receive(register queue_t * q,register mblk_t * mp)2443 hid_mctl_receive(register queue_t *q, register mblk_t *mp)
2444 {
2445 hid_state_t *hidp = (hid_state_t *)q->q_ptr;
2446 struct iocblk *iocp;
2447 int error = HID_FAILURE;
2448 uchar_t request_type;
2449 hid_req_t *hid_req_data = NULL;
2450 hid_polled_input_callback_t hid_polled_input;
2451 hid_vid_pid_t hid_vid_pid;
2452
2453 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
2454 "hid_mctl_receive");
2455
2456 iocp = (struct iocblk *)mp->b_rptr;
2457
2458 switch (iocp->ioc_cmd) {
2459 case HID_SET_REPORT:
2460 /* FALLTHRU */
2461 case HID_SET_IDLE:
2462 /* FALLTHRU */
2463 case HID_SET_PROTOCOL:
2464 request_type = USB_DEV_REQ_HOST_TO_DEV |
2465 USB_DEV_REQ_RCPT_IF | USB_DEV_REQ_TYPE_CLASS;
2466
2467 break;
2468 case HID_GET_REPORT:
2469 /* FALLTHRU */
2470 case HID_GET_IDLE:
2471 /* FALLTHRU */
2472 case HID_GET_PROTOCOL:
2473 request_type = USB_DEV_REQ_DEV_TO_HOST |
2474 USB_DEV_REQ_RCPT_IF | USB_DEV_REQ_TYPE_CLASS;
2475
2476 break;
2477 case HID_GET_PARSER_HANDLE:
2478 if (canputnext(RD(q))) {
2479 freemsg(mp->b_cont);
2480 mp->b_cont = hid_data2mblk(
2481 (uchar_t *)&hidp->hid_report_descr,
2482 sizeof (hidp->hid_report_descr));
2483 if (mp->b_cont == NULL) {
2484 /*
2485 * can't allocate mblk, indicate
2486 * that nothing is returned
2487 */
2488 iocp->ioc_count = 0;
2489 } else {
2490 iocp->ioc_count =
2491 sizeof (hidp->hid_report_descr);
2492 }
2493 qreply(q, mp);
2494
2495 return (HID_SUCCESS);
2496 } else {
2497
2498 /* retry */
2499 return (HID_ENQUEUE);
2500 }
2501 case HID_GET_VID_PID:
2502 if (canputnext(RD(q))) {
2503 freemsg(mp->b_cont);
2504
2505 hid_vid_pid.VendorId =
2506 hidp->hid_dev_descr->idVendor;
2507 hid_vid_pid.ProductId =
2508 hidp->hid_dev_descr->idProduct;
2509
2510 mp->b_cont = hid_data2mblk(
2511 (uchar_t *)&hid_vid_pid, sizeof (hid_vid_pid_t));
2512 if (mp->b_cont == NULL) {
2513 /*
2514 * can't allocate mblk, indicate that nothing
2515 * is being returned.
2516 */
2517 iocp->ioc_count = 0;
2518 } else {
2519 iocp->ioc_count =
2520 sizeof (hid_vid_pid_t);
2521 }
2522 qreply(q, mp);
2523
2524 return (HID_SUCCESS);
2525 } else {
2526
2527 /* retry */
2528 return (HID_ENQUEUE);
2529 }
2530 case HID_OPEN_POLLED_INPUT:
2531 if (canputnext(RD(q))) {
2532 freemsg(mp->b_cont);
2533
2534 /* Initialize the structure */
2535 hid_polled_input.hid_polled_version =
2536 HID_POLLED_INPUT_V0;
2537 hid_polled_input.hid_polled_read = hid_polled_read;
2538 hid_polled_input.hid_polled_input_enter =
2539 hid_polled_input_enter;
2540 hid_polled_input.hid_polled_input_exit =
2541 hid_polled_input_exit;
2542 hid_polled_input.hid_polled_input_handle =
2543 (hid_polled_handle_t)hidp;
2544
2545 mp->b_cont = hid_data2mblk(
2546 (uchar_t *)&hid_polled_input,
2547 sizeof (hid_polled_input_callback_t));
2548 if (mp->b_cont == NULL) {
2549 /*
2550 * can't allocate mblk, indicate that nothing
2551 * is being returned.
2552 */
2553 iocp->ioc_count = 0;
2554 } else {
2555 /* Call down into USBA */
2556 (void) hid_polled_input_init(hidp);
2557
2558 iocp->ioc_count =
2559 sizeof (hid_polled_input_callback_t);
2560 }
2561 qreply(q, mp);
2562
2563 return (HID_SUCCESS);
2564 } else {
2565
2566 /* retry */
2567 return (HID_ENQUEUE);
2568 }
2569 case HID_CLOSE_POLLED_INPUT:
2570 /* Call down into USBA */
2571 (void) hid_polled_input_fini(hidp);
2572
2573 iocp->ioc_count = 0;
2574 qreply(q, mp);
2575
2576 return (HID_SUCCESS);
2577 default:
2578 hid_qreply_merror(q, mp, EINVAL);
2579
2580 return (HID_FAILURE);
2581 }
2582
2583 /*
2584 * These (device executable) commands require a hid_req_t.
2585 * Make sure one is present
2586 */
2587 if (mp->b_cont == NULL) {
2588 hid_qreply_merror(q, mp, EINVAL);
2589
2590 return (error);
2591 } else {
2592 hid_req_data = (hid_req_t *)mp->b_cont->b_rptr;
2593 if ((iocp->ioc_cmd == HID_SET_REPORT) &&
2594 (hid_req_data->hid_req_wLength == 0)) {
2595 hid_qreply_merror(q, mp, EINVAL);
2596
2597 return (error);
2598 }
2599 }
2600
2601 /*
2602 * Check is version no. is correct. This
2603 * is coming from the user
2604 */
2605 if (hid_req_data->hid_req_version_no != HID_VERSION_V_0) {
2606 hid_qreply_merror(q, mp, EINVAL);
2607
2608 return (error);
2609 }
2610
2611 mutex_enter(&hidp->hid_mutex);
2612 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
2613 "hid_mctl_receive: dev_state=%s",
2614 usb_str_dev_state(hidp->hid_dev_state));
2615
2616 switch (hidp->hid_dev_state) {
2617 case USB_DEV_PWRED_DOWN:
2618 /*
2619 * get the device full powered. We get a callback
2620 * which enables the WQ and kicks off IO
2621 */
2622 hidp->hid_dev_state = USB_DEV_HID_POWER_CHANGE;
2623 mutex_exit(&hidp->hid_mutex);
2624 if (usb_req_raise_power(hidp->hid_dip, 0,
2625 USB_DEV_OS_FULL_PWR, hid_power_change_callback,
2626 hidp, 0) != USB_SUCCESS) {
2627 /* we retry raising power in wsrv */
2628 mutex_enter(&hidp->hid_mutex);
2629 hidp->hid_dev_state = USB_DEV_PWRED_DOWN;
2630 mutex_exit(&hidp->hid_mutex);
2631 }
2632 error = HID_ENQUEUE;
2633
2634 break;
2635 case USB_DEV_HID_POWER_CHANGE:
2636 mutex_exit(&hidp->hid_mutex);
2637 error = HID_ENQUEUE;
2638
2639 break;
2640 case USB_DEV_ONLINE:
2641 if (HID_STREAMS_FLAG(q, hidp) != HID_STREAMS_DISMANTLING) {
2642 /* Send a message down */
2643 mutex_exit(&hidp->hid_mutex);
2644 error = hid_mctl_execute_cmd(q, request_type,
2645 hid_req_data, mp);
2646 if (error == HID_FAILURE) {
2647 hid_qreply_merror(q, mp, EIO);
2648 }
2649 } else {
2650 mutex_exit(&hidp->hid_mutex);
2651 hid_qreply_merror(q, mp, EIO);
2652 }
2653
2654 break;
2655 default:
2656 mutex_exit(&hidp->hid_mutex);
2657 hid_qreply_merror(q, mp, EIO);
2658
2659 break;
2660 }
2661
2662 return (error);
2663 }
2664
2665
2666 /*
2667 * hid_mctl_execute_cmd:
2668 * Send the command to the device.
2669 */
2670 static int
hid_mctl_execute_cmd(queue_t * q,int request_type,hid_req_t * hid_req_data,mblk_t * mp)2671 hid_mctl_execute_cmd(queue_t *q, int request_type, hid_req_t *hid_req_data,
2672 mblk_t *mp)
2673 {
2674 int request_index;
2675 struct iocblk *iocp;
2676 hid_default_pipe_arg_t *def_pipe_arg;
2677 hid_state_t *hidp = (hid_state_t *)q->q_ptr;
2678
2679 iocp = (struct iocblk *)mp->b_rptr;
2680 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
2681 "hid_mctl_execute_cmd: iocp=0x%p", (void *)iocp);
2682
2683 request_index = hidp->hid_if_descr.bInterfaceNumber;
2684
2685 /*
2686 * Set up the argument to be passed back to hid
2687 * when the asynchronous control callback is
2688 * executed.
2689 */
2690 def_pipe_arg = kmem_zalloc(sizeof (hid_default_pipe_arg_t), 0);
2691
2692 if (def_pipe_arg == NULL) {
2693
2694 return (HID_FAILURE);
2695 }
2696
2697 def_pipe_arg->hid_default_pipe_arg_queue = q;
2698 def_pipe_arg->hid_default_pipe_arg_mctlmsg.ioc_cmd = iocp->ioc_cmd;
2699 def_pipe_arg->hid_default_pipe_arg_mctlmsg.ioc_count = 0;
2700 def_pipe_arg->hid_default_pipe_arg_mblk = mp;
2701
2702 /*
2703 * Send the command down to USBA through default
2704 * pipe.
2705 */
2706 if (hid_send_async_ctrl_request(def_pipe_arg, hid_req_data,
2707 request_type, iocp->ioc_cmd, request_index) != USB_SUCCESS) {
2708
2709 kmem_free(def_pipe_arg, sizeof (hid_default_pipe_arg_t));
2710
2711 return (HID_FAILURE);
2712 }
2713
2714 return (HID_INPROGRESS);
2715 }
2716
2717
2718 /*
2719 * hid_send_async_ctrl_request:
2720 * Send an asynchronous control request to USBA. Since hid is a STREAMS
2721 * driver, it is not allowed to wait in its entry points except for the
2722 * open and close entry points. Therefore, hid must use the asynchronous
2723 * USBA calls.
2724 */
2725 static int
hid_send_async_ctrl_request(hid_default_pipe_arg_t * hid_default_pipe_arg,hid_req_t * hid_request,uchar_t request_type,int request_request,ushort_t request_index)2726 hid_send_async_ctrl_request(hid_default_pipe_arg_t *hid_default_pipe_arg,
2727 hid_req_t *hid_request, uchar_t request_type, int request_request,
2728 ushort_t request_index)
2729 {
2730 queue_t *q = hid_default_pipe_arg->hid_default_pipe_arg_queue;
2731 hid_state_t *hidp = (hid_state_t *)q->q_ptr;
2732 usb_ctrl_req_t *ctrl_req;
2733 int rval;
2734 size_t length = 0;
2735
2736 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
2737 "hid_send_async_ctrl_request: "
2738 "rq_type=%d rq_rq=%d index=%d",
2739 request_type, request_request, request_index);
2740
2741 mutex_enter(&hidp->hid_mutex);
2742 hidp->hid_default_pipe_req++;
2743 mutex_exit(&hidp->hid_mutex);
2744
2745 /*
2746 * Note that ctrl_req->ctrl_data should be allocated by usba
2747 * only for IN requests. OUT request(e.g SET_REPORT) can have a
2748 * non-zero wLength value but ctrl_data would be allocated by
2749 * client for them.
2750 */
2751 if (hid_request->hid_req_wLength >= MAX_REPORT_DATA) {
2752 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
2753 "hid_req_wLength is exceeded");
2754 return (USB_FAILURE);
2755 }
2756 if ((request_type & USB_DEV_REQ_DIR_MASK) == USB_DEV_REQ_DEV_TO_HOST) {
2757 length = hid_request->hid_req_wLength;
2758 }
2759
2760 if ((ctrl_req = usb_alloc_ctrl_req(hidp->hid_dip, length, 0)) == NULL) {
2761 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
2762 "unable to alloc ctrl req. async trans failed");
2763 mutex_enter(&hidp->hid_mutex);
2764 hidp->hid_default_pipe_req--;
2765 ASSERT(hidp->hid_default_pipe_req >= 0);
2766 mutex_exit(&hidp->hid_mutex);
2767
2768 return (USB_FAILURE);
2769 }
2770
2771 if ((request_type & USB_DEV_REQ_DIR_MASK) == USB_DEV_REQ_HOST_TO_DEV) {
2772 ASSERT((length == 0) && (ctrl_req->ctrl_data == NULL));
2773 }
2774
2775 ctrl_req->ctrl_bmRequestType = request_type;
2776 ctrl_req->ctrl_bRequest = (uint8_t)request_request;
2777 ctrl_req->ctrl_wValue = hid_request->hid_req_wValue;
2778 ctrl_req->ctrl_wIndex = request_index;
2779 ctrl_req->ctrl_wLength = hid_request->hid_req_wLength;
2780 /* host to device: create a msg from hid_req_data */
2781 if ((request_type & USB_DEV_REQ_DIR_MASK) == USB_DEV_REQ_HOST_TO_DEV) {
2782 mblk_t *pblk = allocb(hid_request->hid_req_wLength, BPRI_HI);
2783 if (pblk == NULL) {
2784 usb_free_ctrl_req(ctrl_req);
2785 return (USB_FAILURE);
2786 }
2787 bcopy(hid_request->hid_req_data, pblk->b_wptr,
2788 hid_request->hid_req_wLength);
2789 pblk->b_wptr += hid_request->hid_req_wLength;
2790 ctrl_req->ctrl_data = pblk;
2791 }
2792 ctrl_req->ctrl_attributes = USB_ATTRS_AUTOCLEARING;
2793 ctrl_req->ctrl_client_private = (usb_opaque_t)hid_default_pipe_arg;
2794 ctrl_req->ctrl_cb = hid_default_pipe_callback;
2795 ctrl_req->ctrl_exc_cb = hid_default_pipe_exception_callback;
2796
2797 if ((rval = usb_pipe_ctrl_xfer(hidp->hid_default_pipe,
2798 ctrl_req, 0)) != USB_SUCCESS) {
2799 mutex_enter(&hidp->hid_mutex);
2800 hidp->hid_default_pipe_req--;
2801 ASSERT(hidp->hid_default_pipe_req >= 0);
2802 mutex_exit(&hidp->hid_mutex);
2803
2804 usb_free_ctrl_req(ctrl_req);
2805 USB_DPRINTF_L2(PRINT_MASK_ALL, hidp->hid_log_handle,
2806 "usb_pipe_ctrl_xfer() failed. rval = %d", rval);
2807
2808 return (USB_FAILURE);
2809 }
2810
2811 return (USB_SUCCESS);
2812 }
2813
2814 /*
2815 * hid_create_pm_components:
2816 * Create the pm components required for power management.
2817 * For keyboard/mouse, the components is created only if the device
2818 * supports a remote wakeup.
2819 * For other hid devices they are created unconditionally.
2820 */
2821 static void
hid_create_pm_components(dev_info_t * dip,hid_state_t * hidp)2822 hid_create_pm_components(dev_info_t *dip, hid_state_t *hidp)
2823 {
2824 hid_power_t *hidpm;
2825 uint_t pwr_states;
2826
2827 USB_DPRINTF_L4(PRINT_MASK_PM, hidp->hid_log_handle,
2828 "hid_create_pm_components: Begin");
2829
2830 /* Allocate the state structure */
2831 hidpm = kmem_zalloc(sizeof (hid_power_t), KM_SLEEP);
2832 hidp->hid_pm = hidpm;
2833 hidpm->hid_state = hidp;
2834 hidpm->hid_raise_power = B_FALSE;
2835 hidpm->hid_pm_capabilities = 0;
2836 hidpm->hid_current_power = USB_DEV_OS_FULL_PWR;
2837
2838 switch (hidp->hid_if_descr.bInterfaceProtocol) {
2839 case KEYBOARD_PROTOCOL:
2840 case MOUSE_PROTOCOL:
2841 hidpm->hid_pm_strategy = HID_PM_ACTIVITY;
2842 if ((hid_is_pm_enabled(dip) == USB_SUCCESS) &&
2843 (usb_handle_remote_wakeup(dip, USB_REMOTE_WAKEUP_ENABLE) ==
2844 USB_SUCCESS)) {
2845
2846 USB_DPRINTF_L3(PRINT_MASK_PM, hidp->hid_log_handle,
2847 "hid_create_pm_components: Remote Wakeup Enabled");
2848
2849 if (usb_create_pm_components(dip, &pwr_states) ==
2850 USB_SUCCESS) {
2851 hidpm->hid_wakeup_enabled = 1;
2852 hidpm->hid_pwr_states = (uint8_t)pwr_states;
2853 }
2854 }
2855
2856 break;
2857 default:
2858 hidpm->hid_pm_strategy = HID_PM_OPEN_CLOSE;
2859 if ((hid_is_pm_enabled(dip) == USB_SUCCESS) &&
2860 (usb_create_pm_components(dip, &pwr_states) ==
2861 USB_SUCCESS)) {
2862 hidpm->hid_wakeup_enabled = 0;
2863 hidpm->hid_pwr_states = (uint8_t)pwr_states;
2864 }
2865
2866 break;
2867 }
2868
2869 USB_DPRINTF_L4(PRINT_MASK_PM, hidp->hid_log_handle,
2870 "hid_create_pm_components: END");
2871 }
2872
2873
2874 /*
2875 * hid_is_pm_enabled
2876 * Check if the device is pm enabled. Always enable
2877 * pm on the new SUN mouse
2878 */
2879 static int
hid_is_pm_enabled(dev_info_t * dip)2880 hid_is_pm_enabled(dev_info_t *dip)
2881 {
2882 hid_state_t *hidp = ddi_get_soft_state(hid_statep,
2883 ddi_get_instance(dip));
2884
2885 if (strcmp(ddi_node_name(dip), "mouse") == 0) {
2886 /* check for overrides first */
2887 if (hid_pm_mouse ||
2888 (ddi_prop_exists(DDI_DEV_T_ANY, dip,
2889 (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
2890 "hid-mouse-pm-enable") == 1)) {
2891
2892 return (USB_SUCCESS);
2893 }
2894
2895 /*
2896 * Always enable PM for 1.05 or greater SUN mouse
2897 * hidp->hid_dev_descr won't be NULL.
2898 */
2899 if ((hidp->hid_dev_descr->idVendor ==
2900 HID_SUN_MOUSE_VENDOR_ID) &&
2901 (hidp->hid_dev_descr->idProduct ==
2902 HID_SUN_MOUSE_PROD_ID) &&
2903 (hidp->hid_dev_descr->bcdDevice >=
2904 HID_SUN_MOUSE_BCDDEVICE)) {
2905
2906 return (USB_SUCCESS);
2907 }
2908 } else {
2909
2910 return (USB_SUCCESS);
2911 }
2912
2913 return (USB_FAILURE);
2914 }
2915
2916
2917 /*
2918 * hid_save_device_state
2919 * Save the current device/driver state.
2920 */
2921 static void
hid_save_device_state(hid_state_t * hidp)2922 hid_save_device_state(hid_state_t *hidp)
2923 {
2924 struct iocblk *mctlmsg;
2925 mblk_t *mp;
2926 queue_t *q;
2927
2928 USB_DPRINTF_L4(PRINT_MASK_EVENTS, hidp->hid_log_handle,
2929 "hid_save_device_state");
2930
2931 if (!(HID_IS_OPEN(hidp)))
2932 return;
2933
2934 if (hidp->hid_internal_flag == HID_STREAMS_OPEN) {
2935 /*
2936 * Send MCTLs up indicating that the device
2937 * will loose its state
2938 */
2939 q = hidp->hid_internal_rq;
2940
2941 mutex_exit(&hidp->hid_mutex);
2942 if (canputnext(q)) {
2943 mp = allocb(sizeof (struct iocblk), BPRI_HI);
2944 if (mp != NULL) {
2945 mp->b_datap->db_type = M_CTL;
2946 mctlmsg = (struct iocblk *)
2947 mp->b_datap->db_base;
2948 mctlmsg->ioc_cmd = HID_DISCONNECT_EVENT;
2949 mctlmsg->ioc_count = 0;
2950 putnext(q, mp);
2951 }
2952 }
2953 mutex_enter(&hidp->hid_mutex);
2954 }
2955
2956 if (hidp->hid_external_flag == HID_STREAMS_OPEN) {
2957 /*
2958 * Send MCTLs up indicating that the device
2959 * will loose its state
2960 */
2961 q = hidp->hid_external_rq;
2962
2963 mutex_exit(&hidp->hid_mutex);
2964 if (canputnext(q)) {
2965 mp = allocb(sizeof (struct iocblk), BPRI_HI);
2966 if (mp != NULL) {
2967 mp->b_datap->db_type = M_CTL;
2968 mctlmsg = (struct iocblk *)
2969 mp->b_datap->db_base;
2970 mctlmsg->ioc_cmd = HID_DISCONNECT_EVENT;
2971 mctlmsg->ioc_count = 0;
2972 putnext(q, mp);
2973 }
2974 }
2975 mutex_enter(&hidp->hid_mutex);
2976 }
2977
2978 mutex_exit(&hidp->hid_mutex);
2979 /* stop polling on the intr pipe */
2980 usb_pipe_stop_intr_polling(hidp->hid_interrupt_pipe, USB_FLAGS_SLEEP);
2981 mutex_enter(&hidp->hid_mutex);
2982 }
2983
2984
2985 /*
2986 * hid_restore_device_state:
2987 * Set original configuration of the device.
2988 * Reopen intr pipe.
2989 * Enable wrq - this starts new transactions on the control pipe.
2990 */
2991 static void
hid_restore_device_state(dev_info_t * dip,hid_state_t * hidp)2992 hid_restore_device_state(dev_info_t *dip, hid_state_t *hidp)
2993 {
2994 int rval;
2995 hid_power_t *hidpm;
2996 struct iocblk *mctlmsg;
2997 mblk_t *mp;
2998 queue_t *q;
2999
3000 hid_pm_busy_component(hidp);
3001 mutex_enter(&hidp->hid_mutex);
3002
3003 USB_DPRINTF_L4(PRINT_MASK_ATTA, hidp->hid_log_handle,
3004 "hid_restore_device_state: %s",
3005 usb_str_dev_state(hidp->hid_dev_state));
3006
3007 hidpm = hidp->hid_pm;
3008 mutex_exit(&hidp->hid_mutex);
3009
3010 /* First bring the device to full power */
3011 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
3012
3013 mutex_enter(&hidp->hid_mutex);
3014 if (hidp->hid_dev_state == USB_DEV_ONLINE) {
3015 /*
3016 * We failed the checkpoint, there is no need to restore
3017 * the device state
3018 */
3019 mutex_exit(&hidp->hid_mutex);
3020 hid_pm_idle_component(hidp);
3021
3022 return;
3023 }
3024 mutex_exit(&hidp->hid_mutex);
3025
3026
3027 /* Check if we are talking to the same device */
3028 if (usb_check_same_device(dip, hidp->hid_log_handle, USB_LOG_L2,
3029 PRINT_MASK_ALL, USB_CHK_BASIC|USB_CHK_CFG, NULL) != USB_SUCCESS) {
3030
3031 /* change the device state from suspended to disconnected */
3032 mutex_enter(&hidp->hid_mutex);
3033 hidp->hid_dev_state = USB_DEV_DISCONNECTED;
3034 mutex_exit(&hidp->hid_mutex);
3035 hid_pm_idle_component(hidp);
3036 goto nodev;
3037 }
3038
3039 hid_set_idle(hidp);
3040 hid_set_protocol(hidp, SET_REPORT_PROTOCOL);
3041
3042 mutex_enter(&hidp->hid_mutex);
3043 /* if the device had remote wakeup earlier, enable it again */
3044 if (hidpm->hid_wakeup_enabled) {
3045 mutex_exit(&hidp->hid_mutex);
3046
3047 if ((rval = usb_handle_remote_wakeup(hidp->hid_dip,
3048 USB_REMOTE_WAKEUP_ENABLE)) != USB_SUCCESS) {
3049 USB_DPRINTF_L2(PRINT_MASK_ATTA,
3050 hidp->hid_log_handle,
3051 "usb_handle_remote_wakeup failed (%d)", rval);
3052 }
3053
3054 mutex_enter(&hidp->hid_mutex);
3055 }
3056
3057 /*
3058 * restart polling on the interrupt pipe only if the device
3059 * was previously operational (open)
3060 */
3061 if (HID_IS_OPEN(hidp)) {
3062 if ((rval = hid_start_intr_polling(hidp)) != USB_SUCCESS) {
3063 USB_DPRINTF_L3(PRINT_MASK_ATTA, hidp->hid_log_handle,
3064 "hid_restore_device_state:"
3065 "unable to restart intr pipe poll"
3066 " rval = %d ", rval);
3067 /*
3068 * change the device state from
3069 * suspended to disconnected
3070 */
3071 hidp->hid_dev_state = USB_DEV_DISCONNECTED;
3072 mutex_exit(&hidp->hid_mutex);
3073 hid_pm_idle_component(hidp);
3074 goto nodev;
3075 }
3076
3077 if (hidp->hid_dev_state == USB_DEV_DISCONNECTED) {
3078 USB_DPRINTF_L2(PRINT_MASK_EVENTS, hidp->hid_log_handle,
3079 "device is being re-connected");
3080 }
3081
3082 /* set the device state ONLINE */
3083 hidp->hid_dev_state = USB_DEV_ONLINE;
3084
3085 /* inform upstream modules that the device is back */
3086 if (hidp->hid_internal_flag == HID_STREAMS_OPEN) {
3087 q = hidp->hid_internal_rq;
3088
3089 mutex_exit(&hidp->hid_mutex);
3090 if (canputnext(q)) {
3091 mp = allocb(sizeof (struct iocblk), BPRI_HI);
3092 if (mp != NULL) {
3093 mp->b_datap->db_type = M_CTL;
3094 mctlmsg = (struct iocblk *)
3095 mp->b_datap->db_base;
3096 mctlmsg->ioc_cmd = HID_CONNECT_EVENT;
3097 mctlmsg->ioc_count = 0;
3098 putnext(q, mp);
3099 }
3100 }
3101 /* enable write side q */
3102 qenable(WR(q));
3103 mutex_enter(&hidp->hid_mutex);
3104 }
3105
3106 if (hidp->hid_external_flag == HID_STREAMS_OPEN) {
3107 q = hidp->hid_external_rq;
3108
3109 mutex_exit(&hidp->hid_mutex);
3110 if (canputnext(q)) {
3111 mp = allocb(sizeof (struct iocblk), BPRI_HI);
3112 if (mp != NULL) {
3113 mp->b_datap->db_type = M_CTL;
3114 mctlmsg = (struct iocblk *)
3115 mp->b_datap->db_base;
3116 mctlmsg->ioc_cmd = HID_CONNECT_EVENT;
3117 mctlmsg->ioc_count = 0;
3118 putnext(q, mp);
3119 }
3120 }
3121 /* enable write side q */
3122 qenable(WR(q));
3123 mutex_enter(&hidp->hid_mutex);
3124 }
3125 } else {
3126 /* set the device state ONLINE */
3127 hidp->hid_dev_state = USB_DEV_ONLINE;
3128 }
3129
3130 mutex_exit(&hidp->hid_mutex);
3131 hid_pm_idle_component(hidp);
3132 return;
3133
3134 nodev:
3135 /*
3136 * Notify applications about device removal. This only
3137 * applies to an external (aka. physical) open. Not sure how to
3138 * notify consconfig to close the internal minor node.
3139 */
3140 mutex_enter(&hidp->hid_mutex);
3141
3142 if ((q = hidp->hid_external_rq) == NULL) {
3143 mutex_exit(&hidp->hid_mutex);
3144 return;
3145 }
3146
3147 mutex_exit(&hidp->hid_mutex);
3148 mp = allocb(sizeof (uchar_t), BPRI_HI);
3149 if (mp != NULL) {
3150 mp->b_datap->db_type = M_ERROR;
3151 mp->b_rptr = mp->b_datap->db_base;
3152 mp->b_wptr = mp->b_rptr + sizeof (char);
3153 *mp->b_rptr = ENODEV;
3154 putnext(q, mp);
3155 }
3156 }
3157
3158
3159 /*
3160 * hid_qreply_merror:
3161 * Pass an error message up.
3162 */
3163 static void
hid_qreply_merror(queue_t * q,mblk_t * mp,uchar_t errval)3164 hid_qreply_merror(queue_t *q, mblk_t *mp, uchar_t errval)
3165 {
3166 mp->b_datap->db_type = M_ERROR;
3167 if (mp->b_cont) {
3168 freemsg(mp->b_cont);
3169 mp->b_cont = NULL;
3170 }
3171 mp->b_rptr = mp->b_datap->db_base;
3172 mp->b_wptr = mp->b_rptr + sizeof (char);
3173 *mp->b_rptr = errval;
3174
3175 qreply(q, mp);
3176 }
3177
3178
3179 /*
3180 * hid_data2mblk:
3181 * Form an mblk from the given data
3182 */
3183 static mblk_t *
hid_data2mblk(uchar_t * buf,int len)3184 hid_data2mblk(uchar_t *buf, int len)
3185 {
3186 mblk_t *mp = NULL;
3187
3188 if (len >= 0) {
3189 mp = allocb(len, BPRI_HI);
3190 if (mp) {
3191 bcopy(buf, mp->b_datap->db_base, len);
3192 mp->b_wptr += len;
3193 }
3194 }
3195
3196 return (mp);
3197 }
3198
3199
3200 /*
3201 * hid_flush :
3202 * Flush data already sent upstreams to client module.
3203 */
3204 static void
hid_flush(queue_t * q)3205 hid_flush(queue_t *q)
3206 {
3207 /*
3208 * Flush pending data already sent upstream
3209 */
3210 if ((q != NULL) && (q->q_next != NULL)) {
3211 (void) putnextctl1(q, M_FLUSH, FLUSHR);
3212 }
3213 }
3214
3215
3216 static void
hid_pm_busy_component(hid_state_t * hid_statep)3217 hid_pm_busy_component(hid_state_t *hid_statep)
3218 {
3219 ASSERT(!mutex_owned(&hid_statep->hid_mutex));
3220
3221 if (hid_statep->hid_pm != NULL) {
3222 mutex_enter(&hid_statep->hid_mutex);
3223 hid_statep->hid_pm->hid_pm_busy++;
3224
3225 USB_DPRINTF_L4(PRINT_MASK_PM, hid_statep->hid_log_handle,
3226 "hid_pm_busy_component: %d",
3227 hid_statep->hid_pm->hid_pm_busy);
3228
3229 mutex_exit(&hid_statep->hid_mutex);
3230 if (pm_busy_component(hid_statep->hid_dip, 0) != DDI_SUCCESS) {
3231 mutex_enter(&hid_statep->hid_mutex);
3232 hid_statep->hid_pm->hid_pm_busy--;
3233
3234 USB_DPRINTF_L2(PRINT_MASK_PM,
3235 hid_statep->hid_log_handle,
3236 "hid_pm_busy_component failed: %d",
3237 hid_statep->hid_pm->hid_pm_busy);
3238
3239 mutex_exit(&hid_statep->hid_mutex);
3240 }
3241
3242 }
3243 }
3244
3245
3246 static void
hid_pm_idle_component(hid_state_t * hid_statep)3247 hid_pm_idle_component(hid_state_t *hid_statep)
3248 {
3249 ASSERT(!mutex_owned(&hid_statep->hid_mutex));
3250
3251 if (hid_statep->hid_pm != NULL) {
3252 if (pm_idle_component(hid_statep->hid_dip, 0) == DDI_SUCCESS) {
3253 mutex_enter(&hid_statep->hid_mutex);
3254 ASSERT(hid_statep->hid_pm->hid_pm_busy > 0);
3255 hid_statep->hid_pm->hid_pm_busy--;
3256
3257 USB_DPRINTF_L4(PRINT_MASK_PM,
3258 hid_statep->hid_log_handle,
3259 "hid_pm_idle_component: %d",
3260 hid_statep->hid_pm->hid_pm_busy);
3261
3262 mutex_exit(&hid_statep->hid_mutex);
3263 }
3264 }
3265 }
3266
3267
3268 /*
3269 * hid_pwrlvl0:
3270 * Functions to handle power transition for various levels
3271 * These functions act as place holders to issue USB commands
3272 * to the devices to change their power levels
3273 */
3274 static int
hid_pwrlvl0(hid_state_t * hidp)3275 hid_pwrlvl0(hid_state_t *hidp)
3276 {
3277 hid_power_t *hidpm;
3278 int rval;
3279 struct iocblk *mctlmsg;
3280 mblk_t *mp_lowpwr, *mp_fullpwr;
3281 queue_t *q;
3282
3283 hidpm = hidp->hid_pm;
3284
3285 switch (hidp->hid_dev_state) {
3286 case USB_DEV_ONLINE:
3287 /* Deny the powerdown request if the device is busy */
3288 if (hidpm->hid_pm_busy != 0) {
3289
3290 return (USB_FAILURE);
3291 }
3292
3293 if (HID_IS_OPEN(hidp)) {
3294 q = hidp->hid_inuse_rq;
3295 mutex_exit(&hidp->hid_mutex);
3296 if (canputnext(q)) {
3297 /* try to preallocate mblks */
3298 mp_lowpwr = allocb(
3299 (int)sizeof (struct iocblk), BPRI_HI);
3300 mp_fullpwr = allocb(
3301 (int)sizeof (struct iocblk), BPRI_HI);
3302 if ((mp_lowpwr != NULL) &&
3303 (mp_fullpwr != NULL)) {
3304 /* stop polling */
3305 usb_pipe_stop_intr_polling(
3306 hidp->hid_interrupt_pipe,
3307 USB_FLAGS_SLEEP);
3308
3309 /*
3310 * Send an MCTL up indicating that
3311 * we are powering off
3312 */
3313 mp_lowpwr->b_datap->db_type = M_CTL;
3314 mctlmsg = (struct iocblk *)
3315 mp_lowpwr->b_datap->db_base;
3316 mctlmsg->ioc_cmd = HID_POWER_OFF;
3317 mctlmsg->ioc_count = 0;
3318 putnext(q, mp_lowpwr);
3319
3320 /* save the full powr mblk */
3321 mutex_enter(&hidp->hid_mutex);
3322 hidpm->hid_pm_pwrup = mp_fullpwr;
3323 } else {
3324 /*
3325 * Since we failed to allocate one
3326 * or more mblks, we fail attempt
3327 * to go into low power this time
3328 */
3329 freemsg(mp_lowpwr);
3330 freemsg(mp_fullpwr);
3331 mutex_enter(&hidp->hid_mutex);
3332
3333 return (USB_FAILURE);
3334 }
3335 } else {
3336 /*
3337 * Since we can't send an mblk up,
3338 * we fail this attempt to go to low power
3339 */
3340 mutex_enter(&hidp->hid_mutex);
3341
3342 return (USB_FAILURE);
3343 }
3344 }
3345
3346 mutex_exit(&hidp->hid_mutex);
3347 /* Issue USB D3 command to the device here */
3348 rval = usb_set_device_pwrlvl3(hidp->hid_dip);
3349 ASSERT(rval == USB_SUCCESS);
3350
3351 mutex_enter(&hidp->hid_mutex);
3352 hidp->hid_dev_state = USB_DEV_PWRED_DOWN;
3353 hidpm->hid_current_power = USB_DEV_OS_PWR_OFF;
3354
3355 /* FALLTHRU */
3356 case USB_DEV_DISCONNECTED:
3357 case USB_DEV_SUSPENDED:
3358 case USB_DEV_PWRED_DOWN:
3359 default:
3360 break;
3361 }
3362
3363 return (USB_SUCCESS);
3364 }
3365
3366
3367 /* ARGSUSED */
3368 static int
hid_pwrlvl1(hid_state_t * hidp)3369 hid_pwrlvl1(hid_state_t *hidp)
3370 {
3371 int rval;
3372
3373 /* Issue USB D2 command to the device here */
3374 rval = usb_set_device_pwrlvl2(hidp->hid_dip);
3375 ASSERT(rval == USB_SUCCESS);
3376
3377 return (USB_FAILURE);
3378 }
3379
3380
3381 /* ARGSUSED */
3382 static int
hid_pwrlvl2(hid_state_t * hidp)3383 hid_pwrlvl2(hid_state_t *hidp)
3384 {
3385 int rval;
3386
3387 rval = usb_set_device_pwrlvl1(hidp->hid_dip);
3388 ASSERT(rval == USB_SUCCESS);
3389
3390 return (USB_FAILURE);
3391 }
3392
3393
3394 static int
hid_pwrlvl3(hid_state_t * hidp)3395 hid_pwrlvl3(hid_state_t *hidp)
3396 {
3397 hid_power_t *hidpm;
3398 int rval;
3399 struct iocblk *mctlmsg;
3400 mblk_t *mp;
3401 queue_t *q;
3402
3403 hidpm = hidp->hid_pm;
3404
3405 switch (hidp->hid_dev_state) {
3406 case USB_DEV_HID_POWER_CHANGE:
3407 case USB_DEV_PWRED_DOWN:
3408 /* Issue USB D0 command to the device here */
3409 rval = usb_set_device_pwrlvl0(hidp->hid_dip);
3410 ASSERT(rval == USB_SUCCESS);
3411
3412 if (HID_IS_OPEN(hidp)) {
3413 /* restart polling on intr pipe */
3414 rval = hid_start_intr_polling(hidp);
3415 if (rval != USB_SUCCESS) {
3416 USB_DPRINTF_L2(PRINT_MASK_EVENTS,
3417 hidp->hid_log_handle,
3418 "unable to restart intr polling rval = %d",
3419 rval);
3420
3421 return (USB_FAILURE);
3422 }
3423
3424 /* Send an MCTL up indicating device in full power */
3425 q = hidp->hid_inuse_rq;
3426 mp = hidpm->hid_pm_pwrup;
3427 hidpm->hid_pm_pwrup = NULL;
3428 mutex_exit(&hidp->hid_mutex);
3429 if (canputnext(q)) {
3430 mp->b_datap->db_type = M_CTL;
3431 mctlmsg = (struct iocblk *)
3432 mp->b_datap->db_base;
3433 mctlmsg->ioc_cmd = HID_FULL_POWER;
3434 mctlmsg->ioc_count = 0;
3435 putnext(q, mp);
3436 } else {
3437 freemsg(mp);
3438 }
3439 mutex_enter(&hidp->hid_mutex);
3440 }
3441
3442 hidp->hid_dev_state = USB_DEV_ONLINE;
3443 hidpm->hid_current_power = USB_DEV_OS_FULL_PWR;
3444
3445 /* FALLTHRU */
3446 case USB_DEV_DISCONNECTED:
3447 case USB_DEV_SUSPENDED:
3448 case USB_DEV_ONLINE:
3449
3450 return (USB_SUCCESS);
3451 default:
3452 USB_DPRINTF_L2(PRINT_MASK_EVENTS, hidp->hid_log_handle,
3453 "hid_pwrlvl3: Improper State");
3454
3455 return (USB_FAILURE);
3456 }
3457 }
3458
3459
3460 /*
3461 * hid_polled_input_init :
3462 * This routine calls down to the lower layers to initialize any state
3463 * information. This routine initializes the lower layers for input.
3464 */
3465 static int
hid_polled_input_init(hid_state_t * hidp)3466 hid_polled_input_init(hid_state_t *hidp)
3467 {
3468 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
3469 "hid_polled_input_init");
3470
3471 /*
3472 * Call the lower layers to intialize any state information
3473 * that they will need to provide the polled characters.
3474 */
3475 if (usb_console_input_init(hidp->hid_dip, hidp->hid_interrupt_pipe,
3476 &hidp->hid_polled_raw_buf,
3477 &hidp->hid_polled_console_info) != USB_SUCCESS) {
3478 /*
3479 * If for some reason the lower layers cannot initialized, then
3480 * bail.
3481 */
3482 (void) hid_polled_input_fini(hidp);
3483
3484 return (USB_FAILURE);
3485 }
3486
3487 return (USB_SUCCESS);
3488 }
3489
3490
3491 /*
3492 * hid_polled_input_fini:
3493 * This routine is called when we are done using this device as an input
3494 * device.
3495 */
3496 static int
hid_polled_input_fini(hid_state_t * hidp)3497 hid_polled_input_fini(hid_state_t *hidp)
3498 {
3499 USB_DPRINTF_L4(PRINT_MASK_ALL, hidp->hid_log_handle,
3500 "hid_polled_input_fini");
3501
3502 /*
3503 * Call the lower layers to free any state information
3504 * only if polled input has been initialised.
3505 */
3506 if ((hidp->hid_polled_console_info) &&
3507 (usb_console_input_fini(hidp->hid_polled_console_info) !=
3508 USB_SUCCESS)) {
3509
3510 return (USB_FAILURE);
3511 }
3512 hidp->hid_polled_console_info = NULL;
3513
3514 return (USB_SUCCESS);
3515 }
3516
3517
3518 /*
3519 * hid_polled_input_enter:
3520 * This is the routine that is called in polled mode to save the USB
3521 * state information before using the USB keyboard as an input device.
3522 * This routine, and all of the routines that it calls, are responsible
3523 * for saving any state information so that it can be restored when
3524 * polling mode is over.
3525 */
3526 static int
3527 /* ARGSUSED */
hid_polled_input_enter(hid_polled_handle_t hid_polled_inputp)3528 hid_polled_input_enter(hid_polled_handle_t hid_polled_inputp)
3529 {
3530 hid_state_t *hidp = (hid_state_t *)hid_polled_inputp;
3531
3532 /*
3533 * Call the lower layers to tell them to save any state information.
3534 */
3535 (void) usb_console_input_enter(hidp->hid_polled_console_info);
3536
3537 return (USB_SUCCESS);
3538 }
3539
3540
3541 /*
3542 * hid_polled_read :
3543 * This is the routine that is called in polled mode when it wants to read
3544 * a character. We will call to the lower layers to see if there is any
3545 * input data available. If there is USB scancodes available, we will
3546 * give them back.
3547 */
3548 static int
hid_polled_read(hid_polled_handle_t hid_polled_input,uchar_t ** buffer)3549 hid_polled_read(hid_polled_handle_t hid_polled_input, uchar_t **buffer)
3550 {
3551 hid_state_t *hidp = (hid_state_t *)hid_polled_input;
3552 uint_t num_bytes;
3553
3554 /*
3555 * Call the lower layers to get the character from the controller.
3556 * The lower layers will return the number of characters that
3557 * were put in the raw buffer. The address of the raw buffer
3558 * was passed down to the lower layers during hid_polled_init.
3559 */
3560 if (usb_console_read(hidp->hid_polled_console_info,
3561 &num_bytes) != USB_SUCCESS) {
3562
3563 return (0);
3564 }
3565
3566 _NOTE(NO_COMPETING_THREADS_NOW);
3567
3568 *buffer = hidp->hid_polled_raw_buf;
3569
3570 _NOTE(COMPETING_THREADS_NOW);
3571
3572 /*
3573 * Return the number of characters that were copied into the
3574 * polled buffer.
3575 */
3576 return (num_bytes);
3577 }
3578
3579
3580 /*
3581 * hid_polled_input_exit :
3582 * This is the routine that is called in polled mode when it is giving up
3583 * control of the USB keyboard. This routine, and the lower layer routines
3584 * that it calls, are responsible for restoring the controller state to the
3585 * state it was in before polled mode.
3586 */
3587 static int
hid_polled_input_exit(hid_polled_handle_t hid_polled_inputp)3588 hid_polled_input_exit(hid_polled_handle_t hid_polled_inputp)
3589 {
3590 hid_state_t *hidp = (hid_state_t *)hid_polled_inputp;
3591
3592 /*
3593 * Call the lower layers to restore any state information.
3594 */
3595 (void) usb_console_input_exit(hidp->hid_polled_console_info);
3596
3597 return (0);
3598 }
3599