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