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