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