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