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