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