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