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