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