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