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