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