4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
26 * Copyright (c) 2018, Joyent, Inc.
30 * USB video class driver (usbvc(7D))
35 * This driver supports USB video class devices that used to capture video,
36 * e.g., some webcams. It is developed according to "USB Device Class
37 * Definition for Video Devices" spec. This spec defines detail info needed by
38 * designing a USB video device. It is available at:
39 * http://www.usb.org/developers/devclass_docs
41 * This driver implements:
43 * - V4L2 interfaces for applications to communicate with video devices.
44 * V4L2 is an API that is widely used by video applications, like Ekiga,
45 * luvcview, etc. The API spec is at:
46 * http://www.thedirks.org/v4l2/
47 * This driver is according to V4L2 spec version 0.20
49 * - Video capture function. (Video output is not supported by now.)
51 * - Isochronous transfer for video data. (Bulk transfer is not supported.)
53 * - read & mmap I/O methods for userland video applications to get video
54 * data. Userland video applications can use read() system call directly,
55 * it is the simplest way but not the most efficient way. Applications can
56 * also use mmap() system call to map several bufs (they are linked as a
57 * buf list), and then use some specific ioctls to start/stop isoc polling,
58 * to queue/dequeue bufs.
60 * 2. Source and header files
61 * ---------------------------
63 * There are two source files and three header files for this driver:
65 * - usbvc.c Main source file, implements usb video class spec.
67 * - usbvc_v4l2.c V4L2 interface specific code.
69 * - usbvc_var.h Main header file, includes soft state structure.
71 * - usbvc.h The descriptors in usb video class spec.
73 * - videodev2.h This header file is included in V4L2 spec. It defines
74 * ioctls and data structures that used as an interface between video
75 * applications and video drivers. This is the only header file that
76 * usbvc driver should export to userland application.
78 * 3. USB video class devices overview
79 * -----------------------------------
80 * According to UVC spec, there must be one control interface in a UVC device.
81 * Control interface is used to receive control commands from user, all the
82 * commands are sent through default ctrl pipe. usbvc driver implements V4L2
83 * API, so ioctls are implemented to relay user commands to UVC device.
85 * There can be no or multiple stream interfaces in a UVC device. Stream
86 * interfaces are used to do video data I/O. In practice, if no stream
87 * interface, the video device can do nothing since it has no data I/O.
89 * usbvc driver parses descriptors of control interface and stream interfaces.
90 * The descriptors tell the function layout and the capability of the device.
91 * During attach, usbvc driver set up some key data structures according to
97 * Userland applications use ioctls to set/get video formats of the device,
98 * and control brightness, contrast, image size, etc.
100 * Besides implementing standard read I/O method to get video data from
101 * the device, usbvc driver also implements some specific ioctls to implement
104 * A view from userland application: ioctl and mmap flow chart:
106 * REQBUFS -> QUERYBUF -> mmap() ->
108 * -> QBUF -> STREAMON -> DQBUF -> process image -> QBUF
112 * |---<--------------------
114 * The above queue and dequeue buf operations can be stopped by issuing a
120 * The device has four states (refer to usbai.h):
122 * - USB_DEV_ONLINE: In action or ready for action.
124 * - USB_DEV_DISCONNECTED: Hotplug removed, or device not present/correct
127 * - USB_DEV_SUSPENDED: Device has been suspended along with the system.
129 * - USB_DEV_PWRED_DOWN: Device has been powered down. (Note that this
130 * driver supports only two power states, powered down and
135 * In order to avoid race conditions between driver entry points, access to
136 * the device is serialized. All the ioctls, and read, open/close are
137 * serialized. The functions usbvc_serialize/release_access are implemented
142 * PM & CPR are supported. pm_busy_component and pm_idle_component mark
143 * the device as busy or idle to the system.
147 #define USBDRV_MAJOR_VER 2
148 #define USBDRV_MINOR_VER 0
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 */
156 /* Descriptors according to USB video class spec */
157 #include <sys/usb/clients/video/usbvc/usbvc.h>
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;
163 static char *name
= "usbvc"; /* Driver name, used all over. */
166 * Function Prototypes
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
);
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
*);
198 static int usbvc_disconnect_event_cb(dev_info_t
*);
199 static int usbvc_reconnect_event_cb(dev_info_t
*);
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
*);
209 /* Parse descriptors */
210 static int usbvc_chk_descr_len(uint8_t, uint8_t, uint8_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
*);
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
*);
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
*);
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
*,
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
*);
243 static usb_event_t usbvc_events
= {
244 usbvc_disconnect_event_cb
,
245 usbvc_reconnect_event_cb
,
249 /* module loading stuff */
250 struct cb_ops usbvc_cb_ops
= {
251 usbvc_open
, /* open */
252 usbvc_close
, /* close */
253 usbvc_strategy
, /* strategy */
256 usbvc_read
, /* read */
258 usbvc_ioctl
, /* ioctl */
259 usbvc_devmap
, /* devmap */
261 ddi_devmap_segmap
, /* segmap */
263 ddi_prop_op
, /* cb_prop_op */
264 NULL
, /* streamtab */
268 static struct dev_ops usbvc_ops
= {
269 DEVO_REV
, /* devo_rev, */
271 usbvc_info
, /* info */
272 nulldev
, /* identify */
274 usbvc_attach
, /* attach */
275 usbvc_detach
, /* detach */
277 &usbvc_cb_ops
, /* driver operations */
278 NULL
, /* bus operations */
279 usbvc_power
, /* power */
280 ddi_quiesce_not_needed
, /* quiesce */
283 static struct modldrv usbvc_modldrv
= {
285 "USB video class driver",
289 static struct modlinkage modlinkage
= {
295 /* Soft state structures */
296 #define USBVC_INITIAL_SOFT_SPACE 1
297 static void *usbvc_statep
;
301 * Module-wide initialization routine.
308 if ((rval
= ddi_soft_state_init(&usbvc_statep
,
309 sizeof (usbvc_state_t
), USBVC_INITIAL_SOFT_SPACE
)) != 0) {
314 if ((rval
= mod_install(&modlinkage
)) != 0) {
315 ddi_soft_state_fini(&usbvc_statep
);
323 * Module-wide tear-down routine.
330 if ((rval
= mod_remove(&modlinkage
)) != 0) {
335 ddi_soft_state_fini(&usbvc_statep
);
342 _info(struct modinfo
*modinfop
)
344 return (mod_info(&modlinkage
, modinfop
));
350 * Get minor number, soft state structure, etc.
354 usbvc_info(dev_info_t
*dip
, ddi_info_cmd_t infocmd
,
355 void *arg
, void **result
)
357 usbvc_state_t
*usbvcp
;
358 int error
= DDI_FAILURE
;
361 case DDI_INFO_DEVT2DEVINFO
:
362 if ((usbvcp
= ddi_get_soft_state(usbvc_statep
,
363 getminor((dev_t
)arg
))) != NULL
) {
364 *result
= usbvcp
->usbvc_dip
;
365 if (*result
!= NULL
) {
372 case DDI_INFO_DEVT2INSTANCE
:
373 *result
= (void *)(uintptr_t)getminor((dev_t
)arg
);
392 * For attach, initialize state and device, including:
393 * state variables, locks, device node
394 * device registration with system
395 * power management, hotplugging
396 * For resume, restore device and state
399 usbvc_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
401 int instance
= ddi_get_instance(dip
);
402 usbvc_state_t
*usbvcp
= NULL
;
410 usbvc_cpr_resume(dip
);
412 return (DDI_SUCCESS
);
415 return (DDI_FAILURE
);
418 if (ddi_soft_state_zalloc(usbvc_statep
, instance
) == DDI_SUCCESS
) {
419 usbvcp
= ddi_get_soft_state(usbvc_statep
, instance
);
421 if (usbvcp
== NULL
) {
423 return (DDI_FAILURE
);
426 usbvcp
->usbvc_dip
= dip
;
428 usbvcp
->usbvc_log_handle
= usb_alloc_log_hdl(dip
,
429 "usbvc", &usbvc_errlevel
,
430 &usbvc_errmask
, &usbvc_instance_debug
, 0);
432 USB_DPRINTF_L3(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
433 "usbvc_attach: enter");
435 if ((status
= usb_client_attach(dip
, USBDRV_VERSION
, 0)) !=
437 USB_DPRINTF_L2(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
438 "usbvc_attach: usb_client_attach failed, error code:%d",
444 if ((status
= usb_get_dev_data(dip
, &usbvcp
->usbvc_reg
,
445 USB_PARSE_LVL_ALL
, 0)) != USB_SUCCESS
) {
446 USB_DPRINTF_L2(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
447 "usbvc_attach: usb_get_dev_data failed, error code:%d",
452 usbvc_init_sync_objs(usbvcp
);
454 /* create minor node */
455 if ((status
= ddi_create_minor_node(dip
, name
, S_IFCHR
, instance
,
456 "usb_video", 0)) != DDI_SUCCESS
) {
457 USB_DPRINTF_L2(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
458 "usbvc_attach: Error creating minor node, error code:%d",
464 mutex_enter(&usbvcp
->usbvc_mutex
);
465 usbvc_init_lists(usbvcp
);
467 usbvcp
->usbvc_default_ph
= usbvcp
->usbvc_reg
->dev_default_ph
;
469 /* Put online before PM init as can get power managed afterward. */
470 usbvcp
->usbvc_dev_state
= USB_DEV_ONLINE
;
471 mutex_exit(&usbvcp
->usbvc_mutex
);
473 /* initialize power management */
474 usbvc_init_power_mgmt(usbvcp
);
476 if ((status
= usbvc_parse_ctrl_if(usbvcp
)) != USB_SUCCESS
) {
477 USB_DPRINTF_L2(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
478 "usbvc_attach: parse ctrl interface fail, error code:%d",
483 if ((status
= usbvc_parse_stream_ifs(usbvcp
)) != USB_SUCCESS
) {
484 USB_DPRINTF_L2(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
485 "usbvc_attach: parse stream interfaces fail, error code:%d",
490 (void) usbvc_set_default_stream_fmt(usbvcp
);
492 /* Register for events */
493 if ((status
= usb_register_event_cbs(dip
, &usbvc_events
, 0)) !=
495 USB_DPRINTF_L2(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
496 "usbvc_attach: register_event_cbs failed, error code:%d",
505 return (DDI_SUCCESS
);
509 usbvc_cleanup(dip
, usbvcp
);
512 return (DDI_FAILURE
);
518 * detach or suspend driver instance
520 * Note: in detach, only contention threads is from pm and disconnnect.
523 usbvc_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
525 int instance
= ddi_get_instance(dip
);
526 usbvc_state_t
*usbvcp
= ddi_get_soft_state(usbvc_statep
, instance
);
527 int rval
= USB_FAILURE
;
531 mutex_enter(&usbvcp
->usbvc_mutex
);
532 ASSERT((usbvcp
->usbvc_drv_state
& USBVC_OPEN
) == 0);
533 mutex_exit(&usbvcp
->usbvc_mutex
);
535 USB_DPRINTF_L3(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
536 "usbvc_detach: enter for detach");
538 usbvc_cleanup(dip
, usbvcp
);
543 USB_DPRINTF_L3(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
544 "usbvc_detach: enter for suspend");
546 usbvc_cpr_suspend(dip
);
555 return ((rval
== USB_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
561 * clean up the driver state for detach
564 usbvc_cleanup(dev_info_t
*dip
, usbvc_state_t
*usbvcp
)
566 USB_DPRINTF_L4(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
569 if (usbvcp
->usbvc_locks_initialized
) {
571 /* This must be done 1st to prevent more events from coming. */
572 usb_unregister_event_cbs(dip
, &usbvc_events
);
575 * At this point, no new activity can be initiated. The driver
576 * has disabled hotplug callbacks. The Solaris framework has
577 * disabled new opens on a device being detached, and does not
578 * allow detaching an open device.
580 * The following ensures that all driver activity has drained.
582 mutex_enter(&usbvcp
->usbvc_mutex
);
583 (void) usbvc_serialize_access(usbvcp
, USBVC_SER_NOSIG
);
584 usbvc_release_access(usbvcp
);
585 mutex_exit(&usbvcp
->usbvc_mutex
);
587 /* All device activity has died down. */
588 usbvc_destroy_power_mgmt(usbvcp
);
589 mutex_enter(&usbvcp
->usbvc_mutex
);
590 usbvc_fini_lists(usbvcp
);
591 mutex_exit(&usbvcp
->usbvc_mutex
);
593 ddi_remove_minor_node(dip
, NULL
);
594 usbvc_fini_sync_objs(usbvcp
);
597 usb_client_detach(dip
, usbvcp
->usbvc_reg
);
598 usb_free_log_hdl(usbvcp
->usbvc_log_handle
);
599 ddi_soft_state_free(usbvc_statep
, ddi_get_instance(dip
));
600 ddi_prop_remove_all(dip
);
606 usbvc_open(dev_t
*devp
, int flag
, int otyp
, cred_t
*cred_p
)
608 usbvc_state_t
*usbvcp
=
609 ddi_get_soft_state(usbvc_statep
, getminor(*devp
));
611 if (usbvcp
== NULL
) {
617 * Keep it simple: one client at a time.
618 * Exclusive open only
620 mutex_enter(&usbvcp
->usbvc_mutex
);
621 USB_DPRINTF_L4(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
622 "usbvc_open: enter, dev_stat=%d", usbvcp
->usbvc_dev_state
);
624 if (usbvcp
->usbvc_dev_state
== USB_DEV_DISCONNECTED
) {
625 mutex_exit(&usbvcp
->usbvc_mutex
);
629 if (usbvcp
->usbvc_dev_state
== USB_DEV_SUSPENDED
) {
630 mutex_exit(&usbvcp
->usbvc_mutex
);
634 if ((usbvcp
->usbvc_drv_state
& USBVC_OPEN
) != 0) {
635 mutex_exit(&usbvcp
->usbvc_mutex
);
639 usbvcp
->usbvc_drv_state
|= USBVC_OPEN
;
641 if (usbvc_serialize_access(usbvcp
, USBVC_SER_SIG
) == 0) {
642 usbvcp
->usbvc_drv_state
&= ~USBVC_OPEN
;
643 usbvcp
->usbvc_serial_inuse
= B_FALSE
;
644 mutex_exit(&usbvcp
->usbvc_mutex
);
650 usbvc_pm_busy_component(usbvcp
);
651 if (usbvcp
->usbvc_pm
->usbvc_current_power
!= USB_DEV_OS_FULL_PWR
) {
652 usbvcp
->usbvc_pm
->usbvc_raise_power
= B_TRUE
;
653 mutex_exit(&usbvcp
->usbvc_mutex
);
654 (void) pm_raise_power(usbvcp
->usbvc_dip
,
655 0, USB_DEV_OS_FULL_PWR
);
656 mutex_enter(&usbvcp
->usbvc_mutex
);
657 usbvcp
->usbvc_pm
->usbvc_raise_power
= B_FALSE
;
660 /* Device is idle until it is used. */
661 usbvc_release_access(usbvcp
);
662 mutex_exit(&usbvcp
->usbvc_mutex
);
664 USB_DPRINTF_L4(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
673 usbvc_close(dev_t dev
, int flag
, int otyp
, cred_t
*cred_p
)
675 usbvc_stream_if_t
*strm_if
;
677 usbvc_state_t
*usbvcp
=
678 ddi_get_soft_state(usbvc_statep
, getminor(dev
));
680 USB_DPRINTF_L4(PRINT_MASK_CLOSE
, usbvcp
->usbvc_log_handle
,
683 mutex_enter(&usbvcp
->usbvc_mutex
);
684 (void) usbvc_serialize_access(usbvcp
, USBVC_SER_NOSIG
);
685 mutex_exit(&usbvcp
->usbvc_mutex
);
687 /* Perform device session cleanup here. */
689 USB_DPRINTF_L3(PRINT_MASK_CLOSE
, usbvcp
->usbvc_log_handle
,
690 "close: cleaning up...");
693 * USBA automatically flushes/resets active non-default pipes
694 * when they are closed. We can't reset default pipe, but we
695 * can wait for all requests on it from this dip to drain.
697 (void) usb_pipe_drain_reqs(usbvcp
->usbvc_dip
,
698 usbvcp
->usbvc_reg
->dev_default_ph
, 0,
699 USB_FLAGS_SLEEP
, NULL
, 0);
701 mutex_enter(&usbvcp
->usbvc_mutex
);
702 strm_if
= usbvcp
->usbvc_curr_strm
;
703 if (strm_if
->start_polling
== 1) {
704 mutex_exit(&usbvcp
->usbvc_mutex
);
705 usb_pipe_stop_isoc_polling(strm_if
->datain_ph
, USB_FLAGS_SLEEP
);
706 mutex_enter(&usbvcp
->usbvc_mutex
);
707 strm_if
->start_polling
= 0;
709 strm_if
->stream_on
= 0;
711 usbvc_close_isoc_pipe(usbvcp
, strm_if
);
712 if_num
= strm_if
->if_descr
->if_alt
->altif_descr
.bInterfaceNumber
;
713 mutex_exit(&usbvcp
->usbvc_mutex
);
715 /* reset alternate to the default one. */
716 (void) usb_set_alt_if(usbvcp
->usbvc_dip
, if_num
, 0,
717 USB_FLAGS_SLEEP
, NULL
, NULL
);
718 mutex_enter(&usbvcp
->usbvc_mutex
);
720 usbvc_free_read_bufs(usbvcp
, strm_if
);
722 /* reset the desired read buf number to the default value on close */
723 strm_if
->buf_read_num
= USBVC_DEFAULT_READ_BUF_NUM
;
725 usbvc_free_map_bufs(usbvcp
, strm_if
);
726 usbvcp
->usbvc_drv_state
&= ~USBVC_OPEN
;
728 usbvc_release_access(usbvcp
);
729 usbvc_pm_idle_component(usbvcp
);
730 mutex_exit(&usbvcp
->usbvc_mutex
);
737 /* Read isoc data from usb video devices */
739 usbvc_read(dev_t dev
, struct uio
*uio_p
, cred_t
*cred_p
)
742 usbvc_stream_if_t
*strm_if
;
743 usbvc_state_t
*usbvcp
=
744 ddi_get_soft_state(usbvc_statep
, getminor(dev
));
746 USB_DPRINTF_L4(PRINT_MASK_READ
, usbvcp
->usbvc_log_handle
,
747 "usbvc_read: enter");
748 mutex_enter(&usbvcp
->usbvc_mutex
);
749 if (usbvcp
->usbvc_dev_state
!= USB_DEV_ONLINE
) {
750 USB_DPRINTF_L2(PRINT_MASK_READ
, usbvcp
->usbvc_log_handle
,
751 "usbvc_read: Device is not available,"
752 " dev_stat=%d", usbvcp
->usbvc_dev_state
);
753 mutex_exit(&usbvcp
->usbvc_mutex
);
757 if ((uio_p
->uio_fmode
& (FNDELAY
|FNONBLOCK
)) &&
758 (usbvcp
->usbvc_serial_inuse
!= B_FALSE
)) {
759 USB_DPRINTF_L2(PRINT_MASK_READ
, usbvcp
->usbvc_log_handle
,
760 "usbvc_read: non-blocking read, return fail.");
761 mutex_exit(&usbvcp
->usbvc_mutex
);
765 if (usbvc_serialize_access(usbvcp
, USBVC_SER_SIG
) <= 0) {
766 USB_DPRINTF_L2(PRINT_MASK_READ
, usbvcp
->usbvc_log_handle
,
767 "usbvc_read: serialize_access failed.");
773 /* Get the first stream interface */
774 strm_if
= usbvcp
->usbvc_curr_strm
;
776 USB_DPRINTF_L2(PRINT_MASK_READ
, usbvcp
->usbvc_log_handle
,
777 "usbvc_read: no stream interfaces");
784 * If it is the first read, open isoc pipe and allocate bufs for
787 if (strm_if
->datain_ph
== NULL
) {
788 if (usbvc_open_isoc_pipe(usbvcp
, strm_if
) != USB_SUCCESS
) {
789 USB_DPRINTF_L2(PRINT_MASK_READ
,
790 usbvcp
->usbvc_log_handle
,
791 "usbvc_read: first read, open pipe fail");
796 if (usbvc_alloc_read_bufs(usbvcp
, strm_if
) != USB_SUCCESS
) {
797 USB_DPRINTF_L2(PRINT_MASK_READ
,
798 usbvcp
->usbvc_log_handle
,
799 "usbvc_read: allocate rw bufs fail");
806 /* start polling if it is not started yet */
807 if (strm_if
->start_polling
!= 1) {
808 if (usbvc_start_isoc_polling(usbvcp
, strm_if
, 0) !=
810 USB_DPRINTF_L2(PRINT_MASK_READ
,
811 usbvcp
->usbvc_log_handle
,
812 "usbvc_read: usbvc_start_isoc_polling fail");
817 strm_if
->start_polling
= 1;
820 if (list_is_empty(&strm_if
->buf_read
.uv_buf_done
)) {
821 USB_DPRINTF_L3(PRINT_MASK_READ
, usbvcp
->usbvc_log_handle
,
822 "usbvc_read: full buf list is empty.");
824 if (uio_p
->uio_fmode
& (FNDELAY
| FNONBLOCK
)) {
825 USB_DPRINTF_L2(PRINT_MASK_READ
,
826 usbvcp
->usbvc_log_handle
, "usbvc_read: fail, "
827 "non-blocking read, done buf is empty.");
833 /* no available buffers, block here */
834 while (list_is_empty(&strm_if
->buf_read
.uv_buf_done
)) {
835 USB_DPRINTF_L3(PRINT_MASK_READ
,
836 usbvcp
->usbvc_log_handle
,
837 "usbvc_read: wait for done buf");
838 if (cv_wait_sig(&usbvcp
->usbvc_read_cv
,
839 &usbvcp
->usbvc_mutex
) <= 0) {
840 /* no done buf and cv is signaled */
845 if (usbvcp
->usbvc_dev_state
!= USB_DEV_ONLINE
) {
847 /* Device is disconnected. */
856 mutex_exit(&usbvcp
->usbvc_mutex
);
857 rval
= physio(usbvc_strategy
, NULL
, dev
, B_READ
,
858 usbvc_minphys
, uio_p
);
860 mutex_enter(&usbvcp
->usbvc_mutex
);
861 usbvc_release_access(usbvcp
);
862 mutex_exit(&usbvcp
->usbvc_mutex
);
867 usbvc_release_access(usbvcp
);
868 mutex_exit(&usbvcp
->usbvc_mutex
);
876 * Called through physio to setup and start the transfer.
879 usbvc_strategy(struct buf
*bp
)
881 usbvc_state_t
*usbvcp
= ddi_get_soft_state(usbvc_statep
,
882 getminor(bp
->b_edev
));
884 USB_DPRINTF_L4(PRINT_MASK_READ
, usbvcp
->usbvc_log_handle
,
885 "usbvc_strategy: enter");
888 * Initialize residual count here in case transfer doesn't even get
891 bp
->b_resid
= bp
->b_bcount
;
893 /* Needed as this is a character driver. */
894 if (bp
->b_flags
& (B_PHYS
| B_PAGEIO
)) {
898 mutex_enter(&usbvcp
->usbvc_mutex
);
900 /* Make sure device has not been disconnected. */
901 if (usbvcp
->usbvc_dev_state
!= USB_DEV_ONLINE
) {
902 USB_DPRINTF_L2(PRINT_MASK_READ
, usbvcp
->usbvc_log_handle
,
903 "usbvc_strategy: device can't be accessed");
904 mutex_exit(&usbvcp
->usbvc_mutex
);
909 /* read data from uv_buf_done list */
910 if (usbvc_read_buf(usbvcp
, bp
) != USB_SUCCESS
) {
911 USB_DPRINTF_L2(PRINT_MASK_READ
, usbvcp
->usbvc_log_handle
,
912 "usbvc_strategy: read full buf list fail");
913 mutex_exit(&usbvcp
->usbvc_mutex
);
918 mutex_exit(&usbvcp
->usbvc_mutex
);
925 USB_DPRINTF_L2(PRINT_MASK_READ
, usbvcp
->usbvc_log_handle
,
926 "usbvc_strategy: strategy fail");
927 bp
->b_private
= NULL
;
937 usbvc_minphys(struct buf
*bp
)
939 dev_t dev
= bp
->b_edev
;
940 usbvc_stream_if_t
*strm_if
;
942 usbvc_state_t
*usbvcp
=
943 ddi_get_soft_state(usbvc_statep
, getminor(dev
));
945 mutex_enter(&usbvcp
->usbvc_mutex
);
946 strm_if
= usbvcp
->usbvc_curr_strm
;
947 LE_TO_UINT32(strm_if
->ctrl_pc
.dwMaxVideoFrameSize
, 0, maxsize
);
948 USB_DPRINTF_L3(PRINT_MASK_READ
, usbvcp
->usbvc_log_handle
,
949 "usbvc_minphys: max read size=%d", maxsize
);
951 if (bp
->b_bcount
> maxsize
) {
952 bp
->b_bcount
= maxsize
;
954 mutex_exit(&usbvcp
->usbvc_mutex
);
963 usbvc_ioctl(dev_t dev
, int cmd
, intptr_t arg
,
964 int mode
, cred_t
*cred_p
, int *rval_p
)
967 usbvc_state_t
*usbvcp
=
968 ddi_get_soft_state(usbvc_statep
, getminor(dev
));
970 if (usbvcp
== NULL
) {
974 USB_DPRINTF_L4(PRINT_MASK_IOCTL
, usbvcp
->usbvc_log_handle
,
975 "ioctl enter, cmd=%x", cmd
);
976 mutex_enter(&usbvcp
->usbvc_mutex
);
977 if (usbvcp
->usbvc_dev_state
!= USB_DEV_ONLINE
) {
978 USB_DPRINTF_L2(PRINT_MASK_IOCTL
, usbvcp
->usbvc_log_handle
,
979 "ioctl: Device is not online,"
980 " dev_stat=%d", usbvcp
->usbvc_dev_state
);
981 mutex_exit(&usbvcp
->usbvc_mutex
);
985 if (usbvc_serialize_access(usbvcp
, USBVC_SER_SIG
) <= 0) {
986 usbvcp
->usbvc_serial_inuse
= B_FALSE
;
987 mutex_exit(&usbvcp
->usbvc_mutex
);
988 USB_DPRINTF_L2(PRINT_MASK_IOCTL
, usbvcp
->usbvc_log_handle
,
989 "serialize_access failed.");
993 mutex_exit(&usbvcp
->usbvc_mutex
);
995 rv
= usbvc_v4l2_ioctl(usbvcp
, cmd
, arg
, mode
);
997 mutex_enter(&usbvcp
->usbvc_mutex
);
998 usbvc_release_access(usbvcp
);
999 mutex_exit(&usbvcp
->usbvc_mutex
);
1001 USB_DPRINTF_L4(PRINT_MASK_IOCTL
, usbvcp
->usbvc_log_handle
,
1002 "usbvc_ioctl exit");
1008 /* Entry for mmap system call */
1010 usbvc_devmap(dev_t dev
, devmap_cookie_t handle
, offset_t off
,
1011 size_t len
, size_t *maplen
, uint_t model
)
1013 usbvc_state_t
*usbvcp
;
1015 usbvc_buf_t
*buf
= NULL
;
1016 usbvc_stream_if_t
*strm_if
;
1017 usbvc_buf_grp_t
*bufgrp
;
1019 usbvcp
= ddi_get_soft_state(usbvc_statep
, getminor(dev
));
1020 if (usbvcp
== NULL
) {
1021 USB_DPRINTF_L2(PRINT_MASK_DEVMAP
, usbvcp
->usbvc_log_handle
,
1022 "usbvc_devmap: usbvcp == NULL");
1027 USB_DPRINTF_L3(PRINT_MASK_DEVMAP
, usbvcp
->usbvc_log_handle
,
1028 "devmap: memory map for instance(%d), off=%llx,"
1029 "len=%ld, maplen=%ld, model=%d", getminor(dev
), off
,
1030 len
, *maplen
, model
);
1032 mutex_enter(&usbvcp
->usbvc_mutex
);
1033 (void) usbvc_serialize_access(usbvcp
, USBVC_SER_NOSIG
);
1034 strm_if
= usbvcp
->usbvc_curr_strm
;
1036 USB_DPRINTF_L2(PRINT_MASK_DEVMAP
, usbvcp
->usbvc_log_handle
,
1037 "usbvc_devmap: No current strm if");
1038 mutex_exit(&usbvcp
->usbvc_mutex
);
1042 bufgrp
= &strm_if
->buf_map
;
1043 for (i
= 0; i
< bufgrp
->buf_cnt
; i
++) {
1044 if (bufgrp
->buf_head
[i
].v4l2_buf
.m
.offset
== off
) {
1045 buf
= &bufgrp
->buf_head
[i
];
1050 USB_DPRINTF_L3(PRINT_MASK_DEVMAP
, usbvcp
->usbvc_log_handle
,
1051 "usbvc_devmap: idx=%d", i
);
1053 mutex_exit(&usbvcp
->usbvc_mutex
);
1058 * round up len to a multiple of a page size, according to chapter
1059 * 10 of "writing device drivers"
1061 len
= ptob(btopr(len
));
1062 if (len
> ptob(btopr(buf
->len
))) {
1063 USB_DPRINTF_L2(PRINT_MASK_DEVMAP
, usbvcp
->usbvc_log_handle
,
1064 "usbvc_devmap: len=0x%lx", len
);
1065 mutex_exit(&usbvcp
->usbvc_mutex
);
1069 mutex_exit(&usbvcp
->usbvc_mutex
);
1071 error
= devmap_umem_setup(handle
, usbvcp
->usbvc_dip
, NULL
,
1072 buf
->umem_cookie
, off
, len
, PROT_ALL
, DEVMAP_DEFAULTS
, NULL
);
1073 mutex_enter(&usbvcp
->usbvc_mutex
);
1075 if (error
== 0 && buf
->status
== USBVC_BUF_INIT
) {
1076 buf
->status
= USBVC_BUF_MAPPED
;
1078 USB_DPRINTF_L3(PRINT_MASK_DEVMAP
, usbvcp
->usbvc_log_handle
,
1079 "usbvc_devmap: devmap_umem_setup, err=%d", error
);
1082 (void) usbvc_release_access(usbvcp
);
1083 mutex_exit(&usbvcp
->usbvc_mutex
);
1094 * Power entry point, the workhorse behind pm_raise_power, pm_lower_power,
1095 * usb_req_raise_power and usb_req_lower_power.
1099 usbvc_power(dev_info_t
*dip
, int comp
, int level
)
1101 usbvc_state_t
*usbvcp
;
1103 int rval
= USB_FAILURE
;
1105 usbvcp
= ddi_get_soft_state(usbvc_statep
, ddi_get_instance(dip
));
1106 mutex_enter(&usbvcp
->usbvc_mutex
);
1107 USB_DPRINTF_L4(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1108 "usbvc_power: enter: level = %d, dev_state: %x",
1109 level
, usbvcp
->usbvc_dev_state
);
1111 if (usbvcp
->usbvc_pm
== NULL
) {
1116 pm
= usbvcp
->usbvc_pm
;
1118 /* Check if we are transitioning to a legal power level */
1119 if (USB_DEV_PWRSTATE_OK(pm
->usbvc_pwr_states
, level
)) {
1120 USB_DPRINTF_L2(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
1121 "usbvc_power: illegal power level = %d "
1122 "pwr_states: %x", level
, pm
->usbvc_pwr_states
);
1127 * if we are about to raise power and asked to lower power, fail
1129 if (pm
->usbvc_raise_power
&& (level
< (int)pm
->usbvc_current_power
)) {
1134 case USB_DEV_OS_PWR_OFF
:
1135 rval
= usbvc_pwrlvl0(usbvcp
);
1138 case USB_DEV_OS_PWR_1
:
1139 rval
= usbvc_pwrlvl1(usbvcp
);
1142 case USB_DEV_OS_PWR_2
:
1143 rval
= usbvc_pwrlvl2(usbvcp
);
1146 case USB_DEV_OS_FULL_PWR
:
1147 rval
= usbvc_pwrlvl3(usbvcp
);
1153 mutex_exit(&usbvcp
->usbvc_mutex
);
1155 return ((rval
== USB_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
1160 * usbvc_init_power_mgmt:
1161 * Initialize power management and remote wakeup functionality.
1162 * No mutex is necessary in this function as it's called only by attach.
1165 usbvc_init_power_mgmt(usbvc_state_t
*usbvcp
)
1167 usbvc_power_t
*usbvcpm
;
1170 USB_DPRINTF_L4(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1171 "init_power_mgmt enter");
1173 /* Allocate the state structure */
1174 usbvcpm
= kmem_zalloc(sizeof (usbvc_power_t
), KM_SLEEP
);
1175 mutex_enter(&usbvcp
->usbvc_mutex
);
1176 usbvcp
->usbvc_pm
= usbvcpm
;
1177 usbvcpm
->usbvc_state
= usbvcp
;
1178 usbvcpm
->usbvc_pm_capabilities
= 0;
1179 usbvcpm
->usbvc_current_power
= USB_DEV_OS_FULL_PWR
;
1180 mutex_exit(&usbvcp
->usbvc_mutex
);
1182 if (usb_create_pm_components(usbvcp
->usbvc_dip
, &pwr_states
) ==
1184 USB_DPRINTF_L2(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1185 "usbvc_init_power_mgmt: created PM components");
1187 if (usb_handle_remote_wakeup(usbvcp
->usbvc_dip
,
1188 USB_REMOTE_WAKEUP_ENABLE
) == USB_SUCCESS
) {
1189 usbvcpm
->usbvc_wakeup_enabled
= 1;
1191 USB_DPRINTF_L2(PRINT_MASK_ATTA
,
1192 usbvcp
->usbvc_log_handle
, "usbvc_init_power_mgmt:"
1193 " remote wakeup not supported");
1196 mutex_enter(&usbvcp
->usbvc_mutex
);
1197 usbvcpm
->usbvc_pwr_states
= (uint8_t)pwr_states
;
1198 usbvc_pm_busy_component(usbvcp
);
1199 usbvcpm
->usbvc_raise_power
= B_TRUE
;
1200 mutex_exit(&usbvcp
->usbvc_mutex
);
1202 (void) pm_raise_power(
1203 usbvcp
->usbvc_dip
, 0, USB_DEV_OS_FULL_PWR
);
1205 mutex_enter(&usbvcp
->usbvc_mutex
);
1206 usbvcpm
->usbvc_raise_power
= B_FALSE
;
1207 usbvc_pm_idle_component(usbvcp
);
1208 mutex_exit(&usbvcp
->usbvc_mutex
);
1211 USB_DPRINTF_L4(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1212 "usbvc_init_power_mgmt: end");
1217 * usbvc_destroy_power_mgmt:
1218 * Shut down and destroy power management and remote wakeup functionality.
1221 usbvc_destroy_power_mgmt(usbvc_state_t
*usbvcp
)
1226 USB_DPRINTF_L4(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1227 "destroy_power_mgmt enter");
1228 mutex_enter(&usbvcp
->usbvc_mutex
);
1229 pm
= usbvcp
->usbvc_pm
;
1230 if (pm
&& (usbvcp
->usbvc_dev_state
!= USB_DEV_DISCONNECTED
)) {
1232 usbvc_pm_busy_component(usbvcp
);
1233 if (pm
->usbvc_wakeup_enabled
) {
1234 pm
->usbvc_raise_power
= B_TRUE
;
1235 mutex_exit(&usbvcp
->usbvc_mutex
);
1237 /* First bring the device to full power */
1238 (void) pm_raise_power(usbvcp
->usbvc_dip
, 0,
1239 USB_DEV_OS_FULL_PWR
);
1240 if ((rval
= usb_handle_remote_wakeup(
1242 USB_REMOTE_WAKEUP_DISABLE
)) !=
1244 USB_DPRINTF_L2(PRINT_MASK_ATTA
,
1245 usbvcp
->usbvc_log_handle
,
1246 "usbvc_destroy_power_mgmt: "
1247 "Error disabling rmt wakeup: rval = %d",
1250 mutex_enter(&usbvcp
->usbvc_mutex
);
1251 pm
->usbvc_raise_power
= B_FALSE
;
1254 mutex_exit(&usbvcp
->usbvc_mutex
);
1257 * Since remote wakeup is disabled now,
1258 * no one can raise power
1259 * and get to device once power is lowered here.
1261 (void) pm_lower_power(usbvcp
->usbvc_dip
, 0, USB_DEV_OS_PWR_OFF
);
1262 mutex_enter(&usbvcp
->usbvc_mutex
);
1263 usbvc_pm_idle_component(usbvcp
);
1267 kmem_free(pm
, sizeof (usbvc_power_t
));
1268 usbvcp
->usbvc_pm
= NULL
;
1270 mutex_exit(&usbvcp
->usbvc_mutex
);
1275 usbvc_pm_busy_component(usbvc_state_t
*usbvcp
)
1277 ASSERT(mutex_owned(&usbvcp
->usbvc_mutex
));
1278 USB_DPRINTF_L4(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1279 "usbvc_pm_busy_component: enter");
1281 usbvcp
->usbvc_pm
->usbvc_pm_busy
++;
1282 mutex_exit(&usbvcp
->usbvc_mutex
);
1284 if (pm_busy_component(usbvcp
->usbvc_dip
, 0) !=
1286 mutex_enter(&usbvcp
->usbvc_mutex
);
1287 USB_DPRINTF_L2(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1288 "usbvc_pm_busy_component: pm busy fail, usbvc_pm_busy=%d",
1289 usbvcp
->usbvc_pm
->usbvc_pm_busy
);
1291 usbvcp
->usbvc_pm
->usbvc_pm_busy
--;
1292 mutex_exit(&usbvcp
->usbvc_mutex
);
1294 mutex_enter(&usbvcp
->usbvc_mutex
);
1295 USB_DPRINTF_L4(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1296 "usbvc_pm_busy_component: exit");
1301 usbvc_pm_idle_component(usbvc_state_t
*usbvcp
)
1303 ASSERT(mutex_owned(&usbvcp
->usbvc_mutex
));
1304 USB_DPRINTF_L4(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1305 "usbvc_pm_idle_component: enter");
1307 if (usbvcp
->usbvc_pm
!= NULL
) {
1308 mutex_exit(&usbvcp
->usbvc_mutex
);
1309 if (pm_idle_component(usbvcp
->usbvc_dip
, 0) ==
1311 mutex_enter(&usbvcp
->usbvc_mutex
);
1312 ASSERT(usbvcp
->usbvc_pm
->usbvc_pm_busy
> 0);
1313 usbvcp
->usbvc_pm
->usbvc_pm_busy
--;
1314 mutex_exit(&usbvcp
->usbvc_mutex
);
1316 mutex_enter(&usbvcp
->usbvc_mutex
);
1317 USB_DPRINTF_L2(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1318 "usbvc_pm_idle_component: %d",
1319 usbvcp
->usbvc_pm
->usbvc_pm_busy
);
1326 * Functions to handle power transition for OS levels 0 -> 3
1329 usbvc_pwrlvl0(usbvc_state_t
*usbvcp
)
1333 USB_DPRINTF_L4(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1334 "usbvc_pwrlvl0, dev_state: %x", usbvcp
->usbvc_dev_state
);
1336 switch (usbvcp
->usbvc_dev_state
) {
1337 case USB_DEV_ONLINE
:
1338 /* Deny the powerdown request if the device is busy */
1339 if (usbvcp
->usbvc_pm
->usbvc_pm_busy
!= 0) {
1340 USB_DPRINTF_L2(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1341 "usbvc_pwrlvl0: usbvc_pm_busy");
1343 return (USB_FAILURE
);
1346 /* Issue USB D3 command to the device here */
1347 rval
= usb_set_device_pwrlvl3(usbvcp
->usbvc_dip
);
1348 ASSERT(rval
== USB_SUCCESS
);
1350 usbvcp
->usbvc_dev_state
= USB_DEV_PWRED_DOWN
;
1351 usbvcp
->usbvc_pm
->usbvc_current_power
= USB_DEV_OS_PWR_OFF
;
1354 case USB_DEV_DISCONNECTED
:
1355 case USB_DEV_SUSPENDED
:
1356 /* allow a disconnect/cpr'ed device to go to lower power */
1358 return (USB_SUCCESS
);
1359 case USB_DEV_PWRED_DOWN
:
1361 USB_DPRINTF_L2(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1362 "usbvc_pwrlvl0: illegal dev state");
1364 return (USB_FAILURE
);
1371 * Functions to handle power transition to OS levels -> 2
1374 usbvc_pwrlvl1(usbvc_state_t
*usbvcp
)
1378 USB_DPRINTF_L4(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1381 /* Issue USB D2 command to the device here */
1382 rval
= usb_set_device_pwrlvl2(usbvcp
->usbvc_dip
);
1383 ASSERT(rval
== USB_SUCCESS
);
1385 return (USB_FAILURE
);
1391 * Functions to handle power transition to OS levels -> 1
1394 usbvc_pwrlvl2(usbvc_state_t
*usbvcp
)
1398 USB_DPRINTF_L4(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1401 /* Issue USB D1 command to the device here */
1402 rval
= usb_set_device_pwrlvl1(usbvcp
->usbvc_dip
);
1403 ASSERT(rval
== USB_SUCCESS
);
1405 return (USB_FAILURE
);
1411 * Functions to handle power transition to OS level -> 0
1414 usbvc_pwrlvl3(usbvc_state_t
*usbvcp
)
1416 USB_DPRINTF_L4(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1417 "usbvc_pwrlvl3, dev_stat=%d", usbvcp
->usbvc_dev_state
);
1419 switch (usbvcp
->usbvc_dev_state
) {
1420 case USB_DEV_PWRED_DOWN
:
1421 /* Issue USB D0 command to the device here */
1422 (void) usb_set_device_pwrlvl0(usbvcp
->usbvc_dip
);
1424 usbvcp
->usbvc_dev_state
= USB_DEV_ONLINE
;
1425 usbvcp
->usbvc_pm
->usbvc_current_power
=
1426 USB_DEV_OS_FULL_PWR
;
1429 case USB_DEV_ONLINE
:
1430 /* we are already in full power */
1432 case USB_DEV_DISCONNECTED
:
1433 case USB_DEV_SUSPENDED
:
1435 * PM framework tries to put us in full power
1436 * during system shutdown. If we are disconnected/cpr'ed
1437 * return success anyways
1440 return (USB_SUCCESS
);
1442 USB_DPRINTF_L2(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1443 "usbvc_pwrlvl3: illegal dev state");
1445 return (USB_FAILURE
);
1451 * usbvc_cpr_suspend:
1453 * Wait for any IO to finish, then close pipes.
1457 usbvc_cpr_suspend(dev_info_t
*dip
)
1459 int instance
= ddi_get_instance(dip
);
1460 usbvc_state_t
*usbvcp
= ddi_get_soft_state(usbvc_statep
, instance
);
1462 USB_DPRINTF_L4(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1463 "usbvc_cpr_suspend enter");
1465 mutex_enter(&usbvcp
->usbvc_mutex
);
1468 * Set dev_state to suspended so other driver threads don't start any
1471 usbvcp
->usbvc_dev_state
= USB_DEV_SUSPENDED
;
1473 mutex_exit(&usbvcp
->usbvc_mutex
);
1475 USB_DPRINTF_L4(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
1476 "usbvc_cpr_suspend: return");
1481 * If the polling has been stopped due to some exceptional errors,
1482 * we reconfigure the device and start polling again. Only for S/R
1483 * resume or hotplug reconnect operations.
1486 usbvc_resume_operation(usbvc_state_t
*usbvcp
)
1488 usbvc_stream_if_t
*strm_if
;
1489 int rv
= USB_SUCCESS
;
1491 USB_DPRINTF_L4(PRINT_MASK_IOCTL
, usbvcp
->usbvc_log_handle
,
1492 "usbvc_resume_operation: enter");
1494 mutex_enter(&usbvcp
->usbvc_mutex
);
1495 strm_if
= usbvcp
->usbvc_curr_strm
;
1497 mutex_exit(&usbvcp
->usbvc_mutex
);
1504 * 1) if application has not started STREAMON ioctl yet,
1506 * 2) if application use READ mode, return immediately
1508 if (strm_if
->stream_on
== 0) {
1509 mutex_exit(&usbvcp
->usbvc_mutex
);
1514 /* isoc pipe is expected to be opened already if (stream_on==1) */
1515 if (!strm_if
->datain_ph
) {
1516 mutex_exit(&usbvcp
->usbvc_mutex
);
1522 mutex_exit(&usbvcp
->usbvc_mutex
);
1524 /* first commit the parameters negotiated and saved during S_FMT */
1525 if ((rv
= usbvc_vs_set_probe_commit(usbvcp
, strm_if
,
1526 &strm_if
->ctrl_pc
, VS_COMMIT_CONTROL
)) != USB_SUCCESS
) {
1527 USB_DPRINTF_L2(PRINT_MASK_IOCTL
,
1528 usbvcp
->usbvc_log_handle
,
1529 "usbvc_resume_operation: set probe failed, rv=%d", rv
);
1534 mutex_enter(&usbvcp
->usbvc_mutex
);
1536 /* Set alt interfaces, must be after probe_commit according to spec */
1537 if ((rv
= usbvc_set_alt(usbvcp
, strm_if
)) != USB_SUCCESS
) {
1538 USB_DPRINTF_L2(PRINT_MASK_IOCTL
,
1539 usbvcp
->usbvc_log_handle
,
1540 "usbvc_resume_operation: set alt failed");
1541 mutex_exit(&usbvcp
->usbvc_mutex
);
1547 * The isoc polling could be stopped by isoc_exc_cb
1548 * during suspend or hotplug. Restart it.
1550 if (usbvc_start_isoc_polling(usbvcp
, strm_if
, V4L2_MEMORY_MMAP
)
1553 mutex_exit(&usbvcp
->usbvc_mutex
);
1558 strm_if
->start_polling
= 1;
1560 mutex_exit(&usbvcp
->usbvc_mutex
);
1568 * usbvc_restore_device_state marks success by putting device back online
1571 usbvc_cpr_resume(dev_info_t
*dip
)
1573 int instance
= ddi_get_instance(dip
);
1574 usbvc_state_t
*usbvcp
= ddi_get_soft_state(usbvc_statep
, instance
);
1576 USB_DPRINTF_L4(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
1580 * NOTE: A pm_raise_power in usbvc_restore_device_state will bring
1581 * the power-up state of device into synch with the system.
1583 mutex_enter(&usbvcp
->usbvc_mutex
);
1584 usbvc_restore_device_state(dip
, usbvcp
);
1585 mutex_exit(&usbvcp
->usbvc_mutex
);
1590 * usbvc_restore_device_state:
1591 * Called during hotplug-reconnect and resume.
1592 * reenable power management
1593 * Verify the device is the same as before the disconnect/suspend.
1594 * Restore device state
1595 * Thaw any IO which was frozen.
1596 * Quiesce device. (Other routines will activate if thawed IO.)
1597 * Set device online.
1598 * Leave device disconnected if there are problems.
1601 usbvc_restore_device_state(dev_info_t
*dip
, usbvc_state_t
*usbvcp
)
1603 USB_DPRINTF_L4(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1604 "usbvc_restore_device_state: enter");
1606 ASSERT(mutex_owned(&usbvcp
->usbvc_mutex
));
1608 ASSERT((usbvcp
->usbvc_dev_state
== USB_DEV_DISCONNECTED
) ||
1609 (usbvcp
->usbvc_dev_state
== USB_DEV_SUSPENDED
));
1611 usbvc_pm_busy_component(usbvcp
);
1612 usbvcp
->usbvc_pm
->usbvc_raise_power
= B_TRUE
;
1613 mutex_exit(&usbvcp
->usbvc_mutex
);
1614 (void) pm_raise_power(dip
, 0, USB_DEV_OS_FULL_PWR
);
1616 /* Check if we are talking to the same device */
1617 if (usb_check_same_device(dip
, usbvcp
->usbvc_log_handle
,
1618 USB_LOG_L0
, PRINT_MASK_ALL
,
1619 USB_CHK_BASIC
|USB_CHK_CFG
, NULL
) != USB_SUCCESS
) {
1624 mutex_enter(&usbvcp
->usbvc_mutex
);
1625 usbvcp
->usbvc_pm
->usbvc_raise_power
= B_FALSE
;
1626 usbvcp
->usbvc_dev_state
= USB_DEV_ONLINE
;
1627 mutex_exit(&usbvcp
->usbvc_mutex
);
1629 if (usbvcp
->usbvc_pm
->usbvc_wakeup_enabled
) {
1631 /* Failure here means device disappeared again. */
1632 if (usb_handle_remote_wakeup(dip
, USB_REMOTE_WAKEUP_ENABLE
) !=
1634 USB_DPRINTF_L2(PRINT_MASK_ATTA
,
1635 usbvcp
->usbvc_log_handle
,
1636 "device may or may not be accessible. "
1637 "Please verify reconnection");
1641 if (usbvc_resume_operation(usbvcp
) != USB_SUCCESS
) {
1642 USB_DPRINTF_L2(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1643 "usbvc_restore_device_state: can't resume operation");
1648 mutex_enter(&usbvcp
->usbvc_mutex
);
1650 usbvc_pm_idle_component(usbvcp
);
1652 USB_DPRINTF_L4(PRINT_MASK_PM
, usbvcp
->usbvc_log_handle
,
1653 "usbvc_restore_device_state: end");
1658 /* change the device state from suspended to disconnected */
1659 mutex_enter(&usbvcp
->usbvc_mutex
);
1660 usbvcp
->usbvc_dev_state
= USB_DEV_DISCONNECTED
;
1661 usbvc_pm_idle_component(usbvcp
);
1668 * usbvc_disconnect_event_cb:
1669 * Called when device hotplug-removed.
1670 * Close pipes. (This does not attempt to contact device.)
1671 * Set state to DISCONNECTED
1674 usbvc_disconnect_event_cb(dev_info_t
*dip
)
1676 int instance
= ddi_get_instance(dip
);
1677 usbvc_state_t
*usbvcp
= ddi_get_soft_state(usbvc_statep
, instance
);
1679 USB_DPRINTF_L4(PRINT_MASK_HOTPLUG
, usbvcp
->usbvc_log_handle
,
1680 "disconnect: enter");
1682 mutex_enter(&usbvcp
->usbvc_mutex
);
1684 * Save any state of device or IO in progress required by
1685 * usbvc_restore_device_state for proper device "thawing" later.
1687 usbvcp
->usbvc_dev_state
= USB_DEV_DISCONNECTED
;
1690 * wake up the read threads in case there are any threads are blocking,
1691 * after being waked up, those threads will quit fail immediately since
1692 * we have changed the dev_stat.
1694 if (usbvcp
->usbvc_io_type
== V4L2_MEMORY_MMAP
) {
1695 cv_broadcast(&usbvcp
->usbvc_mapio_cv
);
1697 cv_broadcast(&usbvcp
->usbvc_read_cv
);
1699 /* Wait for the other threads to quit */
1700 (void) usbvc_serialize_access(usbvcp
, USBVC_SER_SIG
);
1701 usbvc_release_access(usbvcp
);
1702 mutex_exit(&usbvcp
->usbvc_mutex
);
1704 return (USB_SUCCESS
);
1709 * usbvc_reconnect_event_cb:
1710 * Called with device hotplug-inserted
1714 usbvc_reconnect_event_cb(dev_info_t
*dip
)
1716 int instance
= ddi_get_instance(dip
);
1717 usbvc_state_t
*usbvcp
= ddi_get_soft_state(usbvc_statep
, instance
);
1719 USB_DPRINTF_L4(PRINT_MASK_HOTPLUG
, usbvcp
->usbvc_log_handle
,
1720 "reconnect: enter");
1722 mutex_enter(&usbvcp
->usbvc_mutex
);
1723 (void) usbvc_serialize_access(usbvcp
, USBVC_SER_SIG
);
1724 usbvc_restore_device_state(dip
, usbvcp
);
1725 usbvc_release_access(usbvcp
);
1726 mutex_exit(&usbvcp
->usbvc_mutex
);
1728 return (USB_SUCCESS
);
1731 /* Sync objs and lists */
1734 * init/fini sync objects during attach
1737 usbvc_init_sync_objs(usbvc_state_t
*usbvcp
)
1739 mutex_init(&usbvcp
->usbvc_mutex
, NULL
, MUTEX_DRIVER
,
1740 usbvcp
->usbvc_reg
->dev_iblock_cookie
);
1742 cv_init(&usbvcp
->usbvc_serial_cv
, NULL
, CV_DRIVER
, NULL
);
1743 cv_init(&usbvcp
->usbvc_read_cv
, NULL
, CV_DRIVER
, NULL
);
1744 cv_init(&usbvcp
->usbvc_mapio_cv
, NULL
, CV_DRIVER
, NULL
);
1746 usbvcp
->usbvc_serial_inuse
= B_FALSE
;
1748 usbvcp
->usbvc_locks_initialized
= B_TRUE
;
1753 usbvc_fini_sync_objs(usbvc_state_t
*usbvcp
)
1755 cv_destroy(&usbvcp
->usbvc_serial_cv
);
1756 cv_destroy(&usbvcp
->usbvc_read_cv
);
1757 cv_destroy(&usbvcp
->usbvc_mapio_cv
);
1759 mutex_destroy(&usbvcp
->usbvc_mutex
);
1764 usbvc_init_lists(usbvc_state_t
*usbvcp
)
1766 /* video terminals */
1767 list_create(&(usbvcp
->usbvc_term_list
), sizeof (usbvc_terms_t
),
1768 offsetof(usbvc_terms_t
, term_node
));
1771 list_create(&(usbvcp
->usbvc_unit_list
), sizeof (usbvc_units_t
),
1772 offsetof(usbvc_units_t
, unit_node
));
1774 /* stream interfaces */
1775 list_create(&(usbvcp
->usbvc_stream_list
), sizeof (usbvc_stream_if_t
),
1776 offsetof(usbvc_stream_if_t
, stream_if_node
));
1781 * Free all the data structures allocated when parsing descriptors of ctrl
1782 * and stream interfaces. It is safe to call this function because it always
1783 * checks the pointer before free mem.
1786 usbvc_fini_lists(usbvc_state_t
*usbvcp
)
1788 USB_DPRINTF_L4(PRINT_MASK_CLOSE
, usbvcp
->usbvc_log_handle
,
1789 "usbvc_fini_lists: enter");
1791 usbvc_free_ctrl_descr(usbvcp
);
1793 /* Free all video stream structure and the sub-structures */
1794 usbvc_free_stream_descr(usbvcp
);
1796 USB_DPRINTF_L4(PRINT_MASK_CLOSE
, usbvcp
->usbvc_log_handle
,
1797 "usbvc_fini_lists: end");
1802 * Free all the data structures allocated when parsing descriptors of ctrl
1806 usbvc_free_ctrl_descr(usbvc_state_t
*usbvcp
)
1808 usbvc_terms_t
*term
;
1809 usbvc_units_t
*unit
;
1811 USB_DPRINTF_L4(PRINT_MASK_CLOSE
, usbvcp
->usbvc_log_handle
,
1812 "usbvc_free_ctrl_descr: enter");
1814 if (usbvcp
->usbvc_vc_header
) {
1815 kmem_free(usbvcp
->usbvc_vc_header
, sizeof (usbvc_vc_header_t
));
1818 /* Free all video terminal structure */
1819 while (!list_is_empty(&usbvcp
->usbvc_term_list
)) {
1820 term
= list_head(&usbvcp
->usbvc_term_list
);
1822 list_remove(&(usbvcp
->usbvc_term_list
), term
);
1823 kmem_free(term
, sizeof (usbvc_terms_t
));
1827 /* Free all video unit structure */
1828 while (!list_is_empty(&usbvcp
->usbvc_unit_list
)) {
1829 unit
= list_head(&usbvcp
->usbvc_unit_list
);
1831 list_remove(&(usbvcp
->usbvc_unit_list
), unit
);
1832 kmem_free(unit
, sizeof (usbvc_units_t
));
1839 * Free all the data structures allocated when parsing descriptors of stream
1843 usbvc_free_stream_descr(usbvc_state_t
*usbvcp
)
1845 usbvc_stream_if_t
*strm
;
1846 usbvc_input_header_t
*in_hdr
;
1847 usbvc_output_header_t
*out_hdr
;
1848 uint8_t fmt_cnt
, frm_cnt
;
1850 while (!list_is_empty(&usbvcp
->usbvc_stream_list
)) {
1851 USB_DPRINTF_L3(PRINT_MASK_CLOSE
, usbvcp
->usbvc_log_handle
,
1852 "usbvc_fini_lists: stream list not empty.");
1854 strm
= list_head(&usbvcp
->usbvc_stream_list
);
1857 /* unlink this stream's data structure from the list */
1858 list_remove(&(usbvcp
->usbvc_stream_list
), strm
);
1861 /* No real stream data structure in the list */
1865 in_hdr
= strm
->input_header
;
1866 out_hdr
= strm
->output_header
;
1869 fmt_cnt
= in_hdr
->descr
->bNumFormats
;
1870 } else if (out_hdr
) {
1871 fmt_cnt
= out_hdr
->descr
->bNumFormats
;
1874 USB_DPRINTF_L3(PRINT_MASK_CLOSE
,
1875 usbvcp
->usbvc_log_handle
, "usbvc_fini_lists:"
1876 " fmtgrp cnt=%d", fmt_cnt
);
1880 kmem_free(in_hdr
, sizeof (usbvc_input_header_t
));
1883 kmem_free(out_hdr
, sizeof (usbvc_output_header_t
));
1886 /* Free format descriptors */
1887 if (strm
->format_group
) {
1889 usbvc_format_group_t
*fmtgrp
;
1891 for (i
= 0; i
< fmt_cnt
; i
++) {
1892 fmtgrp
= &strm
->format_group
[i
];
1893 if (fmtgrp
->format
== NULL
) {
1897 if (fmtgrp
->still
) {
1898 kmem_free(fmtgrp
->still
,
1899 sizeof (usbvc_still_image_frame_t
));
1901 frm_cnt
= fmtgrp
->format
->bNumFrameDescriptors
;
1903 USB_DPRINTF_L3(PRINT_MASK_CLOSE
,
1904 usbvcp
->usbvc_log_handle
,
1906 " frame cnt=%d", frm_cnt
);
1908 if (fmtgrp
->frames
) {
1909 kmem_free(fmtgrp
->frames
,
1910 sizeof (usbvc_frames_t
) * frm_cnt
);
1913 kmem_free(strm
->format_group
,
1914 sizeof (usbvc_format_group_t
) * fmt_cnt
);
1916 USB_DPRINTF_L3(PRINT_MASK_CLOSE
,
1917 usbvcp
->usbvc_log_handle
, "usbvc_fini_lists:"
1918 " free stream_if_t");
1920 kmem_free(strm
, sizeof (usbvc_stream_if_t
));
1925 * Parse class specific descriptors of the video device
1929 * Check the length of a class specific descriptor. Make sure cvs_buf_len is
1930 * not less than the length expected according to uvc spec.
1933 * - off_num: the cvs_buf offset of the descriptor element that
1934 * indicates the number of variable descriptor elements;
1935 * - size: the size of each variable descriptor element, if zero, then the
1936 * size value is offered by off_size;
1937 * - off_size: the cvs_buf offset of the descriptor element that indicates
1938 * the size of each variable descriptor element;
1941 usbvc_chk_descr_len(uint8_t off_num
, uint8_t size
, uint8_t off_size
,
1942 usb_cvs_data_t
*cvs_data
)
1947 cvs_buf
= cvs_data
->cvs_buf
;
1948 cvs_buf_len
= cvs_data
->cvs_buf_len
;
1951 if (cvs_buf_len
> off_size
) {
1952 size
= cvs_buf
[off_size
];
1955 return (USB_FAILURE
);
1958 if (cvs_buf_len
< (off_num
+ 1)) {
1960 return (USB_FAILURE
);
1963 if (cvs_buf_len
< (cvs_buf
[off_num
] * size
+ off_num
+1)) {
1965 return (USB_FAILURE
);
1968 return (USB_SUCCESS
);
1972 /* Parse the descriptors of control interface */
1974 usbvc_parse_ctrl_if(usbvc_state_t
*usbvcp
)
1978 usb_alt_if_data_t
*if_alt_data
;
1979 usb_cvs_data_t
*cvs_data
;
1984 if_num
= usbvcp
->usbvc_reg
->dev_curr_if
;
1985 if_alt_data
= usbvcp
->usbvc_reg
->dev_curr_cfg
->cfg_if
[if_num
].if_alt
;
1986 cvs_data
= if_alt_data
->altif_cvs
;
1988 for (cvs_num
= 0; cvs_num
< if_alt_data
->altif_n_cvs
; cvs_num
++) {
1989 cvs_buf
= cvs_data
[cvs_num
].cvs_buf
;
1990 cvs_buf_len
= cvs_data
[cvs_num
].cvs_buf_len
;
1991 USB_DPRINTF_L3(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
1992 "usbvc_parse_ctrl_if: cvs_num= %d, cvs_buf_len=%d",
1993 cvs_num
, cvs_buf_len
);
1996 * parse interface cvs descriptors here; by checking
1997 * bDescriptorType (cvs_buf[1])
1999 if (cvs_buf
[1] != CS_INTERFACE
) {
2005 * Different descriptors in VC interface; according to
2006 * bDescriptorSubType (cvs_buf[2])
2008 switch (cvs_buf
[2]) {
2012 * According to uvc spec, there must be one and only
2013 * be one header. If more than one, return failure.
2015 if (usbvcp
->usbvc_vc_header
) {
2017 return (USB_FAILURE
);
2020 * Check if it is a valid HEADER descriptor in case of
2021 * a device not compliant to uvc spec. This descriptor
2022 * is critical, return failure if not a valid one.
2024 if (usbvc_chk_descr_len(11, 1, 0, cvs_data
) !=
2027 return (USB_FAILURE
);
2029 usbvcp
->usbvc_vc_header
=
2030 (usbvc_vc_header_t
*)kmem_zalloc(
2031 sizeof (usbvc_vc_header_t
), KM_SLEEP
);
2032 usbvcp
->usbvc_vc_header
->descr
=
2033 (usbvc_vc_header_descr_t
*)&cvs_buf
[0];
2035 LE_TO_UINT16(usbvcp
->usbvc_vc_header
->descr
->bcdUVC
,
2037 USB_DPRINTF_L3(PRINT_MASK_ATTA
,
2038 usbvcp
->usbvc_log_handle
, "usbvc_parse_ctrl_if:"
2039 " VC header, bcdUVC=%x", version
);
2040 if (usbvcp
->usbvc_vc_header
->descr
->bInCollection
==
2042 USB_DPRINTF_L3(PRINT_MASK_ATTA
,
2043 usbvcp
->usbvc_log_handle
,
2044 "usbvc_parse_ctrl_if: no strm interfaces");
2049 /* stream interface numbers */
2050 usbvcp
->usbvc_vc_header
->baInterfaceNr
= &cvs_buf
[12];
2053 case VC_INPUT_TERMINAL
:
2055 usbvc_terms_t
*term
;
2058 * Check if it is a valid descriptor in case of a
2059 * device not compliant to uvc spec
2061 if (cvs_buf_len
< USBVC_I_TERM_LEN_MIN
) {
2065 term
= (usbvc_terms_t
*)
2066 kmem_zalloc(sizeof (usbvc_terms_t
), KM_SLEEP
);
2067 term
->descr
= (usbvc_term_descr_t
*)cvs_buf
;
2069 USB_DPRINTF_L3(PRINT_MASK_ATTA
,
2070 usbvcp
->usbvc_log_handle
, "usbvc_parse_ctrl_if: "
2071 "input term type=%x", term
->descr
->wTerminalType
);
2072 if (term
->descr
->wTerminalType
== ITT_CAMERA
) {
2073 if (usbvc_chk_descr_len(14, 1, 0, cvs_data
) !=
2075 kmem_free(term
, sizeof (usbvc_terms_t
));
2079 term
->bmControls
= &cvs_buf
[15];
2080 } else if (cvs_buf_len
> 8) { /* other input terms */
2081 term
->bSpecific
= &cvs_buf
[8];
2083 list_insert_tail(&(usbvcp
->usbvc_term_list
), term
);
2087 case VC_OUTPUT_TERMINAL
:
2089 usbvc_terms_t
*term
;
2091 if (cvs_buf_len
< USBVC_O_TERM_LEN_MIN
) {
2095 term
= (usbvc_terms_t
*)
2096 kmem_zalloc(sizeof (usbvc_terms_t
), KM_SLEEP
);
2097 term
->descr
= (usbvc_term_descr_t
*)cvs_buf
;
2099 USB_DPRINTF_L3(PRINT_MASK_ATTA
,
2100 usbvcp
->usbvc_log_handle
, "usbvc_parse_ctrl_if:"
2101 " output term id= %x", term
->descr
->bTerminalID
);
2102 if (cvs_buf_len
> 9) {
2103 term
->bSpecific
= &cvs_buf
[9];
2105 list_insert_tail(&(usbvcp
->usbvc_term_list
), term
);
2109 case VC_PROCESSING_UNIT
:
2112 usbvc_units_t
*unit
;
2114 if (usbvc_chk_descr_len(7, 1, 0, cvs_data
) !=
2123 if ((sz
+ 8) >= cvs_buf_len
) {
2127 unit
= (usbvc_units_t
*)
2128 kmem_zalloc(sizeof (usbvc_units_t
), KM_SLEEP
);
2130 unit
->descr
= (usbvc_unit_descr_t
*)cvs_buf
;
2132 USB_DPRINTF_L3(PRINT_MASK_ATTA
,
2133 usbvcp
->usbvc_log_handle
, "usbvc_parse_ctrl_if: "
2134 "unit type=%x", unit
->descr
->bDescriptorSubType
);
2137 unit
->bmControls
= &cvs_buf
[8];
2139 unit
->iProcessing
= cvs_buf
[8 + sz
];
2142 * video class 1.1 version add one element
2143 * (bmVideoStandards) to processing unit descriptor
2145 if (cvs_buf_len
> (9 + sz
)) {
2146 unit
->bmVideoStandards
= cvs_buf
[9 + sz
];
2148 list_insert_tail(&(usbvcp
->usbvc_unit_list
), unit
);
2152 case VC_SELECTOR_UNIT
:
2155 usbvc_units_t
*unit
;
2157 if (usbvc_chk_descr_len(4, 1, 0, cvs_data
) !=
2163 if ((pins
+ 5) >= cvs_buf_len
) {
2167 unit
= (usbvc_units_t
*)
2168 kmem_zalloc(sizeof (usbvc_units_t
), KM_SLEEP
);
2170 unit
->descr
= (usbvc_unit_descr_t
*)cvs_buf
;
2172 USB_DPRINTF_L3(PRINT_MASK_ATTA
,
2173 usbvcp
->usbvc_log_handle
, "usbvc_parse_ctrl_if: "
2174 "unit type=%x", unit
->descr
->bDescriptorSubType
);
2176 unit
->baSourceID
= &cvs_buf
[5];
2178 unit
->iSelector
= cvs_buf
[5 + pins
];
2180 list_insert_tail(&(usbvcp
->usbvc_unit_list
), unit
);
2184 case VC_EXTENSION_UNIT
:
2187 usbvc_units_t
*unit
;
2189 if (usbvc_chk_descr_len(21, 1, 0, cvs_data
) !=
2195 if ((pins
+ 22) >= cvs_buf_len
) {
2200 /* Size of bmControls */
2201 n
= cvs_buf
[pins
+ 22];
2203 if (usbvc_chk_descr_len(pins
+ 22, 1, 0, cvs_data
) !=
2208 if ((23 + pins
+ n
) >= cvs_buf_len
) {
2212 unit
= (usbvc_units_t
*)
2213 kmem_zalloc(sizeof (usbvc_units_t
), KM_SLEEP
);
2215 unit
->descr
= (usbvc_unit_descr_t
*)cvs_buf
;
2217 USB_DPRINTF_L3(PRINT_MASK_ATTA
,
2218 usbvcp
->usbvc_log_handle
, "usbvc_parse_ctrl_if: "
2219 "unit type=%x", unit
->descr
->bDescriptorSubType
);
2221 unit
->baSourceID
= &cvs_buf
[22];
2223 unit
->bControlSize
= cvs_buf
[22 + pins
];
2225 if (unit
->bControlSize
!= 0) {
2226 unit
->bmControls
= &cvs_buf
[23 + pins
];
2228 unit
->iExtension
= cvs_buf
[23 + pins
+ n
];
2230 list_insert_tail(&(usbvcp
->usbvc_unit_list
), unit
);
2241 * For webcam which is not compliant to video class specification
2242 * and no header descriptor in VC interface, return USB_FAILURE.
2244 if (!usbvcp
->usbvc_vc_header
) {
2245 USB_DPRINTF_L2(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2246 "usbvc_parse_ctrl_if: no header descriptor");
2248 return (USB_FAILURE
);
2251 return (USB_SUCCESS
);
2255 /* Parse all the cvs descriptors in one stream interface. */
2257 usbvc_parse_stream_if(usbvc_state_t
*usbvcp
, int if_num
)
2259 usb_alt_if_data_t
*if_alt_data
;
2261 usbvc_stream_if_t
*strm_if
;
2265 strm_if
= (usbvc_stream_if_t
*)kmem_zalloc(sizeof (usbvc_stream_if_t
),
2267 strm_if
->if_descr
= &usbvcp
->usbvc_reg
->dev_curr_cfg
->cfg_if
[if_num
];
2268 if_alt_data
= strm_if
->if_descr
->if_alt
;
2269 if (usbvc_parse_stream_header(usbvcp
, strm_if
) != USB_SUCCESS
) {
2270 USB_DPRINTF_L2(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2271 "usbvc_parse_stream_if: parse header fail");
2272 kmem_free(strm_if
, sizeof (usbvc_stream_if_t
));
2276 if (usbvc_parse_format_groups(usbvcp
, strm_if
) != USB_SUCCESS
) {
2277 USB_DPRINTF_L2(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2278 "usbvc_parse_stream_if: parse groups fail");
2279 kmem_free(strm_if
, sizeof (usbvc_stream_if_t
));
2284 /* Parse the alternate settings to find the maximum bandwidth. */
2285 for (i
= 0; i
< strm_if
->if_descr
->if_n_alt
; i
++) {
2286 if_alt_data
= &strm_if
->if_descr
->if_alt
[i
];
2287 for (j
= 0; j
< if_alt_data
->altif_n_ep
; j
++) {
2289 if_alt_data
->altif_ep
[j
].ep_descr
.bEndpointAddress
;
2290 if (strm_if
->input_header
!= NULL
&&
2292 strm_if
->input_header
->descr
->bEndpointAddress
) {
2296 if (strm_if
->output_header
!= NULL
&&
2298 strm_if
->output_header
->descr
->bEndpointAddress
) {
2303 if_alt_data
->altif_ep
[j
].ep_descr
.wMaxPacketSize
;
2304 pktsize
= HS_PKT_SIZE(pktsize
);
2305 if (pktsize
> strm_if
->max_isoc_payload
) {
2306 strm_if
->max_isoc_payload
= pktsize
;
2311 /* initialize MJPEC FID toggle */
2312 strm_if
->fid
= 0xff;
2315 * initialize desired number of buffers used internally in read() mode
2317 strm_if
->buf_read_num
= USBVC_DEFAULT_READ_BUF_NUM
;
2319 USB_DPRINTF_L4(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2320 "usbvc_parse_stream_if: return. max_isoc_payload=%x",
2321 strm_if
->max_isoc_payload
);
2328 * Parse all the stream interfaces asociated with the video control interface.
2329 * This driver will attach to a video control interface on the device,
2330 * there might be multiple video stream interfaces associated with one video
2331 * control interface.
2334 usbvc_parse_stream_ifs(usbvc_state_t
*usbvcp
)
2336 int i
, if_cnt
, if_num
;
2337 usbvc_stream_if_t
*strm_if
;
2339 if_cnt
= usbvcp
->usbvc_vc_header
->descr
->bInCollection
;
2341 ASSERT(list_is_empty(&usbvcp
->usbvc_stream_list
));
2342 USB_DPRINTF_L2(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2343 "usbvc_parse_stream_ifs: no stream interfaces");
2345 return (USB_SUCCESS
);
2347 for (i
= 0; i
< if_cnt
; i
++) {
2348 if_num
= usbvcp
->usbvc_vc_header
->baInterfaceNr
[i
];
2349 strm_if
= usbvc_parse_stream_if(usbvcp
, if_num
);
2350 if (strm_if
== NULL
) {
2351 USB_DPRINTF_L2(PRINT_MASK_ATTA
,
2352 usbvcp
->usbvc_log_handle
, "usbvc_parse_stream_ifs:"
2353 " parse stream interface %d failed.", if_num
);
2355 return (USB_FAILURE
);
2357 /* video data buffers */
2358 list_create(&(strm_if
->buf_map
.uv_buf_free
),
2359 sizeof (usbvc_buf_t
), offsetof(usbvc_buf_t
, buf_node
));
2360 list_create(&(strm_if
->buf_map
.uv_buf_done
),
2361 sizeof (usbvc_buf_t
), offsetof(usbvc_buf_t
, buf_node
));
2362 list_create(&(strm_if
->buf_read
.uv_buf_free
),
2363 sizeof (usbvc_buf_t
), offsetof(usbvc_buf_t
, buf_node
));
2364 list_create(&(strm_if
->buf_read
.uv_buf_done
),
2365 sizeof (usbvc_buf_t
), offsetof(usbvc_buf_t
, buf_node
));
2367 list_insert_tail(&(usbvcp
->usbvc_stream_list
), strm_if
);
2370 /* Make the first stream interface as the default one. */
2371 usbvcp
->usbvc_curr_strm
=
2372 (usbvc_stream_if_t
*)list_head(&usbvcp
->usbvc_stream_list
);
2374 return (USB_SUCCESS
);
2379 * Parse colorspace descriptor and still image descriptor of a format group.
2380 * There is only one colorspace or still image descriptor in one format group.
2383 usbvc_parse_color_still(usbvc_state_t
*usbvcp
, usbvc_format_group_t
*fmtgrp
,
2384 usb_cvs_data_t
*cvs_data
, uint_t cvs_num
, uint_t altif_n_cvs
)
2387 uint_t last_frame
, i
;
2391 frame_cnt
= fmtgrp
->format
->bNumFrameDescriptors
;
2392 last_frame
= frame_cnt
+ cvs_num
;
2395 * Find the still image descr and color format descr if there are any.
2396 * UVC Spec: only one still image and one color descr is allowed in
2399 for (i
= 1; i
<= 2; i
++) {
2400 if ((last_frame
+ i
) >= altif_n_cvs
) {
2404 cvs_buf
= cvs_data
[last_frame
+ i
].cvs_buf
;
2405 cvs_buf_len
= cvs_data
[last_frame
+ i
].cvs_buf_len
;
2407 if (cvs_buf
[2] == VS_STILL_IMAGE_FRAME
) {
2409 usbvc_still_image_frame_t
*st
;
2411 if (usbvc_chk_descr_len(4, 4, 0, cvs_data
) !=
2417 /* Number of Image Size patterns of this format */
2420 /* offset of bNumCompressionPattern */
2423 if (off
>= cvs_buf_len
) {
2428 /* Number of compression pattern of this format */
2431 if (usbvc_chk_descr_len(m
, 1, 0, cvs_data
) !=
2436 fmtgrp
->still
= (usbvc_still_image_frame_t
*)
2437 kmem_zalloc(sizeof (usbvc_still_image_frame_t
),
2440 st
->descr
= (usbvc_still_image_frame_descr_t
*)cvs_buf
;
2441 n
= st
->descr
->bNumImageSizePatterns
;
2444 (width_height_t
*)&cvs_buf
[5];
2446 st
->bNumCompressionPattern
= cvs_buf
[off
];
2447 if (cvs_buf
[off
] > 0) {
2448 st
->bCompression
= &cvs_buf
[off
+ 1];
2451 if (cvs_buf
[2] == VS_COLORFORMAT
) {
2452 fmtgrp
->color
= (usbvc_color_matching_descr_t
*)cvs_buf
;
2453 fmtgrp
->v4l2_color
= usbvc_v4l2_colorspace(
2454 fmtgrp
->color
->bColorPrimaries
);
2457 USB_DPRINTF_L4(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2458 "usbvc_parse_color_still: still=%p, color=%p",
2459 (void *)fmtgrp
->still
, (void *)fmtgrp
->color
);
2464 * Parse frame descriptors of a format group. There might be multi frame
2465 * descriptors in one format group.
2468 usbvc_parse_frames(usbvc_state_t
*usbvcp
, usbvc_format_group_t
*fmtgrp
,
2469 usb_cvs_data_t
*cvs_data
, uint_t cvs_num
, uint_t altif_n_cvs
)
2472 usbvc_frames_t
*frm
;
2473 usb_cvs_data_t
*cvs
;
2477 uint8_t frame_cnt
= fmtgrp
->format
->bNumFrameDescriptors
;
2479 USB_DPRINTF_L4(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2480 "usbvc_parse_format_group: frame_cnt=%d", frame_cnt
);
2482 if (frame_cnt
== 0) {
2483 fmtgrp
->frames
= NULL
;
2488 /* All these mem allocated will be freed in cleanup() */
2489 fmtgrp
->frames
= (usbvc_frames_t
*)
2490 kmem_zalloc(sizeof (usbvc_frames_t
) * frame_cnt
, KM_SLEEP
);
2492 last_frame
= frame_cnt
+ cvs_num
;
2497 * Traverse from the format decr's first frame decr to the the last
2500 for (; cvs_num
<= last_frame
; cvs_num
++) {
2501 USB_DPRINTF_L3(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2502 "usbvc_parse_frames: cvs_num=%d, i=%d", cvs_num
, i
);
2503 if (cvs_num
>= altif_n_cvs
) {
2504 USB_DPRINTF_L3(PRINT_MASK_ATTA
,
2505 usbvcp
->usbvc_log_handle
,
2506 "usbvc_parse_frames: less frames than "
2507 "expected, cvs_num=%d, i=%d", cvs_num
, i
);
2511 cvs
= &cvs_data
[cvs_num
];
2512 cvs_buf
= cvs
->cvs_buf
;
2513 cvs_buf_len
= cvs
->cvs_buf_len
;
2514 if (cvs_buf_len
< USBVC_FRAME_LEN_MIN
) {
2519 frm
= &fmtgrp
->frames
[i
];
2520 frm
->descr
= (usbvc_frame_descr_t
*)cvs
->cvs_buf
;
2522 /* Descriptor for discrete frame interval */
2523 if (frm
->descr
->bFrameIntervalType
> 0) {
2524 if (usbvc_chk_descr_len(25, 4, 0, cvs
) != USB_SUCCESS
) {
2531 frm
->dwFrameInterval
= (uint8_t *)&cvs_buf
[26];
2532 } else { /* Continuous interval */
2533 if (cvs_buf_len
< USBVC_FRAME_LEN_CON
) {
2540 /* Continuous frame intervals */
2541 LE_TO_UINT32(cvs_buf
, 26, frm
->dwMinFrameInterval
);
2542 LE_TO_UINT32(cvs_buf
, 30, frm
->dwMaxFrameInterval
);
2543 LE_TO_UINT32(cvs_buf
, 34, frm
->dwFrameIntervalStep
);
2548 fmtgrp
->frame_cnt
= i
;
2549 USB_DPRINTF_L4(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2550 "usbvc_parse_frames: %d frames are actually parsed",
2555 /* Parse one of the format groups in a stream interface */
2557 usbvc_parse_format_group(usbvc_state_t
*usbvcp
, usbvc_format_group_t
*fmtgrp
,
2558 usb_cvs_data_t
*cvs_data
, uint_t cvs_num
, uint_t altif_n_cvs
)
2560 usbvc_format_descr_t
*fmt
;
2562 fmt
= fmtgrp
->format
;
2563 USB_DPRINTF_L4(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2564 "usbvc_parse_format_group: frame_cnt=%d, cvs_num=%d",
2565 fmt
->bNumFrameDescriptors
, cvs_num
);
2567 switch (fmt
->bDescriptorSubType
) {
2568 case VS_FORMAT_UNCOMPRESSED
:
2569 usbvc_parse_color_still(usbvcp
, fmtgrp
, cvs_data
, cvs_num
,
2571 usbvc_parse_frames(usbvcp
, fmtgrp
, cvs_data
, cvs_num
,
2573 fmtgrp
->v4l2_bpp
= fmt
->fmt
.uncompressed
.bBitsPerPixel
/ 8;
2574 fmtgrp
->v4l2_pixelformat
= usbvc_v4l2_guid2fcc(
2575 (uint8_t *)&fmt
->fmt
.uncompressed
.guidFormat
);
2578 case VS_FORMAT_MJPEG
:
2579 usbvc_parse_color_still(usbvcp
, fmtgrp
, cvs_data
, cvs_num
,
2581 usbvc_parse_frames(usbvcp
, fmtgrp
, cvs_data
, cvs_num
,
2583 fmtgrp
->v4l2_bpp
= 0;
2584 fmtgrp
->v4l2_pixelformat
= V4L2_PIX_FMT_MJPEG
;
2587 case VS_FORMAT_MPEG2TS
:
2589 case VS_FORMAT_FRAME_BASED
:
2590 case VS_FORMAT_STREAM_BASED
:
2591 USB_DPRINTF_L2(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2592 "usbvc_parse_format_group: format not supported yet.");
2594 return (USB_FAILURE
);
2596 USB_DPRINTF_L2(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2597 "usbvc_parse_format_group: unknown format.");
2599 return (USB_FAILURE
);
2602 return (USB_SUCCESS
);
2606 /* Parse the descriptors belong to one format */
2608 usbvc_parse_format_groups(usbvc_state_t
*usbvcp
, usbvc_stream_if_t
*strm_if
)
2610 usb_alt_if_data_t
*if_alt_data
;
2611 usb_cvs_data_t
*cvs_data
;
2612 uint8_t fmtgrp_num
, fmtgrp_cnt
;
2615 usbvc_format_group_t
*fmtgrp
;
2619 * bNumFormats indicates the number of formats in this stream
2620 * interface. On some devices, we see this number is larger than
2623 if (strm_if
->input_header
) {
2624 fmtgrp_cnt
= strm_if
->input_header
->descr
->bNumFormats
;
2625 } else if (strm_if
->output_header
) {
2626 fmtgrp_cnt
= strm_if
->output_header
->descr
->bNumFormats
;
2630 return (USB_FAILURE
);
2632 USB_DPRINTF_L3(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2633 "usbvc_parse_format_groups: fmtgrp_cnt=%d", fmtgrp_cnt
);
2635 fmtgrp
= (usbvc_format_group_t
*)
2636 kmem_zalloc(sizeof (usbvc_format_group_t
) * fmtgrp_cnt
, KM_SLEEP
);
2638 if_alt_data
= strm_if
->if_descr
->if_alt
;
2639 cvs_data
= if_alt_data
->altif_cvs
;
2641 for (fmtgrp_num
= 0; fmtgrp_num
< fmtgrp_cnt
&&
2642 cvs_num
< if_alt_data
->altif_n_cvs
; cvs_num
++) {
2643 cvs_buf
= cvs_data
[cvs_num
].cvs_buf
;
2644 switch (cvs_buf
[2]) {
2645 case VS_FORMAT_UNCOMPRESSED
:
2646 case VS_FORMAT_MJPEG
:
2647 case VS_FORMAT_MPEG2TS
:
2649 case VS_FORMAT_FRAME_BASED
:
2650 case VS_FORMAT_STREAM_BASED
:
2651 fmtgrp
[fmtgrp_num
].format
=
2652 (usbvc_format_descr_t
*)cvs_buf
;
2655 * Now cvs_data[cvs_num].cvs_buf is format descriptor,
2656 * usbvc_parse_format_group will then parse the frame
2657 * descriptors following this format descriptor.
2659 (void) usbvc_parse_format_group(usbvcp
,
2660 &fmtgrp
[fmtgrp_num
], cvs_data
, cvs_num
,
2661 if_alt_data
->altif_n_cvs
);
2671 /* Save the number of parsed format groups. */
2672 strm_if
->fmtgrp_cnt
= fmtgrp_num
;
2673 USB_DPRINTF_L3(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2674 "usbvc_parse_format_groups: acctually %d formats parsed",
2678 * If can't find any formats, then free all allocated
2679 * usbvc_format_group_t, return failure.
2681 if (!(fmtgrp
[0].format
)) {
2682 kmem_free(fmtgrp
, sizeof (usbvc_format_group_t
) * fmtgrp_cnt
);
2683 strm_if
->format_group
= NULL
;
2685 USB_DPRINTF_L2(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2686 "usbvc_parse_format_groups: can't find any formats");
2688 return (USB_FAILURE
);
2690 strm_if
->format_group
= fmtgrp
;
2691 USB_DPRINTF_L3(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2692 "usbvc_parse_format_groups: %d format groups parsed", fmtgrp_num
);
2694 return (USB_SUCCESS
);
2699 * Parse the input/output header in one stream interface.
2700 * UVC Spec: there must be one and only one header in one stream interface.
2703 usbvc_parse_stream_header(usbvc_state_t
*usbvcp
, usbvc_stream_if_t
*strm_if
)
2705 usb_alt_if_data_t
*if_alt_data
;
2706 usb_cvs_data_t
*cvs_data
;
2709 usbvc_input_header_t
*in_hdr
;
2710 usbvc_output_header_t
*out_hdr
;
2712 if_alt_data
= strm_if
->if_descr
->if_alt
;
2713 cvs_data
= if_alt_data
->altif_cvs
;
2714 for (cvs_num
= 0; cvs_num
< if_alt_data
->altif_n_cvs
; cvs_num
++) {
2715 cvs_buf
= cvs_data
[cvs_num
].cvs_buf
;
2716 USB_DPRINTF_L3(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2717 "usbvc_parse_stream_header: cvs_num= %d", cvs_num
);
2720 * parse interface cvs descriptors here; by checking
2721 * bDescriptorType (cvs_buf[1])
2723 if (cvs_buf
[1] != CS_INTERFACE
) {
2728 if (cvs_buf
[2] == VS_INPUT_HEADER
) {
2729 if (usbvc_chk_descr_len(3, 0, 12, cvs_data
) !=
2735 strm_if
->input_header
=
2736 (usbvc_input_header_t
*)
2737 kmem_zalloc(sizeof (usbvc_input_header_t
),
2739 in_hdr
= strm_if
->input_header
;
2740 in_hdr
->descr
= (usbvc_input_header_descr_t
*)cvs_buf
;
2741 if (in_hdr
->descr
->bNumFormats
> 0) {
2742 in_hdr
->bmaControls
= &cvs_buf
[13];
2745 return (USB_SUCCESS
);
2746 } else if (cvs_buf
[2] == VS_OUTPUT_HEADER
) {
2747 if (usbvc_chk_descr_len(3, 0, 8, cvs_data
) !=
2752 strm_if
->output_header
=
2753 (usbvc_output_header_t
*)
2754 kmem_zalloc(sizeof (usbvc_output_header_t
),
2756 out_hdr
= strm_if
->output_header
;
2758 (usbvc_output_header_descr_t
*)cvs_buf
;
2759 if (out_hdr
->descr
->bNumFormats
> 0) {
2760 out_hdr
->bmaControls
= &cvs_buf
[13];
2763 return (USB_SUCCESS
);
2769 /* Didn't find one header descriptor. */
2770 USB_DPRINTF_L2(PRINT_MASK_ATTA
, usbvcp
->usbvc_log_handle
,
2771 "usbvc_parse_stream_header: FAIL");
2773 return (USB_FAILURE
);
2776 /* read I/O functions */
2778 /* Allocate bufs for read I/O method */
2780 usbvc_alloc_read_bufs(usbvc_state_t
*usbvcp
, usbvc_stream_if_t
*strm_if
)
2787 ASSERT(mutex_owned(&usbvcp
->usbvc_mutex
));
2789 LE_TO_UINT32(strm_if
->ctrl_pc
.dwMaxVideoFrameSize
, 0, len
);
2792 return (USB_FAILURE
);
2794 for (i
= 0; i
< strm_if
->buf_read_num
; i
++) {
2795 mutex_exit(&usbvcp
->usbvc_mutex
);
2796 buf
= (usbvc_buf_t
*)kmem_zalloc(sizeof (usbvc_buf_t
),
2798 data
= (uchar_t
*)kmem_zalloc(len
, KM_SLEEP
);
2799 mutex_enter(&usbvcp
->usbvc_mutex
);
2802 list_insert_tail(&(strm_if
->buf_read
.uv_buf_free
), buf
);
2804 strm_if
->buf_read
.buf_cnt
= strm_if
->buf_read_num
;
2805 USB_DPRINTF_L4(PRINT_MASK_READ
, usbvcp
->usbvc_log_handle
,
2806 "read_bufs: %d bufs allocated", strm_if
->buf_read
.buf_cnt
);
2808 return (USB_SUCCESS
);
2812 /* Read a done buf, copy data to bp. This function is for read I/O method */
2814 usbvc_read_buf(usbvc_state_t
*usbvcp
, struct buf
*bp
)
2820 ASSERT(mutex_owned(&usbvcp
->usbvc_mutex
));
2822 if (list_is_empty(&usbvcp
->usbvc_curr_strm
->buf_read
.uv_buf_done
)) {
2823 USB_DPRINTF_L2(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
2824 "usbvc_read_buf: empty list(uv_buf_done)!");
2826 return (USB_FAILURE
);
2829 /* read a buf from full list and then put it to free list */
2830 buf
= list_head(&usbvcp
->usbvc_curr_strm
->buf_read
.uv_buf_done
);
2832 USB_DPRINTF_L2(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
2833 "usbvc_read_buf: buf=%p, buf->filled=%d, buf->len=%d,"
2834 " buf->len_read=%d bp->b_bcount=%ld, bp->b_resid=%lu",
2835 (void *)buf
, buf
->filled
, buf
->len
, buf
->len_read
,
2836 bp
->b_bcount
, bp
->b_resid
);
2838 ASSERT(buf
->len_read
<= buf
->filled
);
2840 buf_residue
= buf
->filled
- buf
->len_read
;
2841 len_to_copy
= min(bp
->b_bcount
, buf_residue
);
2843 bcopy(buf
->data
+ buf
->len_read
, bp
->b_un
.b_addr
, len_to_copy
);
2844 bp
->b_private
= NULL
;
2845 buf
->len_read
+= len_to_copy
;
2846 bp
->b_resid
= bp
->b_bcount
- len_to_copy
;
2848 if (len_to_copy
== buf_residue
) {
2850 * the bp can accommodate all the remaining bytes of
2851 * the buf. Then we can reuse this buf.
2854 list_remove(&usbvcp
->usbvc_curr_strm
->buf_read
.uv_buf_done
,
2856 list_insert_tail(&usbvcp
->usbvc_curr_strm
->buf_read
.uv_buf_free
,
2860 return (USB_SUCCESS
);
2864 /* Free one buf which is for read/write IO style */
2866 usbvc_free_read_buf(usbvc_buf_t
*buf
)
2870 kmem_free(buf
->data
, buf
->len
);
2872 kmem_free(buf
, sizeof (usbvc_buf_t
));
2877 /* Free all bufs which are for read/write IO style */
2879 usbvc_free_read_bufs(usbvc_state_t
*usbvcp
, usbvc_stream_if_t
*strm_if
)
2883 ASSERT(mutex_owned(&usbvcp
->usbvc_mutex
));
2889 buf
= strm_if
->buf_read
.buf_filling
;
2890 usbvc_free_read_buf(buf
);
2891 strm_if
->buf_read
.buf_filling
= NULL
;
2893 while (!list_is_empty(&strm_if
->buf_read
.uv_buf_free
)) {
2894 buf
= list_head(&strm_if
->buf_read
.uv_buf_free
);
2896 list_remove(&(strm_if
->buf_read
.uv_buf_free
), buf
);
2897 usbvc_free_read_buf(buf
);
2900 while (!list_is_empty(&strm_if
->buf_read
.uv_buf_done
)) {
2901 buf
= list_head(&strm_if
->buf_read
.uv_buf_done
);
2903 list_remove(&(strm_if
->buf_read
.uv_buf_done
), buf
);
2904 usbvc_free_read_buf(buf
);
2907 strm_if
->buf_read
.buf_cnt
= 0;
2908 USB_DPRINTF_L4(PRINT_MASK_CLOSE
, usbvcp
->usbvc_log_handle
,
2909 "usbvc_free_read_bufs: return");
2914 * Allocate bufs for mapped I/O , return the number of allocated bufs
2915 * if success, return 0 if fail.
2918 usbvc_alloc_map_bufs(usbvc_state_t
*usbvcp
, usbvc_stream_if_t
*strm_if
,
2919 int buf_cnt
, int buf_len
)
2924 ASSERT(mutex_owned(&usbvcp
->usbvc_mutex
));
2925 USB_DPRINTF_L4(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
2926 "usbvc_alloc_map_bufs: bufcnt=%d, buflen=%d", buf_cnt
, buf_len
);
2927 if (buf_len
<= 0 || buf_cnt
<= 0) {
2928 USB_DPRINTF_L2(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
2929 "usbvc_alloc_map_bufs: len<=0, cnt<=0");
2933 mutex_exit(&usbvcp
->usbvc_mutex
);
2935 bufs
= (usbvc_buf_t
*) kmem_zalloc(sizeof (usbvc_buf_t
) * buf_cnt
,
2938 mutex_enter(&usbvcp
->usbvc_mutex
);
2939 strm_if
->buf_map
.buf_head
= bufs
;
2940 buf_len
= ptob(btopr(buf_len
));
2942 mutex_exit(&usbvcp
->usbvc_mutex
);
2943 bufs
[0].data
= ddi_umem_alloc(buf_len
* buf_cnt
, DDI_UMEM_SLEEP
,
2944 &bufs
[0].umem_cookie
);
2945 mutex_enter(&usbvcp
->usbvc_mutex
);
2947 for (i
= 0; i
< buf_cnt
; i
++) {
2948 bufs
[i
].len
= buf_len
;
2949 bufs
[i
].data
= bufs
[0].data
+ (buf_len
* i
);
2950 bufs
[i
].umem_cookie
= bufs
[0].umem_cookie
;
2951 bufs
[i
].status
= USBVC_BUF_INIT
;
2953 bufs
[i
].v4l2_buf
.index
= i
;
2954 bufs
[i
].v4l2_buf
.m
.offset
= i
* bufs
[i
].len
;
2955 bufs
[i
].v4l2_buf
.length
= bufs
[i
].len
;
2956 bufs
[i
].v4l2_buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2957 bufs
[i
].v4l2_buf
.sequence
= 0;
2958 bufs
[i
].v4l2_buf
.field
= V4L2_FIELD_NONE
;
2959 bufs
[i
].v4l2_buf
.memory
= V4L2_MEMORY_MMAP
;
2960 bufs
[i
].v4l2_buf
.flags
= V4L2_MEMORY_MMAP
;
2962 list_insert_tail(&strm_if
->buf_map
.uv_buf_free
, &bufs
[i
]);
2963 USB_DPRINTF_L4(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
2964 "usbvc_alloc_map_bufs: prepare %d buffers of %d bytes",
2965 buf_cnt
, bufs
[i
].len
);
2967 strm_if
->buf_map
.buf_cnt
= buf_cnt
;
2968 strm_if
->buf_map
.buf_filling
= NULL
;
2974 /* Free all bufs which are for memory map IO style */
2976 usbvc_free_map_bufs(usbvc_state_t
*usbvcp
, usbvc_stream_if_t
*strm_if
)
2980 ASSERT(mutex_owned(&usbvcp
->usbvc_mutex
));
2985 strm_if
->buf_map
.buf_filling
= NULL
;
2986 while (!list_is_empty(&strm_if
->buf_map
.uv_buf_free
)) {
2987 buf
= (usbvc_buf_t
*)list_head(&strm_if
->buf_map
.uv_buf_free
);
2988 list_remove(&(strm_if
->buf_map
.uv_buf_free
), buf
);
2990 while (!list_is_empty(&strm_if
->buf_map
.uv_buf_done
)) {
2991 buf
= (usbvc_buf_t
*)list_head(&strm_if
->buf_map
.uv_buf_done
);
2992 list_remove(&(strm_if
->buf_map
.uv_buf_done
), buf
);
2994 buf
= strm_if
->buf_map
.buf_head
;
2996 USB_DPRINTF_L2(PRINT_MASK_CLOSE
, usbvcp
->usbvc_log_handle
,
2997 "usbvc_free_map_bufs: no data buf need be freed, return");
3001 if (buf
->umem_cookie
) {
3002 ddi_umem_free(buf
->umem_cookie
);
3004 kmem_free(buf
, sizeof (usbvc_buf_t
) * strm_if
->buf_map
.buf_cnt
);
3005 strm_if
->buf_map
.buf_cnt
= 0;
3006 strm_if
->buf_map
.buf_head
= NULL
;
3008 USB_DPRINTF_L4(PRINT_MASK_CLOSE
, usbvcp
->usbvc_log_handle
,
3009 "usbvc_free_map_bufs: return");
3014 * Open the isoc pipe, this pipe is for video data transfer
3017 usbvc_open_isoc_pipe(usbvc_state_t
*usbvcp
, usbvc_stream_if_t
*strm_if
)
3019 usb_pipe_policy_t policy
;
3020 int rval
= USB_SUCCESS
;
3022 ASSERT(mutex_owned(&usbvcp
->usbvc_mutex
));
3024 if ((rval
= usbvc_set_alt(usbvcp
, strm_if
)) != USB_SUCCESS
) {
3028 bzero(&policy
, sizeof (usb_pipe_policy_t
));
3029 policy
.pp_max_async_reqs
= 2;
3030 mutex_exit(&usbvcp
->usbvc_mutex
);
3031 if ((rval
= usb_pipe_open(usbvcp
->usbvc_dip
, strm_if
->curr_ep
, &policy
,
3032 USB_FLAGS_SLEEP
, &strm_if
->datain_ph
)) != USB_SUCCESS
) {
3033 USB_DPRINTF_L2(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
3034 "usbvc_open_isoc_pipe: open pipe fail");
3035 mutex_enter(&usbvcp
->usbvc_mutex
);
3039 mutex_enter(&usbvcp
->usbvc_mutex
);
3040 strm_if
->start_polling
= 0;
3042 strm_if
->stream_on
= 0;
3044 USB_DPRINTF_L4(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
3045 "usbvc_open_isoc_pipe: success, datain_ph=%p",
3046 (void *)strm_if
->datain_ph
);
3053 * Open the isoc pipe
3056 usbvc_close_isoc_pipe(usbvc_state_t
*usbvcp
, usbvc_stream_if_t
*strm_if
)
3058 ASSERT(mutex_owned(&usbvcp
->usbvc_mutex
));
3060 USB_DPRINTF_L2(PRINT_MASK_CLOSE
, usbvcp
->usbvc_log_handle
,
3061 "usbvc_close_isoc_pipe: stream interface is NULL");
3065 if (strm_if
->datain_ph
) {
3066 mutex_exit(&usbvcp
->usbvc_mutex
);
3067 usb_pipe_close(usbvcp
->usbvc_dip
, strm_if
->datain_ph
,
3068 USB_FLAGS_SLEEP
, NULL
, NULL
);
3069 mutex_enter(&usbvcp
->usbvc_mutex
);
3071 strm_if
->datain_ph
= NULL
;
3076 * Start to get video data from isoc pipe in the stream interface,
3080 usbvc_start_isoc_polling(usbvc_state_t
*usbvcp
, usbvc_stream_if_t
*strm_if
,
3083 int rval
= USB_SUCCESS
;
3085 usb_isoc_req_t
*req
;
3087 ushort_t n_pkt
, pkt
;
3088 uint32_t frame_size
;
3090 ASSERT(mutex_owned(&usbvcp
->usbvc_mutex
));
3091 pkt_size
= HS_PKT_SIZE(strm_if
->curr_ep
->wMaxPacketSize
);
3092 if_num
= strm_if
->if_descr
->if_alt
->altif_descr
.bInterfaceNumber
;
3093 LE_TO_UINT32(strm_if
->ctrl_pc
.dwMaxVideoFrameSize
, 0, frame_size
);
3094 n_pkt
= (frame_size
+ (pkt_size
) - 1) / (pkt_size
);
3096 USB_DPRINTF_L3(PRINT_MASK_IOCTL
, usbvcp
->usbvc_log_handle
,
3097 "usbvc_start_isoc_polling: if_num=%d, alt=%d, n_pkt=%d,"
3098 " pkt_size=0x%x, MaxPacketSize=0x%x(Tsac#=%d), frame_size=0x%x",
3099 if_num
, strm_if
->curr_alt
, n_pkt
, pkt_size
,
3100 strm_if
->curr_ep
->wMaxPacketSize
,
3101 (1 + ((strm_if
->curr_ep
->wMaxPacketSize
>> 11) & 3)),
3104 if (n_pkt
> USBVC_MAX_PKTS
) {
3105 n_pkt
= USBVC_MAX_PKTS
;
3107 USB_DPRINTF_L3(PRINT_MASK_IOCTL
, usbvcp
->usbvc_log_handle
,
3108 "usbvc_start_isoc_polling: n_pkt=%d", n_pkt
);
3110 mutex_exit(&usbvcp
->usbvc_mutex
);
3111 if ((req
= usb_alloc_isoc_req(usbvcp
->usbvc_dip
, n_pkt
,
3112 n_pkt
* pkt_size
, USB_FLAGS_SLEEP
)) != NULL
) {
3113 mutex_enter(&usbvcp
->usbvc_mutex
);
3115 /* Initialize the packet descriptor */
3116 for (pkt
= 0; pkt
< n_pkt
; pkt
++) {
3117 req
->isoc_pkt_descr
[pkt
].isoc_pkt_length
= pkt_size
;
3120 req
->isoc_pkts_count
= n_pkt
;
3123 * zero here indicates that HCDs will use
3124 * isoc_pkt_descr->isoc_pkt_length to calculate
3127 req
->isoc_pkts_length
= 0;
3128 req
->isoc_attributes
= USB_ATTRS_ISOC_XFER_ASAP
|
3129 USB_ATTRS_SHORT_XFER_OK
| USB_ATTRS_AUTOCLEARING
;
3130 req
->isoc_cb
= usbvc_isoc_cb
;
3131 req
->isoc_exc_cb
= usbvc_isoc_exc_cb
;
3132 usbvcp
->usbvc_io_type
= io_type
;
3133 req
->isoc_client_private
= (usb_opaque_t
)usbvcp
;
3134 mutex_exit(&usbvcp
->usbvc_mutex
);
3135 rval
= usb_pipe_isoc_xfer(strm_if
->datain_ph
, req
, 0);
3136 mutex_enter(&usbvcp
->usbvc_mutex
);
3138 mutex_enter(&usbvcp
->usbvc_mutex
);
3139 USB_DPRINTF_L2(PRINT_MASK_IOCTL
, usbvcp
->usbvc_log_handle
,
3140 "usbvc_start_isoc_polling: alloc_isoc_req fail");
3142 return (USB_FAILURE
);
3145 if (rval
!= USB_SUCCESS
) {
3147 usb_free_isoc_req(req
);
3151 USB_DPRINTF_L4(PRINT_MASK_IOCTL
, usbvcp
->usbvc_log_handle
,
3152 "usbvc_start_isoc_polling: return, rval=%d", rval
);
3157 /* callbacks for receiving video data (isco in transfer) */
3160 /* Isoc transfer callback, get video data */
3162 usbvc_isoc_cb(usb_pipe_handle_t ph
, usb_isoc_req_t
*isoc_req
)
3164 usbvc_state_t
*usbvcp
=
3165 (usbvc_state_t
*)isoc_req
->isoc_client_private
;
3167 mblk_t
*data
= isoc_req
->isoc_data
;
3168 usbvc_buf_grp_t
*bufgrp
;
3170 mutex_enter(&usbvcp
->usbvc_mutex
);
3172 USB_DPRINTF_L3(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3173 "usbvc_isoc_cb: rq=0x%p, fno=%" PRId64
", n_pkts=%u, flag=0x%x,"
3174 " data=0x%p, cnt=%d",
3175 (void *)isoc_req
, isoc_req
->isoc_frame_no
,
3176 isoc_req
->isoc_pkts_count
, isoc_req
->isoc_attributes
,
3177 (void *)isoc_req
->isoc_data
, isoc_req
->isoc_error_count
);
3179 ASSERT((isoc_req
->isoc_cb_flags
& USB_CB_INTR_CONTEXT
) != 0);
3180 for (i
= 0; i
< isoc_req
->isoc_pkts_count
; i
++) {
3182 USB_DPRINTF_L3(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3184 "pktsize=%d status=%d resid=%d",
3186 isoc_req
->isoc_pkt_descr
[i
].isoc_pkt_length
,
3187 isoc_req
->isoc_pkt_descr
[i
].isoc_pkt_status
,
3188 isoc_req
->isoc_pkt_descr
[i
].isoc_pkt_actual_length
);
3190 if (isoc_req
->isoc_pkt_descr
[i
].isoc_pkt_status
!=
3192 USB_DPRINTF_L3(PRINT_MASK_CB
,
3193 usbvcp
->usbvc_log_handle
,
3194 "record: pkt=%d status=%s", i
, usb_str_cr(
3195 isoc_req
->isoc_pkt_descr
[i
].isoc_pkt_status
));
3198 if (usbvcp
->usbvc_io_type
== V4L2_MEMORY_MMAP
) {
3199 bufgrp
= &usbvcp
->usbvc_curr_strm
->buf_map
;
3201 bufgrp
= &usbvcp
->usbvc_curr_strm
->buf_read
;
3204 if (isoc_req
->isoc_pkt_descr
[i
].isoc_pkt_actual_length
) {
3205 if (usbvc_decode_stream_header(usbvcp
, bufgrp
, data
,
3206 isoc_req
->isoc_pkt_descr
[i
].isoc_pkt_actual_length
)
3208 USB_DPRINTF_L3(PRINT_MASK_CB
,
3209 usbvcp
->usbvc_log_handle
, "decode error");
3211 if (bufgrp
->buf_filling
&&
3212 (bufgrp
->buf_filling
->status
== USBVC_BUF_ERR
||
3213 bufgrp
->buf_filling
->status
== USBVC_BUF_DONE
)) {
3215 /* Move the buf to the full list */
3216 list_insert_tail(&bufgrp
->uv_buf_done
,
3217 bufgrp
->buf_filling
);
3219 bufgrp
->buf_filling
= NULL
;
3221 if (usbvcp
->usbvc_io_type
== V4L2_MEMORY_MMAP
) {
3222 cv_broadcast(&usbvcp
->usbvc_mapio_cv
);
3224 cv_broadcast(&usbvcp
->usbvc_read_cv
);
3229 data
->b_rptr
+= isoc_req
->isoc_pkt_descr
[i
].isoc_pkt_length
;
3231 mutex_exit(&usbvcp
->usbvc_mutex
);
3232 usb_free_isoc_req(isoc_req
);
3238 usbvc_isoc_exc_cb(usb_pipe_handle_t ph
, usb_isoc_req_t
*isoc_req
)
3240 usbvc_state_t
*usbvcp
=
3241 (usbvc_state_t
*)isoc_req
->isoc_client_private
;
3242 usb_cr_t completion_reason
;
3244 usbvc_stream_if_t
*strm_if
;
3246 ASSERT(!list_is_empty(&usbvcp
->usbvc_stream_list
));
3248 mutex_enter(&usbvcp
->usbvc_mutex
);
3250 /* get the first stream interface */
3251 strm_if
= usbvcp
->usbvc_curr_strm
;
3253 completion_reason
= isoc_req
->isoc_completion_reason
;
3255 USB_DPRINTF_L3(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3256 "usbvc_isoc_exc_cb: ph=0x%p, isoc_req=0x%p, cr=%d",
3257 (void *)ph
, (void *)isoc_req
, completion_reason
);
3259 ASSERT((isoc_req
->isoc_cb_flags
& USB_CB_INTR_CONTEXT
) == 0);
3261 switch (completion_reason
) {
3262 case USB_CR_STOPPED_POLLING
:
3263 case USB_CR_PIPE_CLOSING
:
3264 case USB_CR_PIPE_RESET
:
3267 case USB_CR_NO_RESOURCES
:
3269 * keep the show going: Since we have the original
3270 * request, we just resubmit it
3272 rval
= usb_pipe_isoc_xfer(strm_if
->datain_ph
, isoc_req
,
3274 USB_DPRINTF_L2(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3275 "usbvc_isoc_exc_cb: restart capture rval=%d", rval
);
3276 mutex_exit(&usbvcp
->usbvc_mutex
);
3280 mutex_exit(&usbvcp
->usbvc_mutex
);
3281 usb_pipe_stop_isoc_polling(ph
, USB_FLAGS_NOSLEEP
);
3282 USB_DPRINTF_L2(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3283 "usbvc_isoc_exc_cb: stop polling");
3284 mutex_enter(&usbvcp
->usbvc_mutex
);
3286 usb_free_isoc_req(isoc_req
);
3287 strm_if
->start_polling
= 0;
3288 USB_DPRINTF_L3(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3289 "usbvc_isoc_exc_cb: start_polling=%d cr=%d",
3290 strm_if
->start_polling
, completion_reason
);
3291 mutex_exit(&usbvcp
->usbvc_mutex
);
3295 * Other utility functions
3299 * Find a proper alternate according to the bandwidth that the current video
3301 * Set alternate by calling usb_set_alt_if;
3302 * Called before open pipes in stream interface.
3305 usbvc_set_alt(usbvc_state_t
*usbvcp
, usbvc_stream_if_t
*strm_if
)
3307 usb_alt_if_data_t
*alt
;
3308 uint_t i
, j
, if_num
;
3309 uint16_t pktsize
, curr_pktsize
;
3311 int rval
= USB_SUCCESS
;
3312 usbvc_input_header_t
*ihd
;
3313 usbvc_output_header_t
*ohd
;
3315 ASSERT(mutex_owned(&usbvcp
->usbvc_mutex
));
3317 LE_TO_UINT32(strm_if
->ctrl_pc
.dwMaxPayloadTransferSize
, 0, bandwidth
);
3319 USB_DPRINTF_L2(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
3320 "usbvc_set_alt: bandwidth is not set yet");
3322 return (USB_FAILURE
);
3324 USB_DPRINTF_L3(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
3325 "usbvc_set_alt: bandwidth=%x", bandwidth
);
3327 strm_if
->curr_ep
= NULL
;
3328 curr_pktsize
= 0xffff;
3329 ohd
= strm_if
->output_header
;
3330 ihd
= strm_if
->input_header
;
3332 * Find one alternate setting whose isoc ep's max pktsize is just
3333 * enough for the bandwidth.
3335 for (i
= 0; i
< strm_if
->if_descr
->if_n_alt
; i
++) {
3336 alt
= &strm_if
->if_descr
->if_alt
[i
];
3338 for (j
= 0; j
< alt
->altif_n_ep
; j
++) {
3340 /* if this stream interface is for input */
3342 alt
->altif_ep
[j
].ep_descr
.bEndpointAddress
!=
3343 ihd
->descr
->bEndpointAddress
) {
3347 /* if this stream interface is for output */
3349 alt
->altif_ep
[j
].ep_descr
.bEndpointAddress
!=
3350 ohd
->descr
->bEndpointAddress
) {
3355 alt
->altif_ep
[j
].ep_descr
.wMaxPacketSize
;
3356 pktsize
= HS_PKT_SIZE(pktsize
);
3357 if (pktsize
>= bandwidth
&& pktsize
< curr_pktsize
) {
3358 curr_pktsize
= pktsize
;
3359 strm_if
->curr_alt
= i
;
3360 strm_if
->curr_ep
= &alt
->altif_ep
[j
].ep_descr
;
3364 if (!strm_if
->curr_ep
) {
3365 USB_DPRINTF_L2(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
3366 "usbvc_set_alt: can't find a proper ep to satisfy"
3367 " the given bandwidth");
3369 return (USB_FAILURE
);
3371 USB_DPRINTF_L3(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
3372 "usbvc_set_alt: strm_if->curr_alt=%d", strm_if
->curr_alt
);
3373 if_num
= strm_if
->if_descr
->if_alt
->altif_descr
.bInterfaceNumber
;
3374 mutex_exit(&usbvcp
->usbvc_mutex
);
3375 if ((rval
= usb_set_alt_if(usbvcp
->usbvc_dip
, if_num
, strm_if
->curr_alt
,
3376 USB_FLAGS_SLEEP
, NULL
, NULL
)) != USB_SUCCESS
) {
3377 mutex_enter(&usbvcp
->usbvc_mutex
);
3378 USB_DPRINTF_L2(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
3379 "usbvc_set_alt: usb_set_alt_if fail, if.alt=%d.%d, rval=%d",
3380 if_num
, strm_if
->curr_alt
, rval
);
3384 mutex_enter(&usbvcp
->usbvc_mutex
);
3386 USB_DPRINTF_L4(PRINT_MASK_OPEN
, usbvcp
->usbvc_log_handle
,
3387 "usbvc_set_alt: return, if_num=%d, alt=%d",
3388 if_num
, strm_if
->curr_alt
);
3395 * Decode stream header for mjpeg and uncompressed format video data.
3396 * mjpeg and uncompressed format have the same stream header. See their
3397 * payload spec, 2.2 and 2.4
3400 usbvc_decode_stream_header(usbvc_state_t
*usbvcp
, usbvc_buf_grp_t
*bufgrp
,
3401 mblk_t
*data
, int actual_len
)
3403 uint32_t len
, buf_left
, data_len
;
3404 usbvc_stream_if_t
*strm_if
;
3405 uchar_t head_flag
, head_len
;
3406 usbvc_buf_t
*buf_filling
;
3408 ASSERT(mutex_owned(&usbvcp
->usbvc_mutex
));
3409 USB_DPRINTF_L4(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3410 "usbvc_decode_stream_header: enter. actual_len=%x", actual_len
);
3412 /* header length check. */
3413 if (actual_len
< 2) {
3414 USB_DPRINTF_L2(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3415 "usbvc_decode_stream_header: header is not completed");
3417 return (USB_FAILURE
);
3419 head_len
= data
->b_rptr
[0];
3420 head_flag
= data
->b_rptr
[1];
3422 USB_DPRINTF_L3(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3423 "usbvc_decode_stream_header: headlen=%x", head_len
);
3425 /* header length check. */
3426 if (actual_len
< head_len
) {
3427 USB_DPRINTF_L2(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3428 "usbvc_decode_stream_header: actual_len < head_len");
3430 return (USB_FAILURE
);
3434 * If there is no stream data in this packet and this packet is not
3435 * used to indicate the end of a frame, then just skip it.
3437 if ((actual_len
== head_len
) && !(head_flag
& USBVC_STREAM_EOF
)) {
3438 USB_DPRINTF_L2(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3439 "usbvc_decode_stream_header: only header, no data");
3441 return (USB_FAILURE
);
3444 /* Get the first stream interface */
3445 strm_if
= usbvcp
->usbvc_curr_strm
;
3447 LE_TO_UINT32(strm_if
->ctrl_pc
.dwMaxVideoFrameSize
, 0, len
);
3448 USB_DPRINTF_L3(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3449 "usbvc_decode_stream_header: dwMaxVideoFrameSize=%x, head_flag=%x",
3453 * if no buf is filling, pick one buf from free list and alloc data
3456 if (!bufgrp
->buf_filling
) {
3457 if (list_is_empty(&bufgrp
->uv_buf_free
)) {
3458 strm_if
->fid
= head_flag
& USBVC_STREAM_FID
;
3459 USB_DPRINTF_L2(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3460 "usbvc_decode_stream_header: free list are empty");
3462 return (USB_FAILURE
);
3465 bufgrp
->buf_filling
=
3466 (usbvc_buf_t
*)list_head(&bufgrp
->uv_buf_free
);
3468 /* unlink from buf free list */
3469 list_remove(&bufgrp
->uv_buf_free
, bufgrp
->buf_filling
);
3471 bufgrp
->buf_filling
->filled
= 0;
3472 USB_DPRINTF_L3(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3473 "usbvc_decode_stream_header: status=%d",
3474 bufgrp
->buf_filling
->status
);
3475 bufgrp
->buf_filling
->status
= USBVC_BUF_EMPTY
;
3477 buf_filling
= bufgrp
->buf_filling
;
3478 ASSERT(buf_filling
->len
>= buf_filling
->filled
);
3479 buf_left
= buf_filling
->len
- buf_filling
->filled
;
3481 /* if no buf room left, then return with a err status */
3482 if (buf_left
== 0) {
3483 /* buffer full, got an EOF packet(head only, no payload) */
3484 if ((head_flag
& USBVC_STREAM_EOF
) &&
3485 (actual_len
== head_len
)) {
3486 buf_filling
->status
= USBVC_BUF_DONE
;
3487 USB_DPRINTF_L3(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3488 "usbvc_decode_stream_header: got a EOF packet");
3490 return (USB_SUCCESS
);
3493 /* Otherwise, mark the buf error and return failure */
3494 buf_filling
->status
= USBVC_BUF_ERR
;
3495 USB_DPRINTF_L3(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3496 "usbvc_decode_stream_header: frame buf full");
3498 return (USB_FAILURE
);
3501 /* get this sample's data length except header */
3502 data_len
= actual_len
- head_len
;
3503 USB_DPRINTF_L3(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3504 "usbvc_decode_stream_header: fid=%x, len=%x, filled=%x",
3505 strm_if
->fid
, buf_filling
->len
, buf_filling
->filled
);
3507 /* if the first sample for a frame */
3508 if (buf_filling
->filled
== 0) {
3510 * Only if it is the frist packet of a frame,
3511 * we will begin filling a frame.
3513 if (strm_if
->fid
!= 0xff && strm_if
->fid
==
3514 (head_flag
& USBVC_STREAM_FID
)) {
3515 USB_DPRINTF_L2(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3516 "usbvc_decode_stream_header: 1st sample of a frame,"
3517 " fid is incorrect.");
3519 return (USB_FAILURE
);
3521 strm_if
->fid
= head_flag
& USBVC_STREAM_FID
;
3523 /* If in the middle of a frame, fid should be consistent. */
3524 } else if (strm_if
->fid
!= (head_flag
& USBVC_STREAM_FID
)) {
3525 USB_DPRINTF_L2(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3526 "usbvc_decode_stream_header: fid is incorrect.");
3527 strm_if
->fid
= head_flag
& USBVC_STREAM_FID
;
3528 buf_filling
->status
= USBVC_BUF_ERR
;
3530 return (USB_FAILURE
);
3533 bcopy((void *)(data
->b_rptr
+ head_len
),
3534 (void *)(buf_filling
->data
+ buf_filling
->filled
),
3535 min(data_len
, buf_left
));
3537 buf_filling
->filled
+= min(data_len
, buf_left
);
3540 /* If the last packet for this frame */
3541 if (head_flag
& USBVC_STREAM_EOF
) {
3542 buf_filling
->status
= USBVC_BUF_DONE
;
3544 if (data_len
> buf_left
) {
3545 buf_filling
->status
= USBVC_BUF_ERR
;
3547 USB_DPRINTF_L4(PRINT_MASK_CB
, usbvcp
->usbvc_log_handle
,
3548 "usbvc_decode_stream_header: buf_status=%d", buf_filling
->status
);
3550 return (USB_SUCCESS
);
3555 * usbvc_serialize_access:
3556 * Get the serial synchronization object before returning.
3559 * usbvcp - Pointer to usbvc state structure
3561 * USBVC_SER_SIG - to wait such that a signal can interrupt
3562 * USBVC_SER_NOSIG - to wait such that a signal cannot interrupt
3565 usbvc_serialize_access(usbvc_state_t
*usbvcp
, boolean_t waitsig
)
3569 ASSERT(mutex_owned(&usbvcp
->usbvc_mutex
));
3571 while (usbvcp
->usbvc_serial_inuse
) {
3572 if (waitsig
== USBVC_SER_SIG
) {
3573 rval
= cv_wait_sig(&usbvcp
->usbvc_serial_cv
,
3574 &usbvcp
->usbvc_mutex
);
3576 cv_wait(&usbvcp
->usbvc_serial_cv
,
3577 &usbvcp
->usbvc_mutex
);
3580 usbvcp
->usbvc_serial_inuse
= B_TRUE
;
3587 * usbvc_release_access:
3588 * Release the serial synchronization object.
3591 usbvc_release_access(usbvc_state_t
*usbvcp
)
3593 ASSERT(mutex_owned(&usbvcp
->usbvc_mutex
));
3594 usbvcp
->usbvc_serial_inuse
= B_FALSE
;
3595 cv_broadcast(&usbvcp
->usbvc_serial_cv
);
3599 /* Send req to video control interface to get ctrl */
3601 usbvc_vc_get_ctrl(usbvc_state_t
*usbvcp
, uint8_t req_code
, uint8_t entity_id
,
3602 uint16_t cs
, uint16_t wlength
, mblk_t
*data
)
3604 usb_cb_flags_t cb_flags
;
3606 usb_ctrl_setup_t setup
;
3608 setup
.bmRequestType
= USBVC_GET_IF
; /* bmRequestType */
3609 setup
.bRequest
= req_code
; /* bRequest */
3610 setup
.wValue
= cs
<<8;
3611 setup
.wIndex
= entity_id
<<8;
3612 setup
.wLength
= wlength
;
3615 if (usb_pipe_ctrl_xfer_wait(usbvcp
->usbvc_default_ph
, &setup
, &data
,
3616 &cr
, &cb_flags
, 0) != USB_SUCCESS
) {
3617 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL
, usbvcp
->usbvc_log_handle
,
3618 "usbvc_vc_get_ctrl: cmd failed, cr=%d, cb_flags=%x",
3621 return (USB_FAILURE
);
3624 return (USB_SUCCESS
);
3628 /* Send req to video control interface to get ctrl */
3630 usbvc_vc_set_ctrl(usbvc_state_t
*usbvcp
, uint8_t req_code
, uint8_t entity_id
,
3631 uint16_t cs
, uint16_t wlength
, mblk_t
*data
)
3633 usb_cb_flags_t cb_flags
;
3635 usb_ctrl_setup_t setup
;
3637 setup
.bmRequestType
= USBVC_SET_IF
; /* bmRequestType */
3638 setup
.bRequest
= req_code
; /* bRequest */
3639 setup
.wValue
= cs
<<8;
3640 setup
.wIndex
= entity_id
<<8;
3641 setup
.wLength
= wlength
;
3644 if (usb_pipe_ctrl_xfer_wait(usbvcp
->usbvc_default_ph
, &setup
, &data
,
3645 &cr
, &cb_flags
, 0) != USB_SUCCESS
) {
3646 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL
, usbvcp
->usbvc_log_handle
,
3647 "usbvc_vc_set_ctrl: cmd failed, cr=%d, cb_flags=%x",
3650 return (USB_FAILURE
);
3653 return (USB_SUCCESS
);
3657 /* Set probe or commit ctrl for video stream interface */
3659 usbvc_vs_set_probe_commit(usbvc_state_t
*usbvcp
, usbvc_stream_if_t
*strm_if
,
3660 usbvc_vs_probe_commit_t
*ctrl_pc
, uchar_t cs
)
3663 usb_cb_flags_t cb_flags
;
3665 usb_ctrl_setup_t setup
;
3668 setup
.bmRequestType
= USBVC_SET_IF
; /* bmRequestType */
3669 setup
.bRequest
= SET_CUR
; /* bRequest */
3671 /* wValue, VS_PROBE_CONTROL or VS_COMMIT_CONTROL */
3674 /* UVC Spec: this value must be put to the high byte */
3675 setup
.wValue
= setup
.wValue
<< 8;
3677 setup
.wIndex
= strm_if
->if_descr
->if_alt
->altif_descr
.bInterfaceNumber
;
3678 setup
.wLength
= usbvcp
->usbvc_vc_header
->descr
->bcdUVC
[0] ? 34 : 26;
3681 USB_DPRINTF_L3(PRINT_MASK_DEVCTRL
, usbvcp
->usbvc_log_handle
,
3682 "usbvc_vs_set_probe_commit: wLength=%d", setup
.wLength
);
3685 if ((data
= allocb(setup
.wLength
, BPRI_HI
)) == NULL
) {
3686 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL
, usbvcp
->usbvc_log_handle
,
3687 "usbvc_vs_set_probe_commit: allocb failed");
3689 return (USB_FAILURE
);
3692 bcopy(ctrl_pc
, data
->b_rptr
, setup
.wLength
);
3693 data
->b_wptr
+= setup
.wLength
;
3695 if ((rval
= usb_pipe_ctrl_xfer_wait(usbvcp
->usbvc_default_ph
, &setup
,
3696 &data
, &cr
, &cb_flags
, 0)) != USB_SUCCESS
) {
3700 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL
, usbvcp
->usbvc_log_handle
,
3701 "usbvc_vs_set_probe_commit: fail, rval=%d, cr=%d, "
3702 "cb_flags=%x", rval
, cr
, cb_flags
);
3710 return (USB_SUCCESS
);
3714 /* Get probe ctrl for vodeo stream interface */
3716 usbvc_vs_get_probe(usbvc_state_t
*usbvcp
, usbvc_stream_if_t
*strm_if
,
3717 usbvc_vs_probe_commit_t
*ctrl_pc
, uchar_t bRequest
)
3719 mblk_t
*data
= NULL
;
3720 usb_cb_flags_t cb_flags
;
3722 usb_ctrl_setup_t setup
;
3724 setup
.bmRequestType
= USBVC_GET_IF
; /* bmRequestType */
3725 setup
.bRequest
= bRequest
; /* bRequest */
3726 setup
.wValue
= VS_PROBE_CONTROL
; /* wValue, PROBE or COMMIT */
3727 setup
.wValue
= setup
.wValue
<< 8;
3729 (uint16_t)strm_if
->if_descr
->if_alt
->altif_descr
.bInterfaceNumber
;
3730 setup
.wLength
= usbvcp
->usbvc_vc_header
->descr
->bcdUVC
[0] ? 34 : 26;
3734 if (usb_pipe_ctrl_xfer_wait(usbvcp
->usbvc_default_ph
, &setup
, &data
,
3735 &cr
, &cb_flags
, 0) != USB_SUCCESS
) {
3739 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL
, usbvcp
->usbvc_log_handle
,
3740 "usbvc_vs_get_probe: cmd failed, cr=%d, cb_flags=%x",
3743 return (USB_FAILURE
);
3745 bcopy(data
->b_rptr
, ctrl_pc
, setup
.wLength
);
3750 return (USB_SUCCESS
);
3754 /* Set a default format when open the device */
3756 usbvc_set_default_stream_fmt(usbvc_state_t
*usbvcp
)
3758 usbvc_vs_probe_commit_t ctrl
, ctrl_get
;
3759 usbvc_stream_if_t
*strm_if
;
3760 usbvc_format_group_t
*curr_fmtgrp
;
3764 USB_DPRINTF_L4(PRINT_MASK_DEVCTRL
, usbvcp
->usbvc_log_handle
,
3765 "usbvc_set_default_stream_fmt: enter");
3767 mutex_enter(&usbvcp
->usbvc_mutex
);
3768 if (list_is_empty(&usbvcp
->usbvc_stream_list
)) {
3769 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL
, usbvcp
->usbvc_log_handle
,
3770 "usbvc_set_default_stream_fmt: no stream interface, fail");
3771 mutex_exit(&usbvcp
->usbvc_mutex
);
3773 return (USB_FAILURE
);
3775 bzero((void *)&ctrl
, sizeof (usbvc_vs_probe_commit_t
));
3777 /* Get the current stream interface */
3778 strm_if
= usbvcp
->usbvc_curr_strm
;
3780 /* Fill the probe commit req data */
3783 for (i
= 0; i
< strm_if
->fmtgrp_cnt
; i
++) {
3784 curr_fmtgrp
= &strm_if
->format_group
[i
];
3787 * If v4l2_pixelformat is NULL, then that means there is not
3788 * a parsed format in format_group[i].
3790 if (!curr_fmtgrp
|| !curr_fmtgrp
->v4l2_pixelformat
||
3791 curr_fmtgrp
->frame_cnt
== 0) {
3792 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL
,
3793 usbvcp
->usbvc_log_handle
,
3794 "usbvc_set_default_stream_fmt: no frame, fail");
3802 if (!curr_fmtgrp
|| curr_fmtgrp
->frame_cnt
== 0) {
3803 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL
, usbvcp
->usbvc_log_handle
,
3804 "usbvc_set_default_stream_fmt: can't find a fmtgrp"
3805 "which has a frame, fail");
3806 mutex_exit(&usbvcp
->usbvc_mutex
);
3808 return (USB_FAILURE
);
3811 ctrl
.bFormatIndex
= curr_fmtgrp
->format
->bFormatIndex
;
3813 /* use the first frame descr as default */
3814 ctrl
.bFrameIndex
= curr_fmtgrp
->frames
[0].descr
->bFrameIndex
;
3816 /* use bcopy to keep the byte sequence as 32 bit little endian */
3817 bcopy(&(curr_fmtgrp
->frames
[0].descr
->dwDefaultFrameInterval
[0]),
3818 &(ctrl
.dwFrameInterval
[0]), 4);
3820 mutex_exit(&usbvcp
->usbvc_mutex
);
3821 if (usbvc_vs_set_probe_commit(usbvcp
, strm_if
, &ctrl
, VS_PROBE_CONTROL
)
3824 return (USB_FAILURE
);
3826 if (usbvc_vs_get_probe(usbvcp
, strm_if
, &ctrl_get
, GET_CUR
)
3829 return (USB_FAILURE
);
3832 mutex_enter(&usbvcp
->usbvc_mutex
);
3833 LE_TO_UINT32(strm_if
->ctrl_pc
.dwMaxPayloadTransferSize
, 0, bandwidth
);
3834 USB_DPRINTF_L3(PRINT_MASK_DEVCTRL
, usbvcp
->usbvc_log_handle
,
3835 "usbvc_set_default_stream_fmt: get bandwidth=%x", bandwidth
);
3837 mutex_exit(&usbvcp
->usbvc_mutex
);
3838 if (usbvc_vs_set_probe_commit(usbvcp
, strm_if
, &ctrl_get
,
3839 VS_COMMIT_CONTROL
) != USB_SUCCESS
) {
3841 return (USB_FAILURE
);
3844 mutex_enter(&usbvcp
->usbvc_mutex
);
3846 /* it's good to check index here before use it */
3847 index
= ctrl_get
.bFormatIndex
- curr_fmtgrp
->format
->bFormatIndex
;
3848 if (index
< strm_if
->fmtgrp_cnt
) {
3849 strm_if
->cur_format_group
= &strm_if
->format_group
[index
];
3851 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL
, usbvcp
->usbvc_log_handle
,
3852 "usbvc_set_default_stream_fmt: format index out of range");
3853 mutex_exit(&usbvcp
->usbvc_mutex
);
3855 return (USB_FAILURE
);
3858 index
= ctrl_get
.bFrameIndex
-
3859 strm_if
->cur_format_group
->frames
[0].descr
->bFrameIndex
;
3860 if (index
< strm_if
->cur_format_group
->frame_cnt
) {
3861 strm_if
->cur_format_group
->cur_frame
=
3862 &strm_if
->cur_format_group
->frames
[index
];
3864 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL
, usbvcp
->usbvc_log_handle
,
3865 "usbvc_set_default_stream: frame index out of range");
3866 mutex_exit(&usbvcp
->usbvc_mutex
);
3868 return (USB_FAILURE
);
3872 * by now, the video format is set successfully. record the current
3873 * setting to strm_if->ctrl_pc
3875 bcopy(&ctrl_get
, &strm_if
->ctrl_pc
, sizeof (usbvc_vs_probe_commit_t
));
3877 mutex_exit(&usbvcp
->usbvc_mutex
);
3879 return (USB_SUCCESS
);