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