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