1 /* $NetBSD: uvideo.c,v 1.83 2022/07/01 01:06:51 riastradh Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Patrick Mahoney 5 * All rights reserved. 6 * 7 * This code was written by Patrick Mahoney (pat@polycrystal.org) as 8 * part of Google Summer of Code 2008. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * USB video specs: 41 * http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_1.zip 42 */ 43 44 #include <sys/cdefs.h> 45 __KERNEL_RCSID(0, "$NetBSD: uvideo.c,v 1.83 2022/07/01 01:06:51 riastradh Exp $"); 46 47 #ifdef _KERNEL_OPT 48 #include "opt_usb.h" 49 #endif 50 51 #ifdef _MODULE 52 #include <sys/module.h> 53 #endif 54 55 #include <sys/param.h> 56 #include <sys/systm.h> 57 #include <sys/kernel.h> 58 #include <sys/kmem.h> 59 #include <sys/device.h> 60 #include <sys/ioctl.h> 61 #include <sys/uio.h> 62 #include <sys/file.h> 63 #include <sys/select.h> 64 #include <sys/proc.h> 65 #include <sys/conf.h> 66 #include <sys/vnode.h> 67 #include <sys/poll.h> 68 #include <sys/queue.h> /* SLIST */ 69 #include <sys/kthread.h> 70 #include <sys/bus.h> 71 72 #include <sys/videoio.h> 73 #include <dev/video_if.h> 74 75 #include <dev/usb/usb.h> 76 #include <dev/usb/usbdi.h> 77 #include <dev/usb/usbdivar.h> 78 #include <dev/usb/usbdi_util.h> 79 #include <dev/usb/usb_quirks.h> 80 81 #include <dev/usb/uvideoreg.h> 82 83 #define UVIDEO_NXFERS 3 84 #define UVIDEO_NFRAMES_MAX 80 85 #define PRI_UVIDEO PRI_BIO 86 87 /* #define UVIDEO_DISABLE_MJPEG */ 88 89 #ifdef UVIDEO_DEBUG 90 #define DPRINTF(x) do { if (uvideodebug) printf x; } while (0) 91 #define DPRINTFN(n,x) do { if (uvideodebug>(n)) printf x; } while (0) 92 int uvideodebug = 20; 93 #else 94 #define DPRINTF(x) __nothing 95 #define DPRINTFN(n,x) __nothing 96 #endif 97 98 typedef enum { 99 UVIDEO_STATE_CLOSED, 100 UVIDEO_STATE_OPENING, 101 UVIDEO_STATE_IDLE 102 } uvideo_state; 103 104 struct uvideo_camera_terminal { 105 uint16_t ct_objective_focal_min; 106 uint16_t ct_objective_focal_max; 107 uint16_t ct_ocular_focal_length; 108 }; 109 110 struct uvideo_processing_unit { 111 uint16_t pu_max_multiplier; /* digital zoom */ 112 uint8_t pu_video_standards; 113 }; 114 115 struct uvideo_extension_unit { 116 guid_t xu_guid; 117 }; 118 119 /* 120 * For simplicity, we consider a Terminal a special case of Unit 121 * rather than a separate entity. 122 */ 123 struct uvideo_unit { 124 uint8_t vu_id; 125 uint8_t vu_type; 126 uint8_t vu_dst_id; 127 uint8_t vu_nsrcs; 128 union { 129 uint8_t vu_src_id; /* vu_nsrcs = 1 */ 130 uint8_t *vu_src_id_ary; /* vu_nsrcs > 1 */ 131 } s; 132 133 /* fields for individual unit/terminal types */ 134 union { 135 struct uvideo_camera_terminal vu_camera; 136 struct uvideo_processing_unit vu_processing; 137 struct uvideo_extension_unit vu_extension; 138 } u; 139 140 /* Used by camera terminal, processing and extension units. */ 141 uint8_t vu_control_size; /* number of bytes in vu_controls */ 142 uint8_t *vu_controls; /* array of bytes. bits are 143 * numbered from 0 at least 144 * significant bit to 145 * (8*vu_control_size - 1)*/ 146 }; 147 148 struct uvideo_alternate { 149 uint8_t altno; 150 uint8_t interval; 151 uint16_t max_packet_size; 152 SLIST_ENTRY(uvideo_alternate) entries; 153 }; 154 SLIST_HEAD(altlist, uvideo_alternate); 155 156 #define UVIDEO_FORMAT_GET_FORMAT_INDEX(fmt) \ 157 ((fmt)->format.priv & 0xff) 158 #define UVIDEO_FORMAT_GET_FRAME_INDEX(fmt) \ 159 (((fmt)->format.priv >> 8) & 0xff) 160 /* TODO: find a better way to set bytes within this 32 bit value? */ 161 #define UVIDEO_FORMAT_SET_FORMAT_INDEX(fmt, index) do { \ 162 (fmt)->format.priv &= ~0xff; \ 163 (fmt)->format.priv |= ((index) & 0xff); \ 164 } while (0) 165 #define UVIDEO_FORMAT_SET_FRAME_INDEX(fmt, index) do { \ 166 (fmt)->format.priv &= ~(0xff << 8); \ 167 ((fmt)->format.priv |= (((index) & 0xff) << 8)); \ 168 } while (0) 169 170 struct uvideo_pixel_format { 171 enum video_pixel_format pixel_format; 172 SIMPLEQ_ENTRY(uvideo_pixel_format) entries; 173 }; 174 SIMPLEQ_HEAD(uvideo_pixel_format_list, uvideo_pixel_format); 175 176 struct uvideo_format { 177 struct video_format format; 178 SIMPLEQ_ENTRY(uvideo_format) entries; 179 }; 180 SIMPLEQ_HEAD(uvideo_format_list, uvideo_format); 181 182 struct uvideo_isoc_xfer; 183 struct uvideo_stream; 184 185 struct uvideo_isoc { 186 struct uvideo_isoc_xfer *i_ix; 187 struct uvideo_stream *i_vs; 188 struct usbd_xfer *i_xfer; 189 uint8_t *i_buf; 190 uint16_t *i_frlengths; 191 }; 192 193 struct uvideo_isoc_xfer { 194 uint8_t ix_endpt; 195 struct usbd_pipe *ix_pipe; 196 struct uvideo_isoc ix_i[UVIDEO_NXFERS]; 197 uint32_t ix_nframes; 198 uint32_t ix_uframe_len; 199 200 struct altlist ix_altlist; 201 }; 202 203 struct uvideo_bulk_xfer { 204 uint8_t bx_endpt; 205 struct usbd_pipe *bx_pipe; 206 struct usbd_xfer *bx_xfer; 207 uint8_t *bx_buffer; 208 int bx_buflen; 209 bool bx_running; 210 kcondvar_t bx_cv; 211 kmutex_t bx_lock; 212 }; 213 214 struct uvideo_stream { 215 device_t vs_videodev; 216 struct uvideo_softc *vs_parent; 217 struct usbd_interface *vs_iface; 218 uint8_t vs_ifaceno; 219 uint8_t vs_subtype; /* input or output */ 220 uint16_t vs_probelen; /* length of probe and 221 * commit data; varies 222 * depending on version 223 * of spec. */ 224 struct uvideo_format_list vs_formats; 225 struct uvideo_pixel_format_list vs_pixel_formats; 226 struct video_format *vs_default_format; 227 struct video_format vs_current_format; 228 229 /* usb transfer details */ 230 uint8_t vs_xfer_type; 231 union { 232 struct uvideo_bulk_xfer bulk; 233 struct uvideo_isoc_xfer isoc; 234 } vs_xfer; 235 236 int vs_frameno; /* toggles between 0 and 1 */ 237 238 /* current video format */ 239 uint32_t vs_max_payload_size; 240 uint32_t vs_frame_interval; 241 SLIST_ENTRY(uvideo_stream) entries; 242 243 uvideo_state vs_state; 244 }; 245 SLIST_HEAD(uvideo_stream_list, uvideo_stream); 246 247 struct uvideo_softc { 248 device_t sc_dev; /* base device */ 249 struct usbd_device *sc_udev; /* device */ 250 struct usbd_interface *sc_iface; /* interface handle */ 251 int sc_ifaceno; /* interface number */ 252 char *sc_devname; 253 254 int sc_dying; 255 256 uint8_t sc_nunits; 257 struct uvideo_unit **sc_unit; 258 259 struct uvideo_stream_list sc_stream_list; 260 261 char sc_businfo[32]; 262 }; 263 264 static int uvideo_match(device_t, cfdata_t, void *); 265 static void uvideo_attach(device_t, device_t, void *); 266 static int uvideo_detach(device_t, int); 267 static void uvideo_childdet(device_t, device_t); 268 static int uvideo_activate(device_t, enum devact); 269 270 static int uvideo_open(void *, int); 271 static void uvideo_close(void *); 272 static const char * uvideo_get_devname(void *); 273 static const char * uvideo_get_businfo(void *); 274 275 static int uvideo_enum_format(void *, uint32_t, struct video_format *); 276 static int uvideo_get_format(void *, struct video_format *); 277 static int uvideo_set_format(void *, struct video_format *); 278 static int uvideo_try_format(void *, struct video_format *); 279 static int uvideo_get_framerate(void *, struct video_fract *); 280 static int uvideo_set_framerate(void *, struct video_fract *); 281 static int uvideo_start_transfer(void *); 282 static int uvideo_stop_transfer(void *); 283 284 static int uvideo_get_control_group(void *, 285 struct video_control_group *); 286 static int uvideo_set_control_group(void *, 287 const struct video_control_group *); 288 289 static usbd_status uvideo_init_control( 290 struct uvideo_softc *, 291 const usb_interface_descriptor_t *, 292 usbd_desc_iter_t *); 293 static usbd_status uvideo_init_collection( 294 struct uvideo_softc *, 295 const usb_interface_descriptor_t *, 296 usbd_desc_iter_t *); 297 298 /* Functions for unit & terminal descriptors */ 299 static struct uvideo_unit * uvideo_unit_alloc(const uvideo_descriptor_t *); 300 static usbd_status uvideo_unit_init(struct uvideo_unit *, 301 const uvideo_descriptor_t *); 302 static void uvideo_unit_free(struct uvideo_unit *); 303 static void uvideo_unit_alloc_controls(struct uvideo_unit *, 304 uint8_t, 305 const uint8_t *); 306 static void uvideo_unit_free_controls(struct uvideo_unit *); 307 static void uvideo_unit_alloc_sources(struct uvideo_unit *, 308 uint8_t, 309 const uint8_t *); 310 static void uvideo_unit_free_sources(struct uvideo_unit *); 311 312 313 314 315 /* 316 * Functions for uvideo_stream, primary unit associated with a video 317 * driver or device file. 318 */ 319 static struct uvideo_stream * uvideo_find_stream(struct uvideo_softc *, 320 uint8_t); 321 #if 0 322 static struct uvideo_format * uvideo_stream_find_format( 323 struct uvideo_stream *, 324 uint8_t, uint8_t); 325 #endif 326 static struct uvideo_format * uvideo_stream_guess_format( 327 struct uvideo_stream *, 328 enum video_pixel_format, uint32_t, uint32_t); 329 static struct uvideo_stream * uvideo_stream_alloc(void); 330 static usbd_status uvideo_stream_init( 331 struct uvideo_stream *, 332 struct uvideo_softc *, 333 const usb_interface_descriptor_t *); 334 static usbd_status uvideo_stream_init_desc( 335 struct uvideo_stream *, 336 const usb_interface_descriptor_t *, 337 usbd_desc_iter_t *); 338 static usbd_status uvideo_stream_init_frame_based_format( 339 struct uvideo_stream *, 340 const uvideo_descriptor_t *, 341 usbd_desc_iter_t *); 342 static void uvideo_stream_free(struct uvideo_stream *); 343 344 static int uvideo_stream_start_xfer(struct uvideo_stream *); 345 static int uvideo_stream_stop_xfer(struct uvideo_stream *); 346 static usbd_status uvideo_stream_recv_process(struct uvideo_stream *, 347 uint8_t *, uint32_t); 348 static usbd_status uvideo_stream_recv_isoc_start(struct uvideo_stream *); 349 static usbd_status uvideo_stream_recv_isoc_start1(struct uvideo_isoc *); 350 static void uvideo_stream_recv_isoc_complete(struct usbd_xfer *, 351 void *, 352 usbd_status); 353 static void uvideo_stream_recv_bulk_transfer(void *); 354 355 /* format probe and commit */ 356 #define uvideo_stream_probe(vs, act, data) \ 357 (uvideo_stream_probe_and_commit((vs), (act), \ 358 UVIDEO_VS_PROBE_CONTROL, (data))) 359 #define uvideo_stream_commit(vs, act, data) \ 360 (uvideo_stream_probe_and_commit((vs), (act), \ 361 UVIDEO_VS_COMMIT_CONTROL, (data))) 362 static usbd_status uvideo_stream_probe_and_commit(struct uvideo_stream *, 363 uint8_t, uint8_t, 364 void *); 365 static void uvideo_init_probe_data(uvideo_probe_and_commit_data_t *); 366 367 368 static int usb_guid_cmp(const usb_guid_t *, const guid_t *); 369 370 371 CFATTACH_DECL2_NEW(uvideo, sizeof(struct uvideo_softc), 372 uvideo_match, uvideo_attach, uvideo_detach, uvideo_activate, NULL, 373 uvideo_childdet); 374 375 376 377 378 static const struct video_hw_if uvideo_hw_if = { 379 .open = uvideo_open, 380 .close = uvideo_close, 381 .get_devname = uvideo_get_devname, 382 .get_businfo = uvideo_get_businfo, 383 .enum_format = uvideo_enum_format, 384 .get_format = uvideo_get_format, 385 .set_format = uvideo_set_format, 386 .try_format = uvideo_try_format, 387 .get_framerate = uvideo_get_framerate, 388 .set_framerate = uvideo_set_framerate, 389 .start_transfer = uvideo_start_transfer, 390 .stop_transfer = uvideo_stop_transfer, 391 .control_iter_init = NULL, 392 .control_iter_next = NULL, 393 .get_control_desc_group = NULL, 394 .get_control_group = uvideo_get_control_group, 395 .set_control_group = uvideo_set_control_group, 396 }; 397 398 #ifdef UVIDEO_DEBUG 399 /* 400 * Some functions to print out descriptors. Mostly useless other than 401 * debugging/exploration purposes. 402 */ 403 static void usb_guid_print(const usb_guid_t *); 404 static void print_descriptor(const usb_descriptor_t *); 405 static void print_interface_descriptor(const usb_interface_descriptor_t *); 406 static void print_endpoint_descriptor(const usb_endpoint_descriptor_t *); 407 408 static void print_vc_descriptor(const usb_descriptor_t *); 409 static void print_vs_descriptor(const usb_descriptor_t *); 410 411 static void print_vc_header_descriptor( 412 const uvideo_vc_header_descriptor_t *); 413 static void print_input_terminal_descriptor( 414 const uvideo_input_terminal_descriptor_t *); 415 static void print_output_terminal_descriptor( 416 const uvideo_output_terminal_descriptor_t *); 417 static void print_camera_terminal_descriptor( 418 const uvideo_camera_terminal_descriptor_t *); 419 static void print_selector_unit_descriptor( 420 const uvideo_selector_unit_descriptor_t *); 421 static void print_processing_unit_descriptor( 422 const uvideo_processing_unit_descriptor_t *); 423 static void print_extension_unit_descriptor( 424 const uvideo_extension_unit_descriptor_t *); 425 static void print_interrupt_endpoint_descriptor( 426 const uvideo_vc_interrupt_endpoint_descriptor_t *); 427 428 static void print_vs_input_header_descriptor( 429 const uvideo_vs_input_header_descriptor_t *); 430 static void print_vs_output_header_descriptor( 431 const uvideo_vs_output_header_descriptor_t *); 432 433 static void print_vs_format_uncompressed_descriptor( 434 const uvideo_vs_format_uncompressed_descriptor_t *); 435 static void print_vs_frame_uncompressed_descriptor( 436 const uvideo_vs_frame_uncompressed_descriptor_t *); 437 static void print_vs_format_mjpeg_descriptor( 438 const uvideo_vs_format_mjpeg_descriptor_t *); 439 static void print_vs_frame_mjpeg_descriptor( 440 const uvideo_vs_frame_mjpeg_descriptor_t *); 441 static void print_vs_format_dv_descriptor( 442 const uvideo_vs_format_dv_descriptor_t *); 443 #endif /* !UVIDEO_DEBUG */ 444 445 #define GET(type, descp, field) \ 446 (KASSERT((descp)->bLength >= sizeof(type)), \ 447 ((const type *)(descp))->field) 448 #define GETP(type, descp, field) \ 449 (KASSERT((descp)->bLength >= sizeof(type)), \ 450 &(((const type *)(descp))->field)) 451 452 /* 453 * Given a format descriptor and frame descriptor, copy values common 454 * to all formats into a struct uvideo_format. 455 */ 456 #define UVIDEO_FORMAT_INIT_FRAME_BASED(format_type, format_desc, \ 457 frame_type, frame_desc, \ 458 format) \ 459 do { \ 460 UVIDEO_FORMAT_SET_FORMAT_INDEX( \ 461 format, \ 462 GET(format_type, format_desc, bFormatIndex)); \ 463 UVIDEO_FORMAT_SET_FRAME_INDEX( \ 464 format, \ 465 GET(frame_type, frame_desc, bFrameIndex)); \ 466 format->format.width = \ 467 UGETW(GET(frame_type, frame_desc, wWidth)); \ 468 format->format.height = \ 469 UGETW(GET(frame_type, frame_desc, wHeight)); \ 470 format->format.aspect_x = \ 471 GET(format_type, format_desc, bAspectRatioX); \ 472 format->format.aspect_y = \ 473 GET(format_type, format_desc, bAspectRatioY); \ 474 } while (0) 475 476 477 static int 478 uvideo_match(device_t parent, cfdata_t match, void *aux) 479 { 480 struct usbif_attach_arg *uiaa = aux; 481 482 /* 483 * TODO: May need to change in the future to work with 484 * Interface Association Descriptor. 485 */ 486 487 /* Trigger on the Video Control Interface which must be present */ 488 if (uiaa->uiaa_class == UICLASS_VIDEO && 489 uiaa->uiaa_subclass == UISUBCLASS_VIDEOCONTROL) 490 return UMATCH_IFACECLASS_IFACESUBCLASS; 491 492 return UMATCH_NONE; 493 } 494 495 static void 496 uvideo_attach(device_t parent, device_t self, void *aux) 497 { 498 struct uvideo_softc *sc = device_private(self); 499 struct usbif_attach_arg *uiaa = aux; 500 usbd_desc_iter_t iter; 501 const usb_interface_descriptor_t *ifdesc; 502 struct uvideo_stream *vs; 503 usbd_status err; 504 505 sc->sc_dev = self; 506 507 sc->sc_devname = usbd_devinfo_alloc(uiaa->uiaa_device, 0); 508 509 aprint_naive("\n"); 510 aprint_normal(": %s\n", sc->sc_devname); 511 512 sc->sc_udev = uiaa->uiaa_device; 513 sc->sc_iface = uiaa->uiaa_iface; 514 sc->sc_ifaceno = uiaa->uiaa_ifaceno; 515 sc->sc_dying = 0; 516 SLIST_INIT(&sc->sc_stream_list); 517 snprintf(sc->sc_businfo, sizeof(sc->sc_businfo), "usb:%08x", 518 sc->sc_udev->ud_cookie.cookie); 519 520 #ifdef UVIDEO_DEBUG 521 /* 522 * Debugging dump of descriptors. TODO: move this to userspace 523 * via a custom IOCTL or something. 524 */ 525 const usb_descriptor_t *desc; 526 usb_desc_iter_init(sc->sc_udev, &iter); 527 while ((desc = usb_desc_iter_next(&iter)) != NULL) { 528 /* print out all descriptors */ 529 printf("uvideo_attach: "); 530 print_descriptor(desc); 531 } 532 #endif /* !UVIDEO_DEBUG */ 533 534 /* iterate through interface descriptors and initialize softc */ 535 usb_desc_iter_init(sc->sc_udev, &iter); 536 while ((ifdesc = usb_desc_iter_next_interface(&iter)) != NULL) { 537 KASSERT(ifdesc->bLength >= USB_INTERFACE_DESCRIPTOR_SIZE); 538 if (ifdesc->bInterfaceClass != UICLASS_VIDEO) { 539 DPRINTFN(50, ("uvideo_attach: " 540 "ignoring non-uvc interface: " 541 "len=%d type=0x%02x " 542 "class=0x%02x subclass=0x%02x\n", 543 ifdesc->bLength, 544 ifdesc->bDescriptorType, 545 ifdesc->bInterfaceClass, 546 ifdesc->bInterfaceSubClass)); 547 continue; 548 } 549 550 switch (ifdesc->bInterfaceSubClass) { 551 case UISUBCLASS_VIDEOCONTROL: 552 err = uvideo_init_control(sc, ifdesc, &iter); 553 if (err != USBD_NORMAL_COMPLETION) { 554 DPRINTF(("uvideo_attach: error with interface " 555 "%d, VideoControl, " 556 "descriptor len=%d type=0x%02x: " 557 "%s (%d)\n", 558 ifdesc->bInterfaceNumber, 559 ifdesc->bLength, 560 ifdesc->bDescriptorType, 561 usbd_errstr(err), err)); 562 } 563 break; 564 case UISUBCLASS_VIDEOSTREAMING: 565 vs = uvideo_find_stream(sc, ifdesc->bInterfaceNumber); 566 if (vs == NULL) { 567 vs = uvideo_stream_alloc(); 568 err = uvideo_stream_init(vs, sc, ifdesc); 569 if (err != USBD_NORMAL_COMPLETION) { 570 DPRINTF(("uvideo_attach: " 571 "error initializing stream: " 572 "%s (%d)\n", 573 usbd_errstr(err), err)); 574 goto bad; 575 } 576 } 577 err = uvideo_stream_init_desc(vs, ifdesc, &iter); 578 if (err != USBD_NORMAL_COMPLETION) { 579 DPRINTF(("uvideo_attach: " 580 "error initializing stream descriptor: " 581 "%s (%d)\n", 582 usbd_errstr(err), err)); 583 goto bad; 584 } 585 break; 586 case UISUBCLASS_VIDEOCOLLECTION: 587 err = uvideo_init_collection(sc, ifdesc, &iter); 588 if (err != USBD_NORMAL_COMPLETION) { 589 DPRINTF(("uvideo_attach: error with interface " 590 "%d, VideoCollection, " 591 "descriptor len=%d type=0x%02x: " 592 "%s (%d)\n", 593 ifdesc->bInterfaceNumber, 594 ifdesc->bLength, 595 ifdesc->bDescriptorType, 596 usbd_errstr(err), err)); 597 goto bad; 598 } 599 break; 600 default: 601 DPRINTF(("uvideo_attach: unknown UICLASS_VIDEO " 602 "subclass=0x%02x\n", 603 ifdesc->bInterfaceSubClass)); 604 break; 605 } 606 607 } 608 609 610 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); 611 612 if (!pmf_device_register(self, NULL, NULL)) 613 aprint_error_dev(self, "couldn't establish power handler\n"); 614 615 SLIST_FOREACH(vs, &sc->sc_stream_list, entries) { 616 /* 617 * If the descriptor is invalid, there may be no 618 * default format. 619 * 620 * XXX Maybe this should just be removed from the list 621 * at some other point, but finding the right other 622 * point is not trivial. 623 */ 624 if (vs->vs_default_format == NULL) 625 continue; 626 /* XXX initialization of vs_videodev is racy */ 627 vs->vs_videodev = video_attach_mi(&uvideo_hw_if, sc->sc_dev, 628 vs); 629 } 630 631 return; 632 633 bad: 634 if (err != USBD_NORMAL_COMPLETION) { 635 DPRINTF(("uvideo_attach: error: %s (%d)\n", 636 usbd_errstr(err), err)); 637 } 638 return; 639 } 640 641 642 static int 643 uvideo_activate(device_t self, enum devact act) 644 { 645 struct uvideo_softc *sc = device_private(self); 646 647 switch (act) { 648 case DVACT_DEACTIVATE: 649 DPRINTF(("uvideo_activate: deactivating\n")); 650 sc->sc_dying = 1; 651 return 0; 652 default: 653 return EOPNOTSUPP; 654 } 655 } 656 657 658 /* Detach child (video interface) */ 659 static void 660 uvideo_childdet(device_t self, device_t child) 661 { 662 struct uvideo_softc *sc = device_private(self); 663 struct uvideo_stream *vs; 664 665 SLIST_FOREACH(vs, &sc->sc_stream_list, entries) { 666 if (child == vs->vs_videodev) { 667 vs->vs_videodev = NULL; 668 break; 669 } 670 } 671 KASSERTMSG(vs != NULL, "unknown child of %s detached: %s @ %p", 672 device_xname(self), device_xname(child), child); 673 } 674 675 676 static int 677 uvideo_detach(device_t self, int flags) 678 { 679 struct uvideo_softc *sc = device_private(self); 680 struct uvideo_stream *vs; 681 int error; 682 683 error = config_detach_children(self, flags); 684 if (error) 685 return error; 686 687 sc->sc_dying = 1; 688 689 pmf_device_deregister(self); 690 691 /* 692 * TODO: close the device if it is currently opened? Or will 693 * close be called automatically? 694 */ 695 696 while (!SLIST_EMPTY(&sc->sc_stream_list)) { 697 vs = SLIST_FIRST(&sc->sc_stream_list); 698 SLIST_REMOVE_HEAD(&sc->sc_stream_list, entries); 699 uvideo_stream_stop_xfer(vs); 700 uvideo_stream_free(vs); 701 } 702 703 #if 0 704 /* 705 * Wait for outstanding request to complete. TODO: what is 706 * appropriate here? 707 */ 708 usbd_delay_ms(sc->sc_udev, 1000); 709 #endif 710 711 DPRINTFN(15, ("uvideo: detaching from %s\n", 712 device_xname(sc->sc_dev))); 713 714 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); 715 716 usbd_devinfo_free(sc->sc_devname); 717 718 return 0; 719 } 720 721 /* 722 * Search the stream list for a stream matching the interface number. 723 * This is an O(n) search, but most devices should have only one or at 724 * most two streams. 725 */ 726 static struct uvideo_stream * 727 uvideo_find_stream(struct uvideo_softc *sc, uint8_t ifaceno) 728 { 729 struct uvideo_stream *vs; 730 731 SLIST_FOREACH(vs, &sc->sc_stream_list, entries) { 732 if (vs->vs_ifaceno == ifaceno) 733 return vs; 734 } 735 736 return NULL; 737 } 738 739 /* 740 * Search the format list for the given format and frame index. This 741 * might be improved through indexing, but the format and frame count 742 * is unknown ahead of time (only after iterating through the 743 * usb device descriptors). 744 */ 745 #if 0 746 static struct uvideo_format * 747 uvideo_stream_find_format(struct uvideo_stream *vs, 748 uint8_t format_index, uint8_t frame_index) 749 { 750 struct uvideo_format *format; 751 752 SIMPLEQ_FOREACH(format, &vs->vs_formats, entries) { 753 if (UVIDEO_FORMAT_GET_FORMAT_INDEX(format) == format_index && 754 UVIDEO_FORMAT_GET_FRAME_INDEX(format) == frame_index) 755 return format; 756 } 757 return NULL; 758 } 759 #endif 760 761 static struct uvideo_format * 762 uvideo_stream_guess_format(struct uvideo_stream *vs, 763 enum video_pixel_format pixel_format, 764 uint32_t width, uint32_t height) 765 { 766 struct uvideo_format *format, *gformat = NULL; 767 768 SIMPLEQ_FOREACH(format, &vs->vs_formats, entries) { 769 if (format->format.pixel_format != pixel_format) 770 continue; 771 if (format->format.width <= width && 772 format->format.height <= height) { 773 if (gformat == NULL || 774 (gformat->format.width < format->format.width && 775 gformat->format.height < format->format.height)) 776 gformat = format; 777 } 778 } 779 780 return gformat; 781 } 782 783 static struct uvideo_stream * 784 uvideo_stream_alloc(void) 785 { 786 return kmem_zalloc(sizeof(*uvideo_stream_alloc()), KM_SLEEP); 787 } 788 789 790 static usbd_status 791 uvideo_init_control(struct uvideo_softc *sc, 792 const usb_interface_descriptor_t *ifdesc, 793 usbd_desc_iter_t *iter) 794 { 795 const usb_descriptor_t *desc; 796 const uvideo_descriptor_t *uvdesc; 797 usbd_desc_iter_t orig; 798 uint8_t i, j, nunits; 799 800 /* save original iterator state */ 801 memcpy(&orig, iter, sizeof(orig)); 802 803 /* count number of units and terminals */ 804 nunits = 0; 805 while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) { 806 if (desc->bDescriptorType != UDESC_CS_INTERFACE || 807 desc->bLength < sizeof(*uvdesc)) 808 continue; 809 uvdesc = (const uvideo_descriptor_t *)desc; 810 811 if (uvdesc->bDescriptorSubtype < UDESC_INPUT_TERMINAL || 812 uvdesc->bDescriptorSubtype > UDESC_EXTENSION_UNIT) 813 continue; 814 KASSERT(nunits < 255); 815 ++nunits; 816 } 817 818 if (nunits == 0) { 819 DPRINTF(("uvideo_init_control: no units\n")); 820 return USBD_NORMAL_COMPLETION; 821 } 822 823 i = 0; 824 825 /* allocate space for units */ 826 sc->sc_nunits = nunits; 827 sc->sc_unit = kmem_alloc(sizeof(*sc->sc_unit) * nunits, KM_SLEEP); 828 829 /* restore original iterator state */ 830 memcpy(iter, &orig, sizeof(orig)); 831 832 /* iterate again, initializing the units */ 833 while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) { 834 if (desc->bDescriptorType != UDESC_CS_INTERFACE || 835 desc->bLength < sizeof(*uvdesc)) 836 continue; 837 uvdesc = (const uvideo_descriptor_t *)desc; 838 839 if (uvdesc->bDescriptorSubtype < UDESC_INPUT_TERMINAL || 840 uvdesc->bDescriptorSubtype > UDESC_EXTENSION_UNIT) 841 continue; 842 843 sc->sc_unit[i] = uvideo_unit_alloc(uvdesc); 844 /* TODO: free other units before returning? */ 845 if (sc->sc_unit[i] == NULL) 846 goto enomem; 847 KASSERT(i < 255); 848 ++i; 849 } 850 851 return USBD_NORMAL_COMPLETION; 852 853 enomem: 854 if (sc->sc_unit != NULL) { 855 for (j = 0; j < i; ++j) { 856 uvideo_unit_free(sc->sc_unit[j]); 857 sc->sc_unit[j] = NULL; 858 } 859 kmem_free(sc->sc_unit, sizeof(*sc->sc_unit) * nunits); 860 sc->sc_unit = NULL; 861 } 862 sc->sc_nunits = 0; 863 864 return USBD_NOMEM; 865 } 866 867 static usbd_status 868 uvideo_init_collection(struct uvideo_softc *sc, 869 const usb_interface_descriptor_t *ifdesc, 870 usbd_desc_iter_t *iter) 871 { 872 DPRINTF(("uvideo: ignoring Video Collection\n")); 873 return USBD_NORMAL_COMPLETION; 874 } 875 876 /* 877 * Allocates space for and initializes a uvideo unit based on the 878 * given descriptor. Returns NULL with bad descriptor or ENOMEM. 879 */ 880 static struct uvideo_unit * 881 uvideo_unit_alloc(const uvideo_descriptor_t *desc) 882 { 883 struct uvideo_unit *vu; 884 usbd_status err; 885 886 KASSERT(desc->bDescriptorType == UDESC_CS_INTERFACE); 887 888 vu = kmem_zalloc(sizeof(*vu), KM_SLEEP); 889 err = uvideo_unit_init(vu, desc); 890 if (err != USBD_NORMAL_COMPLETION) { 891 DPRINTF(("uvideo_unit_alloc: error initializing unit: " 892 "%s (%d)\n", usbd_errstr(err), err)); 893 kmem_free(vu, sizeof(*vu)); 894 return NULL; 895 } 896 897 return vu; 898 } 899 900 static usbd_status 901 uvideo_unit_init(struct uvideo_unit *vu, const uvideo_descriptor_t *desc) 902 { 903 struct uvideo_camera_terminal *ct; 904 struct uvideo_processing_unit *pu; 905 906 const uvideo_input_terminal_descriptor_t *input; 907 const uvideo_camera_terminal_descriptor_t *camera; 908 const uvideo_selector_unit_descriptor_t *selector; 909 const uvideo_processing_unit_descriptor_t *processing; 910 const uvideo_extension_unit_descriptor_t *extension; 911 912 switch (desc->bDescriptorSubtype) { 913 case UDESC_INPUT_TERMINAL: 914 if (desc->bLength < sizeof(*input)) 915 return USBD_INVAL; 916 input = (const uvideo_input_terminal_descriptor_t *)desc; 917 switch (UGETW(input->wTerminalType)) { 918 case UVIDEO_ITT_CAMERA: 919 if (desc->bLength < sizeof(*camera)) 920 return USBD_INVAL; 921 camera = 922 (const uvideo_camera_terminal_descriptor_t *)desc; 923 924 ct = &vu->u.vu_camera; 925 ct->ct_objective_focal_min = 926 UGETW(camera->wObjectiveFocalLengthMin); 927 ct->ct_objective_focal_max = 928 UGETW(camera->wObjectiveFocalLengthMax); 929 ct->ct_ocular_focal_length = 930 UGETW(camera->wOcularFocalLength); 931 932 uvideo_unit_alloc_controls(vu, camera->bControlSize, 933 camera->bmControls); 934 break; 935 default: 936 DPRINTF(("uvideo_unit_init: " 937 "unknown input terminal type 0x%04x\n", 938 UGETW(input->wTerminalType))); 939 return USBD_INVAL; 940 } 941 break; 942 case UDESC_OUTPUT_TERMINAL: 943 break; 944 case UDESC_SELECTOR_UNIT: 945 if (desc->bLength < sizeof(*selector)) 946 return USBD_INVAL; 947 selector = (const uvideo_selector_unit_descriptor_t *)desc; 948 949 uvideo_unit_alloc_sources(vu, selector->bNrInPins, 950 selector->baSourceID); 951 break; 952 case UDESC_PROCESSING_UNIT: 953 if (desc->bLength < sizeof(*processing)) 954 return USBD_INVAL; 955 processing = (const uvideo_processing_unit_descriptor_t *)desc; 956 pu = &vu->u.vu_processing; 957 958 pu->pu_video_standards = PU_GET_VIDEO_STANDARDS(processing); 959 pu->pu_max_multiplier = UGETW(processing->wMaxMultiplier); 960 961 uvideo_unit_alloc_sources(vu, 1, &processing->bSourceID); 962 uvideo_unit_alloc_controls(vu, processing->bControlSize, 963 processing->bmControls); 964 break; 965 case UDESC_EXTENSION_UNIT: 966 if (desc->bLength < sizeof(*extension)) 967 return USBD_INVAL; 968 extension = (const uvideo_extension_unit_descriptor_t *)desc; 969 /* TODO: copy guid */ 970 971 uvideo_unit_alloc_sources(vu, extension->bNrInPins, 972 extension->baSourceID); 973 uvideo_unit_alloc_controls(vu, XU_GET_CONTROL_SIZE(extension), 974 XU_GET_CONTROLS(extension)); 975 break; 976 default: 977 DPRINTF(("uvideo_unit_alloc: unknown descriptor " 978 "type=0x%02x subtype=0x%02x\n", 979 desc->bDescriptorType, desc->bDescriptorSubtype)); 980 return USBD_INVAL; 981 } 982 983 return USBD_NORMAL_COMPLETION; 984 } 985 986 static void 987 uvideo_unit_free(struct uvideo_unit *vu) 988 { 989 uvideo_unit_free_sources(vu); 990 uvideo_unit_free_controls(vu); 991 kmem_free(vu, sizeof(*vu)); 992 } 993 994 static void 995 uvideo_unit_alloc_sources(struct uvideo_unit *vu, 996 uint8_t nsrcs, const uint8_t *src_ids) 997 { 998 999 vu->vu_nsrcs = nsrcs; 1000 if (nsrcs == 0) { 1001 /* do nothing */ 1002 } else if (nsrcs == 1) { 1003 vu->s.vu_src_id = src_ids[0]; 1004 } else { 1005 vu->s.vu_src_id_ary = 1006 kmem_alloc(sizeof(*vu->s.vu_src_id_ary) * nsrcs, KM_SLEEP); 1007 memcpy(vu->s.vu_src_id_ary, src_ids, nsrcs); 1008 } 1009 } 1010 1011 static void 1012 uvideo_unit_free_sources(struct uvideo_unit *vu) 1013 { 1014 1015 if (vu->vu_nsrcs <= 1) 1016 return; 1017 1018 kmem_free(vu->s.vu_src_id_ary, 1019 sizeof(*vu->s.vu_src_id_ary) * vu->vu_nsrcs); 1020 vu->s.vu_src_id_ary = NULL; 1021 vu->vu_nsrcs = 0; 1022 } 1023 1024 static void 1025 uvideo_unit_alloc_controls(struct uvideo_unit *vu, uint8_t size, 1026 const uint8_t *controls) 1027 { 1028 1029 vu->vu_control_size = size; 1030 if (size == 0) 1031 return; 1032 1033 vu->vu_controls = kmem_alloc(sizeof(*vu->vu_controls) * size, KM_SLEEP); 1034 memcpy(vu->vu_controls, controls, size); 1035 } 1036 1037 static void 1038 uvideo_unit_free_controls(struct uvideo_unit *vu) 1039 { 1040 1041 if (vu->vu_control_size == 0) 1042 return; 1043 1044 kmem_free(vu->vu_controls, 1045 sizeof(*vu->vu_controls) * vu->vu_control_size); 1046 vu->vu_controls = NULL; 1047 vu->vu_control_size = 0; 1048 } 1049 1050 1051 /* 1052 * Initialize a stream from a Video Streaming interface 1053 * descriptor. Adds the stream to the stream_list in uvideo_softc. 1054 * This should be called once for new streams, and 1055 * uvideo_stream_init_desc() should then be called for this and each 1056 * additional interface with the same interface number. 1057 */ 1058 static usbd_status 1059 uvideo_stream_init(struct uvideo_stream *vs, 1060 struct uvideo_softc *sc, 1061 const usb_interface_descriptor_t *ifdesc) 1062 { 1063 uWord len; 1064 usbd_status err; 1065 1066 DPRINTF(("%s: %s ifaceno=%d vs=%p\n", __func__, 1067 device_xname(sc->sc_dev), 1068 ifdesc->bInterfaceNumber, 1069 vs)); 1070 1071 SLIST_INSERT_HEAD(&sc->sc_stream_list, vs, entries); 1072 vs->vs_parent = sc; 1073 vs->vs_ifaceno = ifdesc->bInterfaceNumber; 1074 vs->vs_subtype = 0; 1075 SIMPLEQ_INIT(&vs->vs_formats); 1076 SIMPLEQ_INIT(&vs->vs_pixel_formats); 1077 vs->vs_default_format = NULL; 1078 vs->vs_current_format.priv = -1; 1079 vs->vs_xfer_type = 0; 1080 vs->vs_state = UVIDEO_STATE_CLOSED; 1081 1082 err = usbd_device2interface_handle(sc->sc_udev, vs->vs_ifaceno, 1083 &vs->vs_iface); 1084 if (err != USBD_NORMAL_COMPLETION) { 1085 DPRINTF(("uvideo_stream_init: " 1086 "error getting vs interface: " 1087 "%s (%d)\n", 1088 usbd_errstr(err), err)); 1089 return err; 1090 } 1091 1092 /* 1093 * For Xbox Live Vision camera, linux-uvc folk say we need to 1094 * set an alternate interface and wait ~3 seconds prior to 1095 * doing the format probe/commit. We set to alternate 1096 * interface 0, which is the default, zero bandwidth 1097 * interface. This should not have adverse affects on other 1098 * cameras. Errors are ignored. 1099 */ 1100 err = usbd_set_interface(vs->vs_iface, 0); 1101 if (err != USBD_NORMAL_COMPLETION) { 1102 DPRINTF(("uvideo_stream_init: error setting alt interface: " 1103 "%s (%d)\n", 1104 usbd_errstr(err), err)); 1105 } 1106 1107 /* 1108 * Initialize probe and commit data size. This value is 1109 * dependent on the version of the spec the hardware 1110 * implements. 1111 */ 1112 err = uvideo_stream_probe(vs, UR_GET_LEN, &len); 1113 if (err != USBD_NORMAL_COMPLETION) { 1114 DPRINTF(("uvideo_stream_init: " 1115 "error getting probe data len: " 1116 "%s (%d)\n", 1117 usbd_errstr(err), err)); 1118 vs->vs_probelen = 26; /* conservative v1.0 length */ 1119 } else if (UGETW(len) <= sizeof(uvideo_probe_and_commit_data_t)) { 1120 DPRINTFN(15,("uvideo_stream_init: probelen=%d\n", UGETW(len))); 1121 vs->vs_probelen = UGETW(len); 1122 } else { 1123 DPRINTFN(15,("uvideo_stream_init: device returned invalid probe" 1124 " len %d, using default\n", UGETW(len))); 1125 vs->vs_probelen = 26; 1126 } 1127 1128 return USBD_NORMAL_COMPLETION; 1129 } 1130 1131 /* 1132 * Further stream initialization based on a Video Streaming interface 1133 * descriptor and following descriptors belonging to that interface. 1134 * Iterates through all descriptors belonging to this particular 1135 * interface descriptor, modifying the iterator. This may be called 1136 * multiple times because there may be several alternate interfaces 1137 * associated with the same interface number. 1138 */ 1139 static usbd_status 1140 uvideo_stream_init_desc(struct uvideo_stream *vs, 1141 const usb_interface_descriptor_t *ifdesc, 1142 usbd_desc_iter_t *iter) 1143 { 1144 const usb_descriptor_t *desc; 1145 const uvideo_descriptor_t *uvdesc; 1146 struct uvideo_bulk_xfer *bx; 1147 struct uvideo_isoc_xfer *ix; 1148 struct uvideo_alternate *alt; 1149 uint8_t xfer_type, xfer_dir; 1150 uint8_t bmAttributes, bEndpointAddress; 1151 int i; 1152 1153 DPRINTF(("%s: bInterfaceNumber=%d bAlternateSetting=%d\n", __func__, 1154 ifdesc->bInterfaceNumber, ifdesc->bAlternateSetting)); 1155 1156 /* 1157 * Iterate until the next interface descriptor. All 1158 * descriptors until then belong to this streaming 1159 * interface. 1160 */ 1161 while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) { 1162 switch (desc->bDescriptorType) { 1163 case UDESC_ENDPOINT: 1164 if (desc->bLength < sizeof(usb_endpoint_descriptor_t)) 1165 goto baddesc; 1166 bmAttributes = GET(usb_endpoint_descriptor_t, 1167 desc, bmAttributes); 1168 bEndpointAddress = GET(usb_endpoint_descriptor_t, 1169 desc, bEndpointAddress); 1170 xfer_type = UE_GET_XFERTYPE(bmAttributes); 1171 xfer_dir = UE_GET_DIR(bEndpointAddress); 1172 if (xfer_type == UE_BULK && xfer_dir == UE_DIR_IN) { 1173 bx = &vs->vs_xfer.bulk; 1174 if (vs->vs_xfer_type == 0) { 1175 DPRINTFN(15, ("uvideo_attach: " 1176 "BULK stream *\n")); 1177 vs->vs_xfer_type = UE_BULK; 1178 bx->bx_endpt = bEndpointAddress; 1179 DPRINTF(("uvideo_attach: BULK " 1180 "endpoint %x\n", 1181 bx->bx_endpt)); 1182 bx->bx_running = false; 1183 cv_init(&bx->bx_cv, 1184 device_xname(vs->vs_parent->sc_dev) 1185 ); 1186 mutex_init(&bx->bx_lock, 1187 MUTEX_DEFAULT, IPL_NONE); 1188 } 1189 } else if (xfer_type == UE_ISOCHRONOUS) { 1190 ix = &vs->vs_xfer.isoc; 1191 for (i = 0; i < UVIDEO_NXFERS; i++) { 1192 ix->ix_i[i].i_ix = ix; 1193 ix->ix_i[i].i_vs = vs; 1194 } 1195 if (vs->vs_xfer_type == 0) { 1196 DPRINTFN(15, ("uvideo_attach: " 1197 "ISOC stream *\n")); 1198 SLIST_INIT(&ix->ix_altlist); 1199 vs->vs_xfer_type = UE_ISOCHRONOUS; 1200 ix->ix_endpt = 1201 GET(usb_endpoint_descriptor_t, 1202 desc, bEndpointAddress); 1203 } 1204 1205 alt = kmem_alloc(sizeof(*alt), KM_SLEEP); 1206 alt->altno = ifdesc->bAlternateSetting; 1207 alt->interval = 1208 GET(usb_endpoint_descriptor_t, 1209 desc, bInterval); 1210 1211 alt->max_packet_size = 1212 UE_GET_SIZE(UGETW(GET(usb_endpoint_descriptor_t, 1213 desc, wMaxPacketSize))); 1214 alt->max_packet_size *= 1215 (UE_GET_TRANS(UGETW(GET( 1216 usb_endpoint_descriptor_t, desc, 1217 wMaxPacketSize)))) + 1; 1218 1219 SLIST_INSERT_HEAD(&ix->ix_altlist, 1220 alt, entries); 1221 } 1222 break; 1223 case UDESC_CS_INTERFACE: 1224 if (desc->bLength < sizeof(*uvdesc)) 1225 goto baddesc; 1226 uvdesc = (const uvideo_descriptor_t *)desc; 1227 if (ifdesc->bAlternateSetting != 0) { 1228 DPRINTF(("uvideo_stream_init_alternate: " 1229 "unexpected class-specific descriptor " 1230 "len=%d type=0x%02x subtype=0x%02x\n", 1231 uvdesc->bLength, 1232 uvdesc->bDescriptorType, 1233 uvdesc->bDescriptorSubtype)); 1234 break; 1235 } 1236 1237 switch (uvdesc->bDescriptorSubtype) { 1238 case UDESC_VS_INPUT_HEADER: 1239 vs->vs_subtype = UDESC_VS_INPUT_HEADER; 1240 break; 1241 case UDESC_VS_OUTPUT_HEADER: 1242 /* TODO: handle output stream */ 1243 DPRINTF(("uvideo: VS output not implemented\n")); 1244 vs->vs_subtype = UDESC_VS_OUTPUT_HEADER; 1245 return USBD_INVAL; 1246 case UDESC_VS_FORMAT_UNCOMPRESSED: 1247 case UDESC_VS_FORMAT_FRAME_BASED: 1248 case UDESC_VS_FORMAT_MJPEG: 1249 uvideo_stream_init_frame_based_format(vs, 1250 uvdesc, 1251 iter); 1252 break; 1253 case UDESC_VS_FORMAT_MPEG2TS: 1254 case UDESC_VS_FORMAT_DV: 1255 case UDESC_VS_FORMAT_STREAM_BASED: 1256 default: 1257 DPRINTF(("uvideo: unimplemented VS CS " 1258 "descriptor len=%d type=0x%02x " 1259 "subtype=0x%02x\n", 1260 uvdesc->bLength, 1261 uvdesc->bDescriptorType, 1262 uvdesc->bDescriptorSubtype)); 1263 break; 1264 } 1265 break; 1266 default: 1267 baddesc: 1268 DPRINTF(("uvideo_stream_init_desc: " 1269 "bad descriptor " 1270 "len=%d type=0x%02x\n", 1271 desc->bLength, 1272 desc->bDescriptorType)); 1273 break; 1274 } 1275 } 1276 1277 DPRINTF(("%s: bInterfaceNumber=%d bAlternateSetting=%d done\n", 1278 __func__, 1279 ifdesc->bInterfaceNumber, ifdesc->bAlternateSetting)); 1280 1281 return USBD_NORMAL_COMPLETION; 1282 } 1283 1284 /* Finialize and free memory associated with this stream. */ 1285 static void 1286 uvideo_stream_free(struct uvideo_stream *vs) 1287 { 1288 struct uvideo_alternate *alt; 1289 struct uvideo_pixel_format *pixel_format; 1290 struct uvideo_format *format; 1291 1292 /* free linked list of alternate interfaces */ 1293 if (vs->vs_xfer_type == UE_ISOCHRONOUS) { 1294 while (!SLIST_EMPTY(&vs->vs_xfer.isoc.ix_altlist)) { 1295 alt = SLIST_FIRST(&vs->vs_xfer.isoc.ix_altlist); 1296 SLIST_REMOVE_HEAD(&vs->vs_xfer.isoc.ix_altlist, 1297 entries); 1298 kmem_free(alt, sizeof(*alt)); 1299 } 1300 } 1301 1302 /* free linked-list of formats and pixel formats */ 1303 while ((format = SIMPLEQ_FIRST(&vs->vs_formats)) != NULL) { 1304 SIMPLEQ_REMOVE_HEAD(&vs->vs_formats, entries); 1305 kmem_free(format, sizeof(*format)); 1306 } 1307 while ((pixel_format = SIMPLEQ_FIRST(&vs->vs_pixel_formats)) != NULL) { 1308 SIMPLEQ_REMOVE_HEAD(&vs->vs_pixel_formats, entries); 1309 kmem_free(pixel_format, sizeof(*pixel_format)); 1310 } 1311 1312 kmem_free(vs, sizeof(*vs)); 1313 } 1314 1315 1316 static usbd_status 1317 uvideo_stream_init_frame_based_format(struct uvideo_stream *vs, 1318 const uvideo_descriptor_t *format_desc, 1319 usbd_desc_iter_t *iter) 1320 { 1321 struct uvideo_pixel_format *pformat, *pfiter; 1322 enum video_pixel_format pixel_format; 1323 struct uvideo_format *format; 1324 const usb_descriptor_t *desc; 1325 const uvideo_descriptor_t *uvdesc; 1326 uint8_t subtype, subtypelen, default_index, index; 1327 uint32_t frame_interval; 1328 const usb_guid_t *guid; 1329 1330 DPRINTF(("%s: ifaceno=%d subtype=%d probelen=%d\n", __func__, 1331 vs->vs_ifaceno, vs->vs_subtype, vs->vs_probelen)); 1332 1333 pixel_format = VIDEO_FORMAT_UNDEFINED; 1334 1335 switch (format_desc->bDescriptorSubtype) { 1336 case UDESC_VS_FORMAT_UNCOMPRESSED: 1337 DPRINTF(("%s: uncompressed\n", __func__)); 1338 if (format_desc->bLength < 1339 sizeof(uvideo_vs_format_uncompressed_descriptor_t)) { 1340 DPRINTF(("uvideo: truncated uncompressed format: %d\n", 1341 format_desc->bLength)); 1342 return USBD_INVAL; 1343 } 1344 subtype = UDESC_VS_FRAME_UNCOMPRESSED; 1345 subtypelen = sizeof(uvideo_vs_frame_uncompressed_descriptor_t); 1346 default_index = GET(uvideo_vs_format_uncompressed_descriptor_t, 1347 format_desc, 1348 bDefaultFrameIndex); 1349 guid = GETP(uvideo_vs_format_uncompressed_descriptor_t, 1350 format_desc, 1351 guidFormat); 1352 if (usb_guid_cmp(guid, &uvideo_guid_format_yuy2) == 0) 1353 pixel_format = VIDEO_FORMAT_YUY2; 1354 else if (usb_guid_cmp(guid, &uvideo_guid_format_nv12) == 0) 1355 pixel_format = VIDEO_FORMAT_NV12; 1356 else if (usb_guid_cmp(guid, &uvideo_guid_format_uyvy) == 0) 1357 pixel_format = VIDEO_FORMAT_UYVY; 1358 else { 1359 #ifdef UVIDEO_DEBUG 1360 DPRINTF(("%s: unknown format: ", __func__)); 1361 usb_guid_print(guid); 1362 DPRINTF(("\n")); 1363 #endif 1364 } 1365 break; 1366 case UDESC_VS_FORMAT_FRAME_BASED: 1367 DPRINTF(("%s: frame-based\n", __func__)); 1368 if (format_desc->bLength < 1369 sizeof(uvideo_format_frame_based_descriptor_t)) { 1370 DPRINTF(("uvideo: truncated frame-based format: %d\n", 1371 format_desc->bLength)); 1372 return USBD_INVAL; 1373 } 1374 subtype = UDESC_VS_FRAME_FRAME_BASED; 1375 subtypelen = sizeof(uvideo_frame_frame_based_descriptor_t); 1376 default_index = GET(uvideo_format_frame_based_descriptor_t, 1377 format_desc, 1378 bDefaultFrameIndex); 1379 break; 1380 case UDESC_VS_FORMAT_MJPEG: 1381 DPRINTF(("%s: mjpeg\n", __func__)); 1382 if (format_desc->bLength < 1383 sizeof(uvideo_vs_format_mjpeg_descriptor_t)) { 1384 DPRINTF(("uvideo: truncated mjpeg format: %d\n", 1385 format_desc->bLength)); 1386 return USBD_INVAL; 1387 } 1388 subtype = UDESC_VS_FRAME_MJPEG; 1389 subtypelen = sizeof(uvideo_vs_frame_mjpeg_descriptor_t); 1390 default_index = GET(uvideo_vs_format_mjpeg_descriptor_t, 1391 format_desc, 1392 bDefaultFrameIndex); 1393 pixel_format = VIDEO_FORMAT_MJPEG; 1394 break; 1395 default: 1396 DPRINTF(("uvideo: unknown frame based format %d\n", 1397 format_desc->bDescriptorSubtype)); 1398 return USBD_INVAL; 1399 } 1400 1401 KASSERT(subtypelen >= sizeof(*uvdesc)); 1402 1403 pformat = NULL; 1404 SIMPLEQ_FOREACH(pfiter, &vs->vs_pixel_formats, entries) { 1405 if (pfiter->pixel_format == pixel_format) { 1406 pformat = pfiter; 1407 break; 1408 } 1409 } 1410 if (pixel_format != VIDEO_FORMAT_UNDEFINED && pformat == NULL) { 1411 pformat = kmem_zalloc(sizeof(*pformat), KM_SLEEP); 1412 pformat->pixel_format = pixel_format; 1413 DPRINTF(("uvideo: Adding pixel format %d\n", 1414 pixel_format)); 1415 SIMPLEQ_INSERT_TAIL(&vs->vs_pixel_formats, 1416 pformat, entries); 1417 } 1418 1419 /* 1420 * Iterate through frame descriptors directly following the 1421 * format descriptor, and add a format to the format list for 1422 * each frame descriptor. 1423 */ 1424 while ((desc = usb_desc_iter_peek(iter)) != NULL) { 1425 if (desc->bDescriptorType != UDESC_CS_INTERFACE) 1426 break; 1427 if (desc->bLength < sizeof(*uvdesc)) { 1428 DPRINTF(("uvideo: truncated CS descriptor, length %d\n", 1429 desc->bLength)); 1430 break; 1431 } 1432 uvdesc = (const uvideo_descriptor_t *)desc; 1433 if (uvdesc->bDescriptorSubtype != subtype) 1434 break; 1435 if (uvdesc->bLength < subtypelen) { 1436 DPRINTF(("uvideo:" 1437 " truncated CS subtype-0x%x descriptor," 1438 " length %d < %d\n", 1439 uvdesc->bDescriptorSubtype, 1440 uvdesc->bLength, subtypelen)); 1441 break; 1442 } 1443 1444 /* We peeked; now consume. */ 1445 (void)usb_desc_iter_next(iter); 1446 1447 format = kmem_zalloc(sizeof(*format), KM_SLEEP); 1448 format->format.pixel_format = pixel_format; 1449 1450 switch (format_desc->bDescriptorSubtype) { 1451 case UDESC_VS_FORMAT_UNCOMPRESSED: 1452 #ifdef UVIDEO_DEBUG 1453 if (pixel_format == VIDEO_FORMAT_UNDEFINED && 1454 uvideodebug) { 1455 guid = GETP( 1456 uvideo_vs_format_uncompressed_descriptor_t, 1457 format_desc, 1458 guidFormat); 1459 1460 DPRINTF(("uvideo: format undefined ")); 1461 usb_guid_print(guid); 1462 DPRINTF(("\n")); 1463 } 1464 #endif 1465 1466 UVIDEO_FORMAT_INIT_FRAME_BASED( 1467 uvideo_vs_format_uncompressed_descriptor_t, 1468 format_desc, 1469 uvideo_vs_frame_uncompressed_descriptor_t, 1470 uvdesc, 1471 format); 1472 format->format.sample_size = 1473 UGETDW( 1474 GET(uvideo_vs_frame_uncompressed_descriptor_t, 1475 uvdesc, dwMaxVideoFrameBufferSize)); 1476 format->format.stride = 1477 format->format.sample_size / format->format.height; 1478 index = GET(uvideo_vs_frame_uncompressed_descriptor_t, 1479 uvdesc, 1480 bFrameIndex); 1481 frame_interval = 1482 UGETDW( 1483 GET(uvideo_vs_frame_uncompressed_descriptor_t, 1484 uvdesc, 1485 dwDefaultFrameInterval)); 1486 break; 1487 case UDESC_VS_FORMAT_MJPEG: 1488 UVIDEO_FORMAT_INIT_FRAME_BASED( 1489 uvideo_vs_format_mjpeg_descriptor_t, 1490 format_desc, 1491 uvideo_vs_frame_mjpeg_descriptor_t, 1492 uvdesc, 1493 format); 1494 format->format.sample_size = 1495 UGETDW( 1496 GET(uvideo_vs_frame_mjpeg_descriptor_t, 1497 uvdesc, dwMaxVideoFrameBufferSize)); 1498 format->format.stride = 1499 format->format.sample_size / format->format.height; 1500 index = GET(uvideo_vs_frame_mjpeg_descriptor_t, 1501 uvdesc, 1502 bFrameIndex); 1503 frame_interval = 1504 UGETDW( 1505 GET(uvideo_vs_frame_mjpeg_descriptor_t, 1506 uvdesc, 1507 dwDefaultFrameInterval)); 1508 break; 1509 case UDESC_VS_FORMAT_FRAME_BASED: 1510 format->format.pixel_format = VIDEO_FORMAT_UNDEFINED; 1511 UVIDEO_FORMAT_INIT_FRAME_BASED( 1512 uvideo_format_frame_based_descriptor_t, 1513 format_desc, 1514 uvideo_frame_frame_based_descriptor_t, 1515 uvdesc, 1516 format); 1517 index = GET(uvideo_frame_frame_based_descriptor_t, 1518 uvdesc, 1519 bFrameIndex); 1520 format->format.stride = 1521 UGETDW( 1522 GET(uvideo_frame_frame_based_descriptor_t, 1523 uvdesc, dwBytesPerLine)); 1524 format->format.sample_size = 1525 format->format.stride * format->format.height; 1526 frame_interval = 1527 UGETDW( 1528 GET(uvideo_frame_frame_based_descriptor_t, 1529 uvdesc, dwDefaultFrameInterval)); 1530 break; 1531 default: 1532 /* shouldn't ever get here */ 1533 DPRINTF(("uvideo: unknown frame based format %d\n", 1534 format_desc->bDescriptorSubtype)); 1535 kmem_free(format, sizeof(*format)); 1536 return USBD_INVAL; 1537 } 1538 1539 DPRINTF(("uvideo: found format (index %d) type %d " 1540 "size %ux%u size %u stride %u interval %u\n", 1541 index, format->format.pixel_format, format->format.width, 1542 format->format.height, format->format.sample_size, 1543 format->format.stride, frame_interval)); 1544 1545 SIMPLEQ_INSERT_TAIL(&vs->vs_formats, format, entries); 1546 1547 if (vs->vs_default_format == NULL && index == default_index 1548 #ifdef UVIDEO_DISABLE_MJPEG 1549 && subtype != UDESC_VS_FRAME_MJPEG 1550 #endif 1551 ) { 1552 DPRINTF((" ^ picking this one\n")); 1553 vs->vs_default_format = &format->format; 1554 vs->vs_frame_interval = frame_interval; 1555 } 1556 1557 } 1558 1559 return USBD_NORMAL_COMPLETION; 1560 } 1561 1562 static int 1563 uvideo_stream_start_xfer(struct uvideo_stream *vs) 1564 { 1565 struct uvideo_softc *sc = vs->vs_parent; 1566 struct uvideo_bulk_xfer *bx; 1567 struct uvideo_isoc_xfer *ix; 1568 uint32_t vframe_len; /* rough bytes per video frame */ 1569 uint32_t uframe_len; /* bytes per usb frame (TODO: or microframe?) */ 1570 uint32_t nframes; /* number of usb frames (TODO: or microframs?) */ 1571 int i, ret; 1572 int error; 1573 1574 struct uvideo_alternate *alt, *alt_maybe; 1575 usbd_status err; 1576 1577 switch (vs->vs_xfer_type) { 1578 case UE_BULK: 1579 ret = 0; 1580 bx = &vs->vs_xfer.bulk; 1581 1582 err = usbd_open_pipe(vs->vs_iface, bx->bx_endpt, 0, 1583 &bx->bx_pipe); 1584 if (err != USBD_NORMAL_COMPLETION) { 1585 DPRINTF(("uvideo: error opening pipe: %s (%d)\n", 1586 usbd_errstr(err), err)); 1587 return EIO; 1588 } 1589 DPRINTF(("uvideo: pipe %p\n", bx->bx_pipe)); 1590 1591 error = usbd_create_xfer(bx->bx_pipe, vs->vs_max_payload_size, 1592 0, 0, &bx->bx_xfer); 1593 if (error) { 1594 DPRINTF(("uvideo: couldn't allocate xfer\n")); 1595 return error; 1596 } 1597 DPRINTF(("uvideo: xfer %p\n", bx->bx_xfer)); 1598 1599 bx->bx_buflen = vs->vs_max_payload_size; 1600 bx->bx_buffer = usbd_get_buffer(bx->bx_xfer); 1601 1602 mutex_enter(&bx->bx_lock); 1603 if (bx->bx_running == false) { 1604 bx->bx_running = true; 1605 ret = kthread_create(PRI_UVIDEO, 0, NULL, 1606 uvideo_stream_recv_bulk_transfer, vs, 1607 NULL, "%s", device_xname(sc->sc_dev)); 1608 if (ret) { 1609 DPRINTF(("uvideo: couldn't create kthread:" 1610 " %d\n", err)); 1611 bx->bx_running = false; 1612 mutex_exit(&bx->bx_lock); 1613 return err; 1614 } 1615 } else 1616 aprint_error_dev(sc->sc_dev, 1617 "transfer already in progress\n"); 1618 mutex_exit(&bx->bx_lock); 1619 1620 DPRINTF(("uvideo: thread created\n")); 1621 1622 return 0; 1623 case UE_ISOCHRONOUS: 1624 ix = &vs->vs_xfer.isoc; 1625 1626 /* 1627 * Choose an alternate interface most suitable for 1628 * this format. Choose the smallest size that can 1629 * contain max_payload_size. 1630 * 1631 * It is assumed that the list is sorted in descending 1632 * order from largest to smallest packet size. 1633 * 1634 * TODO: what should the strategy be for choosing an 1635 * alt interface? 1636 */ 1637 alt = NULL; 1638 SLIST_FOREACH(alt_maybe, &ix->ix_altlist, entries) { 1639 /* 1640 * TODO: define "packet" and "payload". I think 1641 * several packets can make up one payload which would 1642 * call into question this method of selecting an 1643 * alternate interface... 1644 */ 1645 1646 if (alt_maybe->max_packet_size > vs->vs_max_payload_size) 1647 continue; 1648 1649 if (alt == NULL || 1650 alt_maybe->max_packet_size >= alt->max_packet_size) 1651 alt = alt_maybe; 1652 } 1653 1654 if (alt == NULL) { 1655 DPRINTF(("uvideo_stream_start_xfer: " 1656 "no suitable alternate interface found\n")); 1657 return EINVAL; 1658 } 1659 1660 DPRINTFN(15,("uvideo_stream_start_xfer: " 1661 "choosing alternate interface " 1662 "%d wMaxPacketSize=%d bInterval=%d\n", 1663 alt->altno, alt->max_packet_size, alt->interval)); 1664 1665 err = usbd_set_interface(vs->vs_iface, alt->altno); 1666 if (err != USBD_NORMAL_COMPLETION) { 1667 DPRINTF(("uvideo_stream_start_xfer: " 1668 "error setting alt interface: %s (%d)\n", 1669 usbd_errstr(err), err)); 1670 return EIO; 1671 } 1672 1673 /* TODO: "packet" not same as frame */ 1674 vframe_len = vs->vs_current_format.sample_size; 1675 uframe_len = alt->max_packet_size; 1676 nframes = (vframe_len + uframe_len - 1) / uframe_len; 1677 nframes = (nframes + 7) & ~7; /*round up for ehci inefficiency*/ 1678 nframes = uimin(UVIDEO_NFRAMES_MAX, nframes); 1679 DPRINTF(("uvideo_stream_start_xfer: nframes=%d\n", nframes)); 1680 1681 ix->ix_nframes = nframes; 1682 ix->ix_uframe_len = uframe_len; 1683 for (i = 0; i < UVIDEO_NXFERS; i++) { 1684 struct uvideo_isoc *isoc = &ix->ix_i[i]; 1685 isoc->i_frlengths = 1686 kmem_alloc(sizeof(isoc->i_frlengths[0]) * nframes, 1687 KM_SLEEP); 1688 } 1689 1690 err = usbd_open_pipe(vs->vs_iface, ix->ix_endpt, 1691 USBD_EXCLUSIVE_USE, &ix->ix_pipe); 1692 if (err != USBD_NORMAL_COMPLETION) { 1693 DPRINTF(("uvideo: error opening pipe: %s (%d)\n", 1694 usbd_errstr(err), err)); 1695 return EIO; 1696 } 1697 1698 for (i = 0; i < UVIDEO_NXFERS; i++) { 1699 struct uvideo_isoc *isoc = &ix->ix_i[i]; 1700 error = usbd_create_xfer(ix->ix_pipe, 1701 nframes * uframe_len, 0, ix->ix_nframes, 1702 &isoc->i_xfer); 1703 if (error) { 1704 DPRINTF(("uvideo: " 1705 "couldn't allocate xfer (%d)\n", error)); 1706 return error; 1707 } 1708 1709 isoc->i_buf = usbd_get_buffer(isoc->i_xfer); 1710 } 1711 1712 uvideo_stream_recv_isoc_start(vs); 1713 1714 return 0; 1715 default: 1716 /* should never get here */ 1717 DPRINTF(("uvideo_stream_start_xfer: unknown xfer type %#x\n", 1718 vs->vs_xfer_type)); 1719 return EINVAL; 1720 } 1721 } 1722 1723 static int 1724 uvideo_stream_stop_xfer(struct uvideo_stream *vs) 1725 { 1726 struct uvideo_bulk_xfer *bx; 1727 struct uvideo_isoc_xfer *ix; 1728 usbd_status err; 1729 int i; 1730 1731 switch (vs->vs_xfer_type) { 1732 case UE_BULK: 1733 bx = &vs->vs_xfer.bulk; 1734 1735 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: " 1736 "waiting for thread to complete\n")); 1737 mutex_enter(&bx->bx_lock); 1738 if (bx->bx_running == true) { 1739 bx->bx_running = false; 1740 cv_wait_sig(&bx->bx_cv, &bx->bx_lock); 1741 } 1742 mutex_exit(&bx->bx_lock); 1743 1744 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: cleaning up\n")); 1745 1746 if (bx->bx_pipe) { 1747 usbd_abort_pipe(bx->bx_pipe); 1748 } 1749 1750 if (bx->bx_xfer) { 1751 usbd_destroy_xfer(bx->bx_xfer); 1752 bx->bx_xfer = NULL; 1753 } 1754 1755 if (bx->bx_pipe) { 1756 usbd_close_pipe(bx->bx_pipe); 1757 bx->bx_pipe = NULL; 1758 } 1759 1760 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: done\n")); 1761 1762 return 0; 1763 case UE_ISOCHRONOUS: 1764 ix = &vs->vs_xfer.isoc; 1765 if (ix->ix_pipe != NULL) { 1766 usbd_abort_pipe(ix->ix_pipe); 1767 } 1768 1769 for (i = 0; i < UVIDEO_NXFERS; i++) { 1770 struct uvideo_isoc *isoc = &ix->ix_i[i]; 1771 if (isoc->i_xfer != NULL) { 1772 usbd_destroy_xfer(isoc->i_xfer); 1773 isoc->i_xfer = NULL; 1774 } 1775 } 1776 1777 if (ix->ix_pipe != NULL) { 1778 usbd_close_pipe(ix->ix_pipe); 1779 ix->ix_pipe = NULL; 1780 } 1781 1782 for (i = 0; i < UVIDEO_NXFERS; i++) { 1783 struct uvideo_isoc *isoc = &ix->ix_i[i]; 1784 if (isoc->i_frlengths != NULL) { 1785 kmem_free(isoc->i_frlengths, 1786 sizeof(isoc->i_frlengths[0]) * 1787 ix->ix_nframes); 1788 isoc->i_frlengths = NULL; 1789 } 1790 } 1791 1792 /* Give it some time to settle */ 1793 usbd_delay_ms(vs->vs_parent->sc_udev, 1000); 1794 1795 /* Set to zero bandwidth alternate interface zero */ 1796 err = usbd_set_interface(vs->vs_iface, 0); 1797 if (err != USBD_NORMAL_COMPLETION) { 1798 DPRINTF(("uvideo_stream_stop_transfer: " 1799 "error setting zero bandwidth interface: " 1800 "%s (%d)\n", 1801 usbd_errstr(err), err)); 1802 return EIO; 1803 } 1804 1805 return 0; 1806 default: 1807 /* should never get here */ 1808 DPRINTF(("uvideo_stream_stop_xfer: unknown xfer type %#x\n", 1809 vs->vs_xfer_type)); 1810 return EINVAL; 1811 } 1812 } 1813 1814 static usbd_status 1815 uvideo_stream_recv_isoc_start(struct uvideo_stream *vs) 1816 { 1817 int i; 1818 1819 for (i = 0; i < UVIDEO_NXFERS; i++) 1820 uvideo_stream_recv_isoc_start1(&vs->vs_xfer.isoc.ix_i[i]); 1821 1822 return USBD_NORMAL_COMPLETION; 1823 } 1824 1825 /* Initiate a usb transfer. */ 1826 static usbd_status 1827 uvideo_stream_recv_isoc_start1(struct uvideo_isoc *isoc) 1828 { 1829 struct uvideo_isoc_xfer *ix; 1830 usbd_status err; 1831 int i; 1832 1833 ix = isoc->i_ix; 1834 1835 for (i = 0; i < ix->ix_nframes; ++i) 1836 isoc->i_frlengths[i] = ix->ix_uframe_len; 1837 1838 usbd_setup_isoc_xfer(isoc->i_xfer, 1839 isoc, 1840 isoc->i_frlengths, 1841 ix->ix_nframes, 1842 USBD_SHORT_XFER_OK, 1843 uvideo_stream_recv_isoc_complete); 1844 1845 err = usbd_transfer(isoc->i_xfer); 1846 if (err != USBD_IN_PROGRESS) { 1847 DPRINTF(("uvideo_stream_recv_start: " 1848 "usbd_transfer status=%s (%d)\n", 1849 usbd_errstr(err), err)); 1850 } 1851 return err; 1852 } 1853 1854 static usbd_status 1855 uvideo_stream_recv_process(struct uvideo_stream *vs, uint8_t *buf, uint32_t len) 1856 { 1857 uvideo_payload_header_t *hdr; 1858 struct video_payload payload; 1859 1860 if (len < sizeof(uvideo_payload_header_t)) { 1861 DPRINTF(("uvideo_stream_recv_process: len %d < payload hdr\n", 1862 len)); 1863 return USBD_SHORT_XFER; 1864 } 1865 1866 hdr = (uvideo_payload_header_t *)buf; 1867 1868 if (hdr->bHeaderLength > UVIDEO_PAYLOAD_HEADER_SIZE || 1869 hdr->bHeaderLength < sizeof(uvideo_payload_header_t)) 1870 return USBD_INVAL; 1871 if (hdr->bHeaderLength == len && !(hdr->bmHeaderInfo & UV_END_OF_FRAME)) 1872 return USBD_INVAL; 1873 if (hdr->bmHeaderInfo & UV_ERROR) 1874 return USBD_IOERROR; 1875 1876 payload.data = buf + hdr->bHeaderLength; 1877 payload.size = len - hdr->bHeaderLength; 1878 payload.frameno = hdr->bmHeaderInfo & UV_FRAME_ID; 1879 payload.end_of_frame = hdr->bmHeaderInfo & UV_END_OF_FRAME; 1880 1881 video_submit_payload(vs->vs_videodev, &payload); 1882 1883 return USBD_NORMAL_COMPLETION; 1884 } 1885 1886 /* Callback on completion of usb isoc transfer */ 1887 static void 1888 uvideo_stream_recv_isoc_complete(struct usbd_xfer *xfer, 1889 void *priv, 1890 usbd_status status) 1891 { 1892 struct uvideo_stream *vs; 1893 struct uvideo_isoc_xfer *ix; 1894 struct uvideo_isoc *isoc; 1895 int i; 1896 uint32_t count; 1897 uint8_t *buf; 1898 1899 isoc = priv; 1900 vs = isoc->i_vs; 1901 ix = isoc->i_ix; 1902 1903 if (status != USBD_NORMAL_COMPLETION) { 1904 DPRINTF(("uvideo_stream_recv_isoc_complete: status=%s (%d)\n", 1905 usbd_errstr(status), status)); 1906 1907 if (status == USBD_STALLED) 1908 usbd_clear_endpoint_stall_async(ix->ix_pipe); 1909 else 1910 return; 1911 } else { 1912 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 1913 1914 if (count == 0) { 1915 /* DPRINTF(("uvideo: zero length transfer\n")); */ 1916 goto next; 1917 } 1918 1919 1920 for (i = 0, buf = isoc->i_buf; 1921 i < ix->ix_nframes; 1922 ++i, buf += ix->ix_uframe_len) 1923 { 1924 status = uvideo_stream_recv_process(vs, buf, 1925 isoc->i_frlengths[i]); 1926 if (status == USBD_IOERROR) 1927 break; 1928 } 1929 } 1930 1931 next: 1932 uvideo_stream_recv_isoc_start1(isoc); 1933 } 1934 1935 static void 1936 uvideo_stream_recv_bulk_transfer(void *addr) 1937 { 1938 struct uvideo_stream *vs = addr; 1939 struct uvideo_bulk_xfer *bx = &vs->vs_xfer.bulk; 1940 usbd_status err; 1941 uint32_t len; 1942 1943 DPRINTF(("uvideo_stream_recv_bulk_transfer: " 1944 "vs %p sc %p bx %p buffer %p\n", vs, vs->vs_parent, bx, 1945 bx->bx_buffer)); 1946 1947 while (bx->bx_running) { 1948 len = bx->bx_buflen; 1949 err = usbd_bulk_transfer(bx->bx_xfer, bx->bx_pipe, 1950 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, 1951 bx->bx_buffer, &len); 1952 1953 if (err == USBD_NORMAL_COMPLETION) { 1954 uvideo_stream_recv_process(vs, bx->bx_buffer, len); 1955 } else { 1956 DPRINTF(("uvideo_stream_recv_bulk_transfer: %s\n", 1957 usbd_errstr(err))); 1958 } 1959 } 1960 1961 DPRINTF(("uvideo_stream_recv_bulk_transfer: notify complete\n")); 1962 1963 mutex_enter(&bx->bx_lock); 1964 cv_broadcast(&bx->bx_cv); 1965 mutex_exit(&bx->bx_lock); 1966 1967 DPRINTF(("uvideo_stream_recv_bulk_transfer: return\n")); 1968 1969 kthread_exit(0); 1970 } 1971 1972 /* 1973 * uvideo_open - probe and commit video format and start receiving 1974 * video data 1975 */ 1976 static int 1977 uvideo_open(void *addr, int flags) 1978 { 1979 struct uvideo_stream *vs = addr; 1980 struct uvideo_softc *sc = vs->vs_parent; 1981 struct video_format fmt; 1982 1983 DPRINTF(("uvideo_open: sc=%p\n", sc)); 1984 if (sc->sc_dying) 1985 return EIO; 1986 1987 /* XXX select default format */ 1988 fmt = *vs->vs_default_format; 1989 return uvideo_set_format(addr, &fmt); 1990 } 1991 1992 1993 static void 1994 uvideo_close(void *addr) 1995 { 1996 struct uvideo_stream *vs = addr; 1997 1998 uvideo_stop_transfer(addr); 1999 2000 if (vs->vs_state != UVIDEO_STATE_CLOSED) { 2001 vs->vs_state = UVIDEO_STATE_CLOSED; 2002 } 2003 } 2004 2005 static const char * 2006 uvideo_get_devname(void *addr) 2007 { 2008 struct uvideo_stream *vs = addr; 2009 2010 return vs->vs_parent->sc_devname; 2011 } 2012 2013 static const char * 2014 uvideo_get_businfo(void *addr) 2015 { 2016 struct uvideo_stream *vs = addr; 2017 2018 return vs->vs_parent->sc_businfo; 2019 } 2020 2021 static int 2022 uvideo_enum_format(void *addr, uint32_t index, struct video_format *format) 2023 { 2024 struct uvideo_stream *vs = addr; 2025 struct uvideo_softc *sc = vs->vs_parent; 2026 struct uvideo_format *video_format; 2027 int off; 2028 2029 if (sc->sc_dying) 2030 return EIO; 2031 2032 off = 0; 2033 SIMPLEQ_FOREACH(video_format, &vs->vs_formats, entries) { 2034 if (off++ != index) 2035 continue; 2036 format->pixel_format = video_format->format.pixel_format; 2037 format->width = video_format->format.width; 2038 format->height = video_format->format.height; 2039 return 0; 2040 } 2041 2042 return EINVAL; 2043 } 2044 2045 /* 2046 * uvideo_get_format 2047 */ 2048 static int 2049 uvideo_get_format(void *addr, struct video_format *format) 2050 { 2051 struct uvideo_stream *vs = addr; 2052 struct uvideo_softc *sc = vs->vs_parent; 2053 2054 if (sc->sc_dying) 2055 return EIO; 2056 2057 *format = vs->vs_current_format; 2058 2059 return 0; 2060 } 2061 2062 /* 2063 * uvideo_set_format - TODO: this is broken and does nothing 2064 */ 2065 static int 2066 uvideo_set_format(void *addr, struct video_format *format) 2067 { 2068 struct uvideo_stream *vs = addr; 2069 struct uvideo_softc *sc = vs->vs_parent; 2070 struct uvideo_format *uvfmt; 2071 uvideo_probe_and_commit_data_t probe, maxprobe; 2072 usbd_status err; 2073 2074 DPRINTF(("uvideo_set_format: sc=%p\n", sc)); 2075 if (sc->sc_dying) 2076 return EIO; 2077 2078 uvfmt = uvideo_stream_guess_format(vs, format->pixel_format, 2079 format->width, format->height); 2080 if (uvfmt == NULL) { 2081 DPRINTF(("uvideo: uvideo_stream_guess_format couldn't find " 2082 "%dx%d format %d\n", format->width, format->height, 2083 format->pixel_format)); 2084 return EINVAL; 2085 } 2086 2087 uvideo_init_probe_data(&probe); 2088 probe.bFormatIndex = UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt); 2089 probe.bFrameIndex = UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt); 2090 USETDW(probe.dwFrameInterval, vs->vs_frame_interval); /* XXX */ 2091 2092 maxprobe = probe; 2093 err = uvideo_stream_probe(vs, UR_GET_MAX, &maxprobe); 2094 if (err) { 2095 DPRINTF(("uvideo: error probe/GET_MAX: %s (%d)\n", 2096 usbd_errstr(err), err)); 2097 } else { 2098 USETW(probe.wCompQuality, UGETW(maxprobe.wCompQuality)); 2099 } 2100 2101 err = uvideo_stream_probe(vs, UR_SET_CUR, &probe); 2102 if (err) { 2103 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n", 2104 usbd_errstr(err), err)); 2105 return EIO; 2106 } 2107 2108 uvideo_init_probe_data(&probe); 2109 err = uvideo_stream_probe(vs, UR_GET_CUR, &probe); 2110 if (err) { 2111 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n", 2112 usbd_errstr(err), err)); 2113 return EIO; 2114 } 2115 2116 if (probe.bFormatIndex != UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt)) { 2117 DPRINTF(("uvideo: probe/GET_CUR returned format index %d " 2118 "(expected %d)\n", probe.bFormatIndex, 2119 UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt))); 2120 probe.bFormatIndex = UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt); 2121 } 2122 if (probe.bFrameIndex != UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt)) { 2123 DPRINTF(("uvideo: probe/GET_CUR returned frame index %d " 2124 "(expected %d)\n", probe.bFrameIndex, 2125 UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt))); 2126 probe.bFrameIndex = UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt); 2127 } 2128 USETDW(probe.dwFrameInterval, vs->vs_frame_interval); /* XXX */ 2129 2130 /* 2131 * commit/SET_CUR. Fourth step is to set the alternate 2132 * interface. Currently the fourth step is in 2133 * uvideo_start_transfer. Maybe move it here? 2134 */ 2135 err = uvideo_stream_commit(vs, UR_SET_CUR, &probe); 2136 if (err) { 2137 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n", 2138 usbd_errstr(err), err)); 2139 return EIO; 2140 } 2141 2142 DPRINTFN(15, ("uvideo_set_format: committing to format: " 2143 "bmHint=0x%04x bFormatIndex=%d bFrameIndex=%d " 2144 "dwFrameInterval=%u wKeyFrameRate=%d wPFrameRate=%d " 2145 "wCompQuality=%d wCompWindowSize=%d wDelay=%d " 2146 "dwMaxVideoFrameSize=%u dwMaxPayloadTransferSize=%u", 2147 UGETW(probe.bmHint), 2148 probe.bFormatIndex, 2149 probe.bFrameIndex, 2150 UGETDW(probe.dwFrameInterval), 2151 UGETW(probe.wKeyFrameRate), 2152 UGETW(probe.wPFrameRate), 2153 UGETW(probe.wCompQuality), 2154 UGETW(probe.wCompWindowSize), 2155 UGETW(probe.wDelay), 2156 UGETDW(probe.dwMaxVideoFrameSize), 2157 UGETDW(probe.dwMaxPayloadTransferSize))); 2158 if (vs->vs_probelen == 34) { 2159 DPRINTFN(15, (" dwClockFrequency=%u bmFramingInfo=0x%02x " 2160 "bPreferedVersion=%d bMinVersion=%d " 2161 "bMaxVersion=%d", 2162 UGETDW(probe.dwClockFrequency), 2163 probe.bmFramingInfo, 2164 probe.bPreferedVersion, 2165 probe.bMinVersion, 2166 probe.bMaxVersion)); 2167 } 2168 DPRINTFN(15, ("\n")); 2169 2170 vs->vs_frame_interval = UGETDW(probe.dwFrameInterval); 2171 vs->vs_max_payload_size = UGETDW(probe.dwMaxPayloadTransferSize); 2172 2173 *format = uvfmt->format; 2174 vs->vs_current_format = *format; 2175 DPRINTF(("uvideo_set_format: pixeltype is %d\n", format->pixel_format)); 2176 2177 return 0; 2178 } 2179 2180 static int 2181 uvideo_try_format(void *addr, struct video_format *format) 2182 { 2183 struct uvideo_stream *vs = addr; 2184 struct uvideo_format *uvfmt; 2185 2186 uvfmt = uvideo_stream_guess_format(vs, format->pixel_format, 2187 format->width, format->height); 2188 if (uvfmt == NULL) 2189 return EINVAL; 2190 2191 *format = uvfmt->format; 2192 return 0; 2193 } 2194 2195 static int 2196 uvideo_get_framerate(void *addr, struct video_fract *fract) 2197 { 2198 struct uvideo_stream *vs = addr; 2199 2200 switch (vs->vs_frame_interval) { 2201 case 41666: /* 240 */ 2202 case 83333: /* 120 */ 2203 case 166666: /* 60 */ 2204 case 200000: /* 50 */ 2205 case 333333: /* 30 */ 2206 case 400000: /* 25 */ 2207 case 500000: /* 20 */ 2208 case 666666: /* 15 */ 2209 case 1000000: /* 10 */ 2210 fract->numerator = 1; 2211 fract->denominator = 10000000 / vs->vs_frame_interval; 2212 break; 2213 case 166833: /* 59.94 */ 2214 fract->numerator = 60; 2215 fract->denominator = 1001; 2216 break; 2217 case 333667: /* 29.97 */ 2218 fract->numerator = 30; 2219 fract->denominator = 1001; 2220 break; 2221 default: 2222 fract->numerator = vs->vs_frame_interval; 2223 fract->denominator = 10000000; 2224 break; 2225 } 2226 2227 return 0; 2228 } 2229 2230 static int 2231 uvideo_set_framerate(void *addr, struct video_fract *fract) 2232 { 2233 /* XXX setting framerate is not supported yet, return actual rate */ 2234 return uvideo_get_framerate(addr, fract); 2235 } 2236 2237 static int 2238 uvideo_start_transfer(void *addr) 2239 { 2240 struct uvideo_stream *vs = addr; 2241 int s, err; 2242 2243 s = splusb(); 2244 err = uvideo_stream_start_xfer(vs); 2245 splx(s); 2246 2247 return err; 2248 } 2249 2250 static int 2251 uvideo_stop_transfer(void *addr) 2252 { 2253 struct uvideo_stream *vs = addr; 2254 int err, s; 2255 2256 s = splusb(); 2257 err = uvideo_stream_stop_xfer(vs); 2258 splx(s); 2259 2260 return err; 2261 } 2262 2263 2264 static int 2265 uvideo_get_control_group(void *addr, struct video_control_group *group) 2266 { 2267 struct uvideo_stream *vs = addr; 2268 struct uvideo_softc *sc = vs->vs_parent; 2269 usb_device_request_t req; 2270 usbd_status err; 2271 uint8_t control_id, ent_id, data[16]; 2272 uint16_t len; 2273 int s; 2274 2275 /* request setup */ 2276 switch (group->group_id) { 2277 case VIDEO_CONTROL_PANTILT_RELATIVE: 2278 if (group->length != 4) 2279 return EINVAL; 2280 2281 return EINVAL; 2282 case VIDEO_CONTROL_SHARPNESS: 2283 if (group->length != 1) 2284 return EINVAL; 2285 2286 control_id = UVIDEO_PU_SHARPNESS_CONTROL; 2287 ent_id = 2; /* TODO: hardcoded logitech processing unit */ 2288 len = 2; 2289 break; 2290 default: 2291 return EINVAL; 2292 } 2293 2294 /* do request */ 2295 req.bmRequestType = UVIDEO_REQUEST_TYPE_INTERFACE | 2296 UVIDEO_REQUEST_TYPE_CLASS_SPECIFIC | 2297 UVIDEO_REQUEST_TYPE_GET; 2298 req.bRequest = UR_GET_CUR; 2299 USETW(req.wValue, control_id << 8); 2300 USETW(req.wIndex, (ent_id << 8) | sc->sc_ifaceno); 2301 USETW(req.wLength, len); 2302 2303 s = splusb(); 2304 err = usbd_do_request(sc->sc_udev, &req, data); 2305 splx(s); 2306 if (err != USBD_NORMAL_COMPLETION) { 2307 DPRINTF(("uvideo_set_control: error %s (%d)\n", 2308 usbd_errstr(err), err)); 2309 return EIO; /* TODO: more detail here? */ 2310 } 2311 2312 /* extract request data */ 2313 switch (group->group_id) { 2314 case VIDEO_CONTROL_SHARPNESS: 2315 group->control[0].value = UGETW(data); 2316 break; 2317 default: 2318 return EINVAL; 2319 } 2320 2321 return 0; 2322 } 2323 2324 2325 static int 2326 uvideo_set_control_group(void *addr, const struct video_control_group *group) 2327 { 2328 struct uvideo_stream *vs = addr; 2329 struct uvideo_softc *sc = vs->vs_parent; 2330 usb_device_request_t req; 2331 usbd_status err; 2332 uint8_t control_id, ent_id, data[16]; /* long enough for all controls */ 2333 uint16_t len; 2334 int s; 2335 2336 switch (group->group_id) { 2337 case VIDEO_CONTROL_PANTILT_RELATIVE: 2338 if (group->length != 4) 2339 return EINVAL; 2340 2341 if (group->control[0].value != 0 || 2342 group->control[0].value != 1 || 2343 group->control[0].value != 0xff) 2344 return ERANGE; 2345 2346 if (group->control[2].value != 0 || 2347 group->control[2].value != 1 || 2348 group->control[2].value != 0xff) 2349 return ERANGE; 2350 2351 control_id = UVIDEO_CT_PANTILT_RELATIVE_CONTROL; 2352 ent_id = 1; /* TODO: hardcoded logitech camera terminal */ 2353 len = 4; 2354 data[0] = group->control[0].value; 2355 data[1] = group->control[1].value; 2356 data[2] = group->control[2].value; 2357 data[3] = group->control[3].value; 2358 break; 2359 case VIDEO_CONTROL_BRIGHTNESS: 2360 if (group->length != 1) 2361 return EINVAL; 2362 control_id = UVIDEO_PU_BRIGHTNESS_CONTROL; 2363 ent_id = 2; 2364 len = 2; 2365 USETW(data, group->control[0].value); 2366 break; 2367 case VIDEO_CONTROL_GAIN: 2368 if (group->length != 1) 2369 return EINVAL; 2370 control_id = UVIDEO_PU_GAIN_CONTROL; 2371 ent_id = 2; 2372 len = 2; 2373 USETW(data, group->control[0].value); 2374 break; 2375 case VIDEO_CONTROL_SHARPNESS: 2376 if (group->length != 1) 2377 return EINVAL; 2378 control_id = UVIDEO_PU_SHARPNESS_CONTROL; 2379 ent_id = 2; /* TODO: hardcoded logitech processing unit */ 2380 len = 2; 2381 USETW(data, group->control[0].value); 2382 break; 2383 default: 2384 return EINVAL; 2385 } 2386 2387 req.bmRequestType = UVIDEO_REQUEST_TYPE_INTERFACE | 2388 UVIDEO_REQUEST_TYPE_CLASS_SPECIFIC | 2389 UVIDEO_REQUEST_TYPE_SET; 2390 req.bRequest = UR_SET_CUR; 2391 USETW(req.wValue, control_id << 8); 2392 USETW(req.wIndex, (ent_id << 8) | sc->sc_ifaceno); 2393 USETW(req.wLength, len); 2394 2395 s = splusb(); 2396 err = usbd_do_request(sc->sc_udev, &req, data); 2397 splx(s); 2398 if (err != USBD_NORMAL_COMPLETION) { 2399 DPRINTF(("uvideo_set_control: error %s (%d)\n", 2400 usbd_errstr(err), err)); 2401 return EIO; /* TODO: more detail here? */ 2402 } 2403 2404 return 0; 2405 } 2406 2407 static usbd_status 2408 uvideo_stream_probe_and_commit(struct uvideo_stream *vs, 2409 uint8_t action, uint8_t control, 2410 void *data) 2411 { 2412 usb_device_request_t req; 2413 2414 switch (action) { 2415 case UR_SET_CUR: 2416 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 2417 USETW(req.wLength, vs->vs_probelen); 2418 break; 2419 case UR_GET_CUR: 2420 case UR_GET_MIN: 2421 case UR_GET_MAX: 2422 case UR_GET_DEF: 2423 req.bmRequestType = UT_READ_CLASS_INTERFACE; 2424 USETW(req.wLength, vs->vs_probelen); 2425 break; 2426 case UR_GET_INFO: 2427 req.bmRequestType = UT_READ_CLASS_INTERFACE; 2428 USETW(req.wLength, sizeof(uByte)); 2429 break; 2430 case UR_GET_LEN: 2431 req.bmRequestType = UT_READ_CLASS_INTERFACE; 2432 USETW(req.wLength, sizeof(uWord)); /* is this right? */ 2433 break; 2434 default: 2435 DPRINTF(("uvideo_probe_and_commit: " 2436 "unknown request action %d\n", action)); 2437 return USBD_NOT_STARTED; 2438 } 2439 2440 req.bRequest = action; 2441 USETW2(req.wValue, control, 0); 2442 USETW2(req.wIndex, 0, vs->vs_ifaceno); 2443 2444 return (usbd_do_request_flags(vs->vs_parent->sc_udev, &req, data, 2445 0, 0, 2446 USBD_DEFAULT_TIMEOUT)); 2447 } 2448 2449 static void 2450 uvideo_init_probe_data(uvideo_probe_and_commit_data_t *probe) 2451 { 2452 /* all zeroes tells camera to choose what it wants */ 2453 memset(probe, 0, sizeof(*probe)); 2454 } 2455 2456 2457 #ifdef _MODULE 2458 2459 MODULE(MODULE_CLASS_DRIVER, uvideo, NULL); 2460 static const struct cfiattrdata videobuscf_iattrdata = { 2461 "videobus", 0, { 2462 { NULL, NULL, 0 }, 2463 } 2464 }; 2465 static const struct cfiattrdata * const uvideo_attrs[] = { 2466 &videobuscf_iattrdata, NULL 2467 }; 2468 CFDRIVER_DECL(uvideo, DV_DULL, uvideo_attrs); 2469 extern struct cfattach uvideo_ca; 2470 extern struct cfattach uvideo_ca; 2471 static int uvideoloc[6] = { -1, -1, -1, -1, -1, -1 }; 2472 static struct cfparent uhubparent = { 2473 "usbifif", NULL, DVUNIT_ANY 2474 }; 2475 static struct cfdata uvideo_cfdata[] = { 2476 { 2477 .cf_name = "uvideo", 2478 .cf_atname = "uvideo", 2479 .cf_unit = 0, 2480 .cf_fstate = FSTATE_STAR, 2481 .cf_loc = uvideoloc, 2482 .cf_flags = 0, 2483 .cf_pspec = &uhubparent, 2484 }, 2485 { NULL, NULL, 0, 0, NULL, 0, NULL }, 2486 }; 2487 2488 static int 2489 uvideo_modcmd(modcmd_t cmd, void *arg) 2490 { 2491 int err; 2492 2493 2494 switch (cmd) { 2495 case MODULE_CMD_INIT: 2496 DPRINTF(("uvideo: attempting to load\n")); 2497 2498 err = config_cfdriver_attach(&uvideo_cd); 2499 if (err) 2500 return err; 2501 err = config_cfattach_attach("uvideo", &uvideo_ca); 2502 if (err) { 2503 config_cfdriver_detach(&uvideo_cd); 2504 return err; 2505 } 2506 err = config_cfdata_attach(uvideo_cfdata, 1); 2507 if (err) { 2508 config_cfattach_detach("uvideo", &uvideo_ca); 2509 config_cfdriver_detach(&uvideo_cd); 2510 return err; 2511 } 2512 DPRINTF(("uvideo: loaded module\n")); 2513 return 0; 2514 case MODULE_CMD_FINI: 2515 DPRINTF(("uvideo: attempting to unload module\n")); 2516 err = config_cfdata_detach(uvideo_cfdata); 2517 if (err) 2518 return err; 2519 config_cfattach_detach("uvideo", &uvideo_ca); 2520 config_cfdriver_detach(&uvideo_cd); 2521 DPRINTF(("uvideo: module unload\n")); 2522 return 0; 2523 default: 2524 return ENOTTY; 2525 } 2526 } 2527 2528 #endif /* _MODULE */ 2529 2530 2531 #ifdef UVIDEO_DEBUG 2532 /* 2533 * Some functions to print out descriptors. Mostly useless other than 2534 * debugging/exploration purposes. 2535 */ 2536 2537 2538 static void 2539 print_bitmap(const uByte *start, uByte nbytes) 2540 { 2541 int byte, bit; 2542 2543 /* most significant first */ 2544 for (byte = nbytes-1; byte >= 0; --byte) { 2545 if (byte < nbytes-1) printf("-"); 2546 for (bit = 7; bit >= 0; --bit) 2547 printf("%01d", (start[byte] >> bit) &1); 2548 } 2549 } 2550 2551 static void 2552 print_descriptor(const usb_descriptor_t *desc) 2553 { 2554 static int current_class = -1; 2555 static int current_subclass = -1; 2556 2557 if (desc->bDescriptorType == UDESC_INTERFACE) { 2558 const usb_interface_descriptor_t *id; 2559 2560 if (desc->bLength < sizeof(*id)) { 2561 printf("[truncated interface]\n"); 2562 return; 2563 } 2564 id = (const usb_interface_descriptor_t *)desc; 2565 current_class = id->bInterfaceClass; 2566 current_subclass = id->bInterfaceSubClass; 2567 print_interface_descriptor(id); 2568 printf("\n"); 2569 return; 2570 } 2571 2572 printf(" "); /* indent */ 2573 2574 if (current_class == UICLASS_VIDEO) { 2575 switch (current_subclass) { 2576 case UISUBCLASS_VIDEOCONTROL: 2577 print_vc_descriptor(desc); 2578 break; 2579 case UISUBCLASS_VIDEOSTREAMING: 2580 print_vs_descriptor(desc); 2581 break; 2582 case UISUBCLASS_VIDEOCOLLECTION: 2583 printf("uvc collection: len=%d type=0x%02x", 2584 desc->bLength, desc->bDescriptorType); 2585 break; 2586 } 2587 } else { 2588 printf("non uvc descriptor len=%d type=0x%02x", 2589 desc->bLength, desc->bDescriptorType); 2590 } 2591 2592 printf("\n"); 2593 } 2594 2595 static void 2596 print_vc_descriptor(const usb_descriptor_t *desc) 2597 { 2598 const uvideo_descriptor_t *vcdesc; 2599 2600 printf("VC "); 2601 2602 switch (desc->bDescriptorType) { 2603 case UDESC_ENDPOINT: 2604 if (desc->bLength < sizeof(usb_endpoint_descriptor_t)) { 2605 printf("[truncated endpoint]"); 2606 break; 2607 } 2608 print_endpoint_descriptor( 2609 (const usb_endpoint_descriptor_t *)desc); 2610 break; 2611 case UDESC_CS_INTERFACE: 2612 if (desc->bLength < sizeof(*vcdesc)) { 2613 printf("[truncated class-specific]"); 2614 break; 2615 } 2616 vcdesc = (const uvideo_descriptor_t *)desc; 2617 switch (vcdesc->bDescriptorSubtype) { 2618 case UDESC_VC_HEADER: 2619 if (desc->bLength < 2620 sizeof(uvideo_vc_header_descriptor_t)) { 2621 printf("[truncated videocontrol header]"); 2622 break; 2623 } 2624 print_vc_header_descriptor( 2625 (const uvideo_vc_header_descriptor_t *) 2626 vcdesc); 2627 break; 2628 case UDESC_INPUT_TERMINAL: 2629 if (desc->bLength < 2630 sizeof(uvideo_input_terminal_descriptor_t)) { 2631 printf("[truncated input terminal]"); 2632 break; 2633 } 2634 switch (UGETW( 2635 ((const uvideo_input_terminal_descriptor_t *) 2636 vcdesc)->wTerminalType)) { 2637 case UVIDEO_ITT_CAMERA: 2638 if (desc->bLength < 2639 sizeof(uvideo_camera_terminal_descriptor_t)) { 2640 printf("[truncated camera terminal]"); 2641 break; 2642 } 2643 print_camera_terminal_descriptor( 2644 (const uvideo_camera_terminal_descriptor_t *)vcdesc); 2645 break; 2646 default: 2647 print_input_terminal_descriptor( 2648 (const uvideo_input_terminal_descriptor_t *)vcdesc); 2649 break; 2650 } 2651 break; 2652 case UDESC_OUTPUT_TERMINAL: 2653 if (desc->bLength < 2654 sizeof(uvideo_output_terminal_descriptor_t)) { 2655 printf("[truncated output terminal]"); 2656 break; 2657 } 2658 print_output_terminal_descriptor( 2659 (const uvideo_output_terminal_descriptor_t *) 2660 vcdesc); 2661 break; 2662 case UDESC_SELECTOR_UNIT: 2663 if (desc->bLength < 2664 sizeof(uvideo_selector_unit_descriptor_t)) { 2665 printf("[truncated selector unit]"); 2666 break; 2667 } 2668 print_selector_unit_descriptor( 2669 (const uvideo_selector_unit_descriptor_t *) 2670 vcdesc); 2671 break; 2672 case UDESC_PROCESSING_UNIT: 2673 if (desc->bLength < 2674 sizeof(uvideo_processing_unit_descriptor_t)) { 2675 printf("[truncated processing unit]"); 2676 break; 2677 } 2678 print_processing_unit_descriptor( 2679 (const uvideo_processing_unit_descriptor_t *) 2680 vcdesc); 2681 break; 2682 case UDESC_EXTENSION_UNIT: 2683 if (desc->bLength < 2684 sizeof(uvideo_extension_unit_descriptor_t)) { 2685 printf("[truncated extension unit]"); 2686 break; 2687 } 2688 print_extension_unit_descriptor( 2689 (const uvideo_extension_unit_descriptor_t *) 2690 vcdesc); 2691 break; 2692 default: 2693 printf("class specific interface " 2694 "len=%d type=0x%02x subtype=0x%02x", 2695 vcdesc->bLength, 2696 vcdesc->bDescriptorType, 2697 vcdesc->bDescriptorSubtype); 2698 break; 2699 } 2700 break; 2701 case UDESC_CS_ENDPOINT: 2702 if (desc->bLength < sizeof(*vcdesc)) { 2703 printf("[truncated class-specific]"); 2704 break; 2705 } 2706 vcdesc = (const uvideo_descriptor_t *)desc; 2707 switch (vcdesc->bDescriptorSubtype) { 2708 case UDESC_VC_INTERRUPT_ENDPOINT: 2709 if (desc->bLength < 2710 sizeof(uvideo_vc_interrupt_endpoint_descriptor_t)) { 2711 printf("[truncated " 2712 "videocontrol interrupt endpoint]"); 2713 break; 2714 } 2715 print_interrupt_endpoint_descriptor( 2716 (const uvideo_vc_interrupt_endpoint_descriptor_t *) 2717 vcdesc); 2718 break; 2719 default: 2720 printf("class specific endpoint " 2721 "len=%d type=0x%02x subtype=0x%02x", 2722 vcdesc->bLength, 2723 vcdesc->bDescriptorType, 2724 vcdesc->bDescriptorSubtype); 2725 break; 2726 } 2727 break; 2728 default: 2729 printf("unknown: len=%d type=0x%02x", 2730 desc->bLength, desc->bDescriptorType); 2731 break; 2732 } 2733 } 2734 2735 static void 2736 print_vs_descriptor(const usb_descriptor_t *desc) 2737 { 2738 const uvideo_descriptor_t * vsdesc; 2739 printf("VS "); 2740 2741 switch (desc->bDescriptorType) { 2742 case UDESC_ENDPOINT: 2743 if (desc->bLength < sizeof(usb_endpoint_descriptor_t)) { 2744 printf("[truncated endpoint]"); 2745 break; 2746 } 2747 print_endpoint_descriptor( 2748 (const usb_endpoint_descriptor_t *)desc); 2749 break; 2750 case UDESC_CS_INTERFACE: 2751 if (desc->bLength < sizeof(*vsdesc)) { 2752 printf("[truncated class-specific]"); 2753 break; 2754 } 2755 vsdesc = (const uvideo_descriptor_t *)desc; 2756 switch (vsdesc->bDescriptorSubtype) { 2757 case UDESC_VS_INPUT_HEADER: 2758 if (desc->bLength < 2759 sizeof(uvideo_vs_input_header_descriptor_t)) { 2760 printf("[truncated videostream input header]"); 2761 break; 2762 } 2763 print_vs_input_header_descriptor( 2764 (const uvideo_vs_input_header_descriptor_t *) 2765 vsdesc); 2766 break; 2767 case UDESC_VS_OUTPUT_HEADER: 2768 if (desc->bLength < 2769 sizeof(uvideo_vs_output_header_descriptor_t)) { 2770 printf("[truncated " 2771 "videostream output header]"); 2772 break; 2773 } 2774 print_vs_output_header_descriptor( 2775 (const uvideo_vs_output_header_descriptor_t *) 2776 vsdesc); 2777 break; 2778 case UDESC_VS_FORMAT_UNCOMPRESSED: 2779 if (desc->bLength < 2780 sizeof(uvideo_vs_format_uncompressed_descriptor_t)) 2781 { 2782 printf("[truncated " 2783 "videostream format uncompressed]"); 2784 break; 2785 } 2786 print_vs_format_uncompressed_descriptor( 2787 (const uvideo_vs_format_uncompressed_descriptor_t *) 2788 vsdesc); 2789 break; 2790 case UDESC_VS_FRAME_UNCOMPRESSED: 2791 if (desc->bLength < 2792 sizeof(uvideo_vs_frame_uncompressed_descriptor_t)) 2793 { 2794 printf("[truncated " 2795 "videostream frame uncompressed]"); 2796 break; 2797 } 2798 print_vs_frame_uncompressed_descriptor( 2799 (const uvideo_vs_frame_uncompressed_descriptor_t *) 2800 vsdesc); 2801 break; 2802 case UDESC_VS_FORMAT_MJPEG: 2803 if (desc->bLength < 2804 sizeof(uvideo_vs_format_mjpeg_descriptor_t)) { 2805 printf("[truncated videostream format mjpeg]"); 2806 break; 2807 } 2808 print_vs_format_mjpeg_descriptor( 2809 (const uvideo_vs_format_mjpeg_descriptor_t *) 2810 vsdesc); 2811 break; 2812 case UDESC_VS_FRAME_MJPEG: 2813 if (desc->bLength < 2814 sizeof(uvideo_vs_frame_mjpeg_descriptor_t)) { 2815 printf("[truncated videostream frame mjpeg]"); 2816 break; 2817 } 2818 print_vs_frame_mjpeg_descriptor( 2819 (const uvideo_vs_frame_mjpeg_descriptor_t *) 2820 vsdesc); 2821 break; 2822 case UDESC_VS_FORMAT_DV: 2823 if (desc->bLength < 2824 sizeof(uvideo_vs_format_dv_descriptor_t)) { 2825 printf("[truncated videostream format dv]"); 2826 break; 2827 } 2828 print_vs_format_dv_descriptor( 2829 (const uvideo_vs_format_dv_descriptor_t *) 2830 vsdesc); 2831 break; 2832 default: 2833 printf("unknown cs interface: len=%d type=0x%02x " 2834 "subtype=0x%02x", 2835 vsdesc->bLength, vsdesc->bDescriptorType, 2836 vsdesc->bDescriptorSubtype); 2837 } 2838 break; 2839 default: 2840 printf("unknown: len=%d type=0x%02x", 2841 desc->bLength, desc->bDescriptorType); 2842 break; 2843 } 2844 } 2845 2846 static void 2847 print_interface_descriptor(const usb_interface_descriptor_t *id) 2848 { 2849 printf("Interface: Len=%d Type=0x%02x " 2850 "bInterfaceNumber=0x%02x " 2851 "bAlternateSetting=0x%02x bNumEndpoints=0x%02x " 2852 "bInterfaceClass=0x%02x bInterfaceSubClass=0x%02x " 2853 "bInterfaceProtocol=0x%02x iInterface=0x%02x", 2854 id->bLength, 2855 id->bDescriptorType, 2856 id->bInterfaceNumber, 2857 id->bAlternateSetting, 2858 id->bNumEndpoints, 2859 id->bInterfaceClass, 2860 id->bInterfaceSubClass, 2861 id->bInterfaceProtocol, 2862 id->iInterface); 2863 } 2864 2865 static void 2866 print_endpoint_descriptor(const usb_endpoint_descriptor_t *desc) 2867 { 2868 printf("Endpoint: Len=%d Type=0x%02x " 2869 "bEndpointAddress=0x%02x ", 2870 desc->bLength, 2871 desc->bDescriptorType, 2872 desc->bEndpointAddress); 2873 printf("bmAttributes="); 2874 print_bitmap(&desc->bmAttributes, 1); 2875 printf(" wMaxPacketSize=%d bInterval=%d", 2876 UGETW(desc->wMaxPacketSize), 2877 desc->bInterval); 2878 } 2879 2880 static void 2881 print_vc_header_descriptor( 2882 const uvideo_vc_header_descriptor_t *desc) 2883 { 2884 printf("Interface Header: " 2885 "Len=%d Type=0x%02x Subtype=0x%02x " 2886 "bcdUVC=%d wTotalLength=%d " 2887 "dwClockFrequency=%u bInCollection=%d", 2888 desc->bLength, 2889 desc->bDescriptorType, 2890 desc->bDescriptorSubtype, 2891 UGETW(desc->bcdUVC), 2892 UGETW(desc->wTotalLength), 2893 UGETDW(desc->dwClockFrequency), 2894 desc->bInCollection); 2895 } 2896 2897 static void 2898 print_input_terminal_descriptor( 2899 const uvideo_input_terminal_descriptor_t *desc) 2900 { 2901 printf("Input Terminal: " 2902 "Len=%d Type=0x%02x Subtype=0x%02x " 2903 "bTerminalID=%d wTerminalType=%x bAssocTerminal=%d " 2904 "iTerminal=%d", 2905 desc->bLength, 2906 desc->bDescriptorType, 2907 desc->bDescriptorSubtype, 2908 desc->bTerminalID, 2909 UGETW(desc->wTerminalType), 2910 desc->bAssocTerminal, 2911 desc->iTerminal); 2912 } 2913 2914 static void 2915 print_output_terminal_descriptor( 2916 const uvideo_output_terminal_descriptor_t *desc) 2917 { 2918 printf("Output Terminal: " 2919 "Len=%d Type=0x%02x Subtype=0x%02x " 2920 "bTerminalID=%d wTerminalType=%x bAssocTerminal=%d " 2921 "bSourceID=%d iTerminal=%d", 2922 desc->bLength, 2923 desc->bDescriptorType, 2924 desc->bDescriptorSubtype, 2925 desc->bTerminalID, 2926 UGETW(desc->wTerminalType), 2927 desc->bAssocTerminal, 2928 desc->bSourceID, 2929 desc->iTerminal); 2930 } 2931 2932 static void 2933 print_camera_terminal_descriptor( 2934 const uvideo_camera_terminal_descriptor_t *desc) 2935 { 2936 printf("Camera Terminal: " 2937 "Len=%d Type=0x%02x Subtype=0x%02x " 2938 "bTerminalID=%d wTerminalType=%x bAssocTerminal=%d " 2939 "iTerminal=%d " 2940 "wObjectiveFocalLengthMin/Max=%d/%d " 2941 "wOcularFocalLength=%d " 2942 "bControlSize=%d ", 2943 desc->bLength, 2944 desc->bDescriptorType, 2945 desc->bDescriptorSubtype, 2946 desc->bTerminalID, 2947 UGETW(desc->wTerminalType), 2948 desc->bAssocTerminal, 2949 desc->iTerminal, 2950 UGETW(desc->wObjectiveFocalLengthMin), 2951 UGETW(desc->wObjectiveFocalLengthMax), 2952 UGETW(desc->wOcularFocalLength), 2953 desc->bControlSize); 2954 printf("bmControls="); 2955 print_bitmap(desc->bmControls, desc->bControlSize); 2956 } 2957 2958 static void 2959 print_selector_unit_descriptor( 2960 const uvideo_selector_unit_descriptor_t *desc) 2961 { 2962 int i; 2963 const uByte *b; 2964 printf("Selector Unit: " 2965 "Len=%d Type=0x%02x Subtype=0x%02x " 2966 "bUnitID=%d bNrInPins=%d ", 2967 desc->bLength, 2968 desc->bDescriptorType, 2969 desc->bDescriptorSubtype, 2970 desc->bUnitID, 2971 desc->bNrInPins); 2972 printf("baSourceIDs="); 2973 b = &desc->baSourceID[0]; 2974 for (i = 0; i < desc->bNrInPins; ++i) 2975 printf("%d ", *b++); 2976 printf("iSelector=%d", *b); 2977 } 2978 2979 static void 2980 print_processing_unit_descriptor( 2981 const uvideo_processing_unit_descriptor_t *desc) 2982 { 2983 const uByte *b; 2984 2985 printf("Processing Unit: " 2986 "Len=%d Type=0x%02x Subtype=0x%02x " 2987 "bUnitID=%d bSourceID=%d wMaxMultiplier=%d bControlSize=%d ", 2988 desc->bLength, 2989 desc->bDescriptorType, 2990 desc->bDescriptorSubtype, 2991 desc->bUnitID, 2992 desc->bSourceID, 2993 UGETW(desc->wMaxMultiplier), 2994 desc->bControlSize); 2995 printf("bmControls="); 2996 print_bitmap(desc->bmControls, desc->bControlSize); 2997 b = &desc->bControlSize + desc->bControlSize + 1; 2998 printf(" iProcessing=%d bmVideoStandards=", *b); 2999 b += 1; 3000 print_bitmap(b, 1); 3001 } 3002 3003 static void 3004 print_extension_unit_descriptor( 3005 const uvideo_extension_unit_descriptor_t *desc) 3006 { 3007 const uByte * byte; 3008 uByte controlbytes; 3009 int i; 3010 3011 printf("Extension Unit: " 3012 "Len=%d Type=0x%02x Subtype=0x%02x " 3013 "bUnitID=%d ", 3014 desc->bLength, 3015 desc->bDescriptorType, 3016 desc->bDescriptorSubtype, 3017 desc->bUnitID); 3018 3019 printf("guidExtensionCode="); 3020 usb_guid_print(&desc->guidExtensionCode); 3021 printf(" "); 3022 3023 printf("bNumControls=%d bNrInPins=%d ", 3024 desc->bNumControls, 3025 desc->bNrInPins); 3026 3027 printf("baSourceIDs="); 3028 byte = &desc->baSourceID[0]; 3029 for (i = 0; i < desc->bNrInPins; ++i) 3030 printf("%d ", *byte++); 3031 3032 controlbytes = *byte++; 3033 printf("bControlSize=%d ", controlbytes); 3034 printf("bmControls="); 3035 print_bitmap(byte, controlbytes); 3036 3037 byte += controlbytes; 3038 printf(" iExtension=%d", *byte); 3039 } 3040 3041 static void 3042 print_interrupt_endpoint_descriptor( 3043 const uvideo_vc_interrupt_endpoint_descriptor_t *desc) 3044 { 3045 printf("Interrupt Endpoint: " 3046 "Len=%d Type=0x%02x Subtype=0x%02x " 3047 "wMaxTransferSize=%d ", 3048 desc->bLength, 3049 desc->bDescriptorType, 3050 desc->bDescriptorSubtype, 3051 UGETW(desc->wMaxTransferSize)); 3052 } 3053 3054 3055 static void 3056 print_vs_output_header_descriptor( 3057 const uvideo_vs_output_header_descriptor_t *desc) 3058 { 3059 printf("Interface Output Header: " 3060 "Len=%d Type=0x%02x Subtype=0x%02x " 3061 "bNumFormats=%d wTotalLength=%d bEndpointAddress=%d " 3062 "bTerminalLink=%d bControlSize=%d", 3063 desc->bLength, 3064 desc->bDescriptorType, 3065 desc->bDescriptorSubtype, 3066 desc->bNumFormats, 3067 UGETW(desc->wTotalLength), 3068 desc->bEndpointAddress, 3069 desc->bTerminalLink, 3070 desc->bControlSize); 3071 } 3072 3073 static void 3074 print_vs_input_header_descriptor( 3075 const uvideo_vs_input_header_descriptor_t *desc) 3076 { 3077 printf("Interface Input Header: " 3078 "Len=%d Type=0x%02x Subtype=0x%02x " 3079 "bNumFormats=%d wTotalLength=%d bEndpointAddress=%d " 3080 "bmInfo=%x bTerminalLink=%d bStillCaptureMethod=%d " 3081 "bTriggerSupport=%d bTriggerUsage=%d bControlSize=%d ", 3082 desc->bLength, 3083 desc->bDescriptorType, 3084 desc->bDescriptorSubtype, 3085 desc->bNumFormats, 3086 UGETW(desc->wTotalLength), 3087 desc->bEndpointAddress, 3088 desc->bmInfo, 3089 desc->bTerminalLink, 3090 desc->bStillCaptureMethod, 3091 desc->bTriggerSupport, 3092 desc->bTriggerUsage, 3093 desc->bControlSize); 3094 print_bitmap(desc->bmaControls, desc->bControlSize); 3095 } 3096 3097 static void 3098 print_vs_format_uncompressed_descriptor( 3099 const uvideo_vs_format_uncompressed_descriptor_t *desc) 3100 { 3101 printf("Format Uncompressed: " 3102 "Len=%d Type=0x%02x Subtype=0x%02x " 3103 "bFormatIndex=%d bNumFrameDescriptors=%d ", 3104 desc->bLength, 3105 desc->bDescriptorType, 3106 desc->bDescriptorSubtype, 3107 desc->bFormatIndex, 3108 desc->bNumFrameDescriptors); 3109 usb_guid_print(&desc->guidFormat); 3110 printf(" bBitsPerPixel=%d bDefaultFrameIndex=%d " 3111 "bAspectRatioX=%d bAspectRatioY=%d " 3112 "bmInterlaceFlags=0x%02x bCopyProtect=%d", 3113 desc->bBitsPerPixel, 3114 desc->bDefaultFrameIndex, 3115 desc->bAspectRatioX, 3116 desc->bAspectRatioY, 3117 desc->bmInterlaceFlags, 3118 desc->bCopyProtect); 3119 } 3120 3121 static void 3122 print_vs_frame_uncompressed_descriptor( 3123 const uvideo_vs_frame_uncompressed_descriptor_t *desc) 3124 { 3125 printf("Frame Uncompressed: " 3126 "Len=%d Type=0x%02x Subtype=0x%02x " 3127 "bFrameIndex=%d bmCapabilities=0x%02x " 3128 "wWidth=%d wHeight=%d dwMinBitRate=%u dwMaxBitRate=%u " 3129 "dwMaxVideoFrameBufferSize=%u dwDefaultFrameInterval=%u " 3130 "bFrameIntervalType=%d", 3131 desc->bLength, 3132 desc->bDescriptorType, 3133 desc->bDescriptorSubtype, 3134 desc->bFrameIndex, 3135 desc->bmCapabilities, 3136 UGETW(desc->wWidth), 3137 UGETW(desc->wHeight), 3138 UGETDW(desc->dwMinBitRate), 3139 UGETDW(desc->dwMaxBitRate), 3140 UGETDW(desc->dwMaxVideoFrameBufferSize), 3141 UGETDW(desc->dwDefaultFrameInterval), 3142 desc->bFrameIntervalType); 3143 } 3144 3145 static void 3146 print_vs_format_mjpeg_descriptor( 3147 const uvideo_vs_format_mjpeg_descriptor_t *desc) 3148 { 3149 printf("MJPEG format: " 3150 "Len=%d Type=0x%02x Subtype=0x%02x " 3151 "bFormatIndex=%d bNumFrameDescriptors=%d bmFlags=0x%02x " 3152 "bDefaultFrameIndex=%d bAspectRatioX=%d bAspectRatioY=%d " 3153 "bmInterlaceFlags=0x%02x bCopyProtect=%d", 3154 desc->bLength, 3155 desc->bDescriptorType, 3156 desc->bDescriptorSubtype, 3157 desc->bFormatIndex, 3158 desc->bNumFrameDescriptors, 3159 desc->bmFlags, 3160 desc->bDefaultFrameIndex, 3161 desc->bAspectRatioX, 3162 desc->bAspectRatioY, 3163 desc->bmInterlaceFlags, 3164 desc->bCopyProtect); 3165 } 3166 3167 static void 3168 print_vs_frame_mjpeg_descriptor( 3169 const uvideo_vs_frame_mjpeg_descriptor_t *desc) 3170 { 3171 printf("MJPEG frame: " 3172 "Len=%d Type=0x%02x Subtype=0x%02x " 3173 "bFrameIndex=%d bmCapabilities=0x%02x " 3174 "wWidth=%d wHeight=%d dwMinBitRate=%u dwMaxBitRate=%u " 3175 "dwMaxVideoFrameBufferSize=%u dwDefaultFrameInterval=%u " 3176 "bFrameIntervalType=%d", 3177 desc->bLength, 3178 desc->bDescriptorType, 3179 desc->bDescriptorSubtype, 3180 desc->bFrameIndex, 3181 desc->bmCapabilities, 3182 UGETW(desc->wWidth), 3183 UGETW(desc->wHeight), 3184 UGETDW(desc->dwMinBitRate), 3185 UGETDW(desc->dwMaxBitRate), 3186 UGETDW(desc->dwMaxVideoFrameBufferSize), 3187 UGETDW(desc->dwDefaultFrameInterval), 3188 desc->bFrameIntervalType); 3189 } 3190 3191 static void 3192 print_vs_format_dv_descriptor( 3193 const uvideo_vs_format_dv_descriptor_t *desc) 3194 { 3195 printf("MJPEG format: " 3196 "Len=%d Type=0x%02x Subtype=0x%02x " 3197 "bFormatIndex=%d dwMaxVideoFrameBufferSize=%u " 3198 "bFormatType/Rate=%d bFormatType/Format=%d", 3199 desc->bLength, 3200 desc->bDescriptorType, 3201 desc->bDescriptorSubtype, 3202 desc->bFormatIndex, 3203 UGETDW(desc->dwMaxVideoFrameBufferSize), 3204 UVIDEO_GET_DV_FREQ(desc->bFormatType), 3205 UVIDEO_GET_DV_FORMAT(desc->bFormatType)); 3206 } 3207 3208 #endif /* !UVIDEO_DEBUG */ 3209 3210 #ifdef UVIDEO_DEBUG 3211 static void 3212 usb_guid_print(const usb_guid_t *guid) 3213 { 3214 printf("%04X-%02X-%02X-", 3215 UGETDW(guid->data1), 3216 UGETW(guid->data2), 3217 UGETW(guid->data3)); 3218 printf("%02X%02X-", 3219 guid->data4[0], 3220 guid->data4[1]); 3221 printf("%02X%02X%02X%02X%02X%02X", 3222 guid->data4[2], 3223 guid->data4[3], 3224 guid->data4[4], 3225 guid->data4[5], 3226 guid->data4[6], 3227 guid->data4[7]); 3228 } 3229 #endif /* !UVIDEO_DEBUG */ 3230 3231 /* 3232 * Returns less than zero, zero, or greater than zero if uguid is less 3233 * than, equal to, or greater than guid. 3234 */ 3235 static int 3236 usb_guid_cmp(const usb_guid_t *uguid, const guid_t *guid) 3237 { 3238 if (guid->data1 > UGETDW(uguid->data1)) 3239 return 1; 3240 else if (guid->data1 < UGETDW(uguid->data1)) 3241 return -1; 3242 3243 if (guid->data2 > UGETW(uguid->data2)) 3244 return 1; 3245 else if (guid->data2 < UGETW(uguid->data2)) 3246 return -1; 3247 3248 if (guid->data3 > UGETW(uguid->data3)) 3249 return 1; 3250 else if (guid->data3 < UGETW(uguid->data3)) 3251 return -1; 3252 3253 return memcmp(guid->data4, uguid->data4, 8); 3254 } 3255