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