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