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