Sync usage with man page.
[netbsd-mini2440.git] / sys / dev / usb / uvideo.c
blob87b62e20d5e8b550c499ea7a4bd6caf22aa1301d
1 /* $NetBSD: uvideo.c,v 1.29 2009/03/09 15:59:33 uebayasi Exp $ */
3 /*
4 * Copyright (c) 2008 Patrick Mahoney
5 * All rights reserved.
7 * This code was written by Patrick Mahoney (pat@polycrystal.org) as
8 * part of Google Summer of Code 2008.
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.
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.
40 * USB video specs:
41 * http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_1.zip
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: uvideo.c,v 1.29 2009/03/09 15:59:33 uebayasi Exp $");
47 #ifdef _MODULE
48 #include <sys/module.h>
49 #endif
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/file.h>
60 #include <sys/select.h>
61 #include <sys/proc.h>
62 #include <sys/conf.h>
63 #include <sys/vnode.h>
64 #include <sys/poll.h>
65 #include <sys/queue.h> /* SLIST */
66 #include <sys/kthread.h>
68 #include <sys/videoio.h>
69 #include <dev/video_if.h>
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>
76 #include <dev/usb/uvideoreg.h>
78 #if !defined(_MODULE)
79 #include "opt_uvideo.h"
80 #endif
82 #define UVIDEO_NXFERS 3
83 #define PRI_UVIDEO PRI_BIO
85 /* #define UVIDEO_DISABLE_MJPEG */
87 #ifdef UVIDEO_DEBUG
88 #define DPRINTF(x) do { if (uvideodebug) logprintf x; } while (0)
89 #define DPRINTFN(n,x) do { if (uvideodebug>(n)) logprintf x; } while (0)
90 int uvideodebug = 20;
91 #else
92 #define DPRINTF(x)
93 #define DPRINTFN(n,x)
94 #endif
96 typedef enum {
97 UVIDEO_STATE_CLOSED,
98 UVIDEO_STATE_OPENING,
99 UVIDEO_STATE_IDLE
100 } uvideo_state;
102 struct uvideo_camera_terminal {
103 uint16_t ct_objective_focal_min;
104 uint16_t ct_objective_focal_max;
105 uint16_t ct_ocular_focal_length;
108 struct uvideo_processing_unit {
109 uint16_t pu_max_multiplier; /* digital zoom */
110 uint8_t pu_video_standards;
113 struct uvideo_extension_unit {
114 guid_t xu_guid;
117 /* For simplicity, we consider a Terminal a special case of Unit
118 * rather than a separate entity. */
119 struct uvideo_unit {
120 uint8_t vu_id;
121 uint8_t vu_type;
122 uint8_t vu_dst_id;
123 uint8_t vu_nsrcs;
124 union {
125 uint8_t vu_src_id; /* vu_nsrcs = 1 */
126 uint8_t *vu_src_id_ary; /* vu_nsrcs > 1 */
127 } s;
129 /* fields for individual unit/terminal types */
130 union {
131 struct uvideo_camera_terminal vu_camera;
132 struct uvideo_processing_unit vu_processing;
133 struct uvideo_extension_unit vu_extension;
134 } u;
136 /* Used by camera terminal, processing and extention units. */
137 uint8_t vu_control_size; /* number of bytes in vu_controls */
138 uint8_t *vu_controls; /* array of bytes. bits are
139 * numbered from 0 at least
140 * significant bit to
141 * (8*vu_control_size - 1)*/
144 struct uvideo_alternate {
145 uint8_t altno;
146 uint8_t interval;
147 uint16_t max_packet_size;
148 SLIST_ENTRY(uvideo_alternate) entries;
150 SLIST_HEAD(altlist, uvideo_alternate);
152 #define UVIDEO_FORMAT_GET_FORMAT_INDEX(fmt) \
153 ((fmt)->format.priv & 0xff)
154 #define UVIDEO_FORMAT_GET_FRAME_INDEX(fmt) \
155 (((fmt)->format.priv >> 8) & 0xff)
156 /* TODO: find a better way to set bytes within this 32 bit value? */
157 #define UVIDEO_FORMAT_SET_FORMAT_INDEX(fmt, index) do { \
158 (fmt)->format.priv &= ~0xff; \
159 (fmt)->format.priv |= ((index) & 0xff); \
160 } while (0)
161 #define UVIDEO_FORMAT_SET_FRAME_INDEX(fmt, index) do { \
162 (fmt)->format.priv &= ~(0xff << 8); \
163 ((fmt)->format.priv |= (((index) & 0xff) << 8)); \
164 } while (0)
166 struct uvideo_pixel_format {
167 enum video_pixel_format pixel_format;
168 SIMPLEQ_ENTRY(uvideo_pixel_format) entries;
170 SIMPLEQ_HEAD(uvideo_pixel_format_list, uvideo_pixel_format);
172 struct uvideo_format {
173 struct video_format format;
174 SIMPLEQ_ENTRY(uvideo_format) entries;
176 SIMPLEQ_HEAD(uvideo_format_list, uvideo_format);
178 struct uvideo_isoc_xfer;
179 struct uvideo_stream;
181 struct uvideo_isoc {
182 struct uvideo_isoc_xfer *i_ix;
183 struct uvideo_stream *i_vs;
184 usbd_xfer_handle i_xfer;
185 uint8_t *i_buf;
186 uint16_t *i_frlengths;
189 struct uvideo_isoc_xfer {
190 uint8_t ix_endpt;
191 usbd_pipe_handle ix_pipe;
192 struct uvideo_isoc ix_i[UVIDEO_NXFERS];
193 uint32_t ix_nframes;
194 uint32_t ix_uframe_len;
196 struct altlist ix_altlist;
199 struct uvideo_bulk_xfer {
200 uint8_t bx_endpt;
201 usbd_pipe_handle bx_pipe;
202 usbd_xfer_handle bx_xfer;
203 uint8_t *bx_buffer;
204 int bx_buflen;
205 bool bx_running;
206 kcondvar_t bx_cv;
207 kmutex_t bx_lock;
210 struct uvideo_stream {
211 struct uvideo_softc *vs_parent;
212 usbd_interface_handle vs_iface;
213 uint8_t vs_ifaceno;
214 uint8_t vs_subtype; /* input or output */
215 uint16_t vs_probelen; /* length of probe and
216 * commit data; varies
217 * depending on version
218 * of spec. */
219 struct uvideo_format_list vs_formats;
220 struct uvideo_pixel_format_list vs_pixel_formats;
221 struct video_format *vs_default_format;
222 struct video_format vs_current_format;
224 /* usb transfer details */
225 uint8_t vs_xfer_type;
226 union {
227 struct uvideo_bulk_xfer bulk;
228 struct uvideo_isoc_xfer isoc;
229 } vs_xfer;
231 int vs_frameno; /* toggles between 0 and 1 */
233 /* current video format */
234 uint32_t vs_max_payload_size;
235 uint32_t vs_frame_interval;
236 SLIST_ENTRY(uvideo_stream) entries;
238 SLIST_HEAD(uvideo_stream_list, uvideo_stream);
240 struct uvideo_softc {
241 USBBASEDEVICE sc_dev; /* base device */
242 usbd_device_handle sc_udev; /* device */
243 usbd_interface_handle sc_iface; /* interface handle */
244 int sc_ifaceno; /* interface number */
245 char *sc_devname;
247 device_ptr_t sc_videodev;
249 int sc_dying;
250 uvideo_state sc_state;
252 uint8_t sc_nunits;
253 struct uvideo_unit **sc_unit;
255 struct uvideo_stream *sc_stream_in;
257 struct uvideo_stream_list sc_stream_list;
260 int uvideo_match(device_t, cfdata_t, void *);
261 void uvideo_attach(device_t, device_t, void *);
262 int uvideo_detach(device_t, int);
263 void uvideo_childdet(device_t, device_t);
264 int uvideo_activate(device_t, enum devact);
266 static int uvideo_open(void *, int);
267 static void uvideo_close(void *);
268 static const char * uvideo_get_devname(void *);
270 static int uvideo_enum_format(void *, uint32_t, struct video_format *);
271 static int uvideo_get_format(void *, struct video_format *);
272 static int uvideo_set_format(void *, struct video_format *);
273 static int uvideo_try_format(void *, struct video_format *);
274 static int uvideo_start_transfer(void *);
275 static int uvideo_stop_transfer(void *);
277 static int uvideo_get_control_group(void *,
278 struct video_control_group *);
279 static int uvideo_set_control_group(void *,
280 const struct video_control_group *);
282 static usbd_status uvideo_init_control(
283 struct uvideo_softc *,
284 const usb_interface_descriptor_t *,
285 usbd_desc_iter_t *);
286 static usbd_status uvideo_init_collection(
287 struct uvideo_softc *,
288 const usb_interface_descriptor_t *,
289 usbd_desc_iter_t *);
291 /* Functions for unit & terminal descriptors */
292 static struct uvideo_unit * uvideo_unit_alloc(const uvideo_descriptor_t *);
293 static usbd_status uvideo_unit_init(struct uvideo_unit *,
294 const uvideo_descriptor_t *);
295 static void uvideo_unit_free(struct uvideo_unit *);
296 static usbd_status uvideo_unit_alloc_controls(struct uvideo_unit *,
297 uint8_t,
298 const uint8_t *);
299 static void uvideo_unit_free_controls(struct uvideo_unit *);
300 static usbd_status uvideo_unit_alloc_sources(struct uvideo_unit *,
301 uint8_t,
302 const uint8_t *);
303 static void uvideo_unit_free_sources(struct uvideo_unit *);
308 /* Functions for uvideo_stream, primary unit associated with a video
309 * driver or device file. */
310 static struct uvideo_stream * uvideo_find_stream(struct uvideo_softc *,
311 uint8_t);
312 #if 0
313 static struct uvideo_format * uvideo_stream_find_format(
314 struct uvideo_stream *,
315 uint8_t, uint8_t);
316 #endif
317 static struct uvideo_format * uvideo_stream_guess_format(
318 struct uvideo_stream *,
319 enum video_pixel_format, uint32_t, uint32_t);
320 static struct uvideo_stream * uvideo_stream_alloc(void);
321 static usbd_status uvideo_stream_init(
322 struct uvideo_stream *stream,
323 struct uvideo_softc *sc,
324 const usb_interface_descriptor_t *ifdesc,
325 uint8_t idx);
326 static usbd_status uvideo_stream_init_desc(
327 struct uvideo_stream *,
328 const usb_interface_descriptor_t *ifdesc,
329 usbd_desc_iter_t *iter);
330 static usbd_status uvideo_stream_init_frame_based_format(
331 struct uvideo_stream *,
332 const uvideo_descriptor_t *,
333 usbd_desc_iter_t *);
334 static void uvideo_stream_free(struct uvideo_stream *);
336 static int uvideo_stream_start_xfer(struct uvideo_stream *);
337 static int uvideo_stream_stop_xfer(struct uvideo_stream *);
338 static usbd_status uvideo_stream_recv_process(struct uvideo_stream *,
339 uint8_t *, uint32_t);
340 static usbd_status uvideo_stream_recv_isoc_start(struct uvideo_stream *);
341 static usbd_status uvideo_stream_recv_isoc_start1(struct uvideo_isoc *);
342 static void uvideo_stream_recv_isoc_complete(usbd_xfer_handle,
343 usbd_private_handle,
344 usbd_status);
345 static void uvideo_stream_recv_bulk_transfer(void *);
347 /* format probe and commit */
348 #define uvideo_stream_probe(vs, act, data) \
349 (uvideo_stream_probe_and_commit((vs), (act), \
350 UVIDEO_VS_PROBE_CONTROL, (data)))
351 #define uvideo_stream_commit(vs, act, data) \
352 (uvideo_stream_probe_and_commit((vs), (act), \
353 UVIDEO_VS_COMMIT_CONTROL, (data)))
354 static usbd_status uvideo_stream_probe_and_commit(struct uvideo_stream *,
355 uint8_t, uint8_t,
356 void *);
357 static void uvideo_init_probe_data(uvideo_probe_and_commit_data_t *);
360 static const usb_descriptor_t * usb_desc_iter_peek_next(usbd_desc_iter_t *);
361 static const usb_interface_descriptor_t * usb_desc_iter_next_interface(
362 usbd_desc_iter_t *);
363 static const usb_descriptor_t * usb_desc_iter_next_non_interface(
364 usbd_desc_iter_t *);
366 static int usb_guid_cmp(const usb_guid_t *, const guid_t *);
369 CFATTACH_DECL2_NEW(uvideo, sizeof(struct uvideo_softc),
370 uvideo_match, uvideo_attach, uvideo_detach, uvideo_activate, NULL,
371 uvideo_childdet);
373 extern struct cfdriver uvideo_cd;
376 static const struct video_hw_if uvideo_hw_if = {
377 .open = uvideo_open,
378 .close = uvideo_close,
379 .get_devname = uvideo_get_devname,
380 .enum_format = uvideo_enum_format,
381 .get_format = uvideo_get_format,
382 .set_format = uvideo_set_format,
383 .try_format = uvideo_try_format,
384 .start_transfer = uvideo_start_transfer,
385 .stop_transfer = uvideo_stop_transfer,
386 .control_iter_init = NULL,
387 .control_iter_next = NULL,
388 .get_control_desc_group = NULL,
389 .get_control_group = uvideo_get_control_group,
390 .set_control_group = uvideo_set_control_group,
393 #ifdef UVIDEO_DEBUG
394 /* Some functions to print out descriptors. Mostly useless other than
395 * debugging/exploration purposes. */
396 static void usb_guid_print(const usb_guid_t *);
397 static void print_descriptor(const usb_descriptor_t *);
398 static void print_interface_descriptor(const usb_interface_descriptor_t *);
399 static void print_endpoint_descriptor(const usb_endpoint_descriptor_t *);
401 static void print_vc_descriptor(const usb_descriptor_t *);
402 static void print_vs_descriptor(const usb_descriptor_t *);
404 static void print_vc_header_descriptor(
405 const uvideo_vc_header_descriptor_t *);
406 static void print_input_terminal_descriptor(
407 const uvideo_input_terminal_descriptor_t *);
408 static void print_output_terminal_descriptor(
409 const uvideo_output_terminal_descriptor_t *);
410 static void print_camera_terminal_descriptor(
411 const uvideo_camera_terminal_descriptor_t *);
412 static void print_selector_unit_descriptor(
413 const uvideo_selector_unit_descriptor_t *);
414 static void print_processing_unit_descriptor(
415 const uvideo_processing_unit_descriptor_t *);
416 static void print_extension_unit_descriptor(
417 const uvideo_extension_unit_descriptor_t *);
418 static void print_interrupt_endpoint_descriptor(
419 const uvideo_vc_interrupt_endpoint_descriptor_t *);
421 static void print_vs_input_header_descriptor(
422 const uvideo_vs_input_header_descriptor_t *);
423 static void print_vs_output_header_descriptor(
424 const uvideo_vs_output_header_descriptor_t *);
426 static void print_vs_format_uncompressed_descriptor(
427 const uvideo_vs_format_uncompressed_descriptor_t *);
428 static void print_vs_frame_uncompressed_descriptor(
429 const uvideo_vs_frame_uncompressed_descriptor_t *);
430 static void print_vs_format_mjpeg_descriptor(
431 const uvideo_vs_format_mjpeg_descriptor_t *);
432 static void print_vs_frame_mjpeg_descriptor(
433 const uvideo_vs_frame_mjpeg_descriptor_t *);
434 static void print_vs_format_dv_descriptor(
435 const uvideo_vs_format_dv_descriptor_t *);
436 #endif /* !UVIDEO_DEBUG */
438 #define GET(type, descp, field) (((const type *)(descp))->field)
439 #define GETP(type, descp, field) (&(((const type *)(descp))->field))
441 /* Given a format descriptor and frame descriptor, copy values common
442 * to all formats into a struct uvideo_format. */
443 #define UVIDEO_FORMAT_INIT_FRAME_BASED(format_type, format_desc, \
444 frame_type, frame_desc, \
445 format) \
446 do { \
447 UVIDEO_FORMAT_SET_FORMAT_INDEX( \
448 format, \
449 GET(format_type, format_desc, bFormatIndex)); \
450 UVIDEO_FORMAT_SET_FRAME_INDEX( \
451 format, \
452 GET(frame_type, frame_desc, bFrameIndex)); \
453 format->format.width = \
454 UGETW(GET(frame_type, frame_desc, wWidth)); \
455 format->format.height = \
456 UGETW(GET(frame_type, frame_desc, wHeight)); \
457 format->format.aspect_x = \
458 GET(format_type, format_desc, bAspectRatioX); \
459 format->format.aspect_y = \
460 GET(format_type, format_desc, bAspectRatioY); \
461 } while (0)
464 USB_MATCH(uvideo)
466 USB_IFMATCH_START(uvideo, uaa);
468 /* TODO: May need to change in the future to work with
469 * Interface Association Descriptor. */
471 /* Trigger on the Video Control Interface which must be present */
472 if (uaa->class == UICLASS_VIDEO &&
473 uaa->subclass == UISUBCLASS_VIDEOCONTROL)
474 return UMATCH_IFACECLASS_IFACESUBCLASS;
476 return UMATCH_NONE;
479 USB_ATTACH(uvideo)
481 USB_IFATTACH_START(uvideo, sc, uaa);
482 usbd_desc_iter_t iter;
483 const usb_interface_descriptor_t *ifdesc;
484 struct uvideo_stream *vs;
485 usbd_status err;
486 uint8_t ifaceidx;
488 sc->sc_dev = self;
490 sc->sc_devname = usbd_devinfo_alloc(uaa->device, 0);
492 aprint_naive("\n");
493 aprint_normal(": %s\n", sc->sc_devname);
495 sc->sc_udev = uaa->device;
496 sc->sc_iface = uaa->iface;
497 sc->sc_ifaceno = uaa->ifaceno;
498 sc->sc_dying = 0;
499 sc->sc_state = UVIDEO_STATE_CLOSED;
500 SLIST_INIT(&sc->sc_stream_list);
502 #ifdef UVIDEO_DEBUG
503 /* Debugging dump of descriptors. TODO: move this to userspace
504 * via a custom IOCTL or something. */
505 const usb_descriptor_t *desc;
506 usb_desc_iter_init(sc->sc_udev, &iter);
507 while ((desc = usb_desc_iter_next(&iter)) != NULL) {
508 /* print out all descriptors */
509 printf("uvideo_attach: ");
510 print_descriptor(desc);
512 #endif /* !UVIDEO_DEBUG */
514 /* iterate through interface descriptors and initialize softc */
515 usb_desc_iter_init(sc->sc_udev, &iter);
516 for (ifaceidx = 0;
517 (ifdesc = usb_desc_iter_next_interface(&iter)) != NULL;
518 ++ifaceidx)
520 if (ifdesc->bInterfaceClass != UICLASS_VIDEO) {
521 DPRINTFN(50, ("uvideo_attach: "
522 "ignoring non-uvc interface: "
523 "len=%d type=0x%02x "
524 "class=0x%02x subclass=0x%02x\n",
525 ifdesc->bLength,
526 ifdesc->bDescriptorType,
527 ifdesc->bInterfaceClass,
528 ifdesc->bInterfaceSubClass));
529 continue;
532 switch (ifdesc->bInterfaceSubClass) {
533 case UISUBCLASS_VIDEOCONTROL:
534 err = uvideo_init_control(sc, ifdesc, &iter);
535 if (err != USBD_NORMAL_COMPLETION) {
536 DPRINTF(("uvideo_attach: error with interface "
537 "%d, VideoControl, "
538 "descriptor len=%d type=0x%02x: "
539 "%s (%d)\n",
540 ifdesc->bInterfaceNumber,
541 ifdesc->bLength,
542 ifdesc->bDescriptorType,
543 usbd_errstr(err), err));
545 break;
546 case UISUBCLASS_VIDEOSTREAMING:
547 vs = uvideo_find_stream(sc, ifdesc->bInterfaceNumber);
548 if (vs == NULL) {
549 vs = uvideo_stream_alloc();
550 if (vs == NULL) {
551 DPRINTF(("uvideo_attach: "
552 "failed to alloc stream\n"));
553 err = USBD_NOMEM;
554 goto bad;
556 err = uvideo_stream_init(vs, sc, ifdesc,
557 ifaceidx);
558 if (err != USBD_NORMAL_COMPLETION) {
559 DPRINTF(("uvideo_attach: "
560 "error initializing stream: "
561 "%s (%d)\n",
562 usbd_errstr(err), err));
563 goto bad;
566 err = uvideo_stream_init_desc(vs, ifdesc, &iter);
567 if (err != USBD_NORMAL_COMPLETION) {
568 DPRINTF(("uvideo_attach: "
569 "error initializing stream descriptor: "
570 "%s (%d)\n",
571 usbd_errstr(err), err));
572 goto bad;
574 /* TODO: for now, set (each) stream to stream_in. */
575 sc->sc_stream_in = vs;
576 break;
577 case UISUBCLASS_VIDEOCOLLECTION:
578 err = uvideo_init_collection(sc, ifdesc, &iter);
579 if (err != USBD_NORMAL_COMPLETION) {
580 DPRINTF(("uvideo_attach: error with interface "
581 "%d, VideoCollection, "
582 "descriptor len=%d type=0x%02x: "
583 "%s (%d)\n",
584 ifdesc->bInterfaceNumber,
585 ifdesc->bLength,
586 ifdesc->bDescriptorType,
587 usbd_errstr(err), err));
588 goto bad;
590 break;
591 default:
592 DPRINTF(("uvideo_attach: unknown UICLASS_VIDEO "
593 "subclass=0x%02x\n",
594 ifdesc->bInterfaceSubClass));
595 break;
601 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
602 USBDEV(sc->sc_dev));
604 if (!pmf_device_register(self, NULL, NULL))
605 aprint_error_dev(self, "couldn't establish power handler\n");
607 sc->sc_videodev = video_attach_mi(&uvideo_hw_if, sc->sc_dev);
608 DPRINTF(("uvideo_attach: attached video driver at %p\n",
609 sc->sc_videodev));
611 USB_ATTACH_SUCCESS_RETURN;
613 bad:
614 if (err != USBD_NORMAL_COMPLETION) {
615 DPRINTF(("uvideo_attach: error: %s (%d)\n",
616 usbd_errstr(err), err));
618 USB_ATTACH_ERROR_RETURN;
623 uvideo_activate(device_t self, enum devact act)
625 struct uvideo_softc *sc = device_private(self);
627 switch (act) {
628 case DVACT_DEACTIVATE:
629 DPRINTF(("uvideo_activate: deactivating\n"));
630 sc->sc_dying = 1;
631 return 0;
632 default:
633 return EOPNOTSUPP;
638 /* Detach child (video interface) */
639 void
640 uvideo_childdet(device_t self, device_t child)
642 struct uvideo_softc *sc = device_private(self);
644 KASSERT(sc->sc_videodev == child);
645 sc->sc_videodev = NULL;
650 uvideo_detach(device_t self, int flags)
652 struct uvideo_softc *sc;
653 struct uvideo_stream *vs;
654 int rv;
656 sc = device_private(self);
657 rv = 0;
659 sc->sc_dying = 1;
661 pmf_device_deregister(self);
663 usbd_devinfo_free(sc->sc_devname);
665 /* TODO: close the device if it is currently opened? Or will
666 * close be called automatically? */
668 while (!SLIST_EMPTY(&sc->sc_stream_list)) {
669 vs = SLIST_FIRST(&sc->sc_stream_list);
670 SLIST_REMOVE_HEAD(&sc->sc_stream_list, entries);
671 uvideo_stream_free(vs);
674 /* Wait for outstanding request to complete. TODO: what is
675 * appropriate here? */
676 usbd_delay_ms(sc->sc_udev, 1000);
678 DPRINTFN(15, ("uvideo: detaching from %s\n",
679 USBDEVNAME(sc->sc_dev)));
681 if (sc->sc_videodev != NULL)
682 rv = config_detach(sc->sc_videodev, flags);
684 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
685 USBDEV(sc->sc_dev));
687 return rv;
690 /* Search the stream list for a stream matching the interface number.
691 * This is an O(n) search, but most devices should have only one or at
692 * most two streams. */
693 static struct uvideo_stream *
694 uvideo_find_stream(struct uvideo_softc *sc, uint8_t ifaceno)
696 struct uvideo_stream *vs;
698 SLIST_FOREACH(vs, &sc->sc_stream_list, entries) {
699 if (vs->vs_ifaceno == ifaceno)
700 return vs;
703 return NULL;
706 /* Search the format list for the given format and frame index. This
707 * might be improved through indexing, but the format and frame count
708 * is unknown ahead of time (only after iterating through the
709 * usb device descriptors). */
710 #if 0
711 static struct uvideo_format *
712 uvideo_stream_find_format(struct uvideo_stream *vs,
713 uint8_t format_index, uint8_t frame_index)
715 struct uvideo_format *format;
717 SIMPLEQ_FOREACH(format, &vs->vs_formats, entries) {
718 if (UVIDEO_FORMAT_GET_FORMAT_INDEX(format) == format_index &&
719 UVIDEO_FORMAT_GET_FRAME_INDEX(format) == frame_index)
720 return format;
722 return NULL;
724 #endif
726 static struct uvideo_format *
727 uvideo_stream_guess_format(struct uvideo_stream *vs,
728 enum video_pixel_format pixel_format,
729 uint32_t width, uint32_t height)
731 struct uvideo_format *format, *gformat = NULL;
733 SIMPLEQ_FOREACH(format, &vs->vs_formats, entries) {
734 if (format->format.pixel_format != pixel_format)
735 continue;
736 if (format->format.width <= width &&
737 format->format.height <= height) {
738 if (gformat == NULL ||
739 (gformat->format.width < format->format.width &&
740 gformat->format.height < format->format.height))
741 gformat = format;
745 return gformat;
748 static struct uvideo_stream *
749 uvideo_stream_alloc(void)
751 return (kmem_alloc(sizeof(struct uvideo_stream), KM_NOSLEEP));
755 static usbd_status
756 uvideo_init_control(struct uvideo_softc *sc,
757 const usb_interface_descriptor_t *ifdesc,
758 usbd_desc_iter_t *iter)
760 const usb_descriptor_t *desc;
761 const uvideo_descriptor_t *uvdesc;
762 usbd_desc_iter_t orig;
763 uint8_t i, j, nunits;
765 /* save original iterator state */
766 memcpy(&orig, iter, sizeof(orig));
768 /* count number of units and terminals */
769 nunits = 0;
770 while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) {
771 uvdesc = (const uvideo_descriptor_t *)desc;
773 if (uvdesc->bDescriptorType != UDESC_CS_INTERFACE)
774 continue;
775 if (uvdesc->bDescriptorSubtype < UDESC_INPUT_TERMINAL ||
776 uvdesc->bDescriptorSubtype > UDESC_EXTENSION_UNIT)
777 continue;
778 ++nunits;
781 if (nunits == 0) {
782 DPRINTF(("uvideo_init_control: no units\n"));
783 return USBD_NORMAL_COMPLETION;
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;
792 /* restore original iterator state */
793 memcpy(iter, &orig, sizeof(orig));
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;
800 if (uvdesc->bDescriptorType != UDESC_CS_INTERFACE)
801 continue;
802 if (uvdesc->bDescriptorSubtype < UDESC_INPUT_TERMINAL ||
803 uvdesc->bDescriptorSubtype > UDESC_EXTENSION_UNIT)
804 continue;
806 sc->sc_unit[i] = uvideo_unit_alloc(uvdesc);
807 /* TODO: free other units before returning? */
808 if (sc->sc_unit[i] == NULL)
809 goto enomem;
810 ++i;
813 return USBD_NORMAL_COMPLETION;
815 enomem:
816 if (sc->sc_unit != NULL) {
817 for (j = 0; j < i; ++j) {
818 uvideo_unit_free(sc->sc_unit[j]);
819 sc->sc_unit[j] = NULL;
821 kmem_free(sc->sc_unit, sizeof(*sc->sc_unit) * nunits);
822 sc->sc_unit = NULL;
824 sc->sc_nunits = 0;
826 return USBD_NOMEM;
829 static usbd_status
830 uvideo_init_collection(struct uvideo_softc *sc,
831 const usb_interface_descriptor_t *ifdesc,
832 usbd_desc_iter_t *iter)
834 DPRINTF(("uvideo: ignoring Video Collection\n"));
835 return USBD_NORMAL_COMPLETION;
838 /* Allocates space for and initializes a uvideo unit based on the
839 * given descriptor. Returns NULL with bad descriptor or ENOMEM. */
840 static struct uvideo_unit *
841 uvideo_unit_alloc(const uvideo_descriptor_t *desc)
843 struct uvideo_unit *vu;
844 usbd_status err;
846 if (desc->bDescriptorType != UDESC_CS_INTERFACE)
847 return NULL;
849 vu = kmem_alloc(sizeof(*vu), KM_SLEEP);
850 if (vu == NULL)
851 return NULL;
853 err = uvideo_unit_init(vu, desc);
854 if (err != USBD_NORMAL_COMPLETION) {
855 DPRINTF(("uvideo_unit_alloc: error initializing unit: "
856 "%s (%d)\n", usbd_errstr(err), err));
857 kmem_free(vu, sizeof(*vu));
858 return NULL;
861 return vu;
864 static usbd_status
865 uvideo_unit_init(struct uvideo_unit *vu, const uvideo_descriptor_t *desc)
867 struct uvideo_camera_terminal *ct;
868 struct uvideo_processing_unit *pu;
869 struct uvideo_extension_unit *xu;
871 const uvideo_input_terminal_descriptor_t *input;
872 const uvideo_output_terminal_descriptor_t *output;
873 const uvideo_camera_terminal_descriptor_t *camera;
874 const uvideo_selector_unit_descriptor_t *selector;
875 const uvideo_processing_unit_descriptor_t *processing;
876 const uvideo_extension_unit_descriptor_t *extension;
878 memset(vu, 0, sizeof(*vu));
880 switch (desc->bDescriptorSubtype) {
881 case UDESC_INPUT_TERMINAL:
882 input = (const uvideo_input_terminal_descriptor_t *)desc;
883 switch (UGETW(input->wTerminalType)) {
884 case UVIDEO_ITT_CAMERA:
885 camera =
886 (const uvideo_camera_terminal_descriptor_t *)desc;
887 ct = &vu->u.vu_camera;
889 ct->ct_objective_focal_min =
890 UGETW(camera->wObjectiveFocalLengthMin);
891 ct->ct_objective_focal_max =
892 UGETW(camera->wObjectiveFocalLengthMax);
893 ct->ct_ocular_focal_length =
894 UGETW(camera->wOcularFocalLength);
896 uvideo_unit_alloc_controls(vu, camera->bControlSize,
897 camera->bmControls);
898 break;
899 default:
900 DPRINTF(("uvideo_unit_init: "
901 "unknown input terminal type 0x%04x\n",
902 UGETW(input->wTerminalType)));
903 return USBD_INVAL;
905 break;
906 case UDESC_OUTPUT_TERMINAL:
907 output = (const uvideo_output_terminal_descriptor_t *)desc;
908 break;
909 case UDESC_SELECTOR_UNIT:
910 selector = (const uvideo_selector_unit_descriptor_t *)desc;
912 uvideo_unit_alloc_sources(vu, selector->bNrInPins,
913 selector->baSourceID);
914 break;
915 case UDESC_PROCESSING_UNIT:
916 processing = (const uvideo_processing_unit_descriptor_t *)desc;
917 pu = &vu->u.vu_processing;
919 pu->pu_video_standards = PU_GET_VIDEO_STANDARDS(processing);
920 pu->pu_max_multiplier = UGETW(processing->wMaxMultiplier);
922 uvideo_unit_alloc_sources(vu, 1, &processing->bSourceID);
923 uvideo_unit_alloc_controls(vu, processing->bControlSize,
924 processing->bmControls);
925 break;
926 case UDESC_EXTENSION_UNIT:
927 extension = (const uvideo_extension_unit_descriptor_t *)desc;
928 xu = &vu->u.vu_extension;
929 /* TODO: copy guid */
931 uvideo_unit_alloc_sources(vu, extension->bNrInPins,
932 extension->baSourceID);
933 uvideo_unit_alloc_controls(vu, XU_GET_CONTROL_SIZE(extension),
934 XU_GET_CONTROLS(extension));
935 break;
936 default:
937 DPRINTF(("uvideo_unit_alloc: unknown descriptor "
938 "type=0x%02x subtype=0x%02x\n",
939 desc->bDescriptorType, desc->bDescriptorSubtype));
940 return USBD_INVAL;
943 return USBD_NORMAL_COMPLETION;
946 static void
947 uvideo_unit_free(struct uvideo_unit *vu)
949 uvideo_unit_free_sources(vu);
950 uvideo_unit_free_controls(vu);
951 kmem_free(vu, sizeof(*vu));
954 static usbd_status
955 uvideo_unit_alloc_sources(struct uvideo_unit *vu,
956 uint8_t nsrcs, const uint8_t *src_ids)
958 vu->vu_nsrcs = nsrcs;
960 if (nsrcs == 0) {
961 /* do nothing */
962 } else if (nsrcs == 1) {
963 vu->s.vu_src_id = src_ids[0];
964 } else {
965 vu->s.vu_src_id_ary =
966 kmem_alloc(sizeof(*vu->s.vu_src_id_ary) * nsrcs, KM_SLEEP);
967 if (vu->s.vu_src_id_ary == NULL) {
968 vu->vu_nsrcs = 0;
969 return USBD_NOMEM;
972 memcpy(vu->s.vu_src_id_ary, src_ids, nsrcs);
975 return USBD_NORMAL_COMPLETION;
978 static void
979 uvideo_unit_free_sources(struct uvideo_unit *vu)
981 if (vu->vu_nsrcs == 1)
982 return;
984 kmem_free(vu->s.vu_src_id_ary,
985 sizeof(*vu->s.vu_src_id_ary) * vu->vu_nsrcs);
986 vu->vu_nsrcs = 0;
987 vu->s.vu_src_id_ary = NULL;
990 static usbd_status
991 uvideo_unit_alloc_controls(struct uvideo_unit *vu, uint8_t size,
992 const uint8_t *controls)
994 vu->vu_controls = kmem_alloc(sizeof(*vu->vu_controls) * size, KM_SLEEP);
995 if (vu->vu_controls == NULL)
996 return USBD_NOMEM;
998 vu->vu_control_size = size;
999 memcpy(vu->vu_controls, controls, size);
1001 return USBD_NORMAL_COMPLETION;
1004 static void
1005 uvideo_unit_free_controls(struct uvideo_unit *vu)
1007 kmem_free(vu->vu_controls,
1008 sizeof(*vu->vu_controls) * vu->vu_control_size);
1009 vu->vu_controls = NULL;
1010 vu->vu_control_size = 0;
1014 /* Initialize a stream from a Video Streaming interface
1015 * descriptor. Adds the stream to the stream_list in uvideo_softc.
1016 * This should be called once for new streams, and
1017 * uvideo_stream_init_desc() should then be called for this and each
1018 * additional interface with the same interface number. */
1019 static usbd_status
1020 uvideo_stream_init(struct uvideo_stream *vs,
1021 struct uvideo_softc *sc,
1022 const usb_interface_descriptor_t *ifdesc,
1023 uint8_t idx)
1025 uWord len;
1026 usbd_status err;
1028 SLIST_INSERT_HEAD(&sc->sc_stream_list, vs, entries);
1029 memset(vs, 0, sizeof(*vs));
1030 vs->vs_parent = sc;
1031 vs->vs_ifaceno = ifdesc->bInterfaceNumber;
1032 vs->vs_subtype = 0;
1033 SIMPLEQ_INIT(&vs->vs_formats);
1034 SIMPLEQ_INIT(&vs->vs_pixel_formats);
1035 vs->vs_default_format = NULL;
1036 vs->vs_current_format.priv = -1;
1037 vs->vs_xfer_type = 0;
1039 err = usbd_device2interface_handle(sc->sc_udev, idx, &vs->vs_iface);
1040 if (err != USBD_NORMAL_COMPLETION) {
1041 DPRINTF(("uvideo_stream_init: "
1042 "error getting vs interface: "
1043 "%s (%d)\n",
1044 usbd_errstr(err), err));
1045 return err;
1048 /* For Xbox Live Vision camera, linux-uvc folk say we need to
1049 * set an alternate interface and wait ~3 seconds prior to
1050 * doing the format probe/commit. We set to alternate
1051 * interface 0, which is the default, zero bandwidth
1052 * interface. This should not have adverse affects on other
1053 * cameras. Errors are ignored. */
1054 err = usbd_set_interface(vs->vs_iface, 0);
1055 if (err != USBD_NORMAL_COMPLETION) {
1056 DPRINTF(("uvideo_stream_init: error setting alt interface: "
1057 "%s (%d)\n",
1058 usbd_errstr(err), err));
1061 /* Initialize probe and commit data size. This value is
1062 * dependent on the version of the spec the hardware
1063 * implements. */
1064 err = uvideo_stream_probe(vs, UR_GET_LEN, &len);
1065 if (err != USBD_NORMAL_COMPLETION) {
1066 DPRINTF(("uvideo_stream_init: "
1067 "error getting probe data len: "
1068 "%s (%d)\n",
1069 usbd_errstr(err), err));
1070 vs->vs_probelen = 26; /* conservative v1.0 length */
1071 } else if (UGETW(len) <= sizeof(uvideo_probe_and_commit_data_t)) {
1072 DPRINTFN(15,("uvideo_stream_init: probelen=%d\n", UGETW(len)));
1073 vs->vs_probelen = UGETW(len);
1074 } else {
1075 DPRINTFN(15,("uvideo_stream_init: device returned invalid probe"
1076 " len %d, using default\n", UGETW(len)));
1077 vs->vs_probelen = 26;
1080 return USBD_NORMAL_COMPLETION;
1083 /* Further stream initialization based on a Video Streaming interface
1084 * descriptor and following descriptors belonging to that interface.
1085 * Iterates through all descriptors belonging to this particular
1086 * interface descriptor, modifying the iterator. This may be called
1087 * multiple times because there may be several alternate interfaces
1088 * associated with the same interface number. */
1089 static usbd_status
1090 uvideo_stream_init_desc(struct uvideo_stream *vs,
1091 const usb_interface_descriptor_t *ifdesc,
1092 usbd_desc_iter_t *iter)
1094 const usb_descriptor_t *desc;
1095 const uvideo_descriptor_t *uvdesc;
1096 struct uvideo_bulk_xfer *bx;
1097 struct uvideo_isoc_xfer *ix;
1098 struct uvideo_alternate *alt;
1099 uint8_t xfer_type, xfer_dir;
1100 uint8_t bmAttributes, bEndpointAddress;
1101 int i;
1103 /* Iterate until the next interface descriptor. All
1104 * descriptors until then belong to this streaming
1105 * interface. */
1106 while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) {
1107 uvdesc = (const uvideo_descriptor_t *)desc;
1109 switch (uvdesc->bDescriptorType) {
1110 case UDESC_ENDPOINT:
1111 bmAttributes = GET(usb_endpoint_descriptor_t,
1112 desc, bmAttributes);
1113 bEndpointAddress = GET(usb_endpoint_descriptor_t,
1114 desc, bEndpointAddress);
1115 xfer_type = UE_GET_XFERTYPE(bmAttributes);
1116 xfer_dir = UE_GET_DIR(bEndpointAddress);
1117 if (xfer_type == UE_BULK && xfer_dir == UE_DIR_IN) {
1118 bx = &vs->vs_xfer.bulk;
1119 if (vs->vs_xfer_type == 0) {
1120 DPRINTFN(15, ("uvideo_attach: "
1121 "BULK stream *\n"));
1122 vs->vs_xfer_type = UE_BULK;
1123 bx->bx_endpt = bEndpointAddress;
1124 DPRINTF(("uvideo_attach: BULK "
1125 "endpoint %x\n",
1126 bx->bx_endpt));
1127 bx->bx_running = false;
1128 cv_init(&bx->bx_cv,
1129 device_xname(vs->vs_parent->sc_dev)
1131 mutex_init(&bx->bx_lock,
1132 MUTEX_DEFAULT, IPL_NONE);
1134 } else if (xfer_type == UE_ISOCHRONOUS) {
1135 ix = &vs->vs_xfer.isoc;
1136 for (i = 0; i < UVIDEO_NXFERS; i++) {
1137 ix->ix_i[i].i_ix = ix;
1138 ix->ix_i[i].i_vs = vs;
1140 if (vs->vs_xfer_type == 0) {
1141 DPRINTFN(15, ("uvideo_attach: "
1142 "ISOC stream *\n"));
1143 SLIST_INIT(&ix->ix_altlist);
1144 vs->vs_xfer_type = UE_ISOCHRONOUS;
1145 ix->ix_endpt =
1146 GET(usb_endpoint_descriptor_t,
1147 desc, bEndpointAddress);
1150 alt = kmem_alloc(sizeof(*alt), KM_NOSLEEP);
1151 if (alt == NULL)
1152 return USBD_NOMEM;
1154 alt->altno = ifdesc->bAlternateSetting;
1155 alt->interval =
1156 GET(usb_endpoint_descriptor_t,
1157 desc, bInterval);
1159 alt->max_packet_size =
1160 UE_GET_SIZE(UGETW(GET(usb_endpoint_descriptor_t,
1161 desc, wMaxPacketSize)));
1162 alt->max_packet_size *=
1163 (UE_GET_TRANS(UGETW(GET(
1164 usb_endpoint_descriptor_t, desc,
1165 wMaxPacketSize)))) + 1;
1167 SLIST_INSERT_HEAD(&ix->ix_altlist,
1168 alt, entries);
1170 break;
1171 case UDESC_CS_INTERFACE:
1172 if (ifdesc->bAlternateSetting != 0) {
1173 DPRINTF(("uvideo_stream_init_alternate: "
1174 "unexpected class-specific descriptor "
1175 "len=%d type=0x%02x subtype=0x%02x\n",
1176 uvdesc->bLength,
1177 uvdesc->bDescriptorType,
1178 uvdesc->bDescriptorSubtype));
1179 break;
1182 switch (uvdesc->bDescriptorSubtype) {
1183 case UDESC_VS_INPUT_HEADER:
1184 vs->vs_subtype = UDESC_VS_INPUT_HEADER;
1185 break;
1186 case UDESC_VS_OUTPUT_HEADER:
1187 /* TODO: handle output stream */
1188 DPRINTF(("uvideo: VS output not implemented\n"));
1189 vs->vs_subtype = UDESC_VS_OUTPUT_HEADER;
1190 return USBD_INVAL;
1191 case UDESC_VS_FORMAT_UNCOMPRESSED:
1192 case UDESC_VS_FORMAT_FRAME_BASED:
1193 case UDESC_VS_FORMAT_MJPEG:
1194 uvideo_stream_init_frame_based_format(vs,
1195 uvdesc,
1196 iter);
1197 break;
1198 case UDESC_VS_FORMAT_MPEG2TS:
1199 case UDESC_VS_FORMAT_DV:
1200 case UDESC_VS_FORMAT_STREAM_BASED:
1201 default:
1202 DPRINTF(("uvideo: unimplemented VS CS "
1203 "descriptor len=%d type=0x%02x "
1204 "subtype=0x%02x\n",
1205 uvdesc->bLength,
1206 uvdesc->bDescriptorType,
1207 uvdesc->bDescriptorSubtype));
1208 break;
1210 break;
1211 default:
1212 DPRINTF(("uvideo_stream_init_desc: "
1213 "unknown descriptor "
1214 "len=%d type=0x%02x\n",
1215 uvdesc->bLength,
1216 uvdesc->bDescriptorType));
1217 break;
1221 return USBD_NORMAL_COMPLETION;
1224 /* Finialize and free memory associated with this stream. */
1225 static void
1226 uvideo_stream_free(struct uvideo_stream *vs)
1228 struct uvideo_alternate *alt;
1229 struct uvideo_pixel_format *pixel_format;
1230 struct uvideo_format *format;
1232 /* free linked list of alternate interfaces */
1233 if (vs->vs_xfer_type == UE_ISOCHRONOUS) {
1234 while (!SLIST_EMPTY(&vs->vs_xfer.isoc.ix_altlist)) {
1235 alt = SLIST_FIRST(&vs->vs_xfer.isoc.ix_altlist);
1236 SLIST_REMOVE_HEAD(&vs->vs_xfer.isoc.ix_altlist,
1237 entries);
1238 kmem_free(alt, sizeof(*alt));
1242 /* free linked-list of formats and pixel formats */
1243 while ((format = SIMPLEQ_FIRST(&vs->vs_formats)) != NULL) {
1244 SIMPLEQ_REMOVE_HEAD(&vs->vs_formats, entries);
1245 kmem_free(format, sizeof(struct uvideo_format));
1247 while ((pixel_format = SIMPLEQ_FIRST(&vs->vs_pixel_formats)) != NULL) {
1248 SIMPLEQ_REMOVE_HEAD(&vs->vs_pixel_formats, entries);
1249 kmem_free(pixel_format, sizeof(struct uvideo_pixel_format));
1252 kmem_free(vs, sizeof(*vs));
1256 static usbd_status
1257 uvideo_stream_init_frame_based_format(struct uvideo_stream *vs,
1258 const uvideo_descriptor_t *format_desc,
1259 usbd_desc_iter_t *iter)
1261 struct uvideo_pixel_format *pformat, *pfiter;
1262 enum video_pixel_format pixel_format;
1263 struct uvideo_format *format;
1264 const uvideo_descriptor_t *uvdesc;
1265 uint8_t subtype, default_index, index;
1266 uint32_t frame_interval;
1267 const usb_guid_t *guid;
1269 pixel_format = VIDEO_FORMAT_UNDEFINED;
1271 switch (format_desc->bDescriptorSubtype) {
1272 case UDESC_VS_FORMAT_UNCOMPRESSED:
1273 subtype = UDESC_VS_FRAME_UNCOMPRESSED;
1274 default_index = GET(uvideo_vs_format_uncompressed_descriptor_t,
1275 format_desc,
1276 bDefaultFrameIndex);
1277 guid = GETP(uvideo_vs_format_uncompressed_descriptor_t,
1278 format_desc,
1279 guidFormat);
1280 if (usb_guid_cmp(guid, &uvideo_guid_format_yuy2) == 0)
1281 pixel_format = VIDEO_FORMAT_YUY2;
1282 else if (usb_guid_cmp(guid, &uvideo_guid_format_nv12) == 0)
1283 pixel_format = VIDEO_FORMAT_NV12;
1284 else if (usb_guid_cmp(guid, &uvideo_guid_format_uyvy) == 0)
1285 pixel_format = VIDEO_FORMAT_UYVY;
1286 break;
1287 case UDESC_VS_FORMAT_FRAME_BASED:
1288 subtype = UDESC_VS_FRAME_FRAME_BASED;
1289 default_index = GET(uvideo_format_frame_based_descriptor_t,
1290 format_desc,
1291 bDefaultFrameIndex);
1292 break;
1293 case UDESC_VS_FORMAT_MJPEG:
1294 subtype = UDESC_VS_FRAME_MJPEG;
1295 default_index = GET(uvideo_vs_format_mjpeg_descriptor_t,
1296 format_desc,
1297 bDefaultFrameIndex);
1298 pixel_format = VIDEO_FORMAT_MJPEG;
1299 break;
1300 default:
1301 DPRINTF(("uvideo: unknown frame based format %d\n",
1302 format_desc->bDescriptorSubtype));
1303 return USBD_INVAL;
1306 pformat = NULL;
1307 SIMPLEQ_FOREACH(pfiter, &vs->vs_pixel_formats, entries) {
1308 if (pfiter->pixel_format == pixel_format) {
1309 pformat = pfiter;
1310 break;
1313 if (pixel_format != VIDEO_FORMAT_UNDEFINED && pformat == NULL) {
1314 pformat = kmem_zalloc(sizeof(*pformat), KM_SLEEP);
1315 pformat->pixel_format = pixel_format;
1316 DPRINTF(("uvideo: Adding pixel format %d\n",
1317 pixel_format));
1318 SIMPLEQ_INSERT_TAIL(&vs->vs_pixel_formats,
1319 pformat, entries);
1322 /* Iterate through frame descriptors directly following the
1323 * format descriptor, and add a format to the format list for
1324 * each frame descriptor. */
1325 while ((uvdesc = (const uvideo_descriptor_t *) usb_desc_iter_peek_next(iter)) &&
1326 (uvdesc != NULL) && (uvdesc->bDescriptorSubtype == subtype))
1328 uvdesc = (const uvideo_descriptor_t *) usb_desc_iter_next(iter);
1330 format = kmem_zalloc(sizeof(struct uvideo_format), KM_SLEEP);
1331 if (format == NULL) {
1332 DPRINTF(("uvideo: failed to alloc video format\n"));
1333 return USBD_NOMEM;
1336 format->format.pixel_format = pixel_format;
1338 switch (format_desc->bDescriptorSubtype) {
1339 case UDESC_VS_FORMAT_UNCOMPRESSED:
1340 #ifdef UVIDEO_DEBUG
1341 if (pixel_format == VIDEO_FORMAT_UNDEFINED &&
1342 uvideodebug) {
1343 guid = GETP(
1344 uvideo_vs_format_uncompressed_descriptor_t,
1345 format_desc,
1346 guidFormat);
1348 DPRINTF(("uvideo: format undefined "));
1349 usb_guid_print(guid);
1350 DPRINTF(("\n"));
1352 #endif
1354 UVIDEO_FORMAT_INIT_FRAME_BASED(
1355 uvideo_vs_format_uncompressed_descriptor_t,
1356 format_desc,
1357 uvideo_vs_frame_uncompressed_descriptor_t,
1358 uvdesc,
1359 format);
1360 format->format.sample_size =
1361 UGETDW(
1362 GET(uvideo_vs_frame_uncompressed_descriptor_t,
1363 uvdesc, dwMaxVideoFrameBufferSize));
1364 format->format.stride =
1365 format->format.sample_size / format->format.height;
1366 index = GET(uvideo_vs_frame_uncompressed_descriptor_t,
1367 uvdesc,
1368 bFrameIndex);
1369 frame_interval =
1370 UGETDW(
1371 GET(uvideo_vs_frame_uncompressed_descriptor_t,
1372 uvdesc,
1373 dwDefaultFrameInterval));
1374 break;
1375 case UDESC_VS_FORMAT_MJPEG:
1376 UVIDEO_FORMAT_INIT_FRAME_BASED(
1377 uvideo_vs_format_mjpeg_descriptor_t,
1378 format_desc,
1379 uvideo_vs_frame_mjpeg_descriptor_t,
1380 uvdesc,
1381 format);
1382 format->format.sample_size =
1383 UGETDW(
1384 GET(uvideo_vs_frame_mjpeg_descriptor_t,
1385 uvdesc, dwMaxVideoFrameBufferSize));
1386 format->format.stride =
1387 format->format.sample_size / format->format.height;
1388 index = GET(uvideo_vs_frame_mjpeg_descriptor_t,
1389 uvdesc,
1390 bFrameIndex);
1391 frame_interval =
1392 UGETDW(
1393 GET(uvideo_vs_frame_mjpeg_descriptor_t,
1394 uvdesc,
1395 dwDefaultFrameInterval));
1396 break;
1397 case UDESC_VS_FORMAT_FRAME_BASED:
1398 format->format.pixel_format = VIDEO_FORMAT_UNDEFINED;
1399 UVIDEO_FORMAT_INIT_FRAME_BASED(
1400 uvideo_format_frame_based_descriptor_t,
1401 format_desc,
1402 uvideo_frame_frame_based_descriptor_t,
1403 uvdesc,
1404 format);
1405 index = GET(uvideo_frame_frame_based_descriptor_t,
1406 uvdesc,
1407 bFrameIndex);
1408 format->format.stride =
1409 UGETDW(
1410 GET(uvideo_frame_frame_based_descriptor_t,
1411 uvdesc, dwBytesPerLine));
1412 format->format.sample_size =
1413 format->format.stride * format->format.height;
1414 frame_interval =
1415 UGETDW(
1416 GET(uvideo_frame_frame_based_descriptor_t,
1417 uvdesc, dwDefaultFrameInterval));
1418 break;
1419 default:
1420 /* shouldn't ever get here */
1421 DPRINTF(("uvideo: unknown frame based format %d\n",
1422 format_desc->bDescriptorSubtype));
1423 kmem_free(format, sizeof(struct uvideo_format));
1424 return USBD_INVAL;
1427 DPRINTF(("uvideo: found format (index %d) type %d "
1428 "size %ux%u size %u stride %u interval %u\n",
1429 index, format->format.pixel_format, format->format.width,
1430 format->format.height, format->format.sample_size,
1431 format->format.stride, frame_interval));
1433 SIMPLEQ_INSERT_TAIL(&vs->vs_formats, format, entries);
1435 if (vs->vs_default_format == NULL && index == default_index
1436 #ifdef UVIDEO_DISABLE_MJPEG
1437 && subtype != UDESC_VS_FRAME_MJPEG
1438 #endif
1440 DPRINTF((" ^ picking this one\n"));
1441 vs->vs_default_format = &format->format;
1442 vs->vs_frame_interval = frame_interval;
1447 return USBD_NORMAL_COMPLETION;
1450 static int
1451 uvideo_stream_start_xfer(struct uvideo_stream *vs)
1453 struct uvideo_softc *sc = vs->vs_parent;
1454 struct uvideo_bulk_xfer *bx;
1455 struct uvideo_isoc_xfer *ix;
1456 uint32_t vframe_len; /* rough bytes per video frame */
1457 uint32_t uframe_len; /* bytes per usb frame (TODO: or microframe?) */
1458 uint32_t nframes; /* number of usb frames (TODO: or microframs?) */
1459 int i, ret;
1461 struct uvideo_alternate *alt, *alt_maybe;
1462 usbd_status err;
1464 switch (vs->vs_xfer_type) {
1465 case UE_BULK:
1466 ret = 0;
1467 bx = &vs->vs_xfer.bulk;
1469 bx->bx_xfer = usbd_alloc_xfer(sc->sc_udev);
1470 if (bx->bx_xfer == NULL) {
1471 DPRINTF(("uvideo: couldn't allocate xfer\n"));
1472 return ENOMEM;
1474 DPRINTF(("uvideo: xfer %p\n", bx->bx_xfer));
1476 bx->bx_buflen = vs->vs_max_payload_size;
1478 DPRINTF(("uvideo: allocating %u byte buffer\n", bx->bx_buflen));
1479 bx->bx_buffer = usbd_alloc_buffer(bx->bx_xfer, bx->bx_buflen);
1481 if (bx->bx_buffer == NULL) {
1482 DPRINTF(("uvideo: couldn't allocate buffer\n"));
1483 return ENOMEM;
1486 err = usbd_open_pipe(vs->vs_iface, bx->bx_endpt, 0,
1487 &bx->bx_pipe);
1488 if (err != USBD_NORMAL_COMPLETION) {
1489 DPRINTF(("uvideo: error opening pipe: %s (%d)\n",
1490 usbd_errstr(err), err));
1491 return EIO;
1493 DPRINTF(("uvideo: pipe %p\n", bx->bx_pipe));
1495 mutex_enter(&bx->bx_lock);
1496 if (bx->bx_running == false) {
1497 bx->bx_running = true;
1498 ret = kthread_create(PRI_UVIDEO, 0, NULL,
1499 uvideo_stream_recv_bulk_transfer, vs,
1500 NULL, device_xname(sc->sc_dev));
1501 if (ret) {
1502 DPRINTF(("uvideo: couldn't create kthread:"
1503 " %d\n", err));
1504 bx->bx_running = false;
1505 mutex_exit(&bx->bx_lock);
1506 return err;
1508 } else
1509 aprint_error_dev(sc->sc_dev,
1510 "transfer already in progress\n");
1511 mutex_exit(&bx->bx_lock);
1513 DPRINTF(("uvideo: thread created\n"));
1515 return 0;
1516 case UE_ISOCHRONOUS:
1517 ix = &vs->vs_xfer.isoc;
1519 /* Choose an alternate interface most suitable for
1520 * this format. Choose the smallest size that can
1521 * contain max_payload_size.
1523 * It is assumed that the list is sorted in descending
1524 * order from largest to smallest packet size.
1526 * TODO: what should the strategy be for choosing an
1527 * alt interface?
1529 alt = NULL;
1530 SLIST_FOREACH(alt_maybe, &ix->ix_altlist, entries) {
1531 /* TODO: define "packet" and "payload". I think
1532 * several packets can make up one payload which would
1533 * call into question this method of selecting an
1534 * alternate interface... */
1536 if (alt_maybe->max_packet_size > vs->vs_max_payload_size)
1537 continue;
1539 if (alt == NULL ||
1540 alt_maybe->max_packet_size >= alt->max_packet_size)
1541 alt = alt_maybe;
1544 if (alt == NULL) {
1545 DPRINTF(("uvideo_stream_start_xfer: "
1546 "no suitable alternate interface found\n"));
1547 return EINVAL;
1550 DPRINTFN(15,("uvideo_stream_start_xfer: "
1551 "choosing alternate interface "
1552 "%d wMaxPacketSize=%d bInterval=%d\n",
1553 alt->altno, alt->max_packet_size, alt->interval));
1555 err = usbd_set_interface(vs->vs_iface, alt->altno);
1556 if (err != USBD_NORMAL_COMPLETION) {
1557 DPRINTF(("uvideo_stream_start_xfer: "
1558 "error setting alt interface: %s (%d)\n",
1559 usbd_errstr(err), err));
1560 return EIO;
1563 /* TODO: "packet" not same as frame */
1564 vframe_len = vs->vs_current_format.sample_size;
1565 uframe_len = alt->max_packet_size;
1566 nframes = (vframe_len + uframe_len - 1) / uframe_len;
1567 nframes = (nframes + 7) & ~7; /*round up for ehci inefficiency*/
1568 DPRINTF(("uvideo_stream_start_xfer: nframes=%d\n", nframes));
1570 ix->ix_nframes = nframes;
1571 ix->ix_uframe_len = uframe_len;
1572 for (i = 0; i < UVIDEO_NXFERS; i++) {
1573 struct uvideo_isoc *isoc = &ix->ix_i[i];
1574 isoc->i_frlengths =
1575 kmem_alloc(sizeof(isoc->i_frlengths[0]) * nframes,
1576 KM_SLEEP);
1577 if (isoc->i_frlengths == NULL) {
1578 DPRINTF(("uvideo: failed to alloc frlengths:"
1579 "%s (%d)\n",
1580 usbd_errstr(err), err));
1581 return ENOMEM;
1585 err = usbd_open_pipe(vs->vs_iface, ix->ix_endpt,
1586 USBD_EXCLUSIVE_USE, &ix->ix_pipe);
1587 if (err != USBD_NORMAL_COMPLETION) {
1588 DPRINTF(("uvideo: error opening pipe: %s (%d)\n",
1589 usbd_errstr(err), err));
1590 return EIO;
1593 for (i = 0; i < UVIDEO_NXFERS; i++) {
1594 struct uvideo_isoc *isoc = &ix->ix_i[i];
1595 isoc->i_xfer = usbd_alloc_xfer(sc->sc_udev);
1596 if (isoc->i_xfer == NULL) {
1597 DPRINTF(("uvideo: failed to alloc xfer: %s"
1598 " (%d)\n",
1599 usbd_errstr(err), err));
1600 return ENOMEM;
1603 isoc->i_buf = usbd_alloc_buffer(isoc->i_xfer,
1604 nframes * uframe_len);
1606 if (isoc->i_buf == NULL) {
1607 DPRINTF(("uvideo: failed to alloc buf: %s"
1608 " (%d)\n",
1609 usbd_errstr(err), err));
1610 return ENOMEM;
1614 uvideo_stream_recv_isoc_start(vs);
1616 return 0;
1617 default:
1618 /* should never get here */
1619 DPRINTF(("uvideo_stream_start_xfer: unknown xfer type 0x%x\n",
1620 vs->vs_xfer_type));
1621 return EINVAL;
1625 static int
1626 uvideo_stream_stop_xfer(struct uvideo_stream *vs)
1628 struct uvideo_bulk_xfer *bx;
1629 struct uvideo_isoc_xfer *ix;
1630 usbd_status err;
1631 int i;
1633 switch (vs->vs_xfer_type) {
1634 case UE_BULK:
1635 bx = &vs->vs_xfer.bulk;
1637 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: "
1638 "waiting for thread to complete\n"));
1639 mutex_enter(&bx->bx_lock);
1640 if (bx->bx_running == true) {
1641 bx->bx_running = false;
1642 cv_wait_sig(&bx->bx_cv, &bx->bx_lock);
1644 mutex_exit(&bx->bx_lock);
1646 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: cleaning up\n"));
1648 if (bx->bx_pipe) {
1649 usbd_abort_pipe(bx->bx_pipe);
1650 usbd_close_pipe(bx->bx_pipe);
1651 bx->bx_pipe = NULL;
1654 if (bx->bx_xfer) {
1655 usbd_free_xfer(bx->bx_xfer);
1656 bx->bx_xfer = NULL;
1659 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: done\n"));
1661 return 0;
1662 case UE_ISOCHRONOUS:
1663 ix = &vs->vs_xfer.isoc;
1664 if (ix->ix_pipe != NULL) {
1665 usbd_abort_pipe(ix->ix_pipe);
1666 usbd_close_pipe(ix->ix_pipe);
1667 ix->ix_pipe = NULL;
1670 for (i = 0; i < UVIDEO_NXFERS; i++) {
1671 struct uvideo_isoc *isoc = &ix->ix_i[i];
1672 if (isoc->i_xfer != NULL) {
1673 usbd_free_buffer(isoc->i_xfer);
1674 usbd_free_xfer(isoc->i_xfer);
1675 isoc->i_xfer = NULL;
1678 if (isoc->i_frlengths != NULL) {
1679 kmem_free(isoc->i_frlengths,
1680 sizeof(isoc->i_frlengths[0]) *
1681 ix->ix_nframes);
1682 isoc->i_frlengths = NULL;
1686 /* Give it some time to settle */
1687 usbd_delay_ms(vs->vs_parent->sc_udev, 1000);
1689 /* Set to zero bandwidth alternate interface zero */
1690 err = usbd_set_interface(vs->vs_iface, 0);
1691 if (err != USBD_NORMAL_COMPLETION) {
1692 DPRINTF(("uvideo_stream_stop_transfer: "
1693 "error setting zero bandwidth interface: "
1694 "%s (%d)\n",
1695 usbd_errstr(err), err));
1696 return EIO;
1699 return 0;
1700 default:
1701 /* should never get here */
1702 DPRINTF(("uvideo_stream_stop_xfer: unknown xfer type 0x%x\n",
1703 vs->vs_xfer_type));
1704 return EINVAL;
1708 static usbd_status
1709 uvideo_stream_recv_isoc_start(struct uvideo_stream *vs)
1711 int i;
1713 for (i = 0; i < UVIDEO_NXFERS; i++)
1714 uvideo_stream_recv_isoc_start1(&vs->vs_xfer.isoc.ix_i[i]);
1716 return USBD_NORMAL_COMPLETION;
1719 /* Initiate a usb transfer. */
1720 static usbd_status
1721 uvideo_stream_recv_isoc_start1(struct uvideo_isoc *isoc)
1723 struct uvideo_isoc_xfer *ix;
1724 usbd_status err;
1725 int i;
1727 ix = isoc->i_ix;
1729 for (i = 0; i < ix->ix_nframes; ++i)
1730 isoc->i_frlengths[i] = ix->ix_uframe_len;
1732 usbd_setup_isoc_xfer(isoc->i_xfer,
1733 ix->ix_pipe,
1734 isoc,
1735 isoc->i_frlengths,
1736 ix->ix_nframes,
1737 USBD_NO_COPY | USBD_SHORT_XFER_OK,
1738 uvideo_stream_recv_isoc_complete);
1740 err = usbd_transfer(isoc->i_xfer);
1741 if (err != USBD_IN_PROGRESS) {
1742 DPRINTF(("uvideo_stream_recv_start: "
1743 "usbd_transfer status=%s (%d)\n",
1744 usbd_errstr(err), err));
1746 return err;
1749 static usbd_status
1750 uvideo_stream_recv_process(struct uvideo_stream *vs, uint8_t *buf, uint32_t len)
1752 uvideo_payload_header_t *hdr;
1753 struct video_payload payload;
1755 if (len < sizeof(uvideo_payload_header_t)) {
1756 DPRINTF(("uvideo_stream_recv_process: len %d < payload hdr\n",
1757 len));
1758 return USBD_SHORT_XFER;
1761 hdr = (uvideo_payload_header_t *)buf;
1763 if (hdr->bHeaderLength > UVIDEO_PAYLOAD_HEADER_SIZE ||
1764 hdr->bHeaderLength < sizeof(uvideo_payload_header_t))
1765 return USBD_INVAL;
1766 if (hdr->bHeaderLength == len && !(hdr->bmHeaderInfo & UV_END_OF_FRAME))
1767 return USBD_INVAL;
1768 if (hdr->bmHeaderInfo & UV_ERROR)
1769 return USBD_IOERROR;
1771 payload.data = buf + hdr->bHeaderLength;
1772 payload.size = len - hdr->bHeaderLength;
1773 payload.frameno = hdr->bmHeaderInfo & UV_FRAME_ID;
1774 payload.end_of_frame = hdr->bmHeaderInfo & UV_END_OF_FRAME;
1776 video_submit_payload(vs->vs_parent->sc_videodev, &payload);
1778 return USBD_NORMAL_COMPLETION;
1781 /* Callback on completion of usb isoc transfer */
1782 static void
1783 uvideo_stream_recv_isoc_complete(usbd_xfer_handle xfer,
1784 usbd_private_handle priv,
1785 usbd_status status)
1787 struct uvideo_stream *vs;
1788 struct uvideo_isoc_xfer *ix;
1789 struct uvideo_isoc *isoc;
1790 int i;
1791 uint32_t count;
1792 const uvideo_payload_header_t *hdr;
1793 uint8_t *buf;
1795 isoc = priv;
1796 vs = isoc->i_vs;
1797 ix = isoc->i_ix;
1799 if (status != USBD_NORMAL_COMPLETION) {
1800 DPRINTF(("uvideo_stream_recv_isoc_complete: status=%s (%d)\n",
1801 usbd_errstr(status), status));
1803 if (status == USBD_STALLED)
1804 usbd_clear_endpoint_stall_async(ix->ix_pipe);
1805 else
1806 return;
1807 } else {
1808 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1810 if (count == 0) {
1811 /* DPRINTF(("uvideo: zero length transfer\n")); */
1812 goto next;
1815 hdr = (const uvideo_payload_header_t *)isoc->i_buf;
1817 for (i = 0, buf = isoc->i_buf;
1818 i < ix->ix_nframes;
1819 ++i, buf += ix->ix_uframe_len)
1821 status = uvideo_stream_recv_process(vs, buf,
1822 isoc->i_frlengths[i]);
1823 if (status == USBD_IOERROR)
1824 break;
1828 next:
1829 uvideo_stream_recv_isoc_start1(isoc);
1832 static void
1833 uvideo_stream_recv_bulk_transfer(void *addr)
1835 struct uvideo_stream *vs = addr;
1836 struct uvideo_bulk_xfer *bx = &vs->vs_xfer.bulk;
1837 usbd_status err;
1838 uint32_t len;
1840 DPRINTF(("uvideo_stream_recv_bulk_transfer: "
1841 "vs %p sc %p bx %p buffer %p\n", vs, vs->vs_parent, bx,
1842 bx->bx_buffer));
1844 while (bx->bx_running) {
1845 len = bx->bx_buflen;
1846 err = usbd_bulk_transfer(bx->bx_xfer, bx->bx_pipe,
1847 USBD_SHORT_XFER_OK | USBD_NO_COPY,
1848 USBD_NO_TIMEOUT,
1849 bx->bx_buffer, &len, "uvideorb");
1851 if (err == USBD_NORMAL_COMPLETION) {
1852 uvideo_stream_recv_process(vs, bx->bx_buffer, len);
1853 } else {
1854 DPRINTF(("uvideo_stream_recv_bulk_transfer: %s\n",
1855 usbd_errstr(err)));
1859 DPRINTF(("uvideo_stream_recv_bulk_transfer: notify complete\n"));
1861 mutex_enter(&bx->bx_lock);
1862 cv_broadcast(&bx->bx_cv);
1863 mutex_exit(&bx->bx_lock);
1865 DPRINTF(("uvideo_stream_recv_bulk_transfer: return\n"));
1867 kthread_exit(0);
1871 * uvideo_open - probe and commit video format and start receiving
1872 * video data
1874 static int
1875 uvideo_open(void *addr, int flags)
1877 struct uvideo_softc *sc;
1878 struct uvideo_stream *vs;
1879 struct video_format fmt;
1881 sc = addr;
1882 vs = sc->sc_stream_in;
1884 DPRINTF(("uvideo_open: sc=%p\n", sc));
1885 if (sc->sc_dying)
1886 return EIO;
1888 /* XXX select default format */
1889 fmt = *vs->vs_default_format;
1890 return uvideo_set_format(addr, &fmt);
1894 static void
1895 uvideo_close(void *addr)
1897 struct uvideo_softc *sc;
1899 sc = addr;
1901 if (sc->sc_state != UVIDEO_STATE_CLOSED) {
1902 sc->sc_state = UVIDEO_STATE_CLOSED;
1906 static const char *
1907 uvideo_get_devname(void *addr)
1909 struct uvideo_softc *sc = addr;
1910 return sc->sc_devname;
1913 static int
1914 uvideo_enum_format(void *addr, uint32_t index, struct video_format *format)
1916 struct uvideo_softc *sc = addr;
1917 struct uvideo_stream *vs = sc->sc_stream_in;
1918 struct uvideo_pixel_format *pixel_format;
1919 int off;
1921 if (sc->sc_dying)
1922 return EIO;
1924 off = 0;
1925 SIMPLEQ_FOREACH(pixel_format, &vs->vs_pixel_formats, entries) {
1926 if (off++ != index)
1927 continue;
1928 format->pixel_format = pixel_format->pixel_format;
1929 return 0;
1932 return EINVAL;
1936 * uvideo_get_format
1938 static int
1939 uvideo_get_format(void *addr, struct video_format *format)
1941 struct uvideo_softc *sc = addr;
1942 struct uvideo_stream *vs = sc->sc_stream_in;
1944 if (sc->sc_dying)
1945 return EIO;
1947 *format = vs->vs_current_format;
1949 return 0;
1953 * uvideo_set_format - TODO: this is boken and does nothing
1955 static int
1956 uvideo_set_format(void *addr, struct video_format *format)
1958 struct uvideo_softc *sc;
1959 struct uvideo_stream *vs;
1960 struct uvideo_format *uvfmt;
1961 uvideo_probe_and_commit_data_t probe, maxprobe;
1962 uint8_t ifaceno;
1963 usbd_status err;
1965 sc = addr;
1967 DPRINTF(("uvideo_set_format: sc=%p\n", sc));
1968 if (sc->sc_dying)
1969 return EIO;
1971 vs = sc->sc_stream_in;
1972 ifaceno = vs->vs_ifaceno;
1974 uvfmt = uvideo_stream_guess_format(vs, format->pixel_format,
1975 format->width, format->height);
1976 if (uvfmt == NULL) {
1977 DPRINTF(("uvideo: uvideo_stream_guess_format couldn't find "
1978 "%dx%d format %d\n", format->width, format->height,
1979 format->pixel_format));
1980 return EINVAL;
1983 uvideo_init_probe_data(&probe);
1984 probe.bFormatIndex = UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt);
1985 probe.bFrameIndex = UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt);
1986 USETDW(probe.dwFrameInterval, vs->vs_frame_interval); /* XXX */
1988 maxprobe = probe;
1989 err = uvideo_stream_probe(vs, UR_GET_MAX, &maxprobe);
1990 if (err) {
1991 DPRINTF(("uvideo: error probe/GET_MAX: %s (%d)\n",
1992 usbd_errstr(err), err));
1993 } else {
1994 USETW(probe.wCompQuality, UGETW(maxprobe.wCompQuality));
1997 err = uvideo_stream_probe(vs, UR_SET_CUR, &probe);
1998 if (err) {
1999 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n",
2000 usbd_errstr(err), err));
2001 return EIO;
2004 uvideo_init_probe_data(&probe);
2005 err = uvideo_stream_probe(vs, UR_GET_CUR, &probe);
2006 if (err) {
2007 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n",
2008 usbd_errstr(err), err));
2009 return EIO;
2012 if (probe.bFormatIndex != UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt)) {
2013 DPRINTF(("uvideo: probe/GET_CUR returned format index %d "
2014 "(expected %d)\n", probe.bFormatIndex,
2015 UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt)));
2016 probe.bFormatIndex = UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt);
2018 if (probe.bFrameIndex != UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt)) {
2019 DPRINTF(("uvideo: probe/GET_CUR returned frame index %d "
2020 "(expected %d)\n", probe.bFrameIndex,
2021 UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt)));
2022 probe.bFrameIndex = UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt);
2024 USETDW(probe.dwFrameInterval, vs->vs_frame_interval); /* XXX */
2026 /* commit/SET_CUR. Fourth step is to set the alternate
2027 * interface. Currently the fourth step is in
2028 * uvideo_start_transfer. Maybe move it here? */
2029 err = uvideo_stream_commit(vs, UR_SET_CUR, &probe);
2030 if (err) {
2031 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n",
2032 usbd_errstr(err), err));
2033 return EIO;
2036 DPRINTFN(15, ("uvideo_set_format: committing to format: "
2037 "bmHint=0x%04x bFormatIndex=%d bFrameIndex=%d "
2038 "dwFrameInterval=%u wKeyFrameRate=%d wPFrameRate=%d "
2039 "wCompQuality=%d wCompWindowSize=%d wDelay=%d "
2040 "dwMaxVideoFrameSize=%u dwMaxPayloadTransferSize=%u",
2041 UGETW(probe.bmHint),
2042 probe.bFormatIndex,
2043 probe.bFrameIndex,
2044 UGETDW(probe.dwFrameInterval),
2045 UGETW(probe.wKeyFrameRate),
2046 UGETW(probe.wPFrameRate),
2047 UGETW(probe.wCompQuality),
2048 UGETW(probe.wCompWindowSize),
2049 UGETW(probe.wDelay),
2050 UGETDW(probe.dwMaxVideoFrameSize),
2051 UGETDW(probe.dwMaxPayloadTransferSize)));
2052 if (vs->vs_probelen == 34) {
2053 DPRINTFN(15, (" dwClockFrequency=%u bmFramingInfo=0x%02x "
2054 "bPreferedVersion=%d bMinVersion=%d "
2055 "bMaxVersion=%d",
2056 UGETDW(probe.dwClockFrequency),
2057 probe.bmFramingInfo,
2058 probe.bPreferedVersion,
2059 probe.bMinVersion,
2060 probe.bMaxVersion));
2062 DPRINTFN(15, ("\n"));
2064 vs->vs_frame_interval = UGETDW(probe.dwFrameInterval);
2065 vs->vs_max_payload_size = UGETDW(probe.dwMaxPayloadTransferSize);
2067 *format = uvfmt->format;
2068 vs->vs_current_format = *format;
2069 DPRINTF(("uvideo_set_format: pixeltype is %d\n", format->pixel_format));
2071 return 0;
2074 static int
2075 uvideo_try_format(void *addr, struct video_format *format)
2077 struct uvideo_softc *sc = addr;
2078 struct uvideo_stream *vs = sc->sc_stream_in;
2079 struct uvideo_format *uvfmt;
2081 uvfmt = uvideo_stream_guess_format(vs, format->pixel_format,
2082 format->width, format->height);
2083 if (uvfmt == NULL)
2084 return EINVAL;
2086 *format = uvfmt->format;
2087 return 0;
2090 static int
2091 uvideo_start_transfer(void *addr)
2093 struct uvideo_softc *sc = addr;
2094 struct uvideo_stream *vs;
2095 int s, err;
2097 /* FIXME: this functions should be stream specific */
2098 vs = SLIST_FIRST(&sc->sc_stream_list);
2099 s = splusb();
2100 err = uvideo_stream_start_xfer(vs);
2101 splx(s);
2103 return err;
2106 static int
2107 uvideo_stop_transfer(void *addr)
2109 struct uvideo_softc *sc;
2110 int err, s;
2112 sc = addr;
2114 s = splusb();
2115 err = uvideo_stream_stop_xfer(sc->sc_stream_in);
2116 splx(s);
2118 return err;
2122 static int
2123 uvideo_get_control_group(void *addr, struct video_control_group *group)
2125 struct uvideo_softc *sc;
2126 usb_device_request_t req;
2127 usbd_status err;
2128 uint8_t control_id, ent_id, data[16];
2129 uint16_t len;
2130 int s;
2132 sc = addr;
2134 /* request setup */
2135 switch (group->group_id) {
2136 case VIDEO_CONTROL_PANTILT_RELATIVE:
2137 if (group->length != 4)
2138 return EINVAL;
2140 return EINVAL;
2141 case VIDEO_CONTROL_SHARPNESS:
2142 if (group->length != 1)
2143 return EINVAL;
2145 control_id = UVIDEO_PU_SHARPNESS_CONTROL;
2146 ent_id = 2; /* TODO: hardcoded logitech processing unit */
2147 len = 2;
2148 break;
2149 default:
2150 return EINVAL;
2153 /* do request */
2154 req.bmRequestType = UVIDEO_REQUEST_TYPE_INTERFACE |
2155 UVIDEO_REQUEST_TYPE_CLASS_SPECIFIC |
2156 UVIDEO_REQUEST_TYPE_GET;
2157 req.bRequest = UR_GET_CUR;
2158 USETW(req.wValue, control_id << 8);
2159 USETW(req.wIndex, (ent_id << 8) | sc->sc_ifaceno);
2160 USETW(req.wLength, len);
2162 s = splusb();
2163 err = usbd_do_request(sc->sc_udev, &req, data);
2164 splx(s);
2165 if (err != USBD_NORMAL_COMPLETION) {
2166 DPRINTF(("uvideo_set_control: error %s (%d)\n",
2167 usbd_errstr(err), err));
2168 return EIO; /* TODO: more detail here? */
2171 /* extract request data */
2172 switch (group->group_id) {
2173 case VIDEO_CONTROL_SHARPNESS:
2174 group->control[0].value = UGETW(data);
2175 break;
2176 default:
2177 return EINVAL;
2180 return 0;
2184 static int
2185 uvideo_set_control_group(void *addr, const struct video_control_group *group)
2187 struct uvideo_softc *sc;
2188 usb_device_request_t req;
2189 usbd_status err;
2190 uint8_t control_id, ent_id, data[16]; /* long enough for all controls */
2191 uint16_t len;
2192 int s;
2194 sc = addr;
2196 switch (group->group_id) {
2197 case VIDEO_CONTROL_PANTILT_RELATIVE:
2198 if (group->length != 4)
2199 return EINVAL;
2201 if (group->control[0].value != 0 ||
2202 group->control[0].value != 1 ||
2203 group->control[0].value != 0xff)
2204 return ERANGE;
2206 if (group->control[2].value != 0 ||
2207 group->control[2].value != 1 ||
2208 group->control[2].value != 0xff)
2209 return ERANGE;
2211 control_id = UVIDEO_CT_PANTILT_RELATIVE_CONTROL;
2212 ent_id = 1; /* TODO: hardcoded logitech camera terminal */
2213 len = 4;
2214 data[0] = group->control[0].value;
2215 data[1] = group->control[1].value;
2216 data[2] = group->control[2].value;
2217 data[3] = group->control[3].value;
2218 break;
2219 case VIDEO_CONTROL_BRIGHTNESS:
2220 if (group->length != 1)
2221 return EINVAL;
2222 control_id = UVIDEO_PU_BRIGHTNESS_CONTROL;
2223 ent_id = 2;
2224 len = 2;
2225 USETW(data, group->control[0].value);
2226 break;
2227 case VIDEO_CONTROL_GAIN:
2228 if (group->length != 1)
2229 return EINVAL;
2230 control_id = UVIDEO_PU_GAIN_CONTROL;
2231 ent_id = 2;
2232 len = 2;
2233 USETW(data, group->control[0].value);
2234 break;
2235 case VIDEO_CONTROL_SHARPNESS:
2236 if (group->length != 1)
2237 return EINVAL;
2238 control_id = UVIDEO_PU_SHARPNESS_CONTROL;
2239 ent_id = 2; /* TODO: hardcoded logitech processing unit */
2240 len = 2;
2241 USETW(data, group->control[0].value);
2242 break;
2243 default:
2244 return EINVAL;
2247 req.bmRequestType = UVIDEO_REQUEST_TYPE_INTERFACE |
2248 UVIDEO_REQUEST_TYPE_CLASS_SPECIFIC |
2249 UVIDEO_REQUEST_TYPE_SET;
2250 req.bRequest = UR_SET_CUR;
2251 USETW(req.wValue, control_id << 8);
2252 USETW(req.wIndex, (ent_id << 8) | sc->sc_ifaceno);
2253 USETW(req.wLength, len);
2255 s = splusb();
2256 err = usbd_do_request(sc->sc_udev, &req, data);
2257 splx(s);
2258 if (err != USBD_NORMAL_COMPLETION) {
2259 DPRINTF(("uvideo_set_control: error %s (%d)\n",
2260 usbd_errstr(err), err));
2261 return EIO; /* TODO: more detail here? */
2264 return 0;
2267 static usbd_status
2268 uvideo_stream_probe_and_commit(struct uvideo_stream *vs,
2269 uint8_t action, uint8_t control,
2270 void *data)
2272 usb_device_request_t req;
2274 switch (action) {
2275 case UR_SET_CUR:
2276 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
2277 USETW(req.wLength, vs->vs_probelen);
2278 break;
2279 case UR_GET_CUR:
2280 case UR_GET_MIN:
2281 case UR_GET_MAX:
2282 case UR_GET_DEF:
2283 req.bmRequestType = UT_READ_CLASS_INTERFACE;
2284 USETW(req.wLength, vs->vs_probelen);
2285 break;
2286 case UR_GET_INFO:
2287 req.bmRequestType = UT_READ_CLASS_INTERFACE;
2288 USETW(req.wLength, sizeof(uByte));
2289 break;
2290 case UR_GET_LEN:
2291 req.bmRequestType = UT_READ_CLASS_INTERFACE;
2292 USETW(req.wLength, sizeof(uWord)); /* is this right? */
2293 break;
2294 default:
2295 DPRINTF(("uvideo_probe_and_commit: "
2296 "unknown request action %d\n", action));
2297 return USBD_NOT_STARTED;
2300 req.bRequest = action;
2301 USETW2(req.wValue, control, 0);
2302 USETW2(req.wIndex, 0, vs->vs_ifaceno);
2304 return (usbd_do_request_flags(vs->vs_parent->sc_udev, &req, data,
2305 0, 0,
2306 USBD_DEFAULT_TIMEOUT));
2309 static void
2310 uvideo_init_probe_data(uvideo_probe_and_commit_data_t *probe)
2312 /* all zeroes tells camera to choose what it wants */
2313 memset(probe, 0, sizeof(*probe));
2317 #ifdef _MODULE
2319 MODULE(MODULE_CLASS_DRIVER, uvideo, NULL);
2320 static const struct cfiattrdata videobuscf_iattrdata = {
2321 "videobus", 0, {
2322 { NULL, NULL, 0 },
2325 static const struct cfiattrdata * const uvideo_attrs[] = {
2326 &videobuscf_iattrdata, NULL
2328 CFDRIVER_DECL(uvideo, DV_DULL, uvideo_attrs);
2329 extern struct cfattach uvideo_ca;
2330 extern struct cfattach uvideo_ca;
2331 static int uvideoloc[6] = { -1, -1, -1, -1, -1, -1 };
2332 static struct cfparent uhubparent = {
2333 "usbifif", NULL, DVUNIT_ANY
2335 static struct cfdata uvideo_cfdata[] = {
2337 .cf_name = "uvideo",
2338 .cf_atname = "uvideo",
2339 .cf_unit = 0,
2340 .cf_fstate = FSTATE_STAR,
2341 .cf_loc = uvideoloc,
2342 .cf_flags = 0,
2343 .cf_pspec = &uhubparent,
2345 { NULL }
2348 static int
2349 uvideo_modcmd(modcmd_t cmd, void *arg)
2351 int err;
2354 switch (cmd) {
2355 case MODULE_CMD_INIT:
2356 DPRINTF(("uvideo: attempting to load\n"));
2358 err = config_cfdriver_attach(&uvideo_cd);
2359 if (err)
2360 return err;
2361 err = config_cfattach_attach("uvideo", &uvideo_ca);
2362 if (err) {
2363 config_cfdriver_detach(&uvideo_cd);
2364 return err;
2366 err = config_cfdata_attach(uvideo_cfdata, 1);
2367 if (err) {
2368 config_cfattach_detach("uvideo", &uvideo_ca);
2369 config_cfdriver_detach(&uvideo_cd);
2370 return err;
2372 DPRINTF(("uvideo: loaded module\n"));
2373 return 0;
2374 case MODULE_CMD_FINI:
2375 DPRINTF(("uvideo: attempting to unload module\n"));
2376 err = config_cfdata_detach(uvideo_cfdata);
2377 if (err)
2378 return err;
2379 config_cfattach_detach("uvideo", &uvideo_ca);
2380 config_cfdriver_detach(&uvideo_cd);
2381 DPRINTF(("uvideo: module unload\n"));
2382 return 0;
2383 default:
2384 return ENOTTY;
2388 #endif /* _MODULE */
2391 #ifdef UVIDEO_DEBUG
2392 /* Some functions to print out descriptors. Mostly useless other than
2393 * debugging/exploration purposes. */
2396 static void
2397 print_bitmap(const uByte *start, uByte nbytes)
2399 int byte, bit;
2401 /* most significant first */
2402 for (byte = nbytes-1; byte >= 0; --byte) {
2403 if (byte < nbytes-1) printf("-");
2404 for (bit = 7; bit >= 0; --bit)
2405 printf("%01d", (start[byte] >> bit) &1);
2409 static void
2410 print_descriptor(const usb_descriptor_t *desc)
2412 static int current_class = -1;
2413 static int current_subclass = -1;
2415 if (desc->bDescriptorType == UDESC_INTERFACE) {
2416 const usb_interface_descriptor_t *id;
2417 id = (const usb_interface_descriptor_t *)desc;
2418 current_class = id->bInterfaceClass;
2419 current_subclass = id->bInterfaceSubClass;
2420 print_interface_descriptor(id);
2421 printf("\n");
2422 return;
2425 printf(" "); /* indent */
2427 if (current_class == UICLASS_VIDEO) {
2428 switch (current_subclass) {
2429 case UISUBCLASS_VIDEOCONTROL:
2430 print_vc_descriptor(desc);
2431 break;
2432 case UISUBCLASS_VIDEOSTREAMING:
2433 print_vs_descriptor(desc);
2434 break;
2435 case UISUBCLASS_VIDEOCOLLECTION:
2436 printf("uvc collection: len=%d type=0x%02x",
2437 desc->bLength, desc->bDescriptorType);
2438 break;
2440 } else {
2441 printf("non uvc descriptor len=%d type=0x%02x",
2442 desc->bLength, desc->bDescriptorType);
2445 printf("\n");
2448 static void
2449 print_vc_descriptor(const usb_descriptor_t *desc)
2451 const uvideo_descriptor_t *vcdesc;
2453 printf("VC ");
2455 switch (desc->bDescriptorType) {
2456 case UDESC_ENDPOINT:
2457 print_endpoint_descriptor(
2458 (const usb_endpoint_descriptor_t *)desc);
2459 break;
2460 case UDESC_CS_INTERFACE:
2461 vcdesc = (const uvideo_descriptor_t *)desc;
2462 switch (vcdesc->bDescriptorSubtype) {
2463 case UDESC_VC_HEADER:
2464 print_vc_header_descriptor(
2465 (const uvideo_vc_header_descriptor_t *)
2466 vcdesc);
2467 break;
2468 case UDESC_INPUT_TERMINAL:
2469 switch (UGETW(
2470 ((const uvideo_input_terminal_descriptor_t *)
2471 vcdesc)->wTerminalType)) {
2472 case UVIDEO_ITT_CAMERA:
2473 print_camera_terminal_descriptor(
2474 (const uvideo_camera_terminal_descriptor_t *)vcdesc);
2475 break;
2476 default:
2477 print_input_terminal_descriptor(
2478 (const uvideo_input_terminal_descriptor_t *)vcdesc);
2479 break;
2481 break;
2482 case UDESC_OUTPUT_TERMINAL:
2483 print_output_terminal_descriptor(
2484 (const uvideo_output_terminal_descriptor_t *)
2485 vcdesc);
2486 break;
2487 case UDESC_SELECTOR_UNIT:
2488 print_selector_unit_descriptor(
2489 (const uvideo_selector_unit_descriptor_t *)
2490 vcdesc);
2491 break;
2492 case UDESC_PROCESSING_UNIT:
2493 print_processing_unit_descriptor(
2494 (const uvideo_processing_unit_descriptor_t *)
2495 vcdesc);
2496 break;
2497 case UDESC_EXTENSION_UNIT:
2498 print_extension_unit_descriptor(
2499 (const uvideo_extension_unit_descriptor_t *)
2500 vcdesc);
2501 break;
2502 default:
2503 printf("class specific interface "
2504 "len=%d type=0x%02x subtype=0x%02x",
2505 vcdesc->bLength,
2506 vcdesc->bDescriptorType,
2507 vcdesc->bDescriptorSubtype);
2508 break;
2510 break;
2511 case UDESC_CS_ENDPOINT:
2512 vcdesc = (const uvideo_descriptor_t *)desc;
2513 switch (vcdesc->bDescriptorSubtype) {
2514 case UDESC_VC_INTERRUPT_ENDPOINT:
2515 print_interrupt_endpoint_descriptor(
2516 (const uvideo_vc_interrupt_endpoint_descriptor_t *)
2517 vcdesc);
2518 break;
2519 default:
2520 printf("class specific endpoint "
2521 "len=%d type=0x%02x subtype=0x%02x",
2522 vcdesc->bLength,
2523 vcdesc->bDescriptorType,
2524 vcdesc->bDescriptorSubtype);
2525 break;
2527 break;
2528 default:
2529 printf("unknown: len=%d type=0x%02x",
2530 desc->bLength, desc->bDescriptorType);
2531 break;
2535 static void
2536 print_vs_descriptor(const usb_descriptor_t *desc)
2538 const uvideo_descriptor_t * vsdesc;
2539 printf("VS ");
2541 switch (desc->bDescriptorType) {
2542 case UDESC_ENDPOINT:
2543 print_endpoint_descriptor(
2544 (const usb_endpoint_descriptor_t *)desc);
2545 break;
2546 case UDESC_CS_INTERFACE:
2547 vsdesc = (const uvideo_descriptor_t *)desc;
2548 switch (vsdesc->bDescriptorSubtype) {
2549 case UDESC_VS_INPUT_HEADER:
2550 print_vs_input_header_descriptor(
2551 (const uvideo_vs_input_header_descriptor_t *)
2552 vsdesc);
2553 break;
2554 case UDESC_VS_OUTPUT_HEADER:
2555 print_vs_output_header_descriptor(
2556 (const uvideo_vs_output_header_descriptor_t *)
2557 vsdesc);
2558 break;
2559 case UDESC_VS_FORMAT_UNCOMPRESSED:
2560 print_vs_format_uncompressed_descriptor(
2561 (const uvideo_vs_format_uncompressed_descriptor_t *)
2562 vsdesc);
2563 break;
2564 case UDESC_VS_FRAME_UNCOMPRESSED:
2565 print_vs_frame_uncompressed_descriptor(
2566 (const uvideo_vs_frame_uncompressed_descriptor_t *)
2567 vsdesc);
2568 break;
2569 case UDESC_VS_FORMAT_MJPEG:
2570 print_vs_format_mjpeg_descriptor(
2571 (const uvideo_vs_format_mjpeg_descriptor_t *)
2572 vsdesc);
2573 break;
2574 case UDESC_VS_FRAME_MJPEG:
2575 print_vs_frame_mjpeg_descriptor(
2576 (const uvideo_vs_frame_mjpeg_descriptor_t *)
2577 vsdesc);
2578 break;
2579 case UDESC_VS_FORMAT_DV:
2580 print_vs_format_dv_descriptor(
2581 (const uvideo_vs_format_dv_descriptor_t *)
2582 vsdesc);
2583 break;
2584 default:
2585 printf("unknown cs interface: len=%d type=0x%02x "
2586 "subtype=0x%02x",
2587 vsdesc->bLength, vsdesc->bDescriptorType,
2588 vsdesc->bDescriptorSubtype);
2590 break;
2591 default:
2592 printf("unknown: len=%d type=0x%02x",
2593 desc->bLength, desc->bDescriptorType);
2594 break;
2598 static void
2599 print_interface_descriptor(const usb_interface_descriptor_t *id)
2601 printf("Interface: Len=%d Type=0x%02x "
2602 "bInterfaceNumber=0x%02x "
2603 "bAlternateSetting=0x%02x bNumEndpoints=0x%02x "
2604 "bInterfaceClass=0x%02x bInterfaceSubClass=0x%02x "
2605 "bInterfaceProtocol=0x%02x iInterface=0x%02x",
2606 id->bLength,
2607 id->bDescriptorType,
2608 id->bInterfaceNumber,
2609 id->bAlternateSetting,
2610 id->bNumEndpoints,
2611 id->bInterfaceClass,
2612 id->bInterfaceSubClass,
2613 id->bInterfaceProtocol,
2614 id->iInterface);
2617 static void
2618 print_endpoint_descriptor(const usb_endpoint_descriptor_t *desc)
2620 printf("Endpoint: Len=%d Type=0x%02x "
2621 "bEndpointAddress=0x%02x ",
2622 desc->bLength,
2623 desc->bDescriptorType,
2624 desc->bEndpointAddress);
2625 printf("bmAttributes=");
2626 print_bitmap(&desc->bmAttributes, 1);
2627 printf(" wMaxPacketSize=%d bInterval=%d",
2628 UGETW(desc->wMaxPacketSize),
2629 desc->bInterval);
2632 static void
2633 print_vc_header_descriptor(
2634 const uvideo_vc_header_descriptor_t *desc)
2636 printf("Interface Header: "
2637 "Len=%d Type=0x%02x Subtype=0x%02x "
2638 "bcdUVC=%d wTotalLength=%d "
2639 "dwClockFrequency=%u bInCollection=%d",
2640 desc->bLength,
2641 desc->bDescriptorType,
2642 desc->bDescriptorSubtype,
2643 UGETW(desc->bcdUVC),
2644 UGETW(desc->wTotalLength),
2645 UGETDW(desc->dwClockFrequency),
2646 desc->bInCollection);
2649 static void
2650 print_input_terminal_descriptor(
2651 const uvideo_input_terminal_descriptor_t *desc)
2653 printf("Input Terminal: "
2654 "Len=%d Type=0x%02x Subtype=0x%02x "
2655 "bTerminalID=%d wTerminalType=%x bAssocTerminal=%d "
2656 "iTerminal=%d",
2657 desc->bLength,
2658 desc->bDescriptorType,
2659 desc->bDescriptorSubtype,
2660 desc->bTerminalID,
2661 UGETW(desc->wTerminalType),
2662 desc->bAssocTerminal,
2663 desc->iTerminal);
2666 static void
2667 print_output_terminal_descriptor(
2668 const uvideo_output_terminal_descriptor_t *desc)
2670 printf("Output Terminal: "
2671 "Len=%d Type=0x%02x Subtype=0x%02x "
2672 "bTerminalID=%d wTerminalType=%x bAssocTerminal=%d "
2673 "bSourceID=%d iTerminal=%d",
2674 desc->bLength,
2675 desc->bDescriptorType,
2676 desc->bDescriptorSubtype,
2677 desc->bTerminalID,
2678 UGETW(desc->wTerminalType),
2679 desc->bAssocTerminal,
2680 desc->bSourceID,
2681 desc->iTerminal);
2684 static void
2685 print_camera_terminal_descriptor(
2686 const uvideo_camera_terminal_descriptor_t *desc)
2688 printf("Camera Terminal: "
2689 "Len=%d Type=0x%02x Subtype=0x%02x "
2690 "bTerminalID=%d wTerminalType=%x bAssocTerminal=%d "
2691 "iTerminal=%d "
2692 "wObjectiveFocalLengthMin/Max=%d/%d "
2693 "wOcularFocalLength=%d "
2694 "bControlSize=%d ",
2695 desc->bLength,
2696 desc->bDescriptorType,
2697 desc->bDescriptorSubtype,
2698 desc->bTerminalID,
2699 UGETW(desc->wTerminalType),
2700 desc->bAssocTerminal,
2701 desc->iTerminal,
2702 UGETW(desc->wObjectiveFocalLengthMin),
2703 UGETW(desc->wObjectiveFocalLengthMax),
2704 UGETW(desc->wOcularFocalLength),
2705 desc->bControlSize);
2706 printf("bmControls=");
2707 print_bitmap(desc->bmControls, desc->bControlSize);
2710 static void
2711 print_selector_unit_descriptor(
2712 const uvideo_selector_unit_descriptor_t *desc)
2714 int i;
2715 const uByte *b;
2716 printf("Selector Unit: "
2717 "Len=%d Type=0x%02x Subtype=0x%02x "
2718 "bUnitID=%d bNrInPins=%d ",
2719 desc->bLength,
2720 desc->bDescriptorType,
2721 desc->bDescriptorSubtype,
2722 desc->bUnitID,
2723 desc->bNrInPins);
2724 printf("baSourceIDs=");
2725 b = &desc->baSourceID[0];
2726 for (i = 0; i < desc->bNrInPins; ++i)
2727 printf("%d ", *b++);
2728 printf("iSelector=%d", *b);
2731 static void
2732 print_processing_unit_descriptor(
2733 const uvideo_processing_unit_descriptor_t *desc)
2735 const uByte *b;
2737 printf("Processing Unit: "
2738 "Len=%d Type=0x%02x Subtype=0x%02x "
2739 "bUnitID=%d bSourceID=%d wMaxMultiplier=%d bControlSize=%d ",
2740 desc->bLength,
2741 desc->bDescriptorType,
2742 desc->bDescriptorSubtype,
2743 desc->bUnitID,
2744 desc->bSourceID,
2745 UGETW(desc->wMaxMultiplier),
2746 desc->bControlSize);
2747 printf("bmControls=");
2748 print_bitmap(desc->bmControls, desc->bControlSize);
2749 b = &desc->bControlSize + desc->bControlSize + 1;
2750 printf(" iProcessing=%d bmVideoStandards=", *b);
2751 b += 1;
2752 print_bitmap(b, 1);
2755 static void
2756 print_extension_unit_descriptor(
2757 const uvideo_extension_unit_descriptor_t *desc)
2759 const uByte * byte;
2760 uByte controlbytes;
2761 int i;
2763 printf("Extension Unit: "
2764 "Len=%d Type=0x%02x Subtype=0x%02x "
2765 "bUnitID=%d ",
2766 desc->bLength,
2767 desc->bDescriptorType,
2768 desc->bDescriptorSubtype,
2769 desc->bUnitID);
2771 printf("guidExtensionCode=");
2772 usb_guid_print(&desc->guidExtensionCode);
2773 printf(" ");
2775 printf("bNumControls=%d bNrInPins=%d ",
2776 desc->bNumControls,
2777 desc->bNrInPins);
2779 printf("baSourceIDs=");
2780 byte = &desc->baSourceID[0];
2781 for (i = 0; i < desc->bNrInPins; ++i)
2782 printf("%d ", *byte++);
2784 controlbytes = *byte++;
2785 printf("bControlSize=%d ", controlbytes);
2786 printf("bmControls=");
2787 print_bitmap(byte, controlbytes);
2789 byte += controlbytes;
2790 printf(" iExtension=%d", *byte);
2793 static void
2794 print_interrupt_endpoint_descriptor(
2795 const uvideo_vc_interrupt_endpoint_descriptor_t *desc)
2797 printf("Interrupt Endpoint: "
2798 "Len=%d Type=0x%02x Subtype=0x%02x "
2799 "wMaxTransferSize=%d ",
2800 desc->bLength,
2801 desc->bDescriptorType,
2802 desc->bDescriptorSubtype,
2803 UGETW(desc->wMaxTransferSize));
2807 static void
2808 print_vs_output_header_descriptor(
2809 const uvideo_vs_output_header_descriptor_t *desc)
2811 printf("Interface Output Header: "
2812 "Len=%d Type=0x%02x Subtype=0x%02x "
2813 "bNumFormats=%d wTotalLength=%d bEndpointAddress=%d "
2814 "bTerminalLink=%d bControlSize=%d",
2815 desc->bLength,
2816 desc->bDescriptorType,
2817 desc->bDescriptorSubtype,
2818 desc->bNumFormats,
2819 UGETW(desc->wTotalLength),
2820 desc->bEndpointAddress,
2821 desc->bTerminalLink,
2822 desc->bControlSize);
2825 static void
2826 print_vs_input_header_descriptor(
2827 const uvideo_vs_input_header_descriptor_t *desc)
2829 printf("Interface Input Header: "
2830 "Len=%d Type=0x%02x Subtype=0x%02x "
2831 "bNumFormats=%d wTotalLength=%d bEndpointAddress=%d "
2832 "bmInfo=%x bTerminalLink=%d bStillCaptureMethod=%d "
2833 "bTriggerSupport=%d bTriggerUsage=%d bControlSize=%d ",
2834 desc->bLength,
2835 desc->bDescriptorType,
2836 desc->bDescriptorSubtype,
2837 desc->bNumFormats,
2838 UGETW(desc->wTotalLength),
2839 desc->bEndpointAddress,
2840 desc->bmInfo,
2841 desc->bTerminalLink,
2842 desc->bStillCaptureMethod,
2843 desc->bTriggerSupport,
2844 desc->bTriggerUsage,
2845 desc->bControlSize);
2846 print_bitmap(desc->bmaControls, desc->bControlSize);
2849 static void
2850 print_vs_format_uncompressed_descriptor(
2851 const uvideo_vs_format_uncompressed_descriptor_t *desc)
2853 printf("Format Uncompressed: "
2854 "Len=%d Type=0x%02x Subtype=0x%02x "
2855 "bFormatIndex=%d bNumFrameDescriptors=%d ",
2856 desc->bLength,
2857 desc->bDescriptorType,
2858 desc->bDescriptorSubtype,
2859 desc->bFormatIndex,
2860 desc->bNumFrameDescriptors);
2861 usb_guid_print(&desc->guidFormat);
2862 printf(" bBitsPerPixel=%d bDefaultFrameIndex=%d "
2863 "bAspectRatioX=%d bAspectRatioY=%d "
2864 "bmInterlaceFlags=0x%02x bCopyProtect=%d",
2865 desc->bBitsPerPixel,
2866 desc->bDefaultFrameIndex,
2867 desc->bAspectRatioX,
2868 desc->bAspectRatioY,
2869 desc->bmInterlaceFlags,
2870 desc->bCopyProtect);
2873 static void
2874 print_vs_frame_uncompressed_descriptor(
2875 const uvideo_vs_frame_uncompressed_descriptor_t *desc)
2877 printf("Frame Uncompressed: "
2878 "Len=%d Type=0x%02x Subtype=0x%02x "
2879 "bFrameIndex=%d bmCapabilities=0x%02x "
2880 "wWidth=%d wHeight=%d dwMinBitRate=%u dwMaxBitRate=%u "
2881 "dwMaxVideoFrameBufferSize=%u dwDefaultFrameInterval=%u "
2882 "bFrameIntervalType=%d",
2883 desc->bLength,
2884 desc->bDescriptorType,
2885 desc->bDescriptorSubtype,
2886 desc->bFrameIndex,
2887 desc->bmCapabilities,
2888 UGETW(desc->wWidth),
2889 UGETW(desc->wHeight),
2890 UGETDW(desc->dwMinBitRate),
2891 UGETDW(desc->dwMaxBitRate),
2892 UGETDW(desc->dwMaxVideoFrameBufferSize),
2893 UGETDW(desc->dwDefaultFrameInterval),
2894 desc->bFrameIntervalType);
2897 static void
2898 print_vs_format_mjpeg_descriptor(
2899 const uvideo_vs_format_mjpeg_descriptor_t *desc)
2901 printf("MJPEG format: "
2902 "Len=%d Type=0x%02x Subtype=0x%02x "
2903 "bFormatIndex=%d bNumFrameDescriptors=%d bmFlags=0x%02x "
2904 "bDefaultFrameIndex=%d bAspectRatioX=%d bAspectRatioY=%d "
2905 "bmInterlaceFlags=0x%02x bCopyProtect=%d",
2906 desc->bLength,
2907 desc->bDescriptorType,
2908 desc->bDescriptorSubtype,
2909 desc->bFormatIndex,
2910 desc->bNumFrameDescriptors,
2911 desc->bmFlags,
2912 desc->bDefaultFrameIndex,
2913 desc->bAspectRatioX,
2914 desc->bAspectRatioY,
2915 desc->bmInterlaceFlags,
2916 desc->bCopyProtect);
2919 static void
2920 print_vs_frame_mjpeg_descriptor(
2921 const uvideo_vs_frame_mjpeg_descriptor_t *desc)
2923 printf("MJPEG frame: "
2924 "Len=%d Type=0x%02x Subtype=0x%02x "
2925 "bFrameIndex=%d bmCapabilities=0x%02x "
2926 "wWidth=%d wHeight=%d dwMinBitRate=%u dwMaxBitRate=%u "
2927 "dwMaxVideoFrameBufferSize=%u dwDefaultFrameInterval=%u "
2928 "bFrameIntervalType=%d",
2929 desc->bLength,
2930 desc->bDescriptorType,
2931 desc->bDescriptorSubtype,
2932 desc->bFrameIndex,
2933 desc->bmCapabilities,
2934 UGETW(desc->wWidth),
2935 UGETW(desc->wHeight),
2936 UGETDW(desc->dwMinBitRate),
2937 UGETDW(desc->dwMaxBitRate),
2938 UGETDW(desc->dwMaxVideoFrameBufferSize),
2939 UGETDW(desc->dwDefaultFrameInterval),
2940 desc->bFrameIntervalType);
2943 static void
2944 print_vs_format_dv_descriptor(
2945 const uvideo_vs_format_dv_descriptor_t *desc)
2947 printf("MJPEG format: "
2948 "Len=%d Type=0x%02x Subtype=0x%02x "
2949 "bFormatIndex=%d dwMaxVideoFrameBufferSize=%u "
2950 "bFormatType/Rate=%d bFormatType/Format=%d",
2951 desc->bLength,
2952 desc->bDescriptorType,
2953 desc->bDescriptorSubtype,
2954 desc->bFormatIndex,
2955 UGETDW(desc->dwMaxVideoFrameBufferSize),
2956 UVIDEO_GET_DV_FREQ(desc->bFormatType),
2957 UVIDEO_GET_DV_FORMAT(desc->bFormatType));
2960 #endif /* !UVIDEO_DEBUG */
2962 static const usb_descriptor_t *
2963 usb_desc_iter_peek_next(usbd_desc_iter_t *iter)
2965 const usb_descriptor_t *desc;
2967 if (iter->cur + sizeof(usb_descriptor_t) >= iter->end) {
2968 if (iter->cur != iter->end)
2969 printf("usb_desc_iter_peek_next: bad descriptor\n");
2970 return NULL;
2972 desc = (const usb_descriptor_t *)iter->cur;
2973 if (desc->bLength == 0) {
2974 printf("usb_desc_iter_peek_next: descriptor length = 0\n");
2975 return NULL;
2977 if (iter->cur + desc->bLength > iter->end) {
2978 printf("usb_desc_iter_peek_next: descriptor length too large\n");
2979 return NULL;
2981 return desc;
2984 /* Return the next interface descriptor, skipping over any other
2985 * descriptors. Returns NULL at the end or on error. */
2986 static const usb_interface_descriptor_t *
2987 usb_desc_iter_next_interface(usbd_desc_iter_t *iter)
2989 const usb_descriptor_t *desc;
2991 while ((desc = usb_desc_iter_peek_next(iter)) != NULL &&
2992 desc->bDescriptorType != UDESC_INTERFACE)
2994 usb_desc_iter_next(iter);
2997 return (const usb_interface_descriptor_t *)usb_desc_iter_next(iter);
3000 /* Returns the next non-interface descriptor, returning NULL when the
3001 * next descriptor would be an interface descriptor. */
3002 static const usb_descriptor_t *
3003 usb_desc_iter_next_non_interface(usbd_desc_iter_t *iter)
3005 const usb_descriptor_t *desc;
3007 if ((desc = usb_desc_iter_peek_next(iter)) != NULL &&
3008 desc->bDescriptorType != UDESC_INTERFACE)
3010 return (usb_desc_iter_next(iter));
3011 } else {
3012 return NULL;
3016 #ifdef UVIDEO_DEBUG
3017 static void
3018 usb_guid_print(const usb_guid_t *guid)
3020 printf("%04X-%02X-%02X-",
3021 UGETDW(guid->data1),
3022 UGETW(guid->data2),
3023 UGETW(guid->data3));
3024 printf("%02X%02X-",
3025 guid->data4[0],
3026 guid->data4[1]);
3027 printf("%02X%02X%02X%02X%02X%02X",
3028 guid->data4[2],
3029 guid->data4[3],
3030 guid->data4[4],
3031 guid->data4[5],
3032 guid->data4[6],
3033 guid->data4[7]);
3035 #endif /* !UVIDEO_DEBUG */
3037 /* Returns less than zero, zero, or greater than zero if uguid is less
3038 * than, equal to, or greater than guid. */
3039 static int
3040 usb_guid_cmp(const usb_guid_t *uguid, const guid_t *guid)
3042 if (guid->data1 > UGETDW(uguid->data1))
3043 return 1;
3044 else if (guid->data1 < UGETDW(uguid->data1))
3045 return -1;
3047 if (guid->data2 > UGETW(uguid->data2))
3048 return 1;
3049 else if (guid->data2 < UGETW(uguid->data2))
3050 return -1;
3052 if (guid->data3 > UGETW(uguid->data3))
3053 return 1;
3054 else if (guid->data3 < UGETW(uguid->data3))
3055 return -1;
3057 return (memcmp(guid->data4, uguid->data4, 8));