1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * Copyright (c) 2018, Joyent, Inc.
27 */
28
29 /*
30 * USB video class driver (usbvc(4D))
31 *
32 * 1. Overview
33 * ------------
34 *
35 * This driver supports USB video class devices that used to capture video,
36 * e.g., some webcams. It is developed according to "USB Device Class
37 * Definition for Video Devices" spec. This spec defines detail info needed by
38 * designing a USB video device. It is available at:
39 * http://www.usb.org/developers/devclass_docs
40 *
41 * This driver implements:
42 *
43 * - V4L2 interfaces for applications to communicate with video devices.
44 * V4L2 is an API that is widely used by video applications, like Ekiga,
45 * luvcview, etc. The API spec is at:
46 * http://www.thedirks.org/v4l2/
47 * This driver is according to V4L2 spec version 0.20
48 *
49 * - Video capture function. (Video output is not supported by now.)
50 *
51 * - Isochronous transfer for video data. (Bulk transfer is not supported.)
52 *
53 * - read & mmap I/O methods for userland video applications to get video
54 * data. Userland video applications can use read() system call directly,
55 * it is the simplest way but not the most efficient way. Applications can
56 * also use mmap() system call to map several bufs (they are linked as a
57 * buf list), and then use some specific ioctls to start/stop isoc polling,
58 * to queue/dequeue bufs.
59 *
60 * 2. Source and header files
61 * ---------------------------
62 *
63 * There are two source files and three header files for this driver:
64 *
65 * - usbvc.c Main source file, implements usb video class spec.
66 *
67 * - usbvc_v4l2.c V4L2 interface specific code.
68 *
69 * - usbvc_var.h Main header file, includes soft state structure.
70 *
71 * - usbvc.h The descriptors in usb video class spec.
72 *
73 * - videodev2.h This header file is included in V4L2 spec. It defines
74 * ioctls and data structures that used as an interface between video
75 * applications and video drivers. This is the only header file that
76 * usbvc driver should export to userland application.
77 *
78 * 3. USB video class devices overview
79 * -----------------------------------
80 * According to UVC spec, there must be one control interface in a UVC device.
81 * Control interface is used to receive control commands from user, all the
82 * commands are sent through default ctrl pipe. usbvc driver implements V4L2
83 * API, so ioctls are implemented to relay user commands to UVC device.
84 *
85 * There can be no or multiple stream interfaces in a UVC device. Stream
86 * interfaces are used to do video data I/O. In practice, if no stream
87 * interface, the video device can do nothing since it has no data I/O.
88 *
89 * usbvc driver parses descriptors of control interface and stream interfaces.
90 * The descriptors tell the function layout and the capability of the device.
91 * During attach, usbvc driver set up some key data structures according to
92 * the descriptors.
93 *
94 * 4. I/O methods
95 * ---------------
96 *
97 * Userland applications use ioctls to set/get video formats of the device,
98 * and control brightness, contrast, image size, etc.
99 *
100 * Besides implementing standard read I/O method to get video data from
101 * the device, usbvc driver also implements some specific ioctls to implement
102 * mmap I/O method.
103 *
104 * A view from userland application: ioctl and mmap flow chart:
105 *
106 * REQBUFS -> QUERYBUF -> mmap() ->
107 *
108 * -> QBUF -> STREAMON -> DQBUF -> process image -> QBUF
109 * ^ |
110 * | |
111 * | v
112 * |---<--------------------
113 *
114 * The above queue and dequeue buf operations can be stopped by issuing a
115 * STREAMOFF ioctl.
116 *
117 * 5. Device states
118 * ----------------
119 *
120 * The device has four states (refer to usbai.h):
121 *
122 * - USB_DEV_ONLINE: In action or ready for action.
123 *
124 * - USB_DEV_DISCONNECTED: Hotplug removed, or device not present/correct
125 * on resume (CPR).
126 *
127 * - USB_DEV_SUSPENDED: Device has been suspended along with the system.
128 *
129 * - USB_DEV_PWRED_DOWN: Device has been powered down. (Note that this
130 * driver supports only two power states, powered down and
131 * full power.)
132 *
133 * 6. Serialize
134 * -------------
135 * In order to avoid race conditions between driver entry points, access to
136 * the device is serialized. All the ioctls, and read, open/close are
137 * serialized. The functions usbvc_serialize/release_access are implemented
138 * for this purpose.
139 *
140 * 7. PM & CPR
141 * ------------
142 * PM & CPR are supported. pm_busy_component and pm_idle_component mark
143 * the device as busy or idle to the system.
144 */
145
146 #if defined(lint) && !defined(DEBUG)
147 #define DEBUG
148 #endif
149
150 #define USBDRV_MAJOR_VER 2
151 #define USBDRV_MINOR_VER 0
152
153 #include <sys/usb/usba.h>
154 #include <sys/fcntl.h>
155 #include <sys/cmn_err.h>
156 #include <sys/usb/clients/video/usbvc/usbvc_var.h>
157 #include <sys/videodev2.h> /* V4L2 API header file */
158
159 /* Descriptors according to USB video class spec */
160 #include <sys/usb/clients/video/usbvc/usbvc.h>
161
162 static uint_t usbvc_errmask = (uint_t)PRINT_MASK_ALL;
163 static uint_t usbvc_errlevel = 4;
164 static uint_t usbvc_instance_debug = (uint_t)-1;
165
166 static char *name = "usbvc"; /* Driver name, used all over. */
167
168 /*
169 * Function Prototypes
170 */
171
172 /* Entries */
173 static int usbvc_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
174 static int usbvc_attach(dev_info_t *, ddi_attach_cmd_t);
175 static int usbvc_detach(dev_info_t *, ddi_detach_cmd_t);
176 static void usbvc_cleanup(dev_info_t *, usbvc_state_t *);
177 static int usbvc_open(dev_t *, int, int, cred_t *);
178 static int usbvc_close(dev_t, int, int, cred_t *);
179 static int usbvc_read(dev_t, struct uio *uip_p, cred_t *);
180 static int usbvc_strategy(struct buf *);
181 static void usbvc_minphys(struct buf *);
182 static int usbvc_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
183 static int usbvc_devmap(dev_t, devmap_cookie_t, offset_t,
184 size_t, size_t *, uint_t);
185
186 /* pm and cpr */
187 static int usbvc_power(dev_info_t *, int, int);
188 static void usbvc_init_power_mgmt(usbvc_state_t *);
189 static void usbvc_destroy_power_mgmt(usbvc_state_t *);
190 static void usbvc_pm_busy_component(usbvc_state_t *);
191 static void usbvc_pm_idle_component(usbvc_state_t *);
192 static int usbvc_pwrlvl0(usbvc_state_t *);
193 static int usbvc_pwrlvl1(usbvc_state_t *);
194 static int usbvc_pwrlvl2(usbvc_state_t *);
195 static int usbvc_pwrlvl3(usbvc_state_t *);
196 static void usbvc_cpr_suspend(dev_info_t *);
197 static void usbvc_cpr_resume(dev_info_t *);
198 static void usbvc_restore_device_state(dev_info_t *, usbvc_state_t *);
199
200 /* Events */
201 static int usbvc_disconnect_event_cb(dev_info_t *);
202 static int usbvc_reconnect_event_cb(dev_info_t *);
203
204 /* Sync objs and lists */
205 static void usbvc_init_sync_objs(usbvc_state_t *);
206 static void usbvc_fini_sync_objs(usbvc_state_t *);
207 static void usbvc_init_lists(usbvc_state_t *);
208 static void usbvc_fini_lists(usbvc_state_t *);
209 static void usbvc_free_ctrl_descr(usbvc_state_t *);
210 static void usbvc_free_stream_descr(usbvc_state_t *);
211
212 /* Parse descriptors */
213 static int usbvc_chk_descr_len(uint8_t, uint8_t, uint8_t,
214 usb_cvs_data_t *);
215 static usbvc_stream_if_t *usbvc_parse_stream_if(usbvc_state_t *, int);
216 static int usbvc_parse_ctrl_if(usbvc_state_t *);
217 static int usbvc_parse_stream_ifs(usbvc_state_t *);
218 static void usbvc_parse_color_still(usbvc_state_t *,
219 usbvc_format_group_t *, usb_cvs_data_t *, uint_t, uint_t);
220 static void usbvc_parse_frames(usbvc_state_t *, usbvc_format_group_t *,
221 usb_cvs_data_t *, uint_t, uint_t);
222 static int usbvc_parse_format_group(usbvc_state_t *,
223 usbvc_format_group_t *, usb_cvs_data_t *, uint_t, uint_t);
224 static int usbvc_parse_format_groups(usbvc_state_t *, usbvc_stream_if_t *);
225 static int usbvc_parse_stream_header(usbvc_state_t *, usbvc_stream_if_t *);
226
227 /* read I/O functions */
228 static int usbvc_alloc_read_bufs(usbvc_state_t *, usbvc_stream_if_t *);
229 static int usbvc_read_buf(usbvc_state_t *, struct buf *);
230 static void usbvc_free_read_buf(usbvc_buf_t *);
231 static void usbvc_free_read_bufs(usbvc_state_t *, usbvc_stream_if_t *);
232 static void usbvc_close_isoc_pipe(usbvc_state_t *, usbvc_stream_if_t *);
233
234 /* callbacks */
235 static void usbvc_isoc_cb(usb_pipe_handle_t, usb_isoc_req_t *);
236 static void usbvc_isoc_exc_cb(usb_pipe_handle_t, usb_isoc_req_t *);
237
238 /* Others */
239 static int usbvc_set_alt(usbvc_state_t *, usbvc_stream_if_t *);
240 static int usbvc_decode_stream_header(usbvc_state_t *, usbvc_buf_grp_t *,
241 mblk_t *, int);
242 static int usbvc_serialize_access(usbvc_state_t *, boolean_t);
243 static void usbvc_release_access(usbvc_state_t *);
244 static int usbvc_set_default_stream_fmt(usbvc_state_t *);
245
246 static usb_event_t usbvc_events = {
247 usbvc_disconnect_event_cb,
248 usbvc_reconnect_event_cb,
249 NULL, NULL
250 };
251
252 /* module loading stuff */
253 struct cb_ops usbvc_cb_ops = {
254 usbvc_open, /* open */
255 usbvc_close, /* close */
256 usbvc_strategy, /* strategy */
257 nulldev, /* print */
258 nulldev, /* dump */
259 usbvc_read, /* read */
260 nodev, /* write */
261 usbvc_ioctl, /* ioctl */
262 usbvc_devmap, /* devmap */
263 nodev, /* mmap */
264 ddi_devmap_segmap, /* segmap */
265 nochpoll, /* poll */
266 ddi_prop_op, /* cb_prop_op */
267 NULL, /* streamtab */
268 D_MP | D_DEVMAP
269 };
270
271 static struct dev_ops usbvc_ops = {
272 DEVO_REV, /* devo_rev, */
273 0, /* refcnt */
274 usbvc_info, /* info */
275 nulldev, /* identify */
276 nulldev, /* probe */
277 usbvc_attach, /* attach */
278 usbvc_detach, /* detach */
279 nodev, /* reset */
280 &usbvc_cb_ops, /* driver operations */
281 NULL, /* bus operations */
282 usbvc_power, /* power */
283 ddi_quiesce_not_needed, /* quiesce */
284 };
285
286 static struct modldrv usbvc_modldrv = {
287 &mod_driverops,
288 "USB video class driver",
289 &usbvc_ops
290 };
291
292 static struct modlinkage modlinkage = {
293 MODREV_1,
294 &usbvc_modldrv,
295 NULL
296 };
297
298 /* Soft state structures */
299 #define USBVC_INITIAL_SOFT_SPACE 1
300 static void *usbvc_statep;
301
302
303 /*
304 * Module-wide initialization routine.
305 */
306 int
_init(void)307 _init(void)
308 {
309 int rval;
310
311 if ((rval = ddi_soft_state_init(&usbvc_statep,
312 sizeof (usbvc_state_t), USBVC_INITIAL_SOFT_SPACE)) != 0) {
313
314 return (rval);
315 }
316
317 if ((rval = mod_install(&modlinkage)) != 0) {
318 ddi_soft_state_fini(&usbvc_statep);
319 }
320
321 return (rval);
322 }
323
324
325 /*
326 * Module-wide tear-down routine.
327 */
328 int
_fini(void)329 _fini(void)
330 {
331 int rval;
332
333 if ((rval = mod_remove(&modlinkage)) != 0) {
334
335 return (rval);
336 }
337
338 ddi_soft_state_fini(&usbvc_statep);
339
340 return (rval);
341 }
342
343
344 int
_info(struct modinfo * modinfop)345 _info(struct modinfo *modinfop)
346 {
347 return (mod_info(&modlinkage, modinfop));
348 }
349
350
351 /*
352 * usbvc_info:
353 * Get minor number, soft state structure, etc.
354 */
355 /*ARGSUSED*/
356 static int
usbvc_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)357 usbvc_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
358 void *arg, void **result)
359 {
360 usbvc_state_t *usbvcp;
361 int error = DDI_FAILURE;
362
363 switch (infocmd) {
364 case DDI_INFO_DEVT2DEVINFO:
365 if ((usbvcp = ddi_get_soft_state(usbvc_statep,
366 getminor((dev_t)arg))) != NULL) {
367 *result = usbvcp->usbvc_dip;
368 if (*result != NULL) {
369 error = DDI_SUCCESS;
370 }
371 } else {
372 *result = NULL;
373 }
374 break;
375 case DDI_INFO_DEVT2INSTANCE:
376 *result = (void *)(uintptr_t)getminor((dev_t)arg);
377 error = DDI_SUCCESS;
378 break;
379 default:
380 break;
381 }
382
383 return (error);
384 }
385
386
387 /*
388 * Entry functions.
389 */
390
391 /*
392 * usbvc_attach:
393 * Attach or resume.
394 *
395 * For attach, initialize state and device, including:
396 * state variables, locks, device node
397 * device registration with system
398 * power management, hotplugging
399 * For resume, restore device and state
400 */
401 static int
usbvc_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)402 usbvc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
403 {
404 int instance = ddi_get_instance(dip);
405 usbvc_state_t *usbvcp = NULL;
406 int status;
407
408 switch (cmd) {
409 case DDI_ATTACH:
410
411 break;
412 case DDI_RESUME:
413 usbvc_cpr_resume(dip);
414
415 return (DDI_SUCCESS);
416 default:
417
418 return (DDI_FAILURE);
419 }
420
421 if (ddi_soft_state_zalloc(usbvc_statep, instance) == DDI_SUCCESS) {
422 usbvcp = ddi_get_soft_state(usbvc_statep, instance);
423 }
424 if (usbvcp == NULL) {
425
426 return (DDI_FAILURE);
427 }
428
429 usbvcp->usbvc_dip = dip;
430
431 usbvcp->usbvc_log_handle = usb_alloc_log_hdl(dip,
432 "usbvc", &usbvc_errlevel,
433 &usbvc_errmask, &usbvc_instance_debug, 0);
434
435 USB_DPRINTF_L3(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
436 "usbvc_attach: enter");
437
438 if ((status = usb_client_attach(dip, USBDRV_VERSION, 0)) !=
439 USB_SUCCESS) {
440 USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
441 "usbvc_attach: usb_client_attach failed, error code:%d",
442 status);
443
444 goto fail;
445 }
446
447 if ((status = usb_get_dev_data(dip, &usbvcp->usbvc_reg,
448 USB_PARSE_LVL_ALL, 0)) != USB_SUCCESS) {
449 USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
450 "usbvc_attach: usb_get_dev_data failed, error code:%d",
451 status);
452
453 goto fail;
454 }
455 usbvc_init_sync_objs(usbvcp);
456
457 /* create minor node */
458 if ((status = ddi_create_minor_node(dip, name, S_IFCHR, instance,
459 "usb_video", 0)) != DDI_SUCCESS) {
460 USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
461 "usbvc_attach: Error creating minor node, error code:%d",
462 status);
463
464 goto fail;
465 }
466
467 mutex_enter(&usbvcp->usbvc_mutex);
468 usbvc_init_lists(usbvcp);
469
470 usbvcp->usbvc_default_ph = usbvcp->usbvc_reg->dev_default_ph;
471
472 /* Put online before PM init as can get power managed afterward. */
473 usbvcp->usbvc_dev_state = USB_DEV_ONLINE;
474 mutex_exit(&usbvcp->usbvc_mutex);
475
476 /* initialize power management */
477 usbvc_init_power_mgmt(usbvcp);
478
479 if ((status = usbvc_parse_ctrl_if(usbvcp)) != USB_SUCCESS) {
480 USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
481 "usbvc_attach: parse ctrl interface fail, error code:%d",
482 status);
483
484 goto fail;
485 }
486 if ((status = usbvc_parse_stream_ifs(usbvcp)) != USB_SUCCESS) {
487 USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
488 "usbvc_attach: parse stream interfaces fail, error code:%d",
489 status);
490
491 goto fail;
492 }
493 (void) usbvc_set_default_stream_fmt(usbvcp);
494
495 /* Register for events */
496 if ((status = usb_register_event_cbs(dip, &usbvc_events, 0)) !=
497 USB_SUCCESS) {
498 USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
499 "usbvc_attach: register_event_cbs failed, error code:%d",
500 status);
501
502 goto fail;
503 }
504
505 /* Report device */
506 ddi_report_dev(dip);
507
508 return (DDI_SUCCESS);
509
510 fail:
511 if (usbvcp) {
512 usbvc_cleanup(dip, usbvcp);
513 }
514
515 return (DDI_FAILURE);
516 }
517
518
519 /*
520 * usbvc_detach:
521 * detach or suspend driver instance
522 *
523 * Note: in detach, only contention threads is from pm and disconnnect.
524 */
525 static int
usbvc_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)526 usbvc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
527 {
528 int instance = ddi_get_instance(dip);
529 usbvc_state_t *usbvcp = ddi_get_soft_state(usbvc_statep, instance);
530 int rval = USB_FAILURE;
531
532 switch (cmd) {
533 case DDI_DETACH:
534 mutex_enter(&usbvcp->usbvc_mutex);
535 ASSERT((usbvcp->usbvc_drv_state & USBVC_OPEN) == 0);
536 mutex_exit(&usbvcp->usbvc_mutex);
537
538 USB_DPRINTF_L3(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
539 "usbvc_detach: enter for detach");
540
541 usbvc_cleanup(dip, usbvcp);
542 rval = USB_SUCCESS;
543
544 break;
545 case DDI_SUSPEND:
546 USB_DPRINTF_L3(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
547 "usbvc_detach: enter for suspend");
548
549 usbvc_cpr_suspend(dip);
550 rval = USB_SUCCESS;
551
552 break;
553 default:
554
555 break;
556 }
557
558 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
559 }
560
561
562 /*
563 * usbvc_cleanup:
564 * clean up the driver state for detach
565 */
566 static void
usbvc_cleanup(dev_info_t * dip,usbvc_state_t * usbvcp)567 usbvc_cleanup(dev_info_t *dip, usbvc_state_t *usbvcp)
568 {
569 USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
570 "Cleanup: enter");
571
572 if (usbvcp->usbvc_locks_initialized) {
573
574 /* This must be done 1st to prevent more events from coming. */
575 usb_unregister_event_cbs(dip, &usbvc_events);
576
577 /*
578 * At this point, no new activity can be initiated. The driver
579 * has disabled hotplug callbacks. The Solaris framework has
580 * disabled new opens on a device being detached, and does not
581 * allow detaching an open device.
582 *
583 * The following ensures that all driver activity has drained.
584 */
585 mutex_enter(&usbvcp->usbvc_mutex);
586 (void) usbvc_serialize_access(usbvcp, USBVC_SER_NOSIG);
587 usbvc_release_access(usbvcp);
588 mutex_exit(&usbvcp->usbvc_mutex);
589
590 /* All device activity has died down. */
591 usbvc_destroy_power_mgmt(usbvcp);
592 mutex_enter(&usbvcp->usbvc_mutex);
593 usbvc_fini_lists(usbvcp);
594 mutex_exit(&usbvcp->usbvc_mutex);
595
596 ddi_remove_minor_node(dip, NULL);
597 usbvc_fini_sync_objs(usbvcp);
598 }
599
600 usb_client_detach(dip, usbvcp->usbvc_reg);
601 usb_free_log_hdl(usbvcp->usbvc_log_handle);
602 ddi_soft_state_free(usbvc_statep, ddi_get_instance(dip));
603 ddi_prop_remove_all(dip);
604 }
605
606
607 /*ARGSUSED*/
608 static int
usbvc_open(dev_t * devp,int flag,int otyp,cred_t * cred_p)609 usbvc_open(dev_t *devp, int flag, int otyp, cred_t *cred_p)
610 {
611 usbvc_state_t *usbvcp =
612 ddi_get_soft_state(usbvc_statep, getminor(*devp));
613
614 if (usbvcp == NULL) {
615
616 return (ENXIO);
617 }
618
619 /*
620 * Keep it simple: one client at a time.
621 * Exclusive open only
622 */
623 mutex_enter(&usbvcp->usbvc_mutex);
624 USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
625 "usbvc_open: enter, dev_stat=%d", usbvcp->usbvc_dev_state);
626
627 if (usbvcp->usbvc_dev_state == USB_DEV_DISCONNECTED) {
628 mutex_exit(&usbvcp->usbvc_mutex);
629
630 return (ENODEV);
631 }
632 if (usbvcp->usbvc_dev_state == USB_DEV_SUSPENDED) {
633 mutex_exit(&usbvcp->usbvc_mutex);
634
635 return (EIO);
636 }
637 if ((usbvcp->usbvc_drv_state & USBVC_OPEN) != 0) {
638 mutex_exit(&usbvcp->usbvc_mutex);
639
640 return (EBUSY);
641 }
642 usbvcp->usbvc_drv_state |= USBVC_OPEN;
643
644 if (usbvc_serialize_access(usbvcp, USBVC_SER_SIG) == 0) {
645 usbvcp->usbvc_drv_state &= ~USBVC_OPEN;
646 usbvcp->usbvc_serial_inuse = B_FALSE;
647 mutex_exit(&usbvcp->usbvc_mutex);
648
649 return (EINTR);
650 }
651
652 /* raise power */
653 usbvc_pm_busy_component(usbvcp);
654 if (usbvcp->usbvc_pm->usbvc_current_power != USB_DEV_OS_FULL_PWR) {
655 usbvcp->usbvc_pm->usbvc_raise_power = B_TRUE;
656 mutex_exit(&usbvcp->usbvc_mutex);
657 (void) pm_raise_power(usbvcp->usbvc_dip,
658 0, USB_DEV_OS_FULL_PWR);
659 mutex_enter(&usbvcp->usbvc_mutex);
660 usbvcp->usbvc_pm->usbvc_raise_power = B_FALSE;
661 }
662
663 /* Device is idle until it is used. */
664 usbvc_release_access(usbvcp);
665 mutex_exit(&usbvcp->usbvc_mutex);
666
667 USB_DPRINTF_L4(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
668 "usbvc_open: end.");
669
670 return (0);
671 }
672
673
674 /*ARGSUSED*/
675 static int
usbvc_close(dev_t dev,int flag,int otyp,cred_t * cred_p)676 usbvc_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
677 {
678 usbvc_stream_if_t *strm_if;
679 int if_num;
680 usbvc_state_t *usbvcp =
681 ddi_get_soft_state(usbvc_statep, getminor(dev));
682
683 USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
684 "close: enter");
685
686 mutex_enter(&usbvcp->usbvc_mutex);
687 (void) usbvc_serialize_access(usbvcp, USBVC_SER_NOSIG);
688 mutex_exit(&usbvcp->usbvc_mutex);
689
690 /* Perform device session cleanup here. */
691
692 USB_DPRINTF_L3(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
693 "close: cleaning up...");
694
695 /*
696 * USBA automatically flushes/resets active non-default pipes
697 * when they are closed. We can't reset default pipe, but we
698 * can wait for all requests on it from this dip to drain.
699 */
700 (void) usb_pipe_drain_reqs(usbvcp->usbvc_dip,
701 usbvcp->usbvc_reg->dev_default_ph, 0,
702 USB_FLAGS_SLEEP, NULL, 0);
703
704 mutex_enter(&usbvcp->usbvc_mutex);
705 strm_if = usbvcp->usbvc_curr_strm;
706 if (strm_if->start_polling == 1) {
707 mutex_exit(&usbvcp->usbvc_mutex);
708 usb_pipe_stop_isoc_polling(strm_if->datain_ph, USB_FLAGS_SLEEP);
709 mutex_enter(&usbvcp->usbvc_mutex);
710 strm_if->start_polling = 0;
711 }
712 strm_if->stream_on = 0;
713
714 usbvc_close_isoc_pipe(usbvcp, strm_if);
715 if_num = strm_if->if_descr->if_alt->altif_descr.bInterfaceNumber;
716 mutex_exit(&usbvcp->usbvc_mutex);
717
718 /* reset alternate to the default one. */
719 (void) usb_set_alt_if(usbvcp->usbvc_dip, if_num, 0,
720 USB_FLAGS_SLEEP, NULL, NULL);
721 mutex_enter(&usbvcp->usbvc_mutex);
722
723 usbvc_free_read_bufs(usbvcp, strm_if);
724
725 /* reset the desired read buf number to the default value on close */
726 strm_if->buf_read_num = USBVC_DEFAULT_READ_BUF_NUM;
727
728 usbvc_free_map_bufs(usbvcp, strm_if);
729 usbvcp->usbvc_drv_state &= ~USBVC_OPEN;
730
731 usbvc_release_access(usbvcp);
732 usbvc_pm_idle_component(usbvcp);
733 mutex_exit(&usbvcp->usbvc_mutex);
734
735 return (0);
736 }
737
738
739 /*ARGSUSED*/
740 /* Read isoc data from usb video devices */
741 static int
usbvc_read(dev_t dev,struct uio * uio_p,cred_t * cred_p)742 usbvc_read(dev_t dev, struct uio *uio_p, cred_t *cred_p)
743 {
744 int rval;
745 usbvc_stream_if_t *strm_if;
746 usbvc_state_t *usbvcp =
747 ddi_get_soft_state(usbvc_statep, getminor(dev));
748
749 USB_DPRINTF_L4(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
750 "usbvc_read: enter");
751 mutex_enter(&usbvcp->usbvc_mutex);
752 if (usbvcp->usbvc_dev_state != USB_DEV_ONLINE) {
753 USB_DPRINTF_L2(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
754 "usbvc_read: Device is not available,"
755 " dev_stat=%d", usbvcp->usbvc_dev_state);
756 mutex_exit(&usbvcp->usbvc_mutex);
757
758 return (EFAULT);
759 }
760 if ((uio_p->uio_fmode & (FNDELAY|FNONBLOCK)) &&
761 (usbvcp->usbvc_serial_inuse != B_FALSE)) {
762 USB_DPRINTF_L2(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
763 "usbvc_read: non-blocking read, return fail.");
764 mutex_exit(&usbvcp->usbvc_mutex);
765
766 return (EAGAIN);
767 }
768 if (usbvc_serialize_access(usbvcp, USBVC_SER_SIG) <= 0) {
769 USB_DPRINTF_L2(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
770 "usbvc_read: serialize_access failed.");
771 rval = EFAULT;
772
773 goto fail;
774 }
775
776 /* Get the first stream interface */
777 strm_if = usbvcp->usbvc_curr_strm;
778 if (!strm_if) {
779 USB_DPRINTF_L2(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
780 "usbvc_read: no stream interfaces");
781 rval = EFAULT;
782
783 goto fail;
784 }
785
786 /*
787 * If it is the first read, open isoc pipe and allocate bufs for
788 * read I/O method.
789 */
790 if (strm_if->datain_ph == NULL) {
791 if (usbvc_open_isoc_pipe(usbvcp, strm_if) != USB_SUCCESS) {
792 USB_DPRINTF_L2(PRINT_MASK_READ,
793 usbvcp->usbvc_log_handle,
794 "usbvc_read: first read, open pipe fail");
795 rval = EFAULT;
796
797 goto fail;
798 }
799 if (usbvc_alloc_read_bufs(usbvcp, strm_if) != USB_SUCCESS) {
800 USB_DPRINTF_L2(PRINT_MASK_READ,
801 usbvcp->usbvc_log_handle,
802 "usbvc_read: allocate rw bufs fail");
803 rval = EFAULT;
804
805 goto fail;
806 }
807 }
808
809 /* start polling if it is not started yet */
810 if (strm_if->start_polling != 1) {
811 if (usbvc_start_isoc_polling(usbvcp, strm_if, 0) !=
812 USB_SUCCESS) {
813 USB_DPRINTF_L2(PRINT_MASK_READ,
814 usbvcp->usbvc_log_handle,
815 "usbvc_read: usbvc_start_isoc_polling fail");
816 rval = EFAULT;
817
818 goto fail;
819 }
820 strm_if->start_polling = 1;
821 }
822
823 if (list_is_empty(&strm_if->buf_read.uv_buf_done)) {
824 USB_DPRINTF_L3(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
825 "usbvc_read: full buf list is empty.");
826
827 if (uio_p->uio_fmode & (FNDELAY | FNONBLOCK)) {
828 USB_DPRINTF_L2(PRINT_MASK_READ,
829 usbvcp->usbvc_log_handle, "usbvc_read: fail, "
830 "non-blocking read, done buf is empty.");
831 rval = EAGAIN;
832
833 goto fail;
834 }
835
836 /* no available buffers, block here */
837 while (list_is_empty(&strm_if->buf_read.uv_buf_done)) {
838 USB_DPRINTF_L3(PRINT_MASK_READ,
839 usbvcp->usbvc_log_handle,
840 "usbvc_read: wait for done buf");
841 if (cv_wait_sig(&usbvcp->usbvc_read_cv,
842 &usbvcp->usbvc_mutex) <= 0) {
843 /* no done buf and cv is signaled */
844 rval = EINTR;
845
846 goto fail;
847 }
848 if (usbvcp->usbvc_dev_state != USB_DEV_ONLINE) {
849
850 /* Device is disconnected. */
851 rval = EINTR;
852
853 goto fail;
854 }
855 }
856
857 }
858
859 mutex_exit(&usbvcp->usbvc_mutex);
860 rval = physio(usbvc_strategy, NULL, dev, B_READ,
861 usbvc_minphys, uio_p);
862
863 mutex_enter(&usbvcp->usbvc_mutex);
864 usbvc_release_access(usbvcp);
865 mutex_exit(&usbvcp->usbvc_mutex);
866
867 return (rval);
868
869 fail:
870 usbvc_release_access(usbvcp);
871 mutex_exit(&usbvcp->usbvc_mutex);
872
873 return (rval);
874 }
875
876
877 /*
878 * strategy:
879 * Called through physio to setup and start the transfer.
880 */
881 static int
usbvc_strategy(struct buf * bp)882 usbvc_strategy(struct buf *bp)
883 {
884 usbvc_state_t *usbvcp = ddi_get_soft_state(usbvc_statep,
885 getminor(bp->b_edev));
886
887 USB_DPRINTF_L4(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
888 "usbvc_strategy: enter");
889
890 /*
891 * Initialize residual count here in case transfer doesn't even get
892 * started.
893 */
894 bp->b_resid = bp->b_bcount;
895
896 /* Needed as this is a character driver. */
897 if (bp->b_flags & (B_PHYS | B_PAGEIO)) {
898 bp_mapin(bp);
899 }
900
901 mutex_enter(&usbvcp->usbvc_mutex);
902
903 /* Make sure device has not been disconnected. */
904 if (usbvcp->usbvc_dev_state != USB_DEV_ONLINE) {
905 USB_DPRINTF_L2(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
906 "usbvc_strategy: device can't be accessed");
907 mutex_exit(&usbvcp->usbvc_mutex);
908
909 goto fail;
910 }
911
912 /* read data from uv_buf_done list */
913 if (usbvc_read_buf(usbvcp, bp) != USB_SUCCESS) {
914 USB_DPRINTF_L2(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
915 "usbvc_strategy: read full buf list fail");
916 mutex_exit(&usbvcp->usbvc_mutex);
917
918 goto fail;
919 }
920
921 mutex_exit(&usbvcp->usbvc_mutex);
922
923 biodone(bp);
924
925 return (0);
926
927 fail:
928 USB_DPRINTF_L2(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
929 "usbvc_strategy: strategy fail");
930 bp->b_private = NULL;
931
932 bioerror(bp, EIO);
933 biodone(bp);
934
935 return (0);
936 }
937
938
939 static void
usbvc_minphys(struct buf * bp)940 usbvc_minphys(struct buf *bp)
941 {
942 dev_t dev = bp->b_edev;
943 usbvc_stream_if_t *strm_if;
944 uint32_t maxsize;
945 usbvc_state_t *usbvcp =
946 ddi_get_soft_state(usbvc_statep, getminor(dev));
947
948 mutex_enter(&usbvcp->usbvc_mutex);
949 strm_if = usbvcp->usbvc_curr_strm;
950 LE_TO_UINT32(strm_if->ctrl_pc.dwMaxVideoFrameSize, 0, maxsize);
951 USB_DPRINTF_L3(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
952 "usbvc_minphys: max read size=%d", maxsize);
953
954 if (bp->b_bcount > maxsize) {
955 bp->b_bcount = maxsize;
956 }
957 mutex_exit(&usbvcp->usbvc_mutex);
958 }
959
960
961 /*
962 * ioctl entry.
963 */
964 /*ARGSUSED*/
965 static int
usbvc_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * cred_p,int * rval_p)966 usbvc_ioctl(dev_t dev, int cmd, intptr_t arg,
967 int mode, cred_t *cred_p, int *rval_p)
968 {
969 int rv = 0;
970 usbvc_state_t *usbvcp =
971 ddi_get_soft_state(usbvc_statep, getminor(dev));
972
973 if (usbvcp == NULL) {
974
975 return (ENXIO);
976 }
977 USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
978 "ioctl enter, cmd=%x", cmd);
979 mutex_enter(&usbvcp->usbvc_mutex);
980 if (usbvcp->usbvc_dev_state != USB_DEV_ONLINE) {
981 USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
982 "ioctl: Device is not online,"
983 " dev_stat=%d", usbvcp->usbvc_dev_state);
984 mutex_exit(&usbvcp->usbvc_mutex);
985
986 return (EFAULT);
987 }
988 if (usbvc_serialize_access(usbvcp, USBVC_SER_SIG) <= 0) {
989 usbvcp->usbvc_serial_inuse = B_FALSE;
990 mutex_exit(&usbvcp->usbvc_mutex);
991 USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
992 "serialize_access failed.");
993
994 return (EFAULT);
995 }
996 mutex_exit(&usbvcp->usbvc_mutex);
997
998 rv = usbvc_v4l2_ioctl(usbvcp, cmd, arg, mode);
999
1000 mutex_enter(&usbvcp->usbvc_mutex);
1001 usbvc_release_access(usbvcp);
1002 mutex_exit(&usbvcp->usbvc_mutex);
1003
1004 USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1005 "usbvc_ioctl exit");
1006
1007 return (rv);
1008 }
1009
1010
1011 /* Entry for mmap system call */
1012 static int
usbvc_devmap(dev_t dev,devmap_cookie_t handle,offset_t off,size_t len,size_t * maplen,uint_t model)1013 usbvc_devmap(dev_t dev, devmap_cookie_t handle, offset_t off,
1014 size_t len, size_t *maplen, uint_t model)
1015 {
1016 usbvc_state_t *usbvcp;
1017 int error, i;
1018 usbvc_buf_t *buf = NULL;
1019 usbvc_stream_if_t *strm_if;
1020 usbvc_buf_grp_t *bufgrp;
1021
1022 usbvcp = ddi_get_soft_state(usbvc_statep, getminor(dev));
1023 if (usbvcp == NULL) {
1024 USB_DPRINTF_L2(PRINT_MASK_DEVMAP, usbvcp->usbvc_log_handle,
1025 "usbvc_devmap: usbvcp == NULL");
1026
1027 return (ENXIO);
1028 }
1029
1030 USB_DPRINTF_L3(PRINT_MASK_DEVMAP, usbvcp->usbvc_log_handle,
1031 "devmap: memory map for instance(%d), off=%llx,"
1032 "len=%ld, maplen=%ld, model=%d", getminor(dev), off,
1033 len, *maplen, model);
1034
1035 mutex_enter(&usbvcp->usbvc_mutex);
1036 (void) usbvc_serialize_access(usbvcp, USBVC_SER_NOSIG);
1037 strm_if = usbvcp->usbvc_curr_strm;
1038 if (!strm_if) {
1039 USB_DPRINTF_L2(PRINT_MASK_DEVMAP, usbvcp->usbvc_log_handle,
1040 "usbvc_devmap: No current strm if");
1041 mutex_exit(&usbvcp->usbvc_mutex);
1042
1043 return (ENXIO);
1044 }
1045 bufgrp = &strm_if->buf_map;
1046 for (i = 0; i < bufgrp->buf_cnt; i++) {
1047 if (bufgrp->buf_head[i].v4l2_buf.m.offset == off) {
1048 buf = &bufgrp->buf_head[i];
1049
1050 break;
1051 }
1052 }
1053 USB_DPRINTF_L3(PRINT_MASK_DEVMAP, usbvcp->usbvc_log_handle,
1054 "usbvc_devmap: idx=%d", i);
1055 if (buf == NULL) {
1056 mutex_exit(&usbvcp->usbvc_mutex);
1057
1058 return (ENXIO);
1059 }
1060 /*
1061 * round up len to a multiple of a page size, according to chapter
1062 * 10 of "writing device drivers"
1063 */
1064 len = ptob(btopr(len));
1065 if (len > ptob(btopr(buf->len))) {
1066 USB_DPRINTF_L2(PRINT_MASK_DEVMAP, usbvcp->usbvc_log_handle,
1067 "usbvc_devmap: len=0x%lx", len);
1068 mutex_exit(&usbvcp->usbvc_mutex);
1069
1070 return (ENXIO);
1071 }
1072 mutex_exit(&usbvcp->usbvc_mutex);
1073
1074 error = devmap_umem_setup(handle, usbvcp->usbvc_dip, NULL,
1075 buf->umem_cookie, off, len, PROT_ALL, DEVMAP_DEFAULTS, NULL);
1076 mutex_enter(&usbvcp->usbvc_mutex);
1077 *maplen = len;
1078 if (error == 0 && buf->status == USBVC_BUF_INIT) {
1079 buf->status = USBVC_BUF_MAPPED;
1080 } else {
1081 USB_DPRINTF_L3(PRINT_MASK_DEVMAP, usbvcp->usbvc_log_handle,
1082 "usbvc_devmap: devmap_umem_setup, err=%d", error);
1083 }
1084
1085 (void) usbvc_release_access(usbvcp);
1086 mutex_exit(&usbvcp->usbvc_mutex);
1087
1088 return (error);
1089 }
1090
1091 /*
1092 * pm and cpr
1093 */
1094
1095 /*
1096 * usbvc_power :
1097 * Power entry point, the workhorse behind pm_raise_power, pm_lower_power,
1098 * usb_req_raise_power and usb_req_lower_power.
1099 */
1100 /* ARGSUSED */
1101 static int
usbvc_power(dev_info_t * dip,int comp,int level)1102 usbvc_power(dev_info_t *dip, int comp, int level)
1103 {
1104 usbvc_state_t *usbvcp;
1105 usbvc_power_t *pm;
1106 int rval = USB_FAILURE;
1107
1108 usbvcp = ddi_get_soft_state(usbvc_statep, ddi_get_instance(dip));
1109 mutex_enter(&usbvcp->usbvc_mutex);
1110 USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1111 "usbvc_power: enter: level = %d, dev_state: %x",
1112 level, usbvcp->usbvc_dev_state);
1113
1114 if (usbvcp->usbvc_pm == NULL) {
1115
1116 goto done;
1117 }
1118
1119 pm = usbvcp->usbvc_pm;
1120
1121 /* Check if we are transitioning to a legal power level */
1122 if (USB_DEV_PWRSTATE_OK(pm->usbvc_pwr_states, level)) {
1123 USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
1124 "usbvc_power: illegal power level = %d "
1125 "pwr_states: %x", level, pm->usbvc_pwr_states);
1126
1127 goto done;
1128 }
1129 /*
1130 * if we are about to raise power and asked to lower power, fail
1131 */
1132 if (pm->usbvc_raise_power && (level < (int)pm->usbvc_current_power)) {
1133
1134 goto done;
1135 }
1136 switch (level) {
1137 case USB_DEV_OS_PWR_OFF :
1138 rval = usbvc_pwrlvl0(usbvcp);
1139
1140 break;
1141 case USB_DEV_OS_PWR_1 :
1142 rval = usbvc_pwrlvl1(usbvcp);
1143
1144 break;
1145 case USB_DEV_OS_PWR_2 :
1146 rval = usbvc_pwrlvl2(usbvcp);
1147
1148 break;
1149 case USB_DEV_OS_FULL_PWR :
1150 rval = usbvc_pwrlvl3(usbvcp);
1151
1152 break;
1153 }
1154
1155 done:
1156 mutex_exit(&usbvcp->usbvc_mutex);
1157
1158 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
1159 }
1160
1161
1162 /*
1163 * usbvc_init_power_mgmt:
1164 * Initialize power management and remote wakeup functionality.
1165 * No mutex is necessary in this function as it's called only by attach.
1166 */
1167 static void
usbvc_init_power_mgmt(usbvc_state_t * usbvcp)1168 usbvc_init_power_mgmt(usbvc_state_t *usbvcp)
1169 {
1170 usbvc_power_t *usbvcpm;
1171 uint_t pwr_states;
1172
1173 USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1174 "init_power_mgmt enter");
1175
1176 /* Allocate the state structure */
1177 usbvcpm = kmem_zalloc(sizeof (usbvc_power_t), KM_SLEEP);
1178 mutex_enter(&usbvcp->usbvc_mutex);
1179 usbvcp->usbvc_pm = usbvcpm;
1180 usbvcpm->usbvc_state = usbvcp;
1181 usbvcpm->usbvc_pm_capabilities = 0;
1182 usbvcpm->usbvc_current_power = USB_DEV_OS_FULL_PWR;
1183 mutex_exit(&usbvcp->usbvc_mutex);
1184
1185 if (usb_create_pm_components(usbvcp->usbvc_dip, &pwr_states) ==
1186 USB_SUCCESS) {
1187 USB_DPRINTF_L2(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1188 "usbvc_init_power_mgmt: created PM components");
1189
1190 if (usb_handle_remote_wakeup(usbvcp->usbvc_dip,
1191 USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) {
1192 usbvcpm->usbvc_wakeup_enabled = 1;
1193 } else {
1194 USB_DPRINTF_L2(PRINT_MASK_ATTA,
1195 usbvcp->usbvc_log_handle, "usbvc_init_power_mgmt:"
1196 " remote wakeup not supported");
1197 }
1198
1199 mutex_enter(&usbvcp->usbvc_mutex);
1200 usbvcpm->usbvc_pwr_states = (uint8_t)pwr_states;
1201 usbvc_pm_busy_component(usbvcp);
1202 usbvcpm->usbvc_raise_power = B_TRUE;
1203 mutex_exit(&usbvcp->usbvc_mutex);
1204
1205 (void) pm_raise_power(
1206 usbvcp->usbvc_dip, 0, USB_DEV_OS_FULL_PWR);
1207
1208 mutex_enter(&usbvcp->usbvc_mutex);
1209 usbvcpm->usbvc_raise_power = B_FALSE;
1210 usbvc_pm_idle_component(usbvcp);
1211 mutex_exit(&usbvcp->usbvc_mutex);
1212
1213 }
1214 USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1215 "usbvc_init_power_mgmt: end");
1216 }
1217
1218
1219 /*
1220 * usbvc_destroy_power_mgmt:
1221 * Shut down and destroy power management and remote wakeup functionality.
1222 */
1223 static void
usbvc_destroy_power_mgmt(usbvc_state_t * usbvcp)1224 usbvc_destroy_power_mgmt(usbvc_state_t *usbvcp)
1225 {
1226 usbvc_power_t *pm;
1227 int rval;
1228
1229 USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1230 "destroy_power_mgmt enter");
1231 mutex_enter(&usbvcp->usbvc_mutex);
1232 pm = usbvcp->usbvc_pm;
1233 if (pm && (usbvcp->usbvc_dev_state != USB_DEV_DISCONNECTED)) {
1234
1235 usbvc_pm_busy_component(usbvcp);
1236 if (pm->usbvc_wakeup_enabled) {
1237 pm->usbvc_raise_power = B_TRUE;
1238 mutex_exit(&usbvcp->usbvc_mutex);
1239
1240 /* First bring the device to full power */
1241 (void) pm_raise_power(usbvcp->usbvc_dip, 0,
1242 USB_DEV_OS_FULL_PWR);
1243 if ((rval = usb_handle_remote_wakeup(
1244 usbvcp->usbvc_dip,
1245 USB_REMOTE_WAKEUP_DISABLE)) !=
1246 USB_SUCCESS) {
1247 USB_DPRINTF_L2(PRINT_MASK_ATTA,
1248 usbvcp->usbvc_log_handle,
1249 "usbvc_destroy_power_mgmt: "
1250 "Error disabling rmt wakeup: rval = %d",
1251 rval);
1252 }
1253 mutex_enter(&usbvcp->usbvc_mutex);
1254 pm->usbvc_raise_power = B_FALSE;
1255
1256 }
1257 mutex_exit(&usbvcp->usbvc_mutex);
1258
1259 /*
1260 * Since remote wakeup is disabled now,
1261 * no one can raise power
1262 * and get to device once power is lowered here.
1263 */
1264 (void) pm_lower_power(usbvcp->usbvc_dip, 0, USB_DEV_OS_PWR_OFF);
1265 mutex_enter(&usbvcp->usbvc_mutex);
1266 usbvc_pm_idle_component(usbvcp);
1267 }
1268
1269 if (pm) {
1270 kmem_free(pm, sizeof (usbvc_power_t));
1271 usbvcp->usbvc_pm = NULL;
1272 }
1273 mutex_exit(&usbvcp->usbvc_mutex);
1274 }
1275
1276
1277 static void
usbvc_pm_busy_component(usbvc_state_t * usbvcp)1278 usbvc_pm_busy_component(usbvc_state_t *usbvcp)
1279 {
1280 ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
1281 USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1282 "usbvc_pm_busy_component: enter");
1283
1284 usbvcp->usbvc_pm->usbvc_pm_busy++;
1285 mutex_exit(&usbvcp->usbvc_mutex);
1286
1287 if (pm_busy_component(usbvcp->usbvc_dip, 0) !=
1288 DDI_SUCCESS) {
1289 mutex_enter(&usbvcp->usbvc_mutex);
1290 USB_DPRINTF_L2(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1291 "usbvc_pm_busy_component: pm busy fail, usbvc_pm_busy=%d",
1292 usbvcp->usbvc_pm->usbvc_pm_busy);
1293
1294 usbvcp->usbvc_pm->usbvc_pm_busy--;
1295 mutex_exit(&usbvcp->usbvc_mutex);
1296 }
1297 mutex_enter(&usbvcp->usbvc_mutex);
1298 USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1299 "usbvc_pm_busy_component: exit");
1300 }
1301
1302
1303 static void
usbvc_pm_idle_component(usbvc_state_t * usbvcp)1304 usbvc_pm_idle_component(usbvc_state_t *usbvcp)
1305 {
1306 ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
1307 USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1308 "usbvc_pm_idle_component: enter");
1309
1310 if (usbvcp->usbvc_pm != NULL) {
1311 mutex_exit(&usbvcp->usbvc_mutex);
1312 if (pm_idle_component(usbvcp->usbvc_dip, 0) ==
1313 DDI_SUCCESS) {
1314 mutex_enter(&usbvcp->usbvc_mutex);
1315 ASSERT(usbvcp->usbvc_pm->usbvc_pm_busy > 0);
1316 usbvcp->usbvc_pm->usbvc_pm_busy--;
1317 mutex_exit(&usbvcp->usbvc_mutex);
1318 }
1319 mutex_enter(&usbvcp->usbvc_mutex);
1320 USB_DPRINTF_L2(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1321 "usbvc_pm_idle_component: %d",
1322 usbvcp->usbvc_pm->usbvc_pm_busy);
1323 }
1324 }
1325
1326
1327 /*
1328 * usbvc_pwrlvl0:
1329 * Functions to handle power transition for OS levels 0 -> 3
1330 */
1331 static int
usbvc_pwrlvl0(usbvc_state_t * usbvcp)1332 usbvc_pwrlvl0(usbvc_state_t *usbvcp)
1333 {
1334 int rval;
1335
1336 USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1337 "usbvc_pwrlvl0, dev_state: %x", usbvcp->usbvc_dev_state);
1338
1339 switch (usbvcp->usbvc_dev_state) {
1340 case USB_DEV_ONLINE:
1341 /* Deny the powerdown request if the device is busy */
1342 if (usbvcp->usbvc_pm->usbvc_pm_busy != 0) {
1343 USB_DPRINTF_L2(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1344 "usbvc_pwrlvl0: usbvc_pm_busy");
1345
1346 return (USB_FAILURE);
1347 }
1348
1349 /* Issue USB D3 command to the device here */
1350 rval = usb_set_device_pwrlvl3(usbvcp->usbvc_dip);
1351 ASSERT(rval == USB_SUCCESS);
1352
1353 usbvcp->usbvc_dev_state = USB_DEV_PWRED_DOWN;
1354 usbvcp->usbvc_pm->usbvc_current_power = USB_DEV_OS_PWR_OFF;
1355
1356 /* FALLTHRU */
1357 case USB_DEV_DISCONNECTED:
1358 case USB_DEV_SUSPENDED:
1359 /* allow a disconnect/cpr'ed device to go to lower power */
1360
1361 return (USB_SUCCESS);
1362 case USB_DEV_PWRED_DOWN:
1363 default:
1364 USB_DPRINTF_L2(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1365 "usbvc_pwrlvl0: illegal dev state");
1366
1367 return (USB_FAILURE);
1368 }
1369 }
1370
1371
1372 /*
1373 * usbvc_pwrlvl1:
1374 * Functions to handle power transition to OS levels -> 2
1375 */
1376 static int
usbvc_pwrlvl1(usbvc_state_t * usbvcp)1377 usbvc_pwrlvl1(usbvc_state_t *usbvcp)
1378 {
1379 int rval;
1380
1381 USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1382 "usbvc_pwrlvl1");
1383
1384 /* Issue USB D2 command to the device here */
1385 rval = usb_set_device_pwrlvl2(usbvcp->usbvc_dip);
1386 ASSERT(rval == USB_SUCCESS);
1387
1388 return (USB_FAILURE);
1389 }
1390
1391
1392 /*
1393 * usbvc_pwrlvl2:
1394 * Functions to handle power transition to OS levels -> 1
1395 */
1396 static int
usbvc_pwrlvl2(usbvc_state_t * usbvcp)1397 usbvc_pwrlvl2(usbvc_state_t *usbvcp)
1398 {
1399 int rval;
1400
1401 USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1402 "usbvc_pwrlvl2");
1403
1404 /* Issue USB D1 command to the device here */
1405 rval = usb_set_device_pwrlvl1(usbvcp->usbvc_dip);
1406 ASSERT(rval == USB_SUCCESS);
1407
1408 return (USB_FAILURE);
1409 }
1410
1411
1412 /*
1413 * usbvc_pwrlvl3:
1414 * Functions to handle power transition to OS level -> 0
1415 */
1416 static int
usbvc_pwrlvl3(usbvc_state_t * usbvcp)1417 usbvc_pwrlvl3(usbvc_state_t *usbvcp)
1418 {
1419 USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1420 "usbvc_pwrlvl3, dev_stat=%d", usbvcp->usbvc_dev_state);
1421
1422 switch (usbvcp->usbvc_dev_state) {
1423 case USB_DEV_PWRED_DOWN:
1424 /* Issue USB D0 command to the device here */
1425 (void) usb_set_device_pwrlvl0(usbvcp->usbvc_dip);
1426
1427 usbvcp->usbvc_dev_state = USB_DEV_ONLINE;
1428 usbvcp->usbvc_pm->usbvc_current_power =
1429 USB_DEV_OS_FULL_PWR;
1430
1431 /* FALLTHRU */
1432 case USB_DEV_ONLINE:
1433 /* we are already in full power */
1434 /* FALLTHRU */
1435 case USB_DEV_DISCONNECTED:
1436 case USB_DEV_SUSPENDED:
1437 /*
1438 * PM framework tries to put us in full power
1439 * during system shutdown. If we are disconnected/cpr'ed
1440 * return success anyways
1441 */
1442
1443 return (USB_SUCCESS);
1444 default:
1445 USB_DPRINTF_L2(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1446 "usbvc_pwrlvl3: illegal dev state");
1447
1448 return (USB_FAILURE);
1449 }
1450 }
1451
1452
1453 /*
1454 * usbvc_cpr_suspend:
1455 * Clean up device.
1456 * Wait for any IO to finish, then close pipes.
1457 * Quiesce device.
1458 */
1459 static void
usbvc_cpr_suspend(dev_info_t * dip)1460 usbvc_cpr_suspend(dev_info_t *dip)
1461 {
1462 int instance = ddi_get_instance(dip);
1463 usbvc_state_t *usbvcp = ddi_get_soft_state(usbvc_statep, instance);
1464
1465 USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1466 "usbvc_cpr_suspend enter");
1467
1468 mutex_enter(&usbvcp->usbvc_mutex);
1469
1470 /*
1471 * Set dev_state to suspended so other driver threads don't start any
1472 * new I/O.
1473 */
1474 usbvcp->usbvc_dev_state = USB_DEV_SUSPENDED;
1475
1476 mutex_exit(&usbvcp->usbvc_mutex);
1477
1478 USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
1479 "usbvc_cpr_suspend: return");
1480 }
1481
1482
1483 /*
1484 * If the polling has been stopped due to some exceptional errors,
1485 * we reconfigure the device and start polling again. Only for S/R
1486 * resume or hotplug reconnect operations.
1487 */
1488 static int
usbvc_resume_operation(usbvc_state_t * usbvcp)1489 usbvc_resume_operation(usbvc_state_t *usbvcp)
1490 {
1491 usbvc_stream_if_t *strm_if;
1492 int rv = USB_SUCCESS;
1493
1494 USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1495 "usbvc_resume_operation: enter");
1496
1497 mutex_enter(&usbvcp->usbvc_mutex);
1498 strm_if = usbvcp->usbvc_curr_strm;
1499 if (!strm_if) {
1500 mutex_exit(&usbvcp->usbvc_mutex);
1501 rv = USB_FAILURE;
1502
1503 return (rv);
1504 }
1505
1506 /*
1507 * 1) if application has not started STREAMON ioctl yet,
1508 * just return
1509 * 2) if application use READ mode, return immediately
1510 */
1511 if (strm_if->stream_on == 0) {
1512 mutex_exit(&usbvcp->usbvc_mutex);
1513
1514 return (rv);
1515 }
1516
1517 /* isoc pipe is expected to be opened already if (stream_on==1) */
1518 if (!strm_if->datain_ph) {
1519 mutex_exit(&usbvcp->usbvc_mutex);
1520 rv = USB_FAILURE;
1521
1522 return (rv);
1523 }
1524
1525 mutex_exit(&usbvcp->usbvc_mutex);
1526
1527 /* first commit the parameters negotiated and saved during S_FMT */
1528 if ((rv = usbvc_vs_set_probe_commit(usbvcp, strm_if,
1529 &strm_if->ctrl_pc, VS_COMMIT_CONTROL)) != USB_SUCCESS) {
1530 USB_DPRINTF_L2(PRINT_MASK_IOCTL,
1531 usbvcp->usbvc_log_handle,
1532 "usbvc_resume_operation: set probe failed, rv=%d", rv);
1533
1534 return (rv);
1535 }
1536
1537 mutex_enter(&usbvcp->usbvc_mutex);
1538
1539 /* Set alt interfaces, must be after probe_commit according to spec */
1540 if ((rv = usbvc_set_alt(usbvcp, strm_if)) != USB_SUCCESS) {
1541 USB_DPRINTF_L2(PRINT_MASK_IOCTL,
1542 usbvcp->usbvc_log_handle,
1543 "usbvc_resume_operation: set alt failed");
1544 mutex_exit(&usbvcp->usbvc_mutex);
1545
1546 return (rv);
1547 }
1548
1549 /*
1550 * The isoc polling could be stopped by isoc_exc_cb
1551 * during suspend or hotplug. Restart it.
1552 */
1553 if (usbvc_start_isoc_polling(usbvcp, strm_if, V4L2_MEMORY_MMAP)
1554 != USB_SUCCESS) {
1555 rv = USB_FAILURE;
1556 mutex_exit(&usbvcp->usbvc_mutex);
1557
1558 return (rv);
1559 }
1560
1561 strm_if->start_polling = 1;
1562
1563 mutex_exit(&usbvcp->usbvc_mutex);
1564
1565 return (rv);
1566 }
1567
1568 /*
1569 * usbvc_cpr_resume:
1570 *
1571 * usbvc_restore_device_state marks success by putting device back online
1572 */
1573 static void
usbvc_cpr_resume(dev_info_t * dip)1574 usbvc_cpr_resume(dev_info_t *dip)
1575 {
1576 int instance = ddi_get_instance(dip);
1577 usbvc_state_t *usbvcp = ddi_get_soft_state(usbvc_statep, instance);
1578
1579 USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
1580 "resume: enter");
1581
1582 /*
1583 * NOTE: A pm_raise_power in usbvc_restore_device_state will bring
1584 * the power-up state of device into synch with the system.
1585 */
1586 mutex_enter(&usbvcp->usbvc_mutex);
1587 usbvc_restore_device_state(dip, usbvcp);
1588 mutex_exit(&usbvcp->usbvc_mutex);
1589 }
1590
1591
1592 /*
1593 * usbvc_restore_device_state:
1594 * Called during hotplug-reconnect and resume.
1595 * reenable power management
1596 * Verify the device is the same as before the disconnect/suspend.
1597 * Restore device state
1598 * Thaw any IO which was frozen.
1599 * Quiesce device. (Other routines will activate if thawed IO.)
1600 * Set device online.
1601 * Leave device disconnected if there are problems.
1602 */
1603 static void
usbvc_restore_device_state(dev_info_t * dip,usbvc_state_t * usbvcp)1604 usbvc_restore_device_state(dev_info_t *dip, usbvc_state_t *usbvcp)
1605 {
1606 USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1607 "usbvc_restore_device_state: enter");
1608
1609 ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
1610
1611 ASSERT((usbvcp->usbvc_dev_state == USB_DEV_DISCONNECTED) ||
1612 (usbvcp->usbvc_dev_state == USB_DEV_SUSPENDED));
1613
1614 usbvc_pm_busy_component(usbvcp);
1615 usbvcp->usbvc_pm->usbvc_raise_power = B_TRUE;
1616 mutex_exit(&usbvcp->usbvc_mutex);
1617 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
1618
1619 /* Check if we are talking to the same device */
1620 if (usb_check_same_device(dip, usbvcp->usbvc_log_handle,
1621 USB_LOG_L0, PRINT_MASK_ALL,
1622 USB_CHK_BASIC|USB_CHK_CFG, NULL) != USB_SUCCESS) {
1623
1624 goto fail;
1625 }
1626
1627 mutex_enter(&usbvcp->usbvc_mutex);
1628 usbvcp->usbvc_pm->usbvc_raise_power = B_FALSE;
1629 usbvcp->usbvc_dev_state = USB_DEV_ONLINE;
1630 mutex_exit(&usbvcp->usbvc_mutex);
1631
1632 if (usbvcp->usbvc_pm->usbvc_wakeup_enabled) {
1633
1634 /* Failure here means device disappeared again. */
1635 if (usb_handle_remote_wakeup(dip, USB_REMOTE_WAKEUP_ENABLE) !=
1636 USB_SUCCESS) {
1637 USB_DPRINTF_L2(PRINT_MASK_ATTA,
1638 usbvcp->usbvc_log_handle,
1639 "device may or may not be accessible. "
1640 "Please verify reconnection");
1641 }
1642 }
1643
1644 if (usbvc_resume_operation(usbvcp) != USB_SUCCESS) {
1645 USB_DPRINTF_L2(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1646 "usbvc_restore_device_state: can't resume operation");
1647
1648 goto fail;
1649 }
1650
1651 mutex_enter(&usbvcp->usbvc_mutex);
1652
1653 usbvc_pm_idle_component(usbvcp);
1654
1655 USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1656 "usbvc_restore_device_state: end");
1657
1658 return;
1659
1660 fail:
1661 /* change the device state from suspended to disconnected */
1662 mutex_enter(&usbvcp->usbvc_mutex);
1663 usbvcp->usbvc_dev_state = USB_DEV_DISCONNECTED;
1664 usbvc_pm_idle_component(usbvcp);
1665 }
1666
1667
1668 /* Events */
1669
1670 /*
1671 * usbvc_disconnect_event_cb:
1672 * Called when device hotplug-removed.
1673 * Close pipes. (This does not attempt to contact device.)
1674 * Set state to DISCONNECTED
1675 */
1676 static int
usbvc_disconnect_event_cb(dev_info_t * dip)1677 usbvc_disconnect_event_cb(dev_info_t *dip)
1678 {
1679 int instance = ddi_get_instance(dip);
1680 usbvc_state_t *usbvcp = ddi_get_soft_state(usbvc_statep, instance);
1681
1682 USB_DPRINTF_L4(PRINT_MASK_HOTPLUG, usbvcp->usbvc_log_handle,
1683 "disconnect: enter");
1684
1685 mutex_enter(&usbvcp->usbvc_mutex);
1686 /*
1687 * Save any state of device or IO in progress required by
1688 * usbvc_restore_device_state for proper device "thawing" later.
1689 */
1690 usbvcp->usbvc_dev_state = USB_DEV_DISCONNECTED;
1691
1692 /*
1693 * wake up the read threads in case there are any threads are blocking,
1694 * after being waked up, those threads will quit fail immediately since
1695 * we have changed the dev_stat.
1696 */
1697 if (usbvcp->usbvc_io_type == V4L2_MEMORY_MMAP) {
1698 cv_broadcast(&usbvcp->usbvc_mapio_cv);
1699 } else {
1700 cv_broadcast(&usbvcp->usbvc_read_cv);
1701 }
1702 /* Wait for the other threads to quit */
1703 (void) usbvc_serialize_access(usbvcp, USBVC_SER_SIG);
1704 usbvc_release_access(usbvcp);
1705 mutex_exit(&usbvcp->usbvc_mutex);
1706
1707 return (USB_SUCCESS);
1708 }
1709
1710
1711 /*
1712 * usbvc_reconnect_event_cb:
1713 * Called with device hotplug-inserted
1714 * Restore state
1715 */
1716 static int
usbvc_reconnect_event_cb(dev_info_t * dip)1717 usbvc_reconnect_event_cb(dev_info_t *dip)
1718 {
1719 int instance = ddi_get_instance(dip);
1720 usbvc_state_t *usbvcp = ddi_get_soft_state(usbvc_statep, instance);
1721
1722 USB_DPRINTF_L4(PRINT_MASK_HOTPLUG, usbvcp->usbvc_log_handle,
1723 "reconnect: enter");
1724
1725 mutex_enter(&usbvcp->usbvc_mutex);
1726 (void) usbvc_serialize_access(usbvcp, USBVC_SER_SIG);
1727 usbvc_restore_device_state(dip, usbvcp);
1728 usbvc_release_access(usbvcp);
1729 mutex_exit(&usbvcp->usbvc_mutex);
1730
1731 return (USB_SUCCESS);
1732 }
1733
1734 /* Sync objs and lists */
1735
1736 /*
1737 * init/fini sync objects during attach
1738 */
1739 static void
usbvc_init_sync_objs(usbvc_state_t * usbvcp)1740 usbvc_init_sync_objs(usbvc_state_t *usbvcp)
1741 {
1742 mutex_init(&usbvcp->usbvc_mutex, NULL, MUTEX_DRIVER,
1743 usbvcp->usbvc_reg->dev_iblock_cookie);
1744
1745 cv_init(&usbvcp->usbvc_serial_cv, NULL, CV_DRIVER, NULL);
1746 cv_init(&usbvcp->usbvc_read_cv, NULL, CV_DRIVER, NULL);
1747 cv_init(&usbvcp->usbvc_mapio_cv, NULL, CV_DRIVER, NULL);
1748
1749 usbvcp->usbvc_serial_inuse = B_FALSE;
1750
1751 usbvcp->usbvc_locks_initialized = B_TRUE;
1752 }
1753
1754
1755 static void
usbvc_fini_sync_objs(usbvc_state_t * usbvcp)1756 usbvc_fini_sync_objs(usbvc_state_t *usbvcp)
1757 {
1758 cv_destroy(&usbvcp->usbvc_serial_cv);
1759 cv_destroy(&usbvcp->usbvc_read_cv);
1760 cv_destroy(&usbvcp->usbvc_mapio_cv);
1761
1762 mutex_destroy(&usbvcp->usbvc_mutex);
1763 }
1764
1765
1766 static void
usbvc_init_lists(usbvc_state_t * usbvcp)1767 usbvc_init_lists(usbvc_state_t *usbvcp)
1768 {
1769 /* video terminals */
1770 list_create(&(usbvcp->usbvc_term_list), sizeof (usbvc_terms_t),
1771 offsetof(usbvc_terms_t, term_node));
1772
1773 /* video units */
1774 list_create(&(usbvcp->usbvc_unit_list), sizeof (usbvc_units_t),
1775 offsetof(usbvc_units_t, unit_node));
1776
1777 /* stream interfaces */
1778 list_create(&(usbvcp->usbvc_stream_list), sizeof (usbvc_stream_if_t),
1779 offsetof(usbvc_stream_if_t, stream_if_node));
1780 }
1781
1782
1783 /*
1784 * Free all the data structures allocated when parsing descriptors of ctrl
1785 * and stream interfaces. It is safe to call this function because it always
1786 * checks the pointer before free mem.
1787 */
1788 static void
usbvc_fini_lists(usbvc_state_t * usbvcp)1789 usbvc_fini_lists(usbvc_state_t *usbvcp)
1790 {
1791 USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
1792 "usbvc_fini_lists: enter");
1793
1794 usbvc_free_ctrl_descr(usbvcp);
1795
1796 /* Free all video stream structure and the sub-structures */
1797 usbvc_free_stream_descr(usbvcp);
1798
1799 USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
1800 "usbvc_fini_lists: end");
1801 }
1802
1803
1804 /*
1805 * Free all the data structures allocated when parsing descriptors of ctrl
1806 * interface.
1807 */
1808 static void
usbvc_free_ctrl_descr(usbvc_state_t * usbvcp)1809 usbvc_free_ctrl_descr(usbvc_state_t *usbvcp)
1810 {
1811 usbvc_terms_t *term;
1812 usbvc_units_t *unit;
1813
1814 USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
1815 "usbvc_free_ctrl_descr: enter");
1816
1817 if (usbvcp->usbvc_vc_header) {
1818 kmem_free(usbvcp->usbvc_vc_header, sizeof (usbvc_vc_header_t));
1819 }
1820
1821 /* Free all video terminal structure */
1822 while (!list_is_empty(&usbvcp->usbvc_term_list)) {
1823 term = list_head(&usbvcp->usbvc_term_list);
1824 if (term != NULL) {
1825 list_remove(&(usbvcp->usbvc_term_list), term);
1826 kmem_free(term, sizeof (usbvc_terms_t));
1827 }
1828 }
1829
1830 /* Free all video unit structure */
1831 while (!list_is_empty(&usbvcp->usbvc_unit_list)) {
1832 unit = list_head(&usbvcp->usbvc_unit_list);
1833 if (unit != NULL) {
1834 list_remove(&(usbvcp->usbvc_unit_list), unit);
1835 kmem_free(unit, sizeof (usbvc_units_t));
1836 }
1837 }
1838 }
1839
1840
1841 /*
1842 * Free all the data structures allocated when parsing descriptors of stream
1843 * interfaces.
1844 */
1845 static void
usbvc_free_stream_descr(usbvc_state_t * usbvcp)1846 usbvc_free_stream_descr(usbvc_state_t *usbvcp)
1847 {
1848 usbvc_stream_if_t *strm;
1849 usbvc_input_header_t *in_hdr;
1850 usbvc_output_header_t *out_hdr;
1851 uint8_t fmt_cnt, frm_cnt;
1852
1853 while (!list_is_empty(&usbvcp->usbvc_stream_list)) {
1854 USB_DPRINTF_L3(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
1855 "usbvc_fini_lists: stream list not empty.");
1856
1857 strm = list_head(&usbvcp->usbvc_stream_list);
1858 if (strm != NULL) {
1859
1860 /* unlink this stream's data structure from the list */
1861 list_remove(&(usbvcp->usbvc_stream_list), strm);
1862 } else {
1863
1864 /* No real stream data structure in the list */
1865 return;
1866 }
1867
1868 in_hdr = strm->input_header;
1869 out_hdr = strm->output_header;
1870
1871 if (in_hdr) {
1872 fmt_cnt = in_hdr->descr->bNumFormats;
1873 } else if (out_hdr) {
1874 fmt_cnt = out_hdr->descr->bNumFormats;
1875 }
1876
1877 USB_DPRINTF_L3(PRINT_MASK_CLOSE,
1878 usbvcp->usbvc_log_handle, "usbvc_fini_lists:"
1879 " fmtgrp cnt=%d", fmt_cnt);
1880
1881 /* Free headers */
1882 if (in_hdr) {
1883 kmem_free(in_hdr, sizeof (usbvc_input_header_t));
1884 }
1885 if (out_hdr) {
1886 kmem_free(out_hdr, sizeof (usbvc_output_header_t));
1887 }
1888
1889 /* Free format descriptors */
1890 if (strm->format_group) {
1891 int i;
1892 usbvc_format_group_t *fmtgrp;
1893
1894 for (i = 0; i < fmt_cnt; i++) {
1895 fmtgrp = &strm->format_group[i];
1896 if (fmtgrp->format == NULL) {
1897
1898 break;
1899 }
1900 if (fmtgrp->still) {
1901 kmem_free(fmtgrp->still,
1902 sizeof (usbvc_still_image_frame_t));
1903 }
1904 frm_cnt = fmtgrp->format->bNumFrameDescriptors;
1905
1906 USB_DPRINTF_L3(PRINT_MASK_CLOSE,
1907 usbvcp->usbvc_log_handle,
1908 "usbvc_fini_lists:"
1909 " frame cnt=%d", frm_cnt);
1910
1911 if (fmtgrp->frames) {
1912 kmem_free(fmtgrp->frames,
1913 sizeof (usbvc_frames_t) * frm_cnt);
1914 }
1915 }
1916 kmem_free(strm->format_group,
1917 sizeof (usbvc_format_group_t) * fmt_cnt);
1918 }
1919 USB_DPRINTF_L3(PRINT_MASK_CLOSE,
1920 usbvcp->usbvc_log_handle, "usbvc_fini_lists:"
1921 " free stream_if_t");
1922
1923 kmem_free(strm, sizeof (usbvc_stream_if_t));
1924 }
1925 }
1926
1927 /*
1928 * Parse class specific descriptors of the video device
1929 */
1930
1931 /*
1932 * Check the length of a class specific descriptor. Make sure cvs_buf_len is
1933 * not less than the length expected according to uvc spec.
1934 *
1935 * Args:
1936 * - off_num: the cvs_buf offset of the descriptor element that
1937 * indicates the number of variable descriptor elements;
1938 * - size: the size of each variable descriptor element, if zero, then the
1939 * size value is offered by off_size;
1940 * - off_size: the cvs_buf offset of the descriptor element that indicates
1941 * the size of each variable descriptor element;
1942 */
1943 static int
usbvc_chk_descr_len(uint8_t off_num,uint8_t size,uint8_t off_size,usb_cvs_data_t * cvs_data)1944 usbvc_chk_descr_len(uint8_t off_num, uint8_t size, uint8_t off_size,
1945 usb_cvs_data_t *cvs_data)
1946 {
1947 uchar_t *cvs_buf;
1948 uint_t cvs_buf_len;
1949
1950 cvs_buf = cvs_data->cvs_buf;
1951 cvs_buf_len = cvs_data->cvs_buf_len;
1952
1953 if (size == 0) {
1954 if (cvs_buf_len > off_size) {
1955 size = cvs_buf[off_size];
1956 } else {
1957
1958 return (USB_FAILURE);
1959 }
1960 }
1961 if (cvs_buf_len < (off_num + 1)) {
1962
1963 return (USB_FAILURE);
1964 }
1965
1966 if (cvs_buf_len < (cvs_buf[off_num] * size + off_num +1)) {
1967
1968 return (USB_FAILURE);
1969 }
1970
1971 return (USB_SUCCESS);
1972 }
1973
1974
1975 /* Parse the descriptors of control interface */
1976 static int
usbvc_parse_ctrl_if(usbvc_state_t * usbvcp)1977 usbvc_parse_ctrl_if(usbvc_state_t *usbvcp)
1978 {
1979 int if_num;
1980 int cvs_num;
1981 usb_alt_if_data_t *if_alt_data;
1982 usb_cvs_data_t *cvs_data;
1983 uchar_t *cvs_buf;
1984 uint_t cvs_buf_len;
1985 uint16_t version;
1986
1987 if_num = usbvcp->usbvc_reg->dev_curr_if;
1988 if_alt_data = usbvcp->usbvc_reg->dev_curr_cfg->cfg_if[if_num].if_alt;
1989 cvs_data = if_alt_data->altif_cvs;
1990
1991 for (cvs_num = 0; cvs_num < if_alt_data->altif_n_cvs; cvs_num++) {
1992 cvs_buf = cvs_data[cvs_num].cvs_buf;
1993 cvs_buf_len = cvs_data[cvs_num].cvs_buf_len;
1994 USB_DPRINTF_L3(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
1995 "usbvc_parse_ctrl_if: cvs_num= %d, cvs_buf_len=%d",
1996 cvs_num, cvs_buf_len);
1997
1998 /*
1999 * parse interface cvs descriptors here; by checking
2000 * bDescriptorType (cvs_buf[1])
2001 */
2002 if (cvs_buf[1] != CS_INTERFACE) {
2003
2004 continue;
2005 }
2006
2007 /*
2008 * Different descriptors in VC interface; according to
2009 * bDescriptorSubType (cvs_buf[2])
2010 */
2011 switch (cvs_buf[2]) {
2012 case VC_HEADER:
2013
2014 /*
2015 * According to uvc spec, there must be one and only
2016 * be one header. If more than one, return failure.
2017 */
2018 if (usbvcp->usbvc_vc_header) {
2019
2020 return (USB_FAILURE);
2021 }
2022 /*
2023 * Check if it is a valid HEADER descriptor in case of
2024 * a device not compliant to uvc spec. This descriptor
2025 * is critical, return failure if not a valid one.
2026 */
2027 if (usbvc_chk_descr_len(11, 1, 0, cvs_data) !=
2028 USB_SUCCESS) {
2029
2030 return (USB_FAILURE);
2031 }
2032 usbvcp->usbvc_vc_header =
2033 (usbvc_vc_header_t *)kmem_zalloc(
2034 sizeof (usbvc_vc_header_t), KM_SLEEP);
2035 usbvcp->usbvc_vc_header->descr =
2036 (usbvc_vc_header_descr_t *)&cvs_buf[0];
2037
2038 LE_TO_UINT16(usbvcp->usbvc_vc_header->descr->bcdUVC,
2039 0, version);
2040 USB_DPRINTF_L3(PRINT_MASK_ATTA,
2041 usbvcp->usbvc_log_handle, "usbvc_parse_ctrl_if:"
2042 " VC header, bcdUVC=%x", version);
2043 if (usbvcp->usbvc_vc_header->descr->bInCollection ==
2044 0) {
2045 USB_DPRINTF_L3(PRINT_MASK_ATTA,
2046 usbvcp->usbvc_log_handle,
2047 "usbvc_parse_ctrl_if: no strm interfaces");
2048
2049 break;
2050 }
2051
2052 /* stream interface numbers */
2053 usbvcp->usbvc_vc_header->baInterfaceNr = &cvs_buf[12];
2054
2055 break;
2056 case VC_INPUT_TERMINAL:
2057 {
2058 usbvc_terms_t *term;
2059
2060 /*
2061 * Check if it is a valid descriptor in case of a
2062 * device not compliant to uvc spec
2063 */
2064 if (cvs_buf_len < USBVC_I_TERM_LEN_MIN) {
2065
2066 break;
2067 }
2068 term = (usbvc_terms_t *)
2069 kmem_zalloc(sizeof (usbvc_terms_t), KM_SLEEP);
2070 term->descr = (usbvc_term_descr_t *)cvs_buf;
2071
2072 USB_DPRINTF_L3(PRINT_MASK_ATTA,
2073 usbvcp->usbvc_log_handle, "usbvc_parse_ctrl_if: "
2074 "input term type=%x", term->descr->wTerminalType);
2075 if (term->descr->wTerminalType == ITT_CAMERA) {
2076 if (usbvc_chk_descr_len(14, 1, 0, cvs_data) !=
2077 USB_SUCCESS) {
2078 kmem_free(term, sizeof (usbvc_terms_t));
2079
2080 break;
2081 }
2082 term->bmControls = &cvs_buf[15];
2083 } else if (cvs_buf_len > 8) { /* other input terms */
2084 term->bSpecific = &cvs_buf[8];
2085 }
2086 list_insert_tail(&(usbvcp->usbvc_term_list), term);
2087
2088 break;
2089 }
2090 case VC_OUTPUT_TERMINAL:
2091 {
2092 usbvc_terms_t *term;
2093
2094 if (cvs_buf_len < USBVC_O_TERM_LEN_MIN) {
2095
2096 break;
2097 }
2098 term = (usbvc_terms_t *)
2099 kmem_zalloc(sizeof (usbvc_terms_t), KM_SLEEP);
2100 term->descr = (usbvc_term_descr_t *)cvs_buf;
2101
2102 USB_DPRINTF_L3(PRINT_MASK_ATTA,
2103 usbvcp->usbvc_log_handle, "usbvc_parse_ctrl_if:"
2104 " output term id= %x", term->descr->bTerminalID);
2105 if (cvs_buf_len > 9) {
2106 term->bSpecific = &cvs_buf[9];
2107 }
2108 list_insert_tail(&(usbvcp->usbvc_term_list), term);
2109
2110 break;
2111 }
2112 case VC_PROCESSING_UNIT:
2113 {
2114 uint8_t sz;
2115 usbvc_units_t *unit;
2116
2117 if (usbvc_chk_descr_len(7, 1, 0, cvs_data) !=
2118 USB_SUCCESS) {
2119
2120 break;
2121 }
2122
2123 /* bControlSize */
2124 sz = cvs_buf[7];
2125
2126 if ((sz + 8) >= cvs_buf_len) {
2127
2128 break;
2129 }
2130 unit = (usbvc_units_t *)
2131 kmem_zalloc(sizeof (usbvc_units_t), KM_SLEEP);
2132
2133 unit->descr = (usbvc_unit_descr_t *)cvs_buf;
2134
2135 USB_DPRINTF_L3(PRINT_MASK_ATTA,
2136 usbvcp->usbvc_log_handle, "usbvc_parse_ctrl_if: "
2137 "unit type=%x", unit->descr->bDescriptorSubType);
2138
2139 if (sz != 0) {
2140 unit->bmControls = &cvs_buf[8];
2141 }
2142 unit->iProcessing = cvs_buf[8 + sz];
2143
2144 /*
2145 * video class 1.1 version add one element
2146 * (bmVideoStandards) to processing unit descriptor
2147 */
2148 if (cvs_buf_len > (9 + sz)) {
2149 unit->bmVideoStandards = cvs_buf[9 + sz];
2150 }
2151 list_insert_tail(&(usbvcp->usbvc_unit_list), unit);
2152
2153 break;
2154 }
2155 case VC_SELECTOR_UNIT:
2156 {
2157 uint8_t pins;
2158 usbvc_units_t *unit;
2159
2160 if (usbvc_chk_descr_len(4, 1, 0, cvs_data) !=
2161 USB_SUCCESS) {
2162
2163 break;
2164 }
2165 pins = cvs_buf[4];
2166 if ((pins + 5) >= cvs_buf_len) {
2167
2168 break;
2169 }
2170 unit = (usbvc_units_t *)
2171 kmem_zalloc(sizeof (usbvc_units_t), KM_SLEEP);
2172
2173 unit->descr = (usbvc_unit_descr_t *)cvs_buf;
2174
2175 USB_DPRINTF_L3(PRINT_MASK_ATTA,
2176 usbvcp->usbvc_log_handle, "usbvc_parse_ctrl_if: "
2177 "unit type=%x", unit->descr->bDescriptorSubType);
2178 if (pins > 0) {
2179 unit->baSourceID = &cvs_buf[5];
2180 }
2181 unit->iSelector = cvs_buf[5 + pins];
2182
2183 list_insert_tail(&(usbvcp->usbvc_unit_list), unit);
2184
2185 break;
2186 }
2187 case VC_EXTENSION_UNIT:
2188 {
2189 uint8_t pins, n;
2190 usbvc_units_t *unit;
2191
2192 if (usbvc_chk_descr_len(21, 1, 0, cvs_data) !=
2193 USB_SUCCESS) {
2194
2195 break;
2196 }
2197 pins = cvs_buf[21];
2198 if ((pins + 22) >= cvs_buf_len) {
2199
2200 break;
2201 }
2202
2203 /* Size of bmControls */
2204 n = cvs_buf[pins + 22];
2205
2206 if (usbvc_chk_descr_len(pins + 22, 1, 0, cvs_data) !=
2207 USB_SUCCESS) {
2208
2209 break;
2210 }
2211 if ((23 + pins + n) >= cvs_buf_len) {
2212
2213 break;
2214 }
2215 unit = (usbvc_units_t *)
2216 kmem_zalloc(sizeof (usbvc_units_t), KM_SLEEP);
2217
2218 unit->descr = (usbvc_unit_descr_t *)cvs_buf;
2219
2220 USB_DPRINTF_L3(PRINT_MASK_ATTA,
2221 usbvcp->usbvc_log_handle, "usbvc_parse_ctrl_if: "
2222 "unit type=%x", unit->descr->bDescriptorSubType);
2223 if (pins != 0) {
2224 unit->baSourceID = &cvs_buf[22];
2225 }
2226 unit->bControlSize = cvs_buf[22 + pins];
2227
2228 if (unit->bControlSize != 0) {
2229 unit->bmControls = &cvs_buf[23 + pins];
2230 }
2231 unit->iExtension = cvs_buf[23 + pins + n];
2232
2233 list_insert_tail(&(usbvcp->usbvc_unit_list), unit);
2234
2235 break;
2236 }
2237 default:
2238
2239 break;
2240 }
2241 }
2242
2243 /*
2244 * For webcam which is not compliant to video class specification
2245 * and no header descriptor in VC interface, return USB_FAILURE.
2246 */
2247 if (!usbvcp->usbvc_vc_header) {
2248 USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2249 "usbvc_parse_ctrl_if: no header descriptor");
2250
2251 return (USB_FAILURE);
2252 }
2253
2254 return (USB_SUCCESS);
2255 }
2256
2257
2258 /* Parse all the cvs descriptors in one stream interface. */
2259 usbvc_stream_if_t *
usbvc_parse_stream_if(usbvc_state_t * usbvcp,int if_num)2260 usbvc_parse_stream_if(usbvc_state_t *usbvcp, int if_num)
2261 {
2262 usb_alt_if_data_t *if_alt_data;
2263 uint_t i, j;
2264 usbvc_stream_if_t *strm_if;
2265 uint16_t pktsize;
2266 uint8_t ep_adr;
2267
2268 strm_if = (usbvc_stream_if_t *)kmem_zalloc(sizeof (usbvc_stream_if_t),
2269 KM_SLEEP);
2270 strm_if->if_descr = &usbvcp->usbvc_reg->dev_curr_cfg->cfg_if[if_num];
2271 if_alt_data = strm_if->if_descr->if_alt;
2272 if (usbvc_parse_stream_header(usbvcp, strm_if) != USB_SUCCESS) {
2273 USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2274 "usbvc_parse_stream_if: parse header fail");
2275 kmem_free(strm_if, sizeof (usbvc_stream_if_t));
2276
2277 return (NULL);
2278 }
2279 if (usbvc_parse_format_groups(usbvcp, strm_if) != USB_SUCCESS) {
2280 USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2281 "usbvc_parse_stream_if: parse groups fail");
2282 kmem_free(strm_if, sizeof (usbvc_stream_if_t));
2283
2284 return (NULL);
2285 }
2286
2287 /* Parse the alternate settings to find the maximum bandwidth. */
2288 for (i = 0; i < strm_if->if_descr->if_n_alt; i++) {
2289 if_alt_data = &strm_if->if_descr->if_alt[i];
2290 for (j = 0; j < if_alt_data->altif_n_ep; j++) {
2291 ep_adr =
2292 if_alt_data->altif_ep[j].ep_descr.bEndpointAddress;
2293 if (strm_if->input_header != NULL &&
2294 ep_adr !=
2295 strm_if->input_header->descr->bEndpointAddress) {
2296
2297 continue;
2298 }
2299 if (strm_if->output_header != NULL &&
2300 ep_adr !=
2301 strm_if->output_header->descr->bEndpointAddress) {
2302
2303 continue;
2304 }
2305 pktsize =
2306 if_alt_data->altif_ep[j].ep_descr.wMaxPacketSize;
2307 pktsize = HS_PKT_SIZE(pktsize);
2308 if (pktsize > strm_if->max_isoc_payload) {
2309 strm_if->max_isoc_payload = pktsize;
2310 }
2311 }
2312 }
2313
2314 /* initialize MJPEC FID toggle */
2315 strm_if->fid = 0xff;
2316
2317 /*
2318 * initialize desired number of buffers used internally in read() mode
2319 */
2320 strm_if->buf_read_num = USBVC_DEFAULT_READ_BUF_NUM;
2321
2322 USB_DPRINTF_L4(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2323 "usbvc_parse_stream_if: return. max_isoc_payload=%x",
2324 strm_if->max_isoc_payload);
2325
2326 return (strm_if);
2327 }
2328
2329
2330 /*
2331 * Parse all the stream interfaces asociated with the video control interface.
2332 * This driver will attach to a video control interface on the device,
2333 * there might be multiple video stream interfaces associated with one video
2334 * control interface.
2335 */
2336 static int
usbvc_parse_stream_ifs(usbvc_state_t * usbvcp)2337 usbvc_parse_stream_ifs(usbvc_state_t *usbvcp)
2338 {
2339 int i, if_cnt, if_num;
2340 usbvc_stream_if_t *strm_if;
2341
2342 if_cnt = usbvcp->usbvc_vc_header->descr->bInCollection;
2343 if (if_cnt == 0) {
2344 ASSERT(list_is_empty(&usbvcp->usbvc_stream_list));
2345 USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2346 "usbvc_parse_stream_ifs: no stream interfaces");
2347
2348 return (USB_SUCCESS);
2349 }
2350 for (i = 0; i < if_cnt; i++) {
2351 if_num = usbvcp->usbvc_vc_header->baInterfaceNr[i];
2352 strm_if = usbvc_parse_stream_if(usbvcp, if_num);
2353 if (strm_if == NULL) {
2354 USB_DPRINTF_L2(PRINT_MASK_ATTA,
2355 usbvcp->usbvc_log_handle, "usbvc_parse_stream_ifs:"
2356 " parse stream interface %d failed.", if_num);
2357
2358 return (USB_FAILURE);
2359 }
2360 /* video data buffers */
2361 list_create(&(strm_if->buf_map.uv_buf_free),
2362 sizeof (usbvc_buf_t), offsetof(usbvc_buf_t, buf_node));
2363 list_create(&(strm_if->buf_map.uv_buf_done),
2364 sizeof (usbvc_buf_t), offsetof(usbvc_buf_t, buf_node));
2365 list_create(&(strm_if->buf_read.uv_buf_free),
2366 sizeof (usbvc_buf_t), offsetof(usbvc_buf_t, buf_node));
2367 list_create(&(strm_if->buf_read.uv_buf_done),
2368 sizeof (usbvc_buf_t), offsetof(usbvc_buf_t, buf_node));
2369
2370 list_insert_tail(&(usbvcp->usbvc_stream_list), strm_if);
2371 }
2372
2373 /* Make the first stream interface as the default one. */
2374 usbvcp->usbvc_curr_strm =
2375 (usbvc_stream_if_t *)list_head(&usbvcp->usbvc_stream_list);
2376
2377 return (USB_SUCCESS);
2378 }
2379
2380
2381 /*
2382 * Parse colorspace descriptor and still image descriptor of a format group.
2383 * There is only one colorspace or still image descriptor in one format group.
2384 */
2385 static void
usbvc_parse_color_still(usbvc_state_t * usbvcp,usbvc_format_group_t * fmtgrp,usb_cvs_data_t * cvs_data,uint_t cvs_num,uint_t altif_n_cvs)2386 usbvc_parse_color_still(usbvc_state_t *usbvcp, usbvc_format_group_t *fmtgrp,
2387 usb_cvs_data_t *cvs_data, uint_t cvs_num, uint_t altif_n_cvs)
2388 {
2389 uint8_t frame_cnt;
2390 uint_t last_frame, i;
2391 uchar_t *cvs_buf;
2392 uint_t cvs_buf_len;
2393
2394 frame_cnt = fmtgrp->format->bNumFrameDescriptors;
2395 last_frame = frame_cnt + cvs_num;
2396
2397 /*
2398 * Find the still image descr and color format descr if there are any.
2399 * UVC Spec: only one still image and one color descr is allowed in
2400 * one format group.
2401 */
2402 for (i = 1; i <= 2; i++) {
2403 if ((last_frame + i) >= altif_n_cvs) {
2404
2405 break;
2406 }
2407 cvs_buf = cvs_data[last_frame + i].cvs_buf;
2408 cvs_buf_len = cvs_data[last_frame + i].cvs_buf_len;
2409
2410 if (cvs_buf[2] == VS_STILL_IMAGE_FRAME) {
2411 uint8_t m, n, off;
2412 usbvc_still_image_frame_t *st;
2413
2414 if (usbvc_chk_descr_len(4, 4, 0, cvs_data) !=
2415 USB_SUCCESS) {
2416
2417 continue;
2418 }
2419
2420 /* Number of Image Size patterns of this format */
2421 n = cvs_buf[4];
2422
2423 /* offset of bNumCompressionPattern */
2424 off = 9 + 4 * n -4;
2425
2426 if (off >= cvs_buf_len) {
2427
2428 continue;
2429 }
2430
2431 /* Number of compression pattern of this format */
2432 m = cvs_buf[off];
2433
2434 if (usbvc_chk_descr_len(m, 1, 0, cvs_data) !=
2435 USB_SUCCESS) {
2436
2437 continue;
2438 }
2439 fmtgrp->still = (usbvc_still_image_frame_t *)
2440 kmem_zalloc(sizeof (usbvc_still_image_frame_t),
2441 KM_SLEEP);
2442 st = fmtgrp->still;
2443 st->descr = (usbvc_still_image_frame_descr_t *)cvs_buf;
2444 n = st->descr->bNumImageSizePatterns;
2445 if (n > 0) {
2446 st->width_height =
2447 (width_height_t *)&cvs_buf[5];
2448 }
2449 st->bNumCompressionPattern = cvs_buf[off];
2450 if (cvs_buf[off] > 0) {
2451 st->bCompression = &cvs_buf[off + 1];
2452 }
2453 }
2454 if (cvs_buf[2] == VS_COLORFORMAT) {
2455 fmtgrp->color = (usbvc_color_matching_descr_t *)cvs_buf;
2456 fmtgrp->v4l2_color = usbvc_v4l2_colorspace(
2457 fmtgrp->color->bColorPrimaries);
2458 }
2459 }
2460 USB_DPRINTF_L4(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2461 "usbvc_parse_color_still: still=%p, color=%p",
2462 (void *)fmtgrp->still, (void *)fmtgrp->color);
2463 }
2464
2465
2466 /*
2467 * Parse frame descriptors of a format group. There might be multi frame
2468 * descriptors in one format group.
2469 */
2470 static void
usbvc_parse_frames(usbvc_state_t * usbvcp,usbvc_format_group_t * fmtgrp,usb_cvs_data_t * cvs_data,uint_t cvs_num,uint_t altif_n_cvs)2471 usbvc_parse_frames(usbvc_state_t *usbvcp, usbvc_format_group_t *fmtgrp,
2472 usb_cvs_data_t *cvs_data, uint_t cvs_num, uint_t altif_n_cvs)
2473 {
2474 uint_t last_frame;
2475 usbvc_frames_t *frm;
2476 usb_cvs_data_t *cvs;
2477 uchar_t *cvs_buf;
2478 uint_t cvs_buf_len;
2479 uint8_t i;
2480 uint8_t frame_cnt = fmtgrp->format->bNumFrameDescriptors;
2481
2482 USB_DPRINTF_L4(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2483 "usbvc_parse_format_group: frame_cnt=%d", frame_cnt);
2484
2485 if (frame_cnt == 0) {
2486 fmtgrp->frames = NULL;
2487
2488 return;
2489 }
2490
2491 /* All these mem allocated will be freed in cleanup() */
2492 fmtgrp->frames = (usbvc_frames_t *)
2493 kmem_zalloc(sizeof (usbvc_frames_t) * frame_cnt, KM_SLEEP);
2494
2495 last_frame = frame_cnt + cvs_num;
2496 cvs_num++;
2497 i = 0;
2498
2499 /*
2500 * Traverse from the format decr's first frame decr to the the last
2501 * frame descr.
2502 */
2503 for (; cvs_num <= last_frame; cvs_num++) {
2504 USB_DPRINTF_L3(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2505 "usbvc_parse_frames: cvs_num=%d, i=%d", cvs_num, i);
2506 if (cvs_num >= altif_n_cvs) {
2507 USB_DPRINTF_L3(PRINT_MASK_ATTA,
2508 usbvcp->usbvc_log_handle,
2509 "usbvc_parse_frames: less frames than "
2510 "expected, cvs_num=%d, i=%d", cvs_num, i);
2511
2512 break;
2513 }
2514 cvs = &cvs_data[cvs_num];
2515 cvs_buf = cvs->cvs_buf;
2516 cvs_buf_len = cvs->cvs_buf_len;
2517 if (cvs_buf_len < USBVC_FRAME_LEN_MIN) {
2518 i++;
2519
2520 continue;
2521 }
2522 frm = &fmtgrp->frames[i];
2523 frm->descr = (usbvc_frame_descr_t *)cvs->cvs_buf;
2524
2525 /* Descriptor for discrete frame interval */
2526 if (frm->descr->bFrameIntervalType > 0) {
2527 if (usbvc_chk_descr_len(25, 4, 0, cvs) != USB_SUCCESS) {
2528 frm->descr = NULL;
2529 i++;
2530
2531 continue;
2532 }
2533
2534 frm->dwFrameInterval = (uint8_t *)&cvs_buf[26];
2535 } else { /* Continuous interval */
2536 if (cvs_buf_len < USBVC_FRAME_LEN_CON) {
2537 frm->descr = NULL;
2538 i++;
2539
2540 continue;
2541 }
2542
2543 /* Continuous frame intervals */
2544 LE_TO_UINT32(cvs_buf, 26, frm->dwMinFrameInterval);
2545 LE_TO_UINT32(cvs_buf, 30, frm->dwMaxFrameInterval);
2546 LE_TO_UINT32(cvs_buf, 34, frm->dwFrameIntervalStep);
2547 }
2548
2549 i++;
2550 }
2551 fmtgrp->frame_cnt = i;
2552 USB_DPRINTF_L4(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2553 "usbvc_parse_frames: %d frames are actually parsed",
2554 fmtgrp->frame_cnt);
2555 }
2556
2557
2558 /* Parse one of the format groups in a stream interface */
2559 static int
usbvc_parse_format_group(usbvc_state_t * usbvcp,usbvc_format_group_t * fmtgrp,usb_cvs_data_t * cvs_data,uint_t cvs_num,uint_t altif_n_cvs)2560 usbvc_parse_format_group(usbvc_state_t *usbvcp, usbvc_format_group_t *fmtgrp,
2561 usb_cvs_data_t *cvs_data, uint_t cvs_num, uint_t altif_n_cvs)
2562 {
2563 usbvc_format_descr_t *fmt;
2564
2565 fmt = fmtgrp->format;
2566 USB_DPRINTF_L4(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2567 "usbvc_parse_format_group: frame_cnt=%d, cvs_num=%d",
2568 fmt->bNumFrameDescriptors, cvs_num);
2569
2570 switch (fmt->bDescriptorSubType) {
2571 case VS_FORMAT_UNCOMPRESSED:
2572 usbvc_parse_color_still(usbvcp, fmtgrp, cvs_data, cvs_num,
2573 altif_n_cvs);
2574 usbvc_parse_frames(usbvcp, fmtgrp, cvs_data, cvs_num,
2575 altif_n_cvs);
2576 fmtgrp->v4l2_bpp = fmt->fmt.uncompressed.bBitsPerPixel / 8;
2577 fmtgrp->v4l2_pixelformat = usbvc_v4l2_guid2fcc(
2578 (uint8_t *)&fmt->fmt.uncompressed.guidFormat);
2579
2580 break;
2581 case VS_FORMAT_MJPEG:
2582 usbvc_parse_color_still(usbvcp, fmtgrp, cvs_data, cvs_num,
2583 altif_n_cvs);
2584 usbvc_parse_frames(usbvcp, fmtgrp, cvs_data, cvs_num,
2585 altif_n_cvs);
2586 fmtgrp->v4l2_bpp = 0;
2587 fmtgrp->v4l2_pixelformat = V4L2_PIX_FMT_MJPEG;
2588
2589 break;
2590 case VS_FORMAT_MPEG2TS:
2591 case VS_FORMAT_DV:
2592 case VS_FORMAT_FRAME_BASED:
2593 case VS_FORMAT_STREAM_BASED:
2594 USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2595 "usbvc_parse_format_group: format not supported yet.");
2596
2597 return (USB_FAILURE);
2598 default:
2599 USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2600 "usbvc_parse_format_group: unknown format.");
2601
2602 return (USB_FAILURE);
2603 }
2604
2605 return (USB_SUCCESS);
2606 }
2607
2608
2609 /* Parse the descriptors belong to one format */
2610 static int
usbvc_parse_format_groups(usbvc_state_t * usbvcp,usbvc_stream_if_t * strm_if)2611 usbvc_parse_format_groups(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
2612 {
2613 usb_alt_if_data_t *if_alt_data;
2614 usb_cvs_data_t *cvs_data;
2615 uint8_t fmtgrp_num, fmtgrp_cnt;
2616 uchar_t *cvs_buf;
2617 uint_t cvs_num = 0;
2618 usbvc_format_group_t *fmtgrp;
2619
2620 fmtgrp_cnt = 0;
2621 /*
2622 * bNumFormats indicates the number of formats in this stream
2623 * interface. On some devices, we see this number is larger than
2624 * the truth.
2625 */
2626 if (strm_if->input_header) {
2627 fmtgrp_cnt = strm_if->input_header->descr->bNumFormats;
2628 } else if (strm_if->output_header) {
2629 fmtgrp_cnt = strm_if->output_header->descr->bNumFormats;
2630 }
2631 if (!fmtgrp_cnt) {
2632
2633 return (USB_FAILURE);
2634 }
2635 USB_DPRINTF_L3(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2636 "usbvc_parse_format_groups: fmtgrp_cnt=%d", fmtgrp_cnt);
2637
2638 fmtgrp = (usbvc_format_group_t *)
2639 kmem_zalloc(sizeof (usbvc_format_group_t) * fmtgrp_cnt, KM_SLEEP);
2640
2641 if_alt_data = strm_if->if_descr->if_alt;
2642 cvs_data = if_alt_data->altif_cvs;
2643
2644 for (fmtgrp_num = 0; fmtgrp_num < fmtgrp_cnt &&
2645 cvs_num < if_alt_data->altif_n_cvs; cvs_num++) {
2646 cvs_buf = cvs_data[cvs_num].cvs_buf;
2647 switch (cvs_buf[2]) {
2648 case VS_FORMAT_UNCOMPRESSED:
2649 case VS_FORMAT_MJPEG:
2650 case VS_FORMAT_MPEG2TS:
2651 case VS_FORMAT_DV:
2652 case VS_FORMAT_FRAME_BASED:
2653 case VS_FORMAT_STREAM_BASED:
2654 fmtgrp[fmtgrp_num].format =
2655 (usbvc_format_descr_t *)cvs_buf;
2656
2657 /*
2658 * Now cvs_data[cvs_num].cvs_buf is format descriptor,
2659 * usbvc_parse_format_group will then parse the frame
2660 * descriptors following this format descriptor.
2661 */
2662 (void) usbvc_parse_format_group(usbvcp,
2663 &fmtgrp[fmtgrp_num], cvs_data, cvs_num,
2664 if_alt_data->altif_n_cvs);
2665
2666 fmtgrp_num++;
2667
2668 break;
2669 default:
2670 break;
2671 }
2672 }
2673
2674 /* Save the number of parsed format groups. */
2675 strm_if->fmtgrp_cnt = fmtgrp_num;
2676 USB_DPRINTF_L3(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2677 "usbvc_parse_format_groups: acctually %d formats parsed",
2678 fmtgrp_num);
2679
2680 /*
2681 * If can't find any formats, then free all allocated
2682 * usbvc_format_group_t, return failure.
2683 */
2684 if (!(fmtgrp[0].format)) {
2685 kmem_free(fmtgrp, sizeof (usbvc_format_group_t) * fmtgrp_cnt);
2686 strm_if->format_group = NULL;
2687
2688 USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2689 "usbvc_parse_format_groups: can't find any formats");
2690
2691 return (USB_FAILURE);
2692 }
2693 strm_if->format_group = fmtgrp;
2694 USB_DPRINTF_L3(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2695 "usbvc_parse_format_groups: %d format groups parsed", fmtgrp_num);
2696
2697 return (USB_SUCCESS);
2698 }
2699
2700
2701 /*
2702 * Parse the input/output header in one stream interface.
2703 * UVC Spec: there must be one and only one header in one stream interface.
2704 */
2705 int
usbvc_parse_stream_header(usbvc_state_t * usbvcp,usbvc_stream_if_t * strm_if)2706 usbvc_parse_stream_header(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
2707 {
2708 usb_alt_if_data_t *if_alt_data;
2709 usb_cvs_data_t *cvs_data;
2710 int cvs_num;
2711 uchar_t *cvs_buf;
2712 usbvc_input_header_t *in_hdr;
2713 usbvc_output_header_t *out_hdr;
2714
2715 if_alt_data = strm_if->if_descr->if_alt;
2716 cvs_data = if_alt_data->altif_cvs;
2717 for (cvs_num = 0; cvs_num < if_alt_data->altif_n_cvs; cvs_num++) {
2718 cvs_buf = cvs_data[cvs_num].cvs_buf;
2719 USB_DPRINTF_L3(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2720 "usbvc_parse_stream_header: cvs_num= %d", cvs_num);
2721
2722 /*
2723 * parse interface cvs descriptors here; by checking
2724 * bDescriptorType (cvs_buf[1])
2725 */
2726 if (cvs_buf[1] != CS_INTERFACE) {
2727
2728 continue;
2729 }
2730
2731 if (cvs_buf[2] == VS_INPUT_HEADER) {
2732 if (usbvc_chk_descr_len(3, 0, 12, cvs_data) !=
2733 USB_SUCCESS) {
2734
2735 continue;
2736 }
2737
2738 strm_if->input_header =
2739 (usbvc_input_header_t *)
2740 kmem_zalloc(sizeof (usbvc_input_header_t),
2741 KM_SLEEP);
2742 in_hdr = strm_if->input_header;
2743 in_hdr->descr = (usbvc_input_header_descr_t *)cvs_buf;
2744 if (in_hdr->descr->bNumFormats > 0) {
2745 in_hdr->bmaControls = &cvs_buf[13];
2746 }
2747
2748 return (USB_SUCCESS);
2749 } else if (cvs_buf[2] == VS_OUTPUT_HEADER) {
2750 if (usbvc_chk_descr_len(3, 0, 8, cvs_data) !=
2751 USB_SUCCESS) {
2752
2753 continue;
2754 }
2755 strm_if->output_header =
2756 (usbvc_output_header_t *)
2757 kmem_zalloc(sizeof (usbvc_output_header_t),
2758 KM_SLEEP);
2759 out_hdr = strm_if->output_header;
2760 out_hdr->descr =
2761 (usbvc_output_header_descr_t *)cvs_buf;
2762 if (out_hdr->descr->bNumFormats > 0) {
2763 out_hdr->bmaControls = &cvs_buf[13];
2764 }
2765
2766 return (USB_SUCCESS);
2767 } else {
2768
2769 continue;
2770 }
2771 }
2772 /* Didn't find one header descriptor. */
2773 USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2774 "usbvc_parse_stream_header: FAIL");
2775
2776 return (USB_FAILURE);
2777 }
2778
2779 /* read I/O functions */
2780
2781 /* Allocate bufs for read I/O method */
2782 static int
usbvc_alloc_read_bufs(usbvc_state_t * usbvcp,usbvc_stream_if_t * strm_if)2783 usbvc_alloc_read_bufs(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
2784 {
2785 usbvc_buf_t *buf;
2786 uchar_t *data;
2787 int i;
2788 uint32_t len;
2789
2790 ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
2791
2792 LE_TO_UINT32(strm_if->ctrl_pc.dwMaxVideoFrameSize, 0, len);
2793 if (!len) {
2794
2795 return (USB_FAILURE);
2796 }
2797 for (i = 0; i < strm_if->buf_read_num; i++) {
2798 mutex_exit(&usbvcp->usbvc_mutex);
2799 buf = (usbvc_buf_t *)kmem_zalloc(sizeof (usbvc_buf_t),
2800 KM_SLEEP);
2801 data = (uchar_t *)kmem_zalloc(len, KM_SLEEP);
2802 mutex_enter(&usbvcp->usbvc_mutex);
2803 buf->data = data;
2804 buf->len = len;
2805 list_insert_tail(&(strm_if->buf_read.uv_buf_free), buf);
2806 }
2807 strm_if->buf_read.buf_cnt = strm_if->buf_read_num;
2808 USB_DPRINTF_L4(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
2809 "read_bufs: %d bufs allocated", strm_if->buf_read.buf_cnt);
2810
2811 return (USB_SUCCESS);
2812 }
2813
2814
2815 /* Read a done buf, copy data to bp. This function is for read I/O method */
2816 static int
usbvc_read_buf(usbvc_state_t * usbvcp,struct buf * bp)2817 usbvc_read_buf(usbvc_state_t *usbvcp, struct buf *bp)
2818 {
2819 usbvc_buf_t *buf;
2820 int buf_residue;
2821 int len_to_copy;
2822
2823 ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
2824
2825 if (list_is_empty(&usbvcp->usbvc_curr_strm->buf_read.uv_buf_done)) {
2826 USB_DPRINTF_L2(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
2827 "usbvc_read_buf: empty list(uv_buf_done)!");
2828
2829 return (USB_FAILURE);
2830 }
2831
2832 /* read a buf from full list and then put it to free list */
2833 buf = list_head(&usbvcp->usbvc_curr_strm->buf_read.uv_buf_done);
2834
2835 USB_DPRINTF_L2(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
2836 "usbvc_read_buf: buf=%p, buf->filled=%d, buf->len=%d,"
2837 " buf->len_read=%d bp->b_bcount=%ld, bp->b_resid=%lu",
2838 (void *)buf, buf->filled, buf->len, buf->len_read,
2839 bp->b_bcount, bp->b_resid);
2840
2841 ASSERT(buf->len_read <= buf->filled);
2842
2843 buf_residue = buf->filled - buf->len_read;
2844 len_to_copy = min(bp->b_bcount, buf_residue);
2845
2846 bcopy(buf->data + buf->len_read, bp->b_un.b_addr, len_to_copy);
2847 bp->b_private = NULL;
2848 buf->len_read += len_to_copy;
2849 bp->b_resid = bp->b_bcount - len_to_copy;
2850
2851 if (len_to_copy == buf_residue) {
2852 /*
2853 * the bp can accommodate all the remaining bytes of
2854 * the buf. Then we can reuse this buf.
2855 */
2856 buf->len_read = 0;
2857 list_remove(&usbvcp->usbvc_curr_strm->buf_read.uv_buf_done,
2858 buf);
2859 list_insert_tail(&usbvcp->usbvc_curr_strm->buf_read.uv_buf_free,
2860 buf);
2861 }
2862
2863 return (USB_SUCCESS);
2864 }
2865
2866
2867 /* Free one buf which is for read/write IO style */
2868 static void
usbvc_free_read_buf(usbvc_buf_t * buf)2869 usbvc_free_read_buf(usbvc_buf_t *buf)
2870 {
2871 if (buf != NULL) {
2872 if (buf->data) {
2873 kmem_free(buf->data, buf->len);
2874 }
2875 kmem_free(buf, sizeof (usbvc_buf_t));
2876 }
2877 }
2878
2879
2880 /* Free all bufs which are for read/write IO style */
2881 static void
usbvc_free_read_bufs(usbvc_state_t * usbvcp,usbvc_stream_if_t * strm_if)2882 usbvc_free_read_bufs(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
2883 {
2884 usbvc_buf_t *buf;
2885
2886 ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
2887
2888 if (!strm_if) {
2889
2890 return;
2891 }
2892 buf = strm_if->buf_read.buf_filling;
2893 usbvc_free_read_buf(buf);
2894 strm_if->buf_read.buf_filling = NULL;
2895
2896 while (!list_is_empty(&strm_if->buf_read.uv_buf_free)) {
2897 buf = list_head(&strm_if->buf_read.uv_buf_free);
2898 if (buf != NULL) {
2899 list_remove(&(strm_if->buf_read.uv_buf_free), buf);
2900 usbvc_free_read_buf(buf);
2901 }
2902 }
2903 while (!list_is_empty(&strm_if->buf_read.uv_buf_done)) {
2904 buf = list_head(&strm_if->buf_read.uv_buf_done);
2905 if (buf != NULL) {
2906 list_remove(&(strm_if->buf_read.uv_buf_done), buf);
2907 usbvc_free_read_buf(buf);
2908 }
2909 }
2910 strm_if->buf_read.buf_cnt = 0;
2911 USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
2912 "usbvc_free_read_bufs: return");
2913 }
2914
2915
2916 /*
2917 * Allocate bufs for mapped I/O , return the number of allocated bufs
2918 * if success, return 0 if fail.
2919 */
2920 int
usbvc_alloc_map_bufs(usbvc_state_t * usbvcp,usbvc_stream_if_t * strm_if,int buf_cnt,int buf_len)2921 usbvc_alloc_map_bufs(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if,
2922 int buf_cnt, int buf_len)
2923 {
2924 int i = 0;
2925 usbvc_buf_t *bufs;
2926
2927 ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
2928 USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
2929 "usbvc_alloc_map_bufs: bufcnt=%d, buflen=%d", buf_cnt, buf_len);
2930 if (buf_len <= 0 || buf_cnt <= 0) {
2931 USB_DPRINTF_L2(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
2932 "usbvc_alloc_map_bufs: len<=0, cnt<=0");
2933
2934 return (0);
2935 }
2936 mutex_exit(&usbvcp->usbvc_mutex);
2937
2938 bufs = (usbvc_buf_t *) kmem_zalloc(sizeof (usbvc_buf_t) * buf_cnt,
2939 KM_SLEEP);
2940
2941 mutex_enter(&usbvcp->usbvc_mutex);
2942 strm_if->buf_map.buf_head = bufs;
2943 buf_len = ptob(btopr(buf_len));
2944
2945 mutex_exit(&usbvcp->usbvc_mutex);
2946 bufs[0].data = ddi_umem_alloc(buf_len * buf_cnt, DDI_UMEM_SLEEP,
2947 &bufs[0].umem_cookie);
2948 mutex_enter(&usbvcp->usbvc_mutex);
2949
2950 for (i = 0; i < buf_cnt; i++) {
2951 bufs[i].len = buf_len;
2952 bufs[i].data = bufs[0].data + (buf_len * i);
2953 bufs[i].umem_cookie = bufs[0].umem_cookie;
2954 bufs[i].status = USBVC_BUF_INIT;
2955
2956 bufs[i].v4l2_buf.index = i;
2957 bufs[i].v4l2_buf.m.offset = i * bufs[i].len;
2958 bufs[i].v4l2_buf.length = bufs[i].len;
2959 bufs[i].v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2960 bufs[i].v4l2_buf.sequence = 0;
2961 bufs[i].v4l2_buf.field = V4L2_FIELD_NONE;
2962 bufs[i].v4l2_buf.memory = V4L2_MEMORY_MMAP;
2963 bufs[i].v4l2_buf.flags = V4L2_MEMORY_MMAP;
2964
2965 list_insert_tail(&strm_if->buf_map.uv_buf_free, &bufs[i]);
2966 USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
2967 "usbvc_alloc_map_bufs: prepare %d buffers of %d bytes",
2968 buf_cnt, bufs[i].len);
2969 }
2970 strm_if->buf_map.buf_cnt = buf_cnt;
2971 strm_if->buf_map.buf_filling = NULL;
2972
2973 return (buf_cnt);
2974 }
2975
2976
2977 /* Free all bufs which are for memory map IO style */
2978 void
usbvc_free_map_bufs(usbvc_state_t * usbvcp,usbvc_stream_if_t * strm_if)2979 usbvc_free_map_bufs(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
2980 {
2981 usbvc_buf_t *buf;
2982
2983 ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
2984 if (!strm_if) {
2985
2986 return;
2987 }
2988 strm_if->buf_map.buf_filling = NULL;
2989 while (!list_is_empty(&strm_if->buf_map.uv_buf_free)) {
2990 buf = (usbvc_buf_t *)list_head(&strm_if->buf_map.uv_buf_free);
2991 list_remove(&(strm_if->buf_map.uv_buf_free), buf);
2992 }
2993 while (!list_is_empty(&strm_if->buf_map.uv_buf_done)) {
2994 buf = (usbvc_buf_t *)list_head(&strm_if->buf_map.uv_buf_done);
2995 list_remove(&(strm_if->buf_map.uv_buf_done), buf);
2996 }
2997 buf = strm_if->buf_map.buf_head;
2998 if (!buf) {
2999 USB_DPRINTF_L2(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
3000 "usbvc_free_map_bufs: no data buf need be freed, return");
3001
3002 return;
3003 }
3004 if (buf->umem_cookie) {
3005 ddi_umem_free(buf->umem_cookie);
3006 }
3007 kmem_free(buf, sizeof (usbvc_buf_t) * strm_if->buf_map.buf_cnt);
3008 strm_if->buf_map.buf_cnt = 0;
3009 strm_if->buf_map.buf_head = NULL;
3010
3011 USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
3012 "usbvc_free_map_bufs: return");
3013 }
3014
3015
3016 /*
3017 * Open the isoc pipe, this pipe is for video data transfer
3018 */
3019 int
usbvc_open_isoc_pipe(usbvc_state_t * usbvcp,usbvc_stream_if_t * strm_if)3020 usbvc_open_isoc_pipe(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
3021 {
3022 usb_pipe_policy_t policy;
3023 int rval = USB_SUCCESS;
3024
3025 ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
3026
3027 if ((rval = usbvc_set_alt(usbvcp, strm_if)) != USB_SUCCESS) {
3028
3029 return (rval);
3030 }
3031 bzero(&policy, sizeof (usb_pipe_policy_t));
3032 policy.pp_max_async_reqs = 2;
3033 mutex_exit(&usbvcp->usbvc_mutex);
3034 if ((rval = usb_pipe_open(usbvcp->usbvc_dip, strm_if->curr_ep, &policy,
3035 USB_FLAGS_SLEEP, &strm_if->datain_ph)) != USB_SUCCESS) {
3036 USB_DPRINTF_L2(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
3037 "usbvc_open_isoc_pipe: open pipe fail");
3038 mutex_enter(&usbvcp->usbvc_mutex);
3039
3040 return (rval);
3041 }
3042 mutex_enter(&usbvcp->usbvc_mutex);
3043 strm_if->start_polling = 0;
3044
3045 strm_if->stream_on = 0;
3046
3047 USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
3048 "usbvc_open_isoc_pipe: success, datain_ph=%p",
3049 (void *)strm_if->datain_ph);
3050
3051 return (rval);
3052 }
3053
3054
3055 /*
3056 * Open the isoc pipe
3057 */
3058 static void
usbvc_close_isoc_pipe(usbvc_state_t * usbvcp,usbvc_stream_if_t * strm_if)3059 usbvc_close_isoc_pipe(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
3060 {
3061 ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
3062 if (!strm_if) {
3063 USB_DPRINTF_L2(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
3064 "usbvc_close_isoc_pipe: stream interface is NULL");
3065
3066 return;
3067 }
3068 if (strm_if->datain_ph) {
3069 mutex_exit(&usbvcp->usbvc_mutex);
3070 usb_pipe_close(usbvcp->usbvc_dip, strm_if->datain_ph,
3071 USB_FLAGS_SLEEP, NULL, NULL);
3072 mutex_enter(&usbvcp->usbvc_mutex);
3073 }
3074 strm_if->datain_ph = NULL;
3075 }
3076
3077
3078 /*
3079 * Start to get video data from isoc pipe in the stream interface,
3080 * issue isoc req.
3081 */
3082 int
usbvc_start_isoc_polling(usbvc_state_t * usbvcp,usbvc_stream_if_t * strm_if,uchar_t io_type)3083 usbvc_start_isoc_polling(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if,
3084 uchar_t io_type)
3085 {
3086 int rval = USB_SUCCESS;
3087 uint_t if_num;
3088 usb_isoc_req_t *req;
3089 ushort_t pkt_size;
3090 ushort_t n_pkt, pkt;
3091 uint32_t frame_size;
3092
3093 ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
3094 pkt_size = HS_PKT_SIZE(strm_if->curr_ep->wMaxPacketSize);
3095 if_num = strm_if->if_descr->if_alt->altif_descr.bInterfaceNumber;
3096 LE_TO_UINT32(strm_if->ctrl_pc.dwMaxVideoFrameSize, 0, frame_size);
3097 n_pkt = (frame_size + (pkt_size) - 1) / (pkt_size);
3098
3099 USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
3100 "usbvc_start_isoc_polling: if_num=%d, alt=%d, n_pkt=%d,"
3101 " pkt_size=0x%x, MaxPacketSize=0x%x(Tsac#=%d), frame_size=0x%x",
3102 if_num, strm_if->curr_alt, n_pkt, pkt_size,
3103 strm_if->curr_ep->wMaxPacketSize,
3104 (1 + ((strm_if->curr_ep->wMaxPacketSize>> 11) & 3)),
3105 frame_size);
3106
3107 if (n_pkt > USBVC_MAX_PKTS) {
3108 n_pkt = USBVC_MAX_PKTS;
3109 }
3110 USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
3111 "usbvc_start_isoc_polling: n_pkt=%d", n_pkt);
3112
3113 mutex_exit(&usbvcp->usbvc_mutex);
3114 if ((req = usb_alloc_isoc_req(usbvcp->usbvc_dip, n_pkt,
3115 n_pkt * pkt_size, USB_FLAGS_SLEEP)) != NULL) {
3116 mutex_enter(&usbvcp->usbvc_mutex);
3117
3118 /* Initialize the packet descriptor */
3119 for (pkt = 0; pkt < n_pkt; pkt++) {
3120 req->isoc_pkt_descr[pkt].isoc_pkt_length = pkt_size;
3121 }
3122
3123 req->isoc_pkts_count = n_pkt;
3124
3125 /*
3126 * zero here indicates that HCDs will use
3127 * isoc_pkt_descr->isoc_pkt_length to calculate
3128 * isoc_pkts_length.
3129 */
3130 req->isoc_pkts_length = 0;
3131 req->isoc_attributes = USB_ATTRS_ISOC_XFER_ASAP |
3132 USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING;
3133 req->isoc_cb = usbvc_isoc_cb;
3134 req->isoc_exc_cb = usbvc_isoc_exc_cb;
3135 usbvcp->usbvc_io_type = io_type;
3136 req->isoc_client_private = (usb_opaque_t)usbvcp;
3137 mutex_exit(&usbvcp->usbvc_mutex);
3138 rval = usb_pipe_isoc_xfer(strm_if->datain_ph, req, 0);
3139 mutex_enter(&usbvcp->usbvc_mutex);
3140 } else {
3141 mutex_enter(&usbvcp->usbvc_mutex);
3142 USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
3143 "usbvc_start_isoc_polling: alloc_isoc_req fail");
3144
3145 return (USB_FAILURE);
3146 }
3147
3148 if (rval != USB_SUCCESS) {
3149 if (req) {
3150 usb_free_isoc_req(req);
3151 req = NULL;
3152 }
3153 }
3154 USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
3155 "usbvc_start_isoc_polling: return, rval=%d", rval);
3156
3157 return (rval);
3158 }
3159
3160 /* callbacks for receiving video data (isco in transfer) */
3161
3162 /*ARGSUSED*/
3163 /* Isoc transfer callback, get video data */
3164 static void
usbvc_isoc_cb(usb_pipe_handle_t ph,usb_isoc_req_t * isoc_req)3165 usbvc_isoc_cb(usb_pipe_handle_t ph, usb_isoc_req_t *isoc_req)
3166 {
3167 usbvc_state_t *usbvcp =
3168 (usbvc_state_t *)isoc_req->isoc_client_private;
3169 int i;
3170 mblk_t *data = isoc_req->isoc_data;
3171 usbvc_buf_grp_t *bufgrp;
3172
3173 mutex_enter(&usbvcp->usbvc_mutex);
3174
3175 USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3176 "usbvc_isoc_cb: rq=0x%p, fno=%" PRId64 ", n_pkts=%u, flag=0x%x,"
3177 " data=0x%p, cnt=%d",
3178 (void *)isoc_req, isoc_req->isoc_frame_no,
3179 isoc_req->isoc_pkts_count, isoc_req->isoc_attributes,
3180 (void *)isoc_req->isoc_data, isoc_req->isoc_error_count);
3181
3182 ASSERT((isoc_req->isoc_cb_flags & USB_CB_INTR_CONTEXT) != 0);
3183 for (i = 0; i < isoc_req->isoc_pkts_count; i++) {
3184
3185 USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3186 "\tpkt%d: "
3187 "pktsize=%d status=%d resid=%d",
3188 i,
3189 isoc_req->isoc_pkt_descr[i].isoc_pkt_length,
3190 isoc_req->isoc_pkt_descr[i].isoc_pkt_status,
3191 isoc_req->isoc_pkt_descr[i].isoc_pkt_actual_length);
3192
3193 if (isoc_req->isoc_pkt_descr[i].isoc_pkt_status !=
3194 USB_CR_OK) {
3195 USB_DPRINTF_L3(PRINT_MASK_CB,
3196 usbvcp->usbvc_log_handle,
3197 "record: pkt=%d status=%s", i, usb_str_cr(
3198 isoc_req->isoc_pkt_descr[i].isoc_pkt_status));
3199 }
3200
3201 if (usbvcp->usbvc_io_type == V4L2_MEMORY_MMAP) {
3202 bufgrp = &usbvcp->usbvc_curr_strm->buf_map;
3203 } else {
3204 bufgrp = &usbvcp->usbvc_curr_strm->buf_read;
3205 }
3206
3207 if (isoc_req->isoc_pkt_descr[i].isoc_pkt_actual_length) {
3208 if (usbvc_decode_stream_header(usbvcp, bufgrp, data,
3209 isoc_req->isoc_pkt_descr[i].isoc_pkt_actual_length)
3210 != USB_SUCCESS) {
3211 USB_DPRINTF_L3(PRINT_MASK_CB,
3212 usbvcp->usbvc_log_handle, "decode error");
3213 }
3214 if (bufgrp->buf_filling &&
3215 (bufgrp->buf_filling->status == USBVC_BUF_ERR ||
3216 bufgrp->buf_filling->status == USBVC_BUF_DONE)) {
3217
3218 /* Move the buf to the full list */
3219 list_insert_tail(&bufgrp->uv_buf_done,
3220 bufgrp->buf_filling);
3221
3222 bufgrp->buf_filling = NULL;
3223
3224 if (usbvcp->usbvc_io_type == V4L2_MEMORY_MMAP) {
3225 cv_broadcast(&usbvcp->usbvc_mapio_cv);
3226 } else {
3227 cv_broadcast(&usbvcp->usbvc_read_cv);
3228 }
3229 }
3230 }
3231
3232 data->b_rptr += isoc_req->isoc_pkt_descr[i].isoc_pkt_length;
3233 }
3234 mutex_exit(&usbvcp->usbvc_mutex);
3235 usb_free_isoc_req(isoc_req);
3236 }
3237
3238
3239 /*ARGSUSED*/
3240 static void
usbvc_isoc_exc_cb(usb_pipe_handle_t ph,usb_isoc_req_t * isoc_req)3241 usbvc_isoc_exc_cb(usb_pipe_handle_t ph, usb_isoc_req_t *isoc_req)
3242 {
3243 usbvc_state_t *usbvcp =
3244 (usbvc_state_t *)isoc_req->isoc_client_private;
3245 usb_cr_t completion_reason;
3246 int rval;
3247 usbvc_stream_if_t *strm_if;
3248
3249 ASSERT(!list_is_empty(&usbvcp->usbvc_stream_list));
3250
3251 mutex_enter(&usbvcp->usbvc_mutex);
3252
3253 /* get the first stream interface */
3254 strm_if = usbvcp->usbvc_curr_strm;
3255
3256 completion_reason = isoc_req->isoc_completion_reason;
3257
3258 USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3259 "usbvc_isoc_exc_cb: ph=0x%p, isoc_req=0x%p, cr=%d",
3260 (void *)ph, (void *)isoc_req, completion_reason);
3261
3262 ASSERT((isoc_req->isoc_cb_flags & USB_CB_INTR_CONTEXT) == 0);
3263
3264 switch (completion_reason) {
3265 case USB_CR_STOPPED_POLLING:
3266 case USB_CR_PIPE_CLOSING:
3267 case USB_CR_PIPE_RESET:
3268
3269 break;
3270 case USB_CR_NO_RESOURCES:
3271 /*
3272 * keep the show going: Since we have the original
3273 * request, we just resubmit it
3274 */
3275 rval = usb_pipe_isoc_xfer(strm_if->datain_ph, isoc_req,
3276 USB_FLAGS_NOSLEEP);
3277 USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3278 "usbvc_isoc_exc_cb: restart capture rval=%d", rval);
3279 mutex_exit(&usbvcp->usbvc_mutex);
3280
3281 return;
3282 default:
3283 mutex_exit(&usbvcp->usbvc_mutex);
3284 usb_pipe_stop_isoc_polling(ph, USB_FLAGS_NOSLEEP);
3285 USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3286 "usbvc_isoc_exc_cb: stop polling");
3287 mutex_enter(&usbvcp->usbvc_mutex);
3288 }
3289 usb_free_isoc_req(isoc_req);
3290 strm_if->start_polling = 0;
3291 USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3292 "usbvc_isoc_exc_cb: start_polling=%d cr=%d",
3293 strm_if->start_polling, completion_reason);
3294 mutex_exit(&usbvcp->usbvc_mutex);
3295 }
3296
3297 /*
3298 * Other utility functions
3299 */
3300
3301 /*
3302 * Find a proper alternate according to the bandwidth that the current video
3303 * format need;
3304 * Set alternate by calling usb_set_alt_if;
3305 * Called before open pipes in stream interface.
3306 */
3307 static int
usbvc_set_alt(usbvc_state_t * usbvcp,usbvc_stream_if_t * strm_if)3308 usbvc_set_alt(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
3309 {
3310 usb_alt_if_data_t *alt;
3311 uint_t i, j, if_num;
3312 uint16_t pktsize, curr_pktsize;
3313 uint32_t bandwidth;
3314 int rval = USB_SUCCESS;
3315 usbvc_input_header_t *ihd;
3316 usbvc_output_header_t *ohd;
3317
3318 ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
3319
3320 LE_TO_UINT32(strm_if->ctrl_pc.dwMaxPayloadTransferSize, 0, bandwidth);
3321 if (!bandwidth) {
3322 USB_DPRINTF_L2(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
3323 "usbvc_set_alt: bandwidth is not set yet");
3324
3325 return (USB_FAILURE);
3326 }
3327 USB_DPRINTF_L3(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
3328 "usbvc_set_alt: bandwidth=%x", bandwidth);
3329
3330 strm_if->curr_ep = NULL;
3331 curr_pktsize = 0xffff;
3332 ohd = strm_if->output_header;
3333 ihd = strm_if->input_header;
3334 /*
3335 * Find one alternate setting whose isoc ep's max pktsize is just
3336 * enough for the bandwidth.
3337 */
3338 for (i = 0; i < strm_if->if_descr->if_n_alt; i++) {
3339 alt = &strm_if->if_descr->if_alt[i];
3340
3341 for (j = 0; j < alt->altif_n_ep; j++) {
3342
3343 /* if this stream interface is for input */
3344 if (ihd != NULL &&
3345 alt->altif_ep[j].ep_descr.bEndpointAddress !=
3346 ihd->descr->bEndpointAddress) {
3347
3348 continue;
3349 }
3350 /* if this stream interface is for output */
3351 if (ohd != NULL &&
3352 alt->altif_ep[j].ep_descr.bEndpointAddress !=
3353 ohd->descr->bEndpointAddress) {
3354
3355 continue;
3356 }
3357 pktsize =
3358 alt->altif_ep[j].ep_descr.wMaxPacketSize;
3359 pktsize = HS_PKT_SIZE(pktsize);
3360 if (pktsize >= bandwidth && pktsize < curr_pktsize) {
3361 curr_pktsize = pktsize;
3362 strm_if->curr_alt = i;
3363 strm_if->curr_ep = &alt->altif_ep[j].ep_descr;
3364 }
3365 }
3366 }
3367 if (!strm_if->curr_ep) {
3368 USB_DPRINTF_L2(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
3369 "usbvc_set_alt: can't find a proper ep to satisfy"
3370 " the given bandwidth");
3371
3372 return (USB_FAILURE);
3373 }
3374 USB_DPRINTF_L3(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
3375 "usbvc_set_alt: strm_if->curr_alt=%d", strm_if->curr_alt);
3376 if_num = strm_if->if_descr->if_alt->altif_descr.bInterfaceNumber;
3377 mutex_exit(&usbvcp->usbvc_mutex);
3378 if ((rval = usb_set_alt_if(usbvcp->usbvc_dip, if_num, strm_if->curr_alt,
3379 USB_FLAGS_SLEEP, NULL, NULL)) != USB_SUCCESS) {
3380 mutex_enter(&usbvcp->usbvc_mutex);
3381 USB_DPRINTF_L2(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
3382 "usbvc_set_alt: usb_set_alt_if fail, if.alt=%d.%d, rval=%d",
3383 if_num, strm_if->curr_alt, rval);
3384
3385 return (rval);
3386 }
3387 mutex_enter(&usbvcp->usbvc_mutex);
3388
3389 USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
3390 "usbvc_set_alt: return, if_num=%d, alt=%d",
3391 if_num, strm_if->curr_alt);
3392
3393 return (rval);
3394 }
3395
3396
3397 /*
3398 * Decode stream header for mjpeg and uncompressed format video data.
3399 * mjpeg and uncompressed format have the same stream header. See their
3400 * payload spec, 2.2 and 2.4
3401 */
3402 static int
usbvc_decode_stream_header(usbvc_state_t * usbvcp,usbvc_buf_grp_t * bufgrp,mblk_t * data,int actual_len)3403 usbvc_decode_stream_header(usbvc_state_t *usbvcp, usbvc_buf_grp_t *bufgrp,
3404 mblk_t *data, int actual_len)
3405 {
3406 uint32_t len, buf_left, data_len;
3407 usbvc_stream_if_t *strm_if;
3408 uchar_t head_flag, head_len;
3409 usbvc_buf_t *buf_filling;
3410
3411 ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
3412 USB_DPRINTF_L4(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3413 "usbvc_decode_stream_header: enter. actual_len=%x", actual_len);
3414
3415 /* header length check. */
3416 if (actual_len < 2) {
3417 USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3418 "usbvc_decode_stream_header: header is not completed");
3419
3420 return (USB_FAILURE);
3421 }
3422 head_len = data->b_rptr[0];
3423 head_flag = data->b_rptr[1];
3424
3425 USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3426 "usbvc_decode_stream_header: headlen=%x", head_len);
3427
3428 /* header length check. */
3429 if (actual_len < head_len) {
3430 USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3431 "usbvc_decode_stream_header: actual_len < head_len");
3432
3433 return (USB_FAILURE);
3434 }
3435
3436 /*
3437 * If there is no stream data in this packet and this packet is not
3438 * used to indicate the end of a frame, then just skip it.
3439 */
3440 if ((actual_len == head_len) && !(head_flag & USBVC_STREAM_EOF)) {
3441 USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3442 "usbvc_decode_stream_header: only header, no data");
3443
3444 return (USB_FAILURE);
3445 }
3446
3447 /* Get the first stream interface */
3448 strm_if = usbvcp->usbvc_curr_strm;
3449
3450 LE_TO_UINT32(strm_if->ctrl_pc.dwMaxVideoFrameSize, 0, len);
3451 USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3452 "usbvc_decode_stream_header: dwMaxVideoFrameSize=%x, head_flag=%x",
3453 len, head_flag);
3454
3455 /*
3456 * if no buf is filling, pick one buf from free list and alloc data
3457 * mem for the buf.
3458 */
3459 if (!bufgrp->buf_filling) {
3460 if (list_is_empty(&bufgrp->uv_buf_free)) {
3461 strm_if->fid = head_flag & USBVC_STREAM_FID;
3462 USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3463 "usbvc_decode_stream_header: free list are empty");
3464
3465 return (USB_FAILURE);
3466
3467 } else {
3468 bufgrp->buf_filling =
3469 (usbvc_buf_t *)list_head(&bufgrp->uv_buf_free);
3470
3471 /* unlink from buf free list */
3472 list_remove(&bufgrp->uv_buf_free, bufgrp->buf_filling);
3473 }
3474 bufgrp->buf_filling->filled = 0;
3475 USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3476 "usbvc_decode_stream_header: status=%d",
3477 bufgrp->buf_filling->status);
3478 bufgrp->buf_filling->status = USBVC_BUF_EMPTY;
3479 }
3480 buf_filling = bufgrp->buf_filling;
3481 ASSERT(buf_filling->len >= buf_filling->filled);
3482 buf_left = buf_filling->len - buf_filling->filled;
3483
3484 /* if no buf room left, then return with a err status */
3485 if (buf_left == 0) {
3486 /* buffer full, got an EOF packet(head only, no payload) */
3487 if ((head_flag & USBVC_STREAM_EOF) &&
3488 (actual_len == head_len)) {
3489 buf_filling->status = USBVC_BUF_DONE;
3490 USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3491 "usbvc_decode_stream_header: got a EOF packet");
3492
3493 return (USB_SUCCESS);
3494 }
3495
3496 /* Otherwise, mark the buf error and return failure */
3497 buf_filling->status = USBVC_BUF_ERR;
3498 USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3499 "usbvc_decode_stream_header: frame buf full");
3500
3501 return (USB_FAILURE);
3502 }
3503
3504 /* get this sample's data length except header */
3505 data_len = actual_len - head_len;
3506 USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3507 "usbvc_decode_stream_header: fid=%x, len=%x, filled=%x",
3508 strm_if->fid, buf_filling->len, buf_filling->filled);
3509
3510 /* if the first sample for a frame */
3511 if (buf_filling->filled == 0) {
3512 /*
3513 * Only if it is the frist packet of a frame,
3514 * we will begin filling a frame.
3515 */
3516 if (strm_if->fid != 0xff && strm_if->fid ==
3517 (head_flag & USBVC_STREAM_FID)) {
3518 USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3519 "usbvc_decode_stream_header: 1st sample of a frame,"
3520 " fid is incorrect.");
3521
3522 return (USB_FAILURE);
3523 }
3524 strm_if->fid = head_flag & USBVC_STREAM_FID;
3525
3526 /* If in the middle of a frame, fid should be consistent. */
3527 } else if (strm_if->fid != (head_flag & USBVC_STREAM_FID)) {
3528 USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3529 "usbvc_decode_stream_header: fid is incorrect.");
3530 strm_if->fid = head_flag & USBVC_STREAM_FID;
3531 buf_filling->status = USBVC_BUF_ERR;
3532
3533 return (USB_FAILURE);
3534 }
3535 if (data_len) {
3536 bcopy((void *)(data->b_rptr + head_len),
3537 (void *)(buf_filling->data + buf_filling->filled),
3538 min(data_len, buf_left));
3539
3540 buf_filling->filled += min(data_len, buf_left);
3541 }
3542
3543 /* If the last packet for this frame */
3544 if (head_flag & USBVC_STREAM_EOF) {
3545 buf_filling->status = USBVC_BUF_DONE;
3546 }
3547 if (data_len > buf_left) {
3548 buf_filling->status = USBVC_BUF_ERR;
3549 }
3550 USB_DPRINTF_L4(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3551 "usbvc_decode_stream_header: buf_status=%d", buf_filling->status);
3552
3553 return (USB_SUCCESS);
3554 }
3555
3556
3557 /*
3558 * usbvc_serialize_access:
3559 * Get the serial synchronization object before returning.
3560 *
3561 * Arguments:
3562 * usbvcp - Pointer to usbvc state structure
3563 * waitsig - Set to:
3564 * USBVC_SER_SIG - to wait such that a signal can interrupt
3565 * USBVC_SER_NOSIG - to wait such that a signal cannot interrupt
3566 */
3567 static int
usbvc_serialize_access(usbvc_state_t * usbvcp,boolean_t waitsig)3568 usbvc_serialize_access(usbvc_state_t *usbvcp, boolean_t waitsig)
3569 {
3570 int rval = 1;
3571
3572 ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
3573
3574 while (usbvcp->usbvc_serial_inuse) {
3575 if (waitsig == USBVC_SER_SIG) {
3576 rval = cv_wait_sig(&usbvcp->usbvc_serial_cv,
3577 &usbvcp->usbvc_mutex);
3578 } else {
3579 cv_wait(&usbvcp->usbvc_serial_cv,
3580 &usbvcp->usbvc_mutex);
3581 }
3582 }
3583 usbvcp->usbvc_serial_inuse = B_TRUE;
3584
3585 return (rval);
3586 }
3587
3588
3589 /*
3590 * usbvc_release_access:
3591 * Release the serial synchronization object.
3592 */
3593 static void
usbvc_release_access(usbvc_state_t * usbvcp)3594 usbvc_release_access(usbvc_state_t *usbvcp)
3595 {
3596 ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
3597 usbvcp->usbvc_serial_inuse = B_FALSE;
3598 cv_broadcast(&usbvcp->usbvc_serial_cv);
3599 }
3600
3601
3602 /* Send req to video control interface to get ctrl */
3603 int
usbvc_vc_get_ctrl(usbvc_state_t * usbvcp,uint8_t req_code,uint8_t entity_id,uint16_t cs,uint16_t wlength,mblk_t * data)3604 usbvc_vc_get_ctrl(usbvc_state_t *usbvcp, uint8_t req_code, uint8_t entity_id,
3605 uint16_t cs, uint16_t wlength, mblk_t *data)
3606 {
3607 usb_cb_flags_t cb_flags;
3608 usb_cr_t cr;
3609 usb_ctrl_setup_t setup;
3610
3611 setup.bmRequestType = USBVC_GET_IF; /* bmRequestType */
3612 setup.bRequest = req_code; /* bRequest */
3613 setup.wValue = cs<<8;
3614 setup.wIndex = entity_id<<8;
3615 setup.wLength = wlength;
3616 setup.attrs = 0;
3617
3618 if (usb_pipe_ctrl_xfer_wait(usbvcp->usbvc_default_ph, &setup, &data,
3619 &cr, &cb_flags, 0) != USB_SUCCESS) {
3620 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3621 "usbvc_vc_get_ctrl: cmd failed, cr=%d, cb_flags=%x",
3622 cr, cb_flags);
3623
3624 return (USB_FAILURE);
3625 }
3626
3627 return (USB_SUCCESS);
3628 }
3629
3630
3631 /* Send req to video control interface to get ctrl */
3632 int
usbvc_vc_set_ctrl(usbvc_state_t * usbvcp,uint8_t req_code,uint8_t entity_id,uint16_t cs,uint16_t wlength,mblk_t * data)3633 usbvc_vc_set_ctrl(usbvc_state_t *usbvcp, uint8_t req_code, uint8_t entity_id,
3634 uint16_t cs, uint16_t wlength, mblk_t *data)
3635 {
3636 usb_cb_flags_t cb_flags;
3637 usb_cr_t cr;
3638 usb_ctrl_setup_t setup;
3639
3640 setup.bmRequestType = USBVC_SET_IF; /* bmRequestType */
3641 setup.bRequest = req_code; /* bRequest */
3642 setup.wValue = cs<<8;
3643 setup.wIndex = entity_id<<8;
3644 setup.wLength = wlength;
3645 setup.attrs = 0;
3646
3647 if (usb_pipe_ctrl_xfer_wait(usbvcp->usbvc_default_ph, &setup, &data,
3648 &cr, &cb_flags, 0) != USB_SUCCESS) {
3649 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3650 "usbvc_vc_set_ctrl: cmd failed, cr=%d, cb_flags=%x",
3651 cr, cb_flags);
3652
3653 return (USB_FAILURE);
3654 }
3655
3656 return (USB_SUCCESS);
3657 }
3658
3659
3660 /* Set probe or commit ctrl for video stream interface */
3661 int
usbvc_vs_set_probe_commit(usbvc_state_t * usbvcp,usbvc_stream_if_t * strm_if,usbvc_vs_probe_commit_t * ctrl_pc,uchar_t cs)3662 usbvc_vs_set_probe_commit(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if,
3663 usbvc_vs_probe_commit_t *ctrl_pc, uchar_t cs)
3664 {
3665 mblk_t *data;
3666 usb_cb_flags_t cb_flags;
3667 usb_cr_t cr;
3668 usb_ctrl_setup_t setup;
3669 int rval;
3670
3671 setup.bmRequestType = USBVC_SET_IF; /* bmRequestType */
3672 setup.bRequest = SET_CUR; /* bRequest */
3673
3674 /* wValue, VS_PROBE_CONTROL or VS_COMMIT_CONTROL */
3675 setup.wValue = cs;
3676
3677 /* UVC Spec: this value must be put to the high byte */
3678 setup.wValue = setup.wValue << 8;
3679
3680 setup.wIndex = strm_if->if_descr->if_alt->altif_descr.bInterfaceNumber;
3681 setup.wLength = usbvcp->usbvc_vc_header->descr->bcdUVC[0] ? 34 : 26;
3682 setup.attrs = 0;
3683
3684 USB_DPRINTF_L3(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3685 "usbvc_vs_set_probe_commit: wLength=%d", setup.wLength);
3686
3687 /* Data block */
3688 if ((data = allocb(setup.wLength, BPRI_HI)) == NULL) {
3689 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3690 "usbvc_vs_set_probe_commit: allocb failed");
3691
3692 return (USB_FAILURE);
3693 }
3694
3695 bcopy(ctrl_pc, data->b_rptr, setup.wLength);
3696 data->b_wptr += setup.wLength;
3697
3698 if ((rval = usb_pipe_ctrl_xfer_wait(usbvcp->usbvc_default_ph, &setup,
3699 &data, &cr, &cb_flags, 0)) != USB_SUCCESS) {
3700 if (data) {
3701 freemsg(data);
3702 }
3703 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3704 "usbvc_vs_set_probe_commit: fail, rval=%d, cr=%d, "
3705 "cb_flags=%x", rval, cr, cb_flags);
3706
3707 return (rval);
3708 }
3709 if (data) {
3710 freemsg(data);
3711 }
3712
3713 return (USB_SUCCESS);
3714 }
3715
3716
3717 /* Get probe ctrl for vodeo stream interface */
3718 int
usbvc_vs_get_probe(usbvc_state_t * usbvcp,usbvc_stream_if_t * strm_if,usbvc_vs_probe_commit_t * ctrl_pc,uchar_t bRequest)3719 usbvc_vs_get_probe(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if,
3720 usbvc_vs_probe_commit_t *ctrl_pc, uchar_t bRequest)
3721 {
3722 mblk_t *data = NULL;
3723 usb_cb_flags_t cb_flags;
3724 usb_cr_t cr;
3725 usb_ctrl_setup_t setup;
3726
3727 setup.bmRequestType = USBVC_GET_IF; /* bmRequestType */
3728 setup.bRequest = bRequest; /* bRequest */
3729 setup.wValue = VS_PROBE_CONTROL; /* wValue, PROBE or COMMIT */
3730 setup.wValue = setup.wValue << 8;
3731 setup.wIndex =
3732 (uint16_t)strm_if->if_descr->if_alt->altif_descr.bInterfaceNumber;
3733 setup.wLength = usbvcp->usbvc_vc_header->descr->bcdUVC[0] ? 34 : 26;
3734
3735 setup.attrs = 0;
3736
3737 if (usb_pipe_ctrl_xfer_wait(usbvcp->usbvc_default_ph, &setup, &data,
3738 &cr, &cb_flags, 0) != USB_SUCCESS) {
3739 if (data) {
3740 freemsg(data);
3741 }
3742 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3743 "usbvc_vs_get_probe: cmd failed, cr=%d, cb_flags=%x",
3744 cr, cb_flags);
3745
3746 return (USB_FAILURE);
3747 }
3748 bcopy(data->b_rptr, ctrl_pc, setup.wLength);
3749 if (data) {
3750 freemsg(data);
3751 }
3752
3753 return (USB_SUCCESS);
3754 }
3755
3756
3757 /* Set a default format when open the device */
3758 static int
usbvc_set_default_stream_fmt(usbvc_state_t * usbvcp)3759 usbvc_set_default_stream_fmt(usbvc_state_t *usbvcp)
3760 {
3761 usbvc_vs_probe_commit_t ctrl, ctrl_get;
3762 usbvc_stream_if_t *strm_if;
3763 usbvc_format_group_t *curr_fmtgrp;
3764 uint32_t bandwidth;
3765 uint8_t index, i;
3766
3767 USB_DPRINTF_L4(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3768 "usbvc_set_default_stream_fmt: enter");
3769
3770 mutex_enter(&usbvcp->usbvc_mutex);
3771 if (list_is_empty(&usbvcp->usbvc_stream_list)) {
3772 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3773 "usbvc_set_default_stream_fmt: no stream interface, fail");
3774 mutex_exit(&usbvcp->usbvc_mutex);
3775
3776 return (USB_FAILURE);
3777 }
3778 bzero((void *)&ctrl, sizeof (usbvc_vs_probe_commit_t));
3779
3780 /* Get the current stream interface */
3781 strm_if = usbvcp->usbvc_curr_strm;
3782
3783 /* Fill the probe commit req data */
3784 ctrl.bmHint[0] = 0;
3785
3786 for (i = 0; i < strm_if->fmtgrp_cnt; i++) {
3787 curr_fmtgrp = &strm_if->format_group[i];
3788
3789 /*
3790 * If v4l2_pixelformat is NULL, then that means there is not
3791 * a parsed format in format_group[i].
3792 */
3793 if (!curr_fmtgrp || !curr_fmtgrp->v4l2_pixelformat ||
3794 curr_fmtgrp->frame_cnt == 0) {
3795 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL,
3796 usbvcp->usbvc_log_handle,
3797 "usbvc_set_default_stream_fmt: no frame, fail");
3798
3799 continue;
3800 } else {
3801
3802 break;
3803 }
3804 }
3805 if (!curr_fmtgrp || curr_fmtgrp->frame_cnt == 0) {
3806 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3807 "usbvc_set_default_stream_fmt: can't find a fmtgrp"
3808 "which has a frame, fail");
3809 mutex_exit(&usbvcp->usbvc_mutex);
3810
3811 return (USB_FAILURE);
3812 }
3813
3814 ctrl.bFormatIndex = curr_fmtgrp->format->bFormatIndex;
3815
3816 /* use the first frame descr as default */
3817 ctrl.bFrameIndex = curr_fmtgrp->frames[0].descr->bFrameIndex;
3818
3819 /* use bcopy to keep the byte sequence as 32 bit little endian */
3820 bcopy(&(curr_fmtgrp->frames[0].descr->dwDefaultFrameInterval[0]),
3821 &(ctrl.dwFrameInterval[0]), 4);
3822
3823 mutex_exit(&usbvcp->usbvc_mutex);
3824 if (usbvc_vs_set_probe_commit(usbvcp, strm_if, &ctrl, VS_PROBE_CONTROL)
3825 != USB_SUCCESS) {
3826
3827 return (USB_FAILURE);
3828 }
3829 if (usbvc_vs_get_probe(usbvcp, strm_if, &ctrl_get, GET_CUR)
3830 != USB_SUCCESS) {
3831
3832 return (USB_FAILURE);
3833 }
3834
3835 mutex_enter(&usbvcp->usbvc_mutex);
3836 LE_TO_UINT32(strm_if->ctrl_pc.dwMaxPayloadTransferSize, 0, bandwidth);
3837 USB_DPRINTF_L3(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3838 "usbvc_set_default_stream_fmt: get bandwidth=%x", bandwidth);
3839
3840 mutex_exit(&usbvcp->usbvc_mutex);
3841 if (usbvc_vs_set_probe_commit(usbvcp, strm_if, &ctrl_get,
3842 VS_COMMIT_CONTROL) != USB_SUCCESS) {
3843
3844 return (USB_FAILURE);
3845 }
3846
3847 mutex_enter(&usbvcp->usbvc_mutex);
3848
3849 /* it's good to check index here before use it */
3850 index = ctrl_get.bFormatIndex - curr_fmtgrp->format->bFormatIndex;
3851 if (index < strm_if->fmtgrp_cnt) {
3852 strm_if->cur_format_group = &strm_if->format_group[index];
3853 } else {
3854 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3855 "usbvc_set_default_stream_fmt: format index out of range");
3856 mutex_exit(&usbvcp->usbvc_mutex);
3857
3858 return (USB_FAILURE);
3859 }
3860
3861 index = ctrl_get.bFrameIndex -
3862 strm_if->cur_format_group->frames[0].descr->bFrameIndex;
3863 if (index < strm_if->cur_format_group->frame_cnt) {
3864 strm_if->cur_format_group->cur_frame =
3865 &strm_if->cur_format_group->frames[index];
3866 } else {
3867 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3868 "usbvc_set_default_stream: frame index out of range");
3869 mutex_exit(&usbvcp->usbvc_mutex);
3870
3871 return (USB_FAILURE);
3872 }
3873
3874 /*
3875 * by now, the video format is set successfully. record the current
3876 * setting to strm_if->ctrl_pc
3877 */
3878 bcopy(&ctrl_get, &strm_if->ctrl_pc, sizeof (usbvc_vs_probe_commit_t));
3879
3880 mutex_exit(&usbvcp->usbvc_mutex);
3881
3882 return (USB_SUCCESS);
3883 }
3884