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