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