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