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