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