Sat Sep 20 18:17:56 2008 UTC ()
Add UYVY support.


(jmcneill)
diff -r1.14 -r1.15 src/sys/dev/usb/uvideo.c
diff -r1.1 -r1.2 src/sys/dev/usb/uvideoreg.h

cvs diff -r1.14 -r1.15 src/sys/dev/usb/uvideo.c (switch to unified diff)

--- src/sys/dev/usb/uvideo.c 2008/09/20 15:55:38 1.14
+++ src/sys/dev/usb/uvideo.c 2008/09/20 18:17:56 1.15
@@ -1,2256 +1,2258 @@ @@ -1,2256 +1,2258 @@
1/* $NetBSD: uvideo.c,v 1.14 2008/09/20 15:55:38 jmcneill Exp $ */ 1/* $NetBSD: uvideo.c,v 1.15 2008/09/20 18:17:56 jmcneill Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2008 Patrick Mahoney 4 * Copyright (c) 2008 Patrick Mahoney
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code was written by Patrick Mahoney (pat@polycrystal.org) as 7 * This code was written by Patrick Mahoney (pat@polycrystal.org) as
8 * part of Google Summer of Code 2008. 8 * part of Google Summer of Code 2008.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software 18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement: 19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD 20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors. 21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its 22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived 23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission. 24 * from this software without specific prior written permission.
25 * 25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE. 36 * POSSIBILITY OF SUCH DAMAGE.
37 */ 37 */
38 38
39/* 39/*
40 * USB video specs: 40 * USB video specs:
41 * http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_1.zip 41 * http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_1.zip
42 */ 42 */
43 43
44#include <sys/cdefs.h> 44#include <sys/cdefs.h>
45__KERNEL_RCSID(0, "$NetBSD: uvideo.c,v 1.14 2008/09/20 15:55:38 jmcneill Exp $"); 45__KERNEL_RCSID(0, "$NetBSD: uvideo.c,v 1.15 2008/09/20 18:17:56 jmcneill Exp $");
46 46
47#ifdef _MODULE 47#ifdef _MODULE
48#include <sys/module.h> 48#include <sys/module.h>
49#endif 49#endif
50 50
51#include <sys/param.h> 51#include <sys/param.h>
52#include <sys/systm.h> 52#include <sys/systm.h>
53#include <sys/kernel.h> 53#include <sys/kernel.h>
54/* #include <sys/malloc.h> */ 54/* #include <sys/malloc.h> */
55#include <sys/kmem.h> 55#include <sys/kmem.h>
56#include <sys/device.h> 56#include <sys/device.h>
57#include <sys/ioctl.h> 57#include <sys/ioctl.h>
58#include <sys/uio.h> 58#include <sys/uio.h>
59#include <sys/tty.h> 59#include <sys/tty.h>
60#include <sys/file.h> 60#include <sys/file.h>
61#include <sys/select.h> 61#include <sys/select.h>
62#include <sys/proc.h> 62#include <sys/proc.h>
63#include <sys/conf.h> 63#include <sys/conf.h>
64#include <sys/vnode.h> 64#include <sys/vnode.h>
65#include <sys/poll.h> 65#include <sys/poll.h>
66#include <sys/queue.h> /* SLIST */ 66#include <sys/queue.h> /* SLIST */
67 67
68#include <sys/videoio.h> 68#include <sys/videoio.h>
69#include <dev/video_if.h> 69#include <dev/video_if.h>
70 70
71#include <dev/usb/usb.h> 71#include <dev/usb/usb.h>
72#include <dev/usb/usbdi.h> 72#include <dev/usb/usbdi.h>
73#include <dev/usb/usbdi_util.h> 73#include <dev/usb/usbdi_util.h>
74#include <dev/usb/usb_quirks.h> 74#include <dev/usb/usb_quirks.h>
75 75
76#include <dev/usb/uvideoreg.h> 76#include <dev/usb/uvideoreg.h>
77 77
78#if !defined(_MODULE) 78#if !defined(_MODULE)
79#include "opt_uvideo.h" 79#include "opt_uvideo.h"
80#endif 80#endif
81 81
82#define UVIDEO_NXFERS 3 82#define UVIDEO_NXFERS 3
83 83
84/* #define UVIDEO_DISABLE_MJPEG */ 84/* #define UVIDEO_DISABLE_MJPEG */
85 85
86#ifdef UVIDEO_DEBUG 86#ifdef UVIDEO_DEBUG
87#define DPRINTF(x) do { if (uvideodebug) logprintf x; } while (0) 87#define DPRINTF(x) do { if (uvideodebug) logprintf x; } while (0)
88#define DPRINTFN(n,x) do { if (uvideodebug>(n)) logprintf x; } while (0) 88#define DPRINTFN(n,x) do { if (uvideodebug>(n)) logprintf x; } while (0)
89int uvideodebug = 20; 89int uvideodebug = 20;
90#else 90#else
91#define DPRINTF(x) 91#define DPRINTF(x)
92#define DPRINTFN(n,x) 92#define DPRINTFN(n,x)
93#endif 93#endif
94 94
95typedef enum { 95typedef enum {
96 UVIDEO_STATE_CLOSED, 96 UVIDEO_STATE_CLOSED,
97 UVIDEO_STATE_OPENING, 97 UVIDEO_STATE_OPENING,
98 UVIDEO_STATE_IDLE 98 UVIDEO_STATE_IDLE
99} uvideo_state; 99} uvideo_state;
100 100
101struct uvideo_camera_terminal { 101struct uvideo_camera_terminal {
102 uint16_t ct_objective_focal_min; 102 uint16_t ct_objective_focal_min;
103 uint16_t ct_objective_focal_max; 103 uint16_t ct_objective_focal_max;
104 uint16_t ct_ocular_focal_length; 104 uint16_t ct_ocular_focal_length;
105}; 105};
106 106
107struct uvideo_processing_unit { 107struct uvideo_processing_unit {
108 uint16_t pu_max_multiplier; /* digital zoom */ 108 uint16_t pu_max_multiplier; /* digital zoom */
109 uint8_t pu_video_standards; 109 uint8_t pu_video_standards;
110}; 110};
111 111
112struct uvideo_extension_unit { 112struct uvideo_extension_unit {
113 guid_t xu_guid; 113 guid_t xu_guid;
114}; 114};
115 115
116/* For simplicity, we consider a Terminal a special case of Unit 116/* For simplicity, we consider a Terminal a special case of Unit
117 * rather than a separate entity. */ 117 * rather than a separate entity. */
118struct uvideo_unit { 118struct uvideo_unit {
119 uint8_t vu_id; 119 uint8_t vu_id;
120 uint8_t vu_type; 120 uint8_t vu_type;
121 uint8_t vu_dst_id; 121 uint8_t vu_dst_id;
122 uint8_t vu_nsrcs; 122 uint8_t vu_nsrcs;
123 union { 123 union {
124 uint8_t vu_src_id; /* vu_nsrcs = 1 */ 124 uint8_t vu_src_id; /* vu_nsrcs = 1 */
125 uint8_t *vu_src_id_ary; /* vu_nsrcs > 1 */ 125 uint8_t *vu_src_id_ary; /* vu_nsrcs > 1 */
126 } s; 126 } s;
127 127
128 /* fields for individual unit/terminal types */ 128 /* fields for individual unit/terminal types */
129 union { 129 union {
130 struct uvideo_camera_terminal vu_camera; 130 struct uvideo_camera_terminal vu_camera;
131 struct uvideo_processing_unit vu_processing; 131 struct uvideo_processing_unit vu_processing;
132 struct uvideo_extension_unit vu_extension; 132 struct uvideo_extension_unit vu_extension;
133 } u; 133 } u;
134 134
135 /* Used by camera terminal, processing and extention units. */ 135 /* Used by camera terminal, processing and extention units. */
136 uint8_t vu_control_size; /* number of bytes in vu_controls */ 136 uint8_t vu_control_size; /* number of bytes in vu_controls */
137 uint8_t *vu_controls; /* array of bytes. bits are 137 uint8_t *vu_controls; /* array of bytes. bits are
138 * numbered from 0 at least 138 * numbered from 0 at least
139 * significant bit to 139 * significant bit to
140 * (8*vu_control_size - 1)*/ 140 * (8*vu_control_size - 1)*/
141}; 141};
142 142
143struct uvideo_alternate { 143struct uvideo_alternate {
144 uint8_t altno; 144 uint8_t altno;
145 uint8_t interval; 145 uint8_t interval;
146 uint16_t max_packet_size; 146 uint16_t max_packet_size;
147 SLIST_ENTRY(uvideo_alternate) entries; 147 SLIST_ENTRY(uvideo_alternate) entries;
148}; 148};
149SLIST_HEAD(altlist, uvideo_alternate); 149SLIST_HEAD(altlist, uvideo_alternate);
150 150
151#define UVIDEO_FORMAT_GET_FORMAT_INDEX(fmt) \ 151#define UVIDEO_FORMAT_GET_FORMAT_INDEX(fmt) \
152 ((fmt)->format.priv & 0xff) 152 ((fmt)->format.priv & 0xff)
153#define UVIDEO_FORMAT_GET_FRAME_INDEX(fmt) \ 153#define UVIDEO_FORMAT_GET_FRAME_INDEX(fmt) \
154 (((fmt)->format.priv >> 8) & 0xff) 154 (((fmt)->format.priv >> 8) & 0xff)
155/* TODO: find a better way to set bytes within this 32 bit value? */ 155/* TODO: find a better way to set bytes within this 32 bit value? */
156#define UVIDEO_FORMAT_SET_FORMAT_INDEX(fmt, index) do { \ 156#define UVIDEO_FORMAT_SET_FORMAT_INDEX(fmt, index) do { \
157 (fmt)->format.priv &= ~0xff; \ 157 (fmt)->format.priv &= ~0xff; \
158 (fmt)->format.priv |= ((index) & 0xff); \ 158 (fmt)->format.priv |= ((index) & 0xff); \
159 } while (0) 159 } while (0)
160#define UVIDEO_FORMAT_SET_FRAME_INDEX(fmt, index) do { \ 160#define UVIDEO_FORMAT_SET_FRAME_INDEX(fmt, index) do { \
161 (fmt)->format.priv &= ~(0xff << 8); \ 161 (fmt)->format.priv &= ~(0xff << 8); \
162 ((fmt)->format.priv |= (((index) & 0xff) << 8)); \ 162 ((fmt)->format.priv |= (((index) & 0xff) << 8)); \
163 } while (0) 163 } while (0)
164 164
165struct uvideo_pixel_format { 165struct uvideo_pixel_format {
166 enum video_pixel_format pixel_format; 166 enum video_pixel_format pixel_format;
167 SIMPLEQ_ENTRY(uvideo_pixel_format) entries; 167 SIMPLEQ_ENTRY(uvideo_pixel_format) entries;
168}; 168};
169SIMPLEQ_HEAD(uvideo_pixel_format_list, uvideo_pixel_format); 169SIMPLEQ_HEAD(uvideo_pixel_format_list, uvideo_pixel_format);
170 170
171struct uvideo_format { 171struct uvideo_format {
172 struct video_format format; 172 struct video_format format;
173 SIMPLEQ_ENTRY(uvideo_format) entries; 173 SIMPLEQ_ENTRY(uvideo_format) entries;
174}; 174};
175SIMPLEQ_HEAD(uvideo_format_list, uvideo_format); 175SIMPLEQ_HEAD(uvideo_format_list, uvideo_format);
176 176
177struct uvideo_isoc_xfer; 177struct uvideo_isoc_xfer;
178struct uvideo_stream; 178struct uvideo_stream;
179 179
180struct uvideo_isoc { 180struct uvideo_isoc {
181 struct uvideo_isoc_xfer *i_ix; 181 struct uvideo_isoc_xfer *i_ix;
182 struct uvideo_stream *i_vs; 182 struct uvideo_stream *i_vs;
183 usbd_xfer_handle i_xfer; 183 usbd_xfer_handle i_xfer;
184 uint8_t *i_buf; 184 uint8_t *i_buf;
185 uint16_t *i_frlengths; 185 uint16_t *i_frlengths;
186}; 186};
187 187
188struct uvideo_isoc_xfer { 188struct uvideo_isoc_xfer {
189 uint8_t ix_endpt; 189 uint8_t ix_endpt;
190 usbd_pipe_handle ix_pipe; 190 usbd_pipe_handle ix_pipe;
191 struct uvideo_isoc ix_i[UVIDEO_NXFERS]; 191 struct uvideo_isoc ix_i[UVIDEO_NXFERS];
192 uint32_t ix_nframes; 192 uint32_t ix_nframes;
193 uint32_t ix_uframe_len; 193 uint32_t ix_uframe_len;
194 194
195 struct altlist ix_altlist; 195 struct altlist ix_altlist;
196}; 196};
197 197
198struct uvideo_bulk_xfer { 198struct uvideo_bulk_xfer {
199 uint8_t bx_endpt; 199 uint8_t bx_endpt;
200 usbd_pipe_handle bx_pipe; 200 usbd_pipe_handle bx_pipe;
201 usbd_xfer_handle bx_xfer; 201 usbd_xfer_handle bx_xfer;
202 uint8_t *bx_buffer; 202 uint8_t *bx_buffer;
203 int bx_buflen; 203 int bx_buflen;
204 int bx_datalen; 204 int bx_datalen;
205}; 205};
206 206
207struct uvideo_stream { 207struct uvideo_stream {
208 struct uvideo_softc *vs_parent; 208 struct uvideo_softc *vs_parent;
209 usbd_interface_handle vs_iface; 209 usbd_interface_handle vs_iface;
210 uint8_t vs_ifaceno; 210 uint8_t vs_ifaceno;
211 uint8_t vs_subtype; /* input or output */ 211 uint8_t vs_subtype; /* input or output */
212 uint16_t vs_probelen; /* length of probe and 212 uint16_t vs_probelen; /* length of probe and
213 * commit data; varies 213 * commit data; varies
214 * depending on version 214 * depending on version
215 * of spec. */ 215 * of spec. */
216 struct uvideo_format_list vs_formats; 216 struct uvideo_format_list vs_formats;
217 struct uvideo_pixel_format_list vs_pixel_formats; 217 struct uvideo_pixel_format_list vs_pixel_formats;
218 struct video_format *vs_default_format; 218 struct video_format *vs_default_format;
219 struct video_format vs_current_format; 219 struct video_format vs_current_format;
220 220
221 /* usb transfer details */ 221 /* usb transfer details */
222 uint8_t vs_xfer_type; 222 uint8_t vs_xfer_type;
223 union { 223 union {
224 struct uvideo_bulk_xfer bulk; 224 struct uvideo_bulk_xfer bulk;
225 struct uvideo_isoc_xfer isoc; 225 struct uvideo_isoc_xfer isoc;
226 } vs_xfer; 226 } vs_xfer;
227 227
228 int vs_frameno; /* toggles between 0 and 1 */ 228 int vs_frameno; /* toggles between 0 and 1 */
229 229
230 /* current video format */ 230 /* current video format */
231 uint32_t vs_max_payload_size; 231 uint32_t vs_max_payload_size;
232 uint32_t vs_max_frame_size; 232 uint32_t vs_max_frame_size;
233 uint32_t vs_frame_interval; 233 uint32_t vs_frame_interval;
234 SLIST_ENTRY(uvideo_stream) entries; 234 SLIST_ENTRY(uvideo_stream) entries;
235}; 235};
236SLIST_HEAD(uvideo_stream_list, uvideo_stream); 236SLIST_HEAD(uvideo_stream_list, uvideo_stream);
237 237
238struct uvideo_softc { 238struct uvideo_softc {
239 USBBASEDEVICE sc_dev; /* base device */ 239 USBBASEDEVICE sc_dev; /* base device */
240 usbd_device_handle sc_udev; /* device */ 240 usbd_device_handle sc_udev; /* device */
241 usbd_interface_handle sc_iface; /* interface handle */ 241 usbd_interface_handle sc_iface; /* interface handle */
242 int sc_ifaceno; /* interface number */ 242 int sc_ifaceno; /* interface number */
243 char *sc_devname; 243 char *sc_devname;
244 244
245 device_ptr_t sc_videodev; 245 device_ptr_t sc_videodev;
246  246
247 int sc_dying; 247 int sc_dying;
248 uvideo_state sc_state; 248 uvideo_state sc_state;
249 249
250 uint8_t sc_nunits; 250 uint8_t sc_nunits;
251 struct uvideo_unit **sc_unit; 251 struct uvideo_unit **sc_unit;
252 252
253 struct uvideo_stream *sc_stream_in; 253 struct uvideo_stream *sc_stream_in;
254 254
255 struct uvideo_stream_list sc_stream_list; 255 struct uvideo_stream_list sc_stream_list;
256}; 256};
257 257
258int uvideo_match(device_t, cfdata_t, void *); 258int uvideo_match(device_t, cfdata_t, void *);
259void uvideo_attach(device_t, device_t, void *); 259void uvideo_attach(device_t, device_t, void *);
260int uvideo_detach(device_t, int); 260int uvideo_detach(device_t, int);
261void uvideo_childdet(device_t, device_t); 261void uvideo_childdet(device_t, device_t);
262int uvideo_activate(device_t, enum devact); 262int uvideo_activate(device_t, enum devact);
263 263
264static int uvideo_open(void *, int); 264static int uvideo_open(void *, int);
265static void uvideo_close(void *); 265static void uvideo_close(void *);
266static const char * uvideo_get_devname(void *); 266static const char * uvideo_get_devname(void *);
267 267
268static int uvideo_enum_format(void *, uint32_t, struct video_format *); 268static int uvideo_enum_format(void *, uint32_t, struct video_format *);
269static int uvideo_get_format(void *, struct video_format *); 269static int uvideo_get_format(void *, struct video_format *);
270static int uvideo_set_format(void *, struct video_format *); 270static int uvideo_set_format(void *, struct video_format *);
271static int uvideo_try_format(void *, struct video_format *); 271static int uvideo_try_format(void *, struct video_format *);
272static int uvideo_start_transfer(void *); 272static int uvideo_start_transfer(void *);
273static int uvideo_stop_transfer(void *); 273static int uvideo_stop_transfer(void *);
274 274
275static int uvideo_get_control_group(void *, 275static int uvideo_get_control_group(void *,
276 struct video_control_group *); 276 struct video_control_group *);
277static int uvideo_set_control_group(void *, 277static int uvideo_set_control_group(void *,
278 const struct video_control_group *); 278 const struct video_control_group *);
279 279
280static usbd_status uvideo_init_control( 280static usbd_status uvideo_init_control(
281 struct uvideo_softc *, 281 struct uvideo_softc *,
282 const usb_interface_descriptor_t *, 282 const usb_interface_descriptor_t *,
283 usbd_desc_iter_t *); 283 usbd_desc_iter_t *);
284static usbd_status uvideo_init_collection( 284static usbd_status uvideo_init_collection(
285 struct uvideo_softc *, 285 struct uvideo_softc *,
286 const usb_interface_descriptor_t *, 286 const usb_interface_descriptor_t *,
287 usbd_desc_iter_t *); 287 usbd_desc_iter_t *);
288 288
289/* Functions for unit & terminal descriptors */ 289/* Functions for unit & terminal descriptors */
290static struct uvideo_unit * uvideo_unit_alloc(const uvideo_descriptor_t *); 290static struct uvideo_unit * uvideo_unit_alloc(const uvideo_descriptor_t *);
291static usbd_status uvideo_unit_init(struct uvideo_unit *, 291static usbd_status uvideo_unit_init(struct uvideo_unit *,
292 const uvideo_descriptor_t *); 292 const uvideo_descriptor_t *);
293static void uvideo_unit_free(struct uvideo_unit *); 293static void uvideo_unit_free(struct uvideo_unit *);
294static usbd_status uvideo_unit_alloc_controls(struct uvideo_unit *, 294static usbd_status uvideo_unit_alloc_controls(struct uvideo_unit *,
295 uint8_t, 295 uint8_t,
296 const uint8_t *); 296 const uint8_t *);
297static void uvideo_unit_free_controls(struct uvideo_unit *); 297static void uvideo_unit_free_controls(struct uvideo_unit *);
298static usbd_status uvideo_unit_alloc_sources(struct uvideo_unit *, 298static usbd_status uvideo_unit_alloc_sources(struct uvideo_unit *,
299 uint8_t, 299 uint8_t,
300 const uint8_t *); 300 const uint8_t *);
301static void uvideo_unit_free_sources(struct uvideo_unit *); 301static void uvideo_unit_free_sources(struct uvideo_unit *);
302 302
303 303
304 304
305 305
306/* Functions for uvideo_stream, primary unit associated with a video 306/* Functions for uvideo_stream, primary unit associated with a video
307 * driver or device file. */ 307 * driver or device file. */
308static struct uvideo_stream * uvideo_find_stream(struct uvideo_softc *, 308static struct uvideo_stream * uvideo_find_stream(struct uvideo_softc *,
309 uint8_t); 309 uint8_t);
310#if 0 310#if 0
311static struct uvideo_format * uvideo_stream_find_format( 311static struct uvideo_format * uvideo_stream_find_format(
312 struct uvideo_stream *, 312 struct uvideo_stream *,
313 uint8_t, uint8_t); 313 uint8_t, uint8_t);
314#endif 314#endif
315static struct uvideo_format * uvideo_stream_guess_format( 315static struct uvideo_format * uvideo_stream_guess_format(
316 struct uvideo_stream *, 316 struct uvideo_stream *,
317 enum video_pixel_format, uint32_t, uint32_t); 317 enum video_pixel_format, uint32_t, uint32_t);
318static struct uvideo_stream * uvideo_stream_alloc(void); 318static struct uvideo_stream * uvideo_stream_alloc(void);
319static usbd_status uvideo_stream_init( 319static usbd_status uvideo_stream_init(
320 struct uvideo_stream *stream, 320 struct uvideo_stream *stream,
321 struct uvideo_softc *sc, 321 struct uvideo_softc *sc,
322 const usb_interface_descriptor_t *ifdesc, 322 const usb_interface_descriptor_t *ifdesc,
323 uint8_t idx); 323 uint8_t idx);
324static usbd_status uvideo_stream_init_desc( 324static usbd_status uvideo_stream_init_desc(
325 struct uvideo_stream *, 325 struct uvideo_stream *,
326 const usb_interface_descriptor_t *ifdesc, 326 const usb_interface_descriptor_t *ifdesc,
327 usbd_desc_iter_t *iter); 327 usbd_desc_iter_t *iter);
328static usbd_status uvideo_stream_init_frame_based_format( 328static usbd_status uvideo_stream_init_frame_based_format(
329 struct uvideo_stream *, 329 struct uvideo_stream *,
330 const uvideo_descriptor_t *, 330 const uvideo_descriptor_t *,
331 usbd_desc_iter_t *); 331 usbd_desc_iter_t *);
332static void uvideo_stream_free(struct uvideo_stream *); 332static void uvideo_stream_free(struct uvideo_stream *);
333 333
334static int uvideo_stream_start_xfer(struct uvideo_stream *); 334static int uvideo_stream_start_xfer(struct uvideo_stream *);
335static int uvideo_stream_stop_xfer(struct uvideo_stream *); 335static int uvideo_stream_stop_xfer(struct uvideo_stream *);
336static usbd_status uvideo_stream_recv_isoc_start(struct uvideo_stream *); 336static usbd_status uvideo_stream_recv_isoc_start(struct uvideo_stream *);
337static usbd_status uvideo_stream_recv_isoc_start1(struct uvideo_isoc *); 337static usbd_status uvideo_stream_recv_isoc_start1(struct uvideo_isoc *);
338static void uvideo_stream_recv_isoc_complete(usbd_xfer_handle, 338static void uvideo_stream_recv_isoc_complete(usbd_xfer_handle,
339 usbd_private_handle, 339 usbd_private_handle,
340 usbd_status); 340 usbd_status);
341 341
342/* format probe and commit */ 342/* format probe and commit */
343#define uvideo_stream_probe(vs, act, data) \ 343#define uvideo_stream_probe(vs, act, data) \
344 (uvideo_stream_probe_and_commit((vs), (act), \ 344 (uvideo_stream_probe_and_commit((vs), (act), \
345 UVIDEO_VS_PROBE_CONTROL, (data))) 345 UVIDEO_VS_PROBE_CONTROL, (data)))
346#define uvideo_stream_commit(vs, act, data) \ 346#define uvideo_stream_commit(vs, act, data) \
347 (uvideo_stream_probe_and_commit((vs), (act), \ 347 (uvideo_stream_probe_and_commit((vs), (act), \
348 UVIDEO_VS_COMMIT_CONTROL, (data))) 348 UVIDEO_VS_COMMIT_CONTROL, (data)))
349static usbd_status uvideo_stream_probe_and_commit(struct uvideo_stream *, 349static usbd_status uvideo_stream_probe_and_commit(struct uvideo_stream *,
350 uint8_t, uint8_t, 350 uint8_t, uint8_t,
351 void *); 351 void *);
352static void uvideo_init_probe_data(uvideo_probe_and_commit_data_t *); 352static void uvideo_init_probe_data(uvideo_probe_and_commit_data_t *);
353 353
354 354
355static const usb_descriptor_t * usb_desc_iter_peek_next(usbd_desc_iter_t *); 355static const usb_descriptor_t * usb_desc_iter_peek_next(usbd_desc_iter_t *);
356static const usb_interface_descriptor_t * usb_desc_iter_next_interface( 356static const usb_interface_descriptor_t * usb_desc_iter_next_interface(
357 usbd_desc_iter_t *); 357 usbd_desc_iter_t *);
358static const usb_descriptor_t * usb_desc_iter_next_non_interface( 358static const usb_descriptor_t * usb_desc_iter_next_non_interface(
359 usbd_desc_iter_t *); 359 usbd_desc_iter_t *);
360 360
361static int usb_guid_cmp(const usb_guid_t *, const guid_t *); 361static int usb_guid_cmp(const usb_guid_t *, const guid_t *);
362 362
363 363
364CFATTACH_DECL2_NEW(uvideo, sizeof(struct uvideo_softc), 364CFATTACH_DECL2_NEW(uvideo, sizeof(struct uvideo_softc),
365 uvideo_match, uvideo_attach, uvideo_detach, uvideo_activate, NULL, 365 uvideo_match, uvideo_attach, uvideo_detach, uvideo_activate, NULL,
366 uvideo_childdet); 366 uvideo_childdet);
367 367
368extern struct cfdriver uvideo_cd; 368extern struct cfdriver uvideo_cd;
369 369
370 370
371static const struct video_hw_if uvideo_hw_if = { 371static const struct video_hw_if uvideo_hw_if = {
372 .open = uvideo_open, 372 .open = uvideo_open,
373 .close = uvideo_close, 373 .close = uvideo_close,
374 .get_devname = uvideo_get_devname, 374 .get_devname = uvideo_get_devname,
375 .enum_format = uvideo_enum_format, 375 .enum_format = uvideo_enum_format,
376 .get_format = uvideo_get_format, 376 .get_format = uvideo_get_format,
377 .set_format = uvideo_set_format, 377 .set_format = uvideo_set_format,
378 .try_format = uvideo_try_format, 378 .try_format = uvideo_try_format,
379 .start_transfer = uvideo_start_transfer, 379 .start_transfer = uvideo_start_transfer,
380 .stop_transfer = uvideo_stop_transfer, 380 .stop_transfer = uvideo_stop_transfer,
381 .control_iter_init = NULL, 381 .control_iter_init = NULL,
382 .control_iter_next = NULL, 382 .control_iter_next = NULL,
383 .get_control_desc_group = NULL, 383 .get_control_desc_group = NULL,
384 .get_control_group = uvideo_get_control_group, 384 .get_control_group = uvideo_get_control_group,
385 .set_control_group = uvideo_set_control_group, 385 .set_control_group = uvideo_set_control_group,
386}; 386};
387 387
388#ifdef UVIDEO_DEBUG 388#ifdef UVIDEO_DEBUG
389/* Some functions to print out descriptors. Mostly useless other than 389/* Some functions to print out descriptors. Mostly useless other than
390 * debugging/exploration purposes. */ 390 * debugging/exploration purposes. */
391static void usb_guid_print(const usb_guid_t *); 391static void usb_guid_print(const usb_guid_t *);
392static void print_descriptor(const usb_descriptor_t *); 392static void print_descriptor(const usb_descriptor_t *);
393static void print_interface_descriptor(const usb_interface_descriptor_t *); 393static void print_interface_descriptor(const usb_interface_descriptor_t *);
394static void print_endpoint_descriptor(const usb_endpoint_descriptor_t *); 394static void print_endpoint_descriptor(const usb_endpoint_descriptor_t *);
395 395
396static void print_vc_descriptor(const usb_descriptor_t *); 396static void print_vc_descriptor(const usb_descriptor_t *);
397static void print_vs_descriptor(const usb_descriptor_t *); 397static void print_vs_descriptor(const usb_descriptor_t *);
398 398
399static void print_vc_header_descriptor( 399static void print_vc_header_descriptor(
400 const uvideo_vc_header_descriptor_t *); 400 const uvideo_vc_header_descriptor_t *);
401static void print_input_terminal_descriptor( 401static void print_input_terminal_descriptor(
402 const uvideo_input_terminal_descriptor_t *); 402 const uvideo_input_terminal_descriptor_t *);
403static void print_output_terminal_descriptor( 403static void print_output_terminal_descriptor(
404 const uvideo_output_terminal_descriptor_t *); 404 const uvideo_output_terminal_descriptor_t *);
405static void print_camera_terminal_descriptor( 405static void print_camera_terminal_descriptor(
406 const uvideo_camera_terminal_descriptor_t *); 406 const uvideo_camera_terminal_descriptor_t *);
407static void print_selector_unit_descriptor( 407static void print_selector_unit_descriptor(
408 const uvideo_selector_unit_descriptor_t *); 408 const uvideo_selector_unit_descriptor_t *);
409static void print_processing_unit_descriptor( 409static void print_processing_unit_descriptor(
410 const uvideo_processing_unit_descriptor_t *); 410 const uvideo_processing_unit_descriptor_t *);
411static void print_extension_unit_descriptor( 411static void print_extension_unit_descriptor(
412 const uvideo_extension_unit_descriptor_t *); 412 const uvideo_extension_unit_descriptor_t *);
413static void print_interrupt_endpoint_descriptor( 413static void print_interrupt_endpoint_descriptor(
414 const uvideo_vc_interrupt_endpoint_descriptor_t *); 414 const uvideo_vc_interrupt_endpoint_descriptor_t *);
415 415
416static void print_vs_input_header_descriptor( 416static void print_vs_input_header_descriptor(
417 const uvideo_vs_input_header_descriptor_t *); 417 const uvideo_vs_input_header_descriptor_t *);
418static void print_vs_output_header_descriptor( 418static void print_vs_output_header_descriptor(
419 const uvideo_vs_output_header_descriptor_t *); 419 const uvideo_vs_output_header_descriptor_t *);
420 420
421static void print_vs_format_uncompressed_descriptor( 421static void print_vs_format_uncompressed_descriptor(
422 const uvideo_vs_format_uncompressed_descriptor_t *); 422 const uvideo_vs_format_uncompressed_descriptor_t *);
423static void print_vs_frame_uncompressed_descriptor( 423static void print_vs_frame_uncompressed_descriptor(
424 const uvideo_vs_frame_uncompressed_descriptor_t *); 424 const uvideo_vs_frame_uncompressed_descriptor_t *);
425static void print_vs_format_mjpeg_descriptor( 425static void print_vs_format_mjpeg_descriptor(
426 const uvideo_vs_format_mjpeg_descriptor_t *); 426 const uvideo_vs_format_mjpeg_descriptor_t *);
427static void print_vs_frame_mjpeg_descriptor( 427static void print_vs_frame_mjpeg_descriptor(
428 const uvideo_vs_frame_mjpeg_descriptor_t *); 428 const uvideo_vs_frame_mjpeg_descriptor_t *);
429static void print_vs_format_dv_descriptor( 429static void print_vs_format_dv_descriptor(
430 const uvideo_vs_format_dv_descriptor_t *); 430 const uvideo_vs_format_dv_descriptor_t *);
431#endif /* !UVIDEO_DEBUG */ 431#endif /* !UVIDEO_DEBUG */
432 432
433#define GET(type, descp, field) (((const type *)(descp))->field) 433#define GET(type, descp, field) (((const type *)(descp))->field)
434#define GETP(type, descp, field) (&(((const type *)(descp))->field)) 434#define GETP(type, descp, field) (&(((const type *)(descp))->field))
435 435
436/* Given a format descriptor and frame descriptor, copy values common 436/* Given a format descriptor and frame descriptor, copy values common
437 * to all formats into a struct uvideo_format. */ 437 * to all formats into a struct uvideo_format. */
438#define UVIDEO_FORMAT_INIT_FRAME_BASED(format_type, format_desc, \ 438#define UVIDEO_FORMAT_INIT_FRAME_BASED(format_type, format_desc, \
439 frame_type, frame_desc, \ 439 frame_type, frame_desc, \
440 format) \ 440 format) \
441 do { \ 441 do { \
442 UVIDEO_FORMAT_SET_FORMAT_INDEX( \ 442 UVIDEO_FORMAT_SET_FORMAT_INDEX( \
443 format, \ 443 format, \
444 GET(format_type, format_desc, bFormatIndex)); \ 444 GET(format_type, format_desc, bFormatIndex)); \
445 UVIDEO_FORMAT_SET_FRAME_INDEX( \ 445 UVIDEO_FORMAT_SET_FRAME_INDEX( \
446 format, \ 446 format, \
447 GET(frame_type, frame_desc, bFrameIndex)); \ 447 GET(frame_type, frame_desc, bFrameIndex)); \
448 format->format.width = \ 448 format->format.width = \
449 UGETW(GET(frame_type, frame_desc, wWidth)); \ 449 UGETW(GET(frame_type, frame_desc, wWidth)); \
450 format->format.height = \ 450 format->format.height = \
451 UGETW(GET(frame_type, frame_desc, wHeight)); \ 451 UGETW(GET(frame_type, frame_desc, wHeight)); \
452 format->format.aspect_x = \ 452 format->format.aspect_x = \
453 GET(format_type, format_desc, bAspectRatioX); \ 453 GET(format_type, format_desc, bAspectRatioX); \
454 format->format.aspect_y = \ 454 format->format.aspect_y = \
455 GET(format_type, format_desc, bAspectRatioY); \ 455 GET(format_type, format_desc, bAspectRatioY); \
456 } while (0) 456 } while (0)
457 457
458 458
459USB_MATCH(uvideo) 459USB_MATCH(uvideo)
460{ 460{
461 USB_IFMATCH_START(uvideo, uaa); 461 USB_IFMATCH_START(uvideo, uaa);
462 462
463 /* TODO: May need to change in the future to work with 463 /* TODO: May need to change in the future to work with
464 * Interface Association Descriptor. */ 464 * Interface Association Descriptor. */
465 465
466 /* Trigger on the Video Control Interface which must be present */ 466 /* Trigger on the Video Control Interface which must be present */
467 if (uaa->class == UICLASS_VIDEO && 467 if (uaa->class == UICLASS_VIDEO &&
468 uaa->subclass == UISUBCLASS_VIDEOCONTROL) 468 uaa->subclass == UISUBCLASS_VIDEOCONTROL)
469 return UMATCH_IFACECLASS_IFACESUBCLASS; 469 return UMATCH_IFACECLASS_IFACESUBCLASS;
470 470
471 return UMATCH_NONE; 471 return UMATCH_NONE;
472} 472}
473 473
474USB_ATTACH(uvideo) 474USB_ATTACH(uvideo)
475{ 475{
476 USB_IFATTACH_START(uvideo, sc, uaa); 476 USB_IFATTACH_START(uvideo, sc, uaa);
477 usbd_desc_iter_t iter; 477 usbd_desc_iter_t iter;
478 const usb_interface_descriptor_t *ifdesc; 478 const usb_interface_descriptor_t *ifdesc;
479 struct uvideo_stream *vs; 479 struct uvideo_stream *vs;
480 usbd_status err; 480 usbd_status err;
481 uint8_t ifaceidx; 481 uint8_t ifaceidx;
482 482
483 sc->sc_dev = self; 483 sc->sc_dev = self;
484 484
485 sc->sc_devname = usbd_devinfo_alloc(uaa->device, 0); 485 sc->sc_devname = usbd_devinfo_alloc(uaa->device, 0);
486 486
487 aprint_naive("\n"); 487 aprint_naive("\n");
488 aprint_normal(": %s\n", sc->sc_devname); 488 aprint_normal(": %s\n", sc->sc_devname);
489  489
490 sc->sc_udev = uaa->device; 490 sc->sc_udev = uaa->device;
491 sc->sc_iface = uaa->iface; 491 sc->sc_iface = uaa->iface;
492 sc->sc_ifaceno = uaa->ifaceno; 492 sc->sc_ifaceno = uaa->ifaceno;
493 sc->sc_dying = 0; 493 sc->sc_dying = 0;
494 sc->sc_state = UVIDEO_STATE_CLOSED; 494 sc->sc_state = UVIDEO_STATE_CLOSED;
495 SLIST_INIT(&sc->sc_stream_list); 495 SLIST_INIT(&sc->sc_stream_list);
496 496
497#ifdef UVIDEO_DEBUG 497#ifdef UVIDEO_DEBUG
498 /* Debugging dump of descriptors. TODO: move this to userspace 498 /* Debugging dump of descriptors. TODO: move this to userspace
499 * via a custom IOCTL or something. */ 499 * via a custom IOCTL or something. */
500 const usb_descriptor_t *desc; 500 const usb_descriptor_t *desc;
501 usb_desc_iter_init(sc->sc_udev, &iter); 501 usb_desc_iter_init(sc->sc_udev, &iter);
502 while ((desc = usb_desc_iter_next(&iter)) != NULL) { 502 while ((desc = usb_desc_iter_next(&iter)) != NULL) {
503 /* print out all descriptors */ 503 /* print out all descriptors */
504 printf("uvideo_attach: "); 504 printf("uvideo_attach: ");
505 print_descriptor(desc); 505 print_descriptor(desc);
506 } 506 }
507#endif /* !UVIDEO_DEBUG */ 507#endif /* !UVIDEO_DEBUG */
508 508
509 /* iterate through interface descriptors and initialize softc */ 509 /* iterate through interface descriptors and initialize softc */
510 usb_desc_iter_init(sc->sc_udev, &iter); 510 usb_desc_iter_init(sc->sc_udev, &iter);
511 for (ifaceidx = 0; 511 for (ifaceidx = 0;
512 (ifdesc = usb_desc_iter_next_interface(&iter)) != NULL; 512 (ifdesc = usb_desc_iter_next_interface(&iter)) != NULL;
513 ++ifaceidx) 513 ++ifaceidx)
514 { 514 {
515 if (ifdesc->bInterfaceClass != UICLASS_VIDEO) { 515 if (ifdesc->bInterfaceClass != UICLASS_VIDEO) {
516 DPRINTFN(50, ("uvideo_attach: " 516 DPRINTFN(50, ("uvideo_attach: "
517 "ignoring non-uvc interface: " 517 "ignoring non-uvc interface: "
518 "len=%d type=0x%02x " 518 "len=%d type=0x%02x "
519 "class=0x%02x subclass=0x%02x\n", 519 "class=0x%02x subclass=0x%02x\n",
520 ifdesc->bLength, 520 ifdesc->bLength,
521 ifdesc->bDescriptorType, 521 ifdesc->bDescriptorType,
522 ifdesc->bInterfaceClass, 522 ifdesc->bInterfaceClass,
523 ifdesc->bInterfaceSubClass)); 523 ifdesc->bInterfaceSubClass));
524 continue; 524 continue;
525 } 525 }
526 526
527 switch (ifdesc->bInterfaceSubClass) { 527 switch (ifdesc->bInterfaceSubClass) {
528 case UISUBCLASS_VIDEOCONTROL: 528 case UISUBCLASS_VIDEOCONTROL:
529 err = uvideo_init_control(sc, ifdesc, &iter); 529 err = uvideo_init_control(sc, ifdesc, &iter);
530 if (err != USBD_NORMAL_COMPLETION) { 530 if (err != USBD_NORMAL_COMPLETION) {
531 DPRINTF(("uvideo_attach: error with interface " 531 DPRINTF(("uvideo_attach: error with interface "
532 "%d, VideoControl, " 532 "%d, VideoControl, "
533 "descriptor len=%d type=0x%02x: " 533 "descriptor len=%d type=0x%02x: "
534 "%s (%d)\n", 534 "%s (%d)\n",
535 ifdesc->bInterfaceNumber, 535 ifdesc->bInterfaceNumber,
536 ifdesc->bLength, 536 ifdesc->bLength,
537 ifdesc->bDescriptorType, 537 ifdesc->bDescriptorType,
538 usbd_errstr(err), err)); 538 usbd_errstr(err), err));
539 } 539 }
540 break; 540 break;
541 case UISUBCLASS_VIDEOSTREAMING: 541 case UISUBCLASS_VIDEOSTREAMING:
542 vs = uvideo_find_stream(sc, ifdesc->bInterfaceNumber); 542 vs = uvideo_find_stream(sc, ifdesc->bInterfaceNumber);
543 if (vs == NULL) { 543 if (vs == NULL) {
544 vs = uvideo_stream_alloc(); 544 vs = uvideo_stream_alloc();
545 if (vs == NULL) { 545 if (vs == NULL) {
546 DPRINTF(("uvideo_attach: " 546 DPRINTF(("uvideo_attach: "
547 "failed to alloc stream\n")); 547 "failed to alloc stream\n"));
548 err = USBD_NOMEM; 548 err = USBD_NOMEM;
549 goto bad; 549 goto bad;
550 } 550 }
551 err = uvideo_stream_init(vs, sc, ifdesc, 551 err = uvideo_stream_init(vs, sc, ifdesc,
552 ifaceidx); 552 ifaceidx);
553 if (err != USBD_NORMAL_COMPLETION) { 553 if (err != USBD_NORMAL_COMPLETION) {
554 DPRINTF(("uvideo_attach: " 554 DPRINTF(("uvideo_attach: "
555 "error initializing stream: " 555 "error initializing stream: "
556 "%s (%d)\n", 556 "%s (%d)\n",
557 usbd_errstr(err), err)); 557 usbd_errstr(err), err));
558 goto bad; 558 goto bad;
559 } 559 }
560 } 560 }
561 err = uvideo_stream_init_desc(vs, ifdesc, &iter); 561 err = uvideo_stream_init_desc(vs, ifdesc, &iter);
562 if (err != USBD_NORMAL_COMPLETION) { 562 if (err != USBD_NORMAL_COMPLETION) {
563 DPRINTF(("uvideo_attach: " 563 DPRINTF(("uvideo_attach: "
564 "error initializing stream descriptor: " 564 "error initializing stream descriptor: "
565 "%s (%d)\n", 565 "%s (%d)\n",
566 usbd_errstr(err), err)); 566 usbd_errstr(err), err));
567 goto bad; 567 goto bad;
568 } 568 }
569 /* TODO: for now, set (each) stream to stream_in. */ 569 /* TODO: for now, set (each) stream to stream_in. */
570 sc->sc_stream_in = vs; 570 sc->sc_stream_in = vs;
571 break; 571 break;
572 case UISUBCLASS_VIDEOCOLLECTION: 572 case UISUBCLASS_VIDEOCOLLECTION:
573 err = uvideo_init_collection(sc, ifdesc, &iter); 573 err = uvideo_init_collection(sc, ifdesc, &iter);
574 if (err != USBD_NORMAL_COMPLETION) { 574 if (err != USBD_NORMAL_COMPLETION) {
575 DPRINTF(("uvideo_attach: error with interface " 575 DPRINTF(("uvideo_attach: error with interface "
576 "%d, VideoCollection, " 576 "%d, VideoCollection, "
577 "descriptor len=%d type=0x%02x: " 577 "descriptor len=%d type=0x%02x: "
578 "%s (%d)\n", 578 "%s (%d)\n",
579 ifdesc->bInterfaceNumber, 579 ifdesc->bInterfaceNumber,
580 ifdesc->bLength, 580 ifdesc->bLength,
581 ifdesc->bDescriptorType, 581 ifdesc->bDescriptorType,
582 usbd_errstr(err), err)); 582 usbd_errstr(err), err));
583 goto bad; 583 goto bad;
584 } 584 }
585 break; 585 break;
586 default: 586 default:
587 DPRINTF(("uvideo_attach: unknown UICLASS_VIDEO " 587 DPRINTF(("uvideo_attach: unknown UICLASS_VIDEO "
588 "subclass=0x%02x\n", 588 "subclass=0x%02x\n",
589 ifdesc->bInterfaceSubClass)); 589 ifdesc->bInterfaceSubClass));
590 break; 590 break;
591 } 591 }
592 592
593 } 593 }
594 594
595  595
596 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 596 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
597 USBDEV(sc->sc_dev)); 597 USBDEV(sc->sc_dev));
598 598
599 sc->sc_videodev = video_attach_mi(&uvideo_hw_if, sc->sc_dev); 599 sc->sc_videodev = video_attach_mi(&uvideo_hw_if, sc->sc_dev);
600 DPRINTF(("uvideo_attach: attached video driver at %p\n", 600 DPRINTF(("uvideo_attach: attached video driver at %p\n",
601 sc->sc_videodev)); 601 sc->sc_videodev));
602 602
603 USB_ATTACH_SUCCESS_RETURN; 603 USB_ATTACH_SUCCESS_RETURN;
604 604
605bad: 605bad:
606 if (err != USBD_NORMAL_COMPLETION) { 606 if (err != USBD_NORMAL_COMPLETION) {
607 DPRINTF(("uvideo_attach: error: %s (%d)\n", 607 DPRINTF(("uvideo_attach: error: %s (%d)\n",
608 usbd_errstr(err), err)); 608 usbd_errstr(err), err));
609 } 609 }
610 USB_ATTACH_ERROR_RETURN; 610 USB_ATTACH_ERROR_RETURN;
611} 611}
612 612
613 613
614int 614int
615uvideo_activate(device_t self, enum devact act) 615uvideo_activate(device_t self, enum devact act)
616{ 616{
617 struct uvideo_softc *sc; 617 struct uvideo_softc *sc;
618 int rv; 618 int rv;
619  619
620 sc = device_private(self); 620 sc = device_private(self);
621 rv = 0; 621 rv = 0;
622 switch (act) { 622 switch (act) {
623 case DVACT_ACTIVATE: 623 case DVACT_ACTIVATE:
624 return EOPNOTSUPP; 624 return EOPNOTSUPP;
625 625
626 case DVACT_DEACTIVATE: 626 case DVACT_DEACTIVATE:
627 DPRINTF(("uvideo_activate: deactivating\n")); 627 DPRINTF(("uvideo_activate: deactivating\n"));
628 if (sc->sc_videodev != NULL) 628 if (sc->sc_videodev != NULL)
629 rv = config_deactivate(sc->sc_videodev); 629 rv = config_deactivate(sc->sc_videodev);
630 sc->sc_dying = 1; 630 sc->sc_dying = 1;
631 break; 631 break;
632 } 632 }
633 return rv; 633 return rv;
634} 634}
635 635
636 636
637/* Detach child (video interface) */ 637/* Detach child (video interface) */
638void 638void
639uvideo_childdet(device_t self, device_t child) 639uvideo_childdet(device_t self, device_t child)
640{ 640{
641 struct uvideo_softc *sc = device_private(self); 641 struct uvideo_softc *sc = device_private(self);
642 642
643 KASSERT(sc->sc_videodev == child); 643 KASSERT(sc->sc_videodev == child);
644 sc->sc_videodev = NULL; 644 sc->sc_videodev = NULL;
645} 645}
646 646
647 647
648int 648int
649uvideo_detach(device_t self, int flags) 649uvideo_detach(device_t self, int flags)
650{ 650{
651 struct uvideo_softc *sc; 651 struct uvideo_softc *sc;
652 struct uvideo_stream *vs; 652 struct uvideo_stream *vs;
653 int rv; 653 int rv;
654 654
655 sc = device_private(self); 655 sc = device_private(self);
656 rv = 0; 656 rv = 0;
657  657
658 sc->sc_dying = 1; 658 sc->sc_dying = 1;
659 659
660 usbd_devinfo_free(sc->sc_devname); 660 usbd_devinfo_free(sc->sc_devname);
661 661
662 /* TODO: close the device if it is currently opened? Or will 662 /* TODO: close the device if it is currently opened? Or will
663 * close be called automatically? */ 663 * close be called automatically? */
664 664
665 while (!SLIST_EMPTY(&sc->sc_stream_list)) { 665 while (!SLIST_EMPTY(&sc->sc_stream_list)) {
666 vs = SLIST_FIRST(&sc->sc_stream_list); 666 vs = SLIST_FIRST(&sc->sc_stream_list);
667 SLIST_REMOVE_HEAD(&sc->sc_stream_list, entries); 667 SLIST_REMOVE_HEAD(&sc->sc_stream_list, entries);
668 uvideo_stream_free(vs); 668 uvideo_stream_free(vs);
669 } 669 }
670 670
671 /* Wait for outstanding request to complete. TODO: what is 671 /* Wait for outstanding request to complete. TODO: what is
672 * appropriate here? */ 672 * appropriate here? */
673 usbd_delay_ms(sc->sc_udev, 1000); 673 usbd_delay_ms(sc->sc_udev, 1000);
674 674
675 DPRINTFN(15, ("uvideo: detaching from %s\n", 675 DPRINTFN(15, ("uvideo: detaching from %s\n",
676 USBDEVNAME(sc->sc_dev))); 676 USBDEVNAME(sc->sc_dev)));
677 677
678 if (sc->sc_videodev != NULL) 678 if (sc->sc_videodev != NULL)
679 rv = config_detach(sc->sc_videodev, flags); 679 rv = config_detach(sc->sc_videodev, flags);
680 680
681 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 681 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
682 USBDEV(sc->sc_dev)); 682 USBDEV(sc->sc_dev));
683 683
684 return rv; 684 return rv;
685} 685}
686 686
687/* Search the stream list for a stream matching the interface number. 687/* Search the stream list for a stream matching the interface number.
688 * This is an O(n) search, but most devices should have only one or at 688 * This is an O(n) search, but most devices should have only one or at
689 * most two streams. */ 689 * most two streams. */
690static struct uvideo_stream * 690static struct uvideo_stream *
691uvideo_find_stream(struct uvideo_softc *sc, uint8_t ifaceno) 691uvideo_find_stream(struct uvideo_softc *sc, uint8_t ifaceno)
692{ 692{
693 struct uvideo_stream *vs; 693 struct uvideo_stream *vs;
694  694
695 SLIST_FOREACH(vs, &sc->sc_stream_list, entries) { 695 SLIST_FOREACH(vs, &sc->sc_stream_list, entries) {
696 if (vs->vs_ifaceno == ifaceno) 696 if (vs->vs_ifaceno == ifaceno)
697 return vs; 697 return vs;
698 } 698 }
699 699
700 return NULL; 700 return NULL;
701} 701}
702 702
703/* Search the format list for the given format and frame index. This 703/* Search the format list for the given format and frame index. This
704 * might be improved through indexing, but the format and frame count 704 * might be improved through indexing, but the format and frame count
705 * is unknown ahead of time (only after iterating through the 705 * is unknown ahead of time (only after iterating through the
706 * usb device descriptors). */ 706 * usb device descriptors). */
707#if 0 707#if 0
708static struct uvideo_format * 708static struct uvideo_format *
709uvideo_stream_find_format(struct uvideo_stream *vs, 709uvideo_stream_find_format(struct uvideo_stream *vs,
710 uint8_t format_index, uint8_t frame_index) 710 uint8_t format_index, uint8_t frame_index)
711{ 711{
712 struct uvideo_format *format; 712 struct uvideo_format *format;
713  713
714 SIMPLEQ_FOREACH(format, &vs->vs_formats, entries) { 714 SIMPLEQ_FOREACH(format, &vs->vs_formats, entries) {
715 if (UVIDEO_FORMAT_GET_FORMAT_INDEX(format) == format_index && 715 if (UVIDEO_FORMAT_GET_FORMAT_INDEX(format) == format_index &&
716 UVIDEO_FORMAT_GET_FRAME_INDEX(format) == frame_index) 716 UVIDEO_FORMAT_GET_FRAME_INDEX(format) == frame_index)
717 return format; 717 return format;
718 } 718 }
719 return NULL; 719 return NULL;
720} 720}
721#endif 721#endif
722 722
723static struct uvideo_format * 723static struct uvideo_format *
724uvideo_stream_guess_format(struct uvideo_stream *vs, 724uvideo_stream_guess_format(struct uvideo_stream *vs,
725 enum video_pixel_format pixel_format, 725 enum video_pixel_format pixel_format,
726 uint32_t width, uint32_t height) 726 uint32_t width, uint32_t height)
727{ 727{
728 struct uvideo_format *format, *gformat = NULL; 728 struct uvideo_format *format, *gformat = NULL;
729 729
730 SIMPLEQ_FOREACH(format, &vs->vs_formats, entries) { 730 SIMPLEQ_FOREACH(format, &vs->vs_formats, entries) {
731 if (format->format.pixel_format != pixel_format) 731 if (format->format.pixel_format != pixel_format)
732 continue; 732 continue;
733 if (format->format.width <= width && 733 if (format->format.width <= width &&
734 format->format.height <= height) { 734 format->format.height <= height) {
735 if (gformat == NULL || 735 if (gformat == NULL ||
736 (gformat->format.width < format->format.width && 736 (gformat->format.width < format->format.width &&
737 gformat->format.height < format->format.height)) 737 gformat->format.height < format->format.height))
738 gformat = format; 738 gformat = format;
739 } 739 }
740 } 740 }
741 741
742 return gformat; 742 return gformat;
743} 743}
744 744
745static struct uvideo_stream * 745static struct uvideo_stream *
746uvideo_stream_alloc(void) 746uvideo_stream_alloc(void)
747{ 747{
748 return (kmem_alloc(sizeof(struct uvideo_stream), KM_NOSLEEP)); 748 return (kmem_alloc(sizeof(struct uvideo_stream), KM_NOSLEEP));
749} 749}
750 750
751 751
752static usbd_status 752static usbd_status
753uvideo_init_control(struct uvideo_softc *sc, 753uvideo_init_control(struct uvideo_softc *sc,
754 const usb_interface_descriptor_t *ifdesc, 754 const usb_interface_descriptor_t *ifdesc,
755 usbd_desc_iter_t *iter) 755 usbd_desc_iter_t *iter)
756{ 756{
757 const usb_descriptor_t *desc; 757 const usb_descriptor_t *desc;
758 const uvideo_descriptor_t *uvdesc; 758 const uvideo_descriptor_t *uvdesc;
759 usbd_desc_iter_t orig; 759 usbd_desc_iter_t orig;
760 uint8_t i, j, nunits; 760 uint8_t i, j, nunits;
761  761
762 /* save original iterator state */ 762 /* save original iterator state */
763 memcpy(&orig, iter, sizeof(orig)); 763 memcpy(&orig, iter, sizeof(orig));
764  764
765 /* count number of units and terminals */ 765 /* count number of units and terminals */
766 nunits = 0; 766 nunits = 0;
767 while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) { 767 while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) {
768 uvdesc = (const uvideo_descriptor_t *)desc; 768 uvdesc = (const uvideo_descriptor_t *)desc;
769 769
770 if (uvdesc->bDescriptorType != UDESC_CS_INTERFACE) 770 if (uvdesc->bDescriptorType != UDESC_CS_INTERFACE)
771 continue; 771 continue;
772 if (uvdesc->bDescriptorSubtype < UDESC_INPUT_TERMINAL || 772 if (uvdesc->bDescriptorSubtype < UDESC_INPUT_TERMINAL ||
773 uvdesc->bDescriptorSubtype > UDESC_EXTENSION_UNIT) 773 uvdesc->bDescriptorSubtype > UDESC_EXTENSION_UNIT)
774 ++nunits; 774 ++nunits;
775 } 775 }
776 776
777 if (nunits == 0) { 777 if (nunits == 0) {
778 DPRINTF(("uvideo_init_control: no units\n")); 778 DPRINTF(("uvideo_init_control: no units\n"));
779 return USBD_NORMAL_COMPLETION; 779 return USBD_NORMAL_COMPLETION;
780 } 780 }
781 781
782 /* allocate space for units */ 782 /* allocate space for units */
783 sc->sc_nunits = nunits; 783 sc->sc_nunits = nunits;
784 sc->sc_unit = kmem_alloc(sizeof(*sc->sc_unit) * nunits, KM_SLEEP); 784 sc->sc_unit = kmem_alloc(sizeof(*sc->sc_unit) * nunits, KM_SLEEP);
785 if (sc->sc_unit == NULL) 785 if (sc->sc_unit == NULL)
786 goto enomem; 786 goto enomem;
787 787
788 /* restore original iterator state */ 788 /* restore original iterator state */
789 memcpy(iter, &orig, sizeof(orig)); 789 memcpy(iter, &orig, sizeof(orig));
790  790
791 /* iterate again, initializing the units */ 791 /* iterate again, initializing the units */
792 i = 0; 792 i = 0;
793 while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) { 793 while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) {
794 uvdesc = (const uvideo_descriptor_t *)desc; 794 uvdesc = (const uvideo_descriptor_t *)desc;
795 795
796 if (uvdesc->bDescriptorType != UDESC_CS_INTERFACE) 796 if (uvdesc->bDescriptorType != UDESC_CS_INTERFACE)
797 continue; 797 continue;
798 if (uvdesc->bDescriptorSubtype < UDESC_INPUT_TERMINAL || 798 if (uvdesc->bDescriptorSubtype < UDESC_INPUT_TERMINAL ||
799 uvdesc->bDescriptorSubtype > UDESC_EXTENSION_UNIT) 799 uvdesc->bDescriptorSubtype > UDESC_EXTENSION_UNIT)
800 continue; 800 continue;
801 801
802 sc->sc_unit[i] = uvideo_unit_alloc(uvdesc); 802 sc->sc_unit[i] = uvideo_unit_alloc(uvdesc);
803 /* TODO: free other units before returning? */ 803 /* TODO: free other units before returning? */
804 if (sc->sc_unit[i] == NULL) 804 if (sc->sc_unit[i] == NULL)
805 goto enomem; 805 goto enomem;
806 ++i; 806 ++i;
807 } 807 }
808  808
809 return USBD_NORMAL_COMPLETION; 809 return USBD_NORMAL_COMPLETION;
810 810
811enomem: 811enomem:
812 if (sc->sc_unit != NULL) { 812 if (sc->sc_unit != NULL) {
813 for (j = 0; j < i; ++j) { 813 for (j = 0; j < i; ++j) {
814 uvideo_unit_free(sc->sc_unit[j]); 814 uvideo_unit_free(sc->sc_unit[j]);
815 sc->sc_unit[j] = NULL; 815 sc->sc_unit[j] = NULL;
816 } 816 }
817 kmem_free(sc->sc_unit, sizeof(*sc->sc_unit) * nunits); 817 kmem_free(sc->sc_unit, sizeof(*sc->sc_unit) * nunits);
818 sc->sc_unit = NULL; 818 sc->sc_unit = NULL;
819 } 819 }
820 sc->sc_nunits = 0; 820 sc->sc_nunits = 0;
821  821
822 return USBD_NOMEM; 822 return USBD_NOMEM;
823} 823}
824 824
825static usbd_status 825static usbd_status
826uvideo_init_collection(struct uvideo_softc *sc, 826uvideo_init_collection(struct uvideo_softc *sc,
827 const usb_interface_descriptor_t *ifdesc, 827 const usb_interface_descriptor_t *ifdesc,
828 usbd_desc_iter_t *iter) 828 usbd_desc_iter_t *iter)
829{ 829{
830 DPRINTF(("uvideo: ignoring Video Collection\n")); 830 DPRINTF(("uvideo: ignoring Video Collection\n"));
831 return USBD_NORMAL_COMPLETION; 831 return USBD_NORMAL_COMPLETION;
832} 832}
833 833
834/* Allocates space for and initializes a uvideo unit based on the 834/* Allocates space for and initializes a uvideo unit based on the
835 * given descriptor. Returns NULL with bad descriptor or ENOMEM. */ 835 * given descriptor. Returns NULL with bad descriptor or ENOMEM. */
836static struct uvideo_unit * 836static struct uvideo_unit *
837uvideo_unit_alloc(const uvideo_descriptor_t *desc) 837uvideo_unit_alloc(const uvideo_descriptor_t *desc)
838{ 838{
839 struct uvideo_unit *vu; 839 struct uvideo_unit *vu;
840 usbd_status err; 840 usbd_status err;
841  841
842 if (desc->bDescriptorType != UDESC_CS_INTERFACE) 842 if (desc->bDescriptorType != UDESC_CS_INTERFACE)
843 return NULL; 843 return NULL;
844 844
845 vu = kmem_alloc(sizeof(*vu), KM_SLEEP); 845 vu = kmem_alloc(sizeof(*vu), KM_SLEEP);
846 if (vu == NULL) 846 if (vu == NULL)
847 return NULL; 847 return NULL;
848 848
849 err = uvideo_unit_init(vu, desc); 849 err = uvideo_unit_init(vu, desc);
850 if (err != USBD_NORMAL_COMPLETION) { 850 if (err != USBD_NORMAL_COMPLETION) {
851 DPRINTF(("uvideo_unit_alloc: error initializing unit: " 851 DPRINTF(("uvideo_unit_alloc: error initializing unit: "
852 "%s (%d)\n", usbd_errstr(err), err)); 852 "%s (%d)\n", usbd_errstr(err), err));
853 kmem_free(vu, sizeof(*vu)); 853 kmem_free(vu, sizeof(*vu));
854 return NULL; 854 return NULL;
855 } 855 }
856 856
857 return vu; 857 return vu;
858} 858}
859 859
860static usbd_status 860static usbd_status
861uvideo_unit_init(struct uvideo_unit *vu, const uvideo_descriptor_t *desc) 861uvideo_unit_init(struct uvideo_unit *vu, const uvideo_descriptor_t *desc)
862{ 862{
863 struct uvideo_camera_terminal *ct; 863 struct uvideo_camera_terminal *ct;
864 struct uvideo_processing_unit *pu; 864 struct uvideo_processing_unit *pu;
865 struct uvideo_extension_unit *xu; 865 struct uvideo_extension_unit *xu;
866  866
867 const uvideo_input_terminal_descriptor_t *input; 867 const uvideo_input_terminal_descriptor_t *input;
868 const uvideo_output_terminal_descriptor_t *output; 868 const uvideo_output_terminal_descriptor_t *output;
869 const uvideo_camera_terminal_descriptor_t *camera; 869 const uvideo_camera_terminal_descriptor_t *camera;
870 const uvideo_selector_unit_descriptor_t *selector; 870 const uvideo_selector_unit_descriptor_t *selector;
871 const uvideo_processing_unit_descriptor_t *processing; 871 const uvideo_processing_unit_descriptor_t *processing;
872 const uvideo_extension_unit_descriptor_t *extension; 872 const uvideo_extension_unit_descriptor_t *extension;
873 873
874 memset(vu, 0, sizeof(*vu)); 874 memset(vu, 0, sizeof(*vu));
875 875
876 switch (desc->bDescriptorSubtype) { 876 switch (desc->bDescriptorSubtype) {
877 case UDESC_INPUT_TERMINAL: 877 case UDESC_INPUT_TERMINAL:
878 input = (const uvideo_input_terminal_descriptor_t *)desc; 878 input = (const uvideo_input_terminal_descriptor_t *)desc;
879 switch (UGETW(input->wTerminalType)) { 879 switch (UGETW(input->wTerminalType)) {
880 case UVIDEO_ITT_CAMERA: 880 case UVIDEO_ITT_CAMERA:
881 camera = 881 camera =
882 (const uvideo_camera_terminal_descriptor_t *)desc; 882 (const uvideo_camera_terminal_descriptor_t *)desc;
883 ct = &vu->u.vu_camera; 883 ct = &vu->u.vu_camera;
884  884
885 ct->ct_objective_focal_min = 885 ct->ct_objective_focal_min =
886 UGETW(camera->wObjectiveFocalLengthMin); 886 UGETW(camera->wObjectiveFocalLengthMin);
887 ct->ct_objective_focal_max = 887 ct->ct_objective_focal_max =
888 UGETW(camera->wObjectiveFocalLengthMax); 888 UGETW(camera->wObjectiveFocalLengthMax);
889 ct->ct_ocular_focal_length = 889 ct->ct_ocular_focal_length =
890 UGETW(camera->wOcularFocalLength); 890 UGETW(camera->wOcularFocalLength);
891 891
892 uvideo_unit_alloc_controls(vu, camera->bControlSize, 892 uvideo_unit_alloc_controls(vu, camera->bControlSize,
893 camera->bmControls); 893 camera->bmControls);
894 break; 894 break;
895 default: 895 default:
896 DPRINTF(("uvideo_unit_init: " 896 DPRINTF(("uvideo_unit_init: "
897 "unknown input terminal type 0x%04x\n", 897 "unknown input terminal type 0x%04x\n",
898 UGETW(input->wTerminalType))); 898 UGETW(input->wTerminalType)));
899 return USBD_INVAL; 899 return USBD_INVAL;
900 } 900 }
901 break; 901 break;
902 case UDESC_OUTPUT_TERMINAL: 902 case UDESC_OUTPUT_TERMINAL:
903 output = (const uvideo_output_terminal_descriptor_t *)desc; 903 output = (const uvideo_output_terminal_descriptor_t *)desc;
904 break; 904 break;
905 case UDESC_SELECTOR_UNIT: 905 case UDESC_SELECTOR_UNIT:
906 selector = (const uvideo_selector_unit_descriptor_t *)desc; 906 selector = (const uvideo_selector_unit_descriptor_t *)desc;
907 907
908 uvideo_unit_alloc_sources(vu, selector->bNrInPins, 908 uvideo_unit_alloc_sources(vu, selector->bNrInPins,
909 selector->baSourceID); 909 selector->baSourceID);
910 break; 910 break;
911 case UDESC_PROCESSING_UNIT: 911 case UDESC_PROCESSING_UNIT:
912 processing = (const uvideo_processing_unit_descriptor_t *)desc; 912 processing = (const uvideo_processing_unit_descriptor_t *)desc;
913 pu = &vu->u.vu_processing; 913 pu = &vu->u.vu_processing;
914 914
915 pu->pu_video_standards = PU_GET_VIDEO_STANDARDS(processing); 915 pu->pu_video_standards = PU_GET_VIDEO_STANDARDS(processing);
916 pu->pu_max_multiplier = UGETW(processing->wMaxMultiplier); 916 pu->pu_max_multiplier = UGETW(processing->wMaxMultiplier);
917 917
918 uvideo_unit_alloc_sources(vu, 1, &processing->bSourceID); 918 uvideo_unit_alloc_sources(vu, 1, &processing->bSourceID);
919 uvideo_unit_alloc_controls(vu, processing->bControlSize, 919 uvideo_unit_alloc_controls(vu, processing->bControlSize,
920 processing->bmControls); 920 processing->bmControls);
921 break; 921 break;
922 case UDESC_EXTENSION_UNIT: 922 case UDESC_EXTENSION_UNIT:
923 extension = (const uvideo_extension_unit_descriptor_t *)desc; 923 extension = (const uvideo_extension_unit_descriptor_t *)desc;
924 xu = &vu->u.vu_extension; 924 xu = &vu->u.vu_extension;
925 /* TODO: copy guid */ 925 /* TODO: copy guid */
926 926
927 uvideo_unit_alloc_sources(vu, extension->bNrInPins, 927 uvideo_unit_alloc_sources(vu, extension->bNrInPins,
928 extension->baSourceID); 928 extension->baSourceID);
929 uvideo_unit_alloc_controls(vu, XU_GET_CONTROL_SIZE(extension), 929 uvideo_unit_alloc_controls(vu, XU_GET_CONTROL_SIZE(extension),
930 XU_GET_CONTROLS(extension)); 930 XU_GET_CONTROLS(extension));
931 break; 931 break;
932 default: 932 default:
933 DPRINTF(("uvideo_unit_alloc: unknown descriptor " 933 DPRINTF(("uvideo_unit_alloc: unknown descriptor "
934 "type=0x%02x subtype=0x%02x\n", 934 "type=0x%02x subtype=0x%02x\n",
935 desc->bDescriptorType, desc->bDescriptorSubtype)); 935 desc->bDescriptorType, desc->bDescriptorSubtype));
936 return USBD_INVAL; 936 return USBD_INVAL;
937 } 937 }
938 938
939 return USBD_NORMAL_COMPLETION; 939 return USBD_NORMAL_COMPLETION;
940} 940}
941 941
942static void 942static void
943uvideo_unit_free(struct uvideo_unit *vu) 943uvideo_unit_free(struct uvideo_unit *vu)
944{ 944{
945 uvideo_unit_free_sources(vu); 945 uvideo_unit_free_sources(vu);
946 uvideo_unit_free_controls(vu); 946 uvideo_unit_free_controls(vu);
947 kmem_free(vu, sizeof(*vu)); 947 kmem_free(vu, sizeof(*vu));
948} 948}
949 949
950static usbd_status 950static usbd_status
951uvideo_unit_alloc_sources(struct uvideo_unit *vu, 951uvideo_unit_alloc_sources(struct uvideo_unit *vu,
952 uint8_t nsrcs, const uint8_t *src_ids) 952 uint8_t nsrcs, const uint8_t *src_ids)
953{ 953{
954 vu->vu_nsrcs = nsrcs; 954 vu->vu_nsrcs = nsrcs;
955  955
956 if (nsrcs == 0) { 956 if (nsrcs == 0) {
957 /* do nothing */ 957 /* do nothing */
958 } else if (nsrcs == 1) { 958 } else if (nsrcs == 1) {
959 vu->s.vu_src_id = src_ids[0]; 959 vu->s.vu_src_id = src_ids[0];
960 } else { 960 } else {
961 vu->s.vu_src_id_ary = 961 vu->s.vu_src_id_ary =
962 kmem_alloc(sizeof(*vu->s.vu_src_id_ary) * nsrcs, KM_SLEEP); 962 kmem_alloc(sizeof(*vu->s.vu_src_id_ary) * nsrcs, KM_SLEEP);
963 if (vu->s.vu_src_id_ary == NULL) { 963 if (vu->s.vu_src_id_ary == NULL) {
964 vu->vu_nsrcs = 0; 964 vu->vu_nsrcs = 0;
965 return USBD_NOMEM; 965 return USBD_NOMEM;
966 } 966 }
967 967
968 memcpy(vu->s.vu_src_id_ary, src_ids, nsrcs); 968 memcpy(vu->s.vu_src_id_ary, src_ids, nsrcs);
969 } 969 }
970 970
971 return USBD_NORMAL_COMPLETION; 971 return USBD_NORMAL_COMPLETION;
972} 972}
973 973
974static void 974static void
975uvideo_unit_free_sources(struct uvideo_unit *vu) 975uvideo_unit_free_sources(struct uvideo_unit *vu)
976{ 976{
977 if (vu->vu_nsrcs == 1) 977 if (vu->vu_nsrcs == 1)
978 return; 978 return;
979 979
980 kmem_free(vu->s.vu_src_id_ary, 980 kmem_free(vu->s.vu_src_id_ary,
981 sizeof(*vu->s.vu_src_id_ary) * vu->vu_nsrcs); 981 sizeof(*vu->s.vu_src_id_ary) * vu->vu_nsrcs);
982 vu->vu_nsrcs = 0; 982 vu->vu_nsrcs = 0;
983 vu->s.vu_src_id_ary = NULL; 983 vu->s.vu_src_id_ary = NULL;
984} 984}
985 985
986static usbd_status 986static usbd_status
987uvideo_unit_alloc_controls(struct uvideo_unit *vu, uint8_t size, 987uvideo_unit_alloc_controls(struct uvideo_unit *vu, uint8_t size,
988 const uint8_t *controls) 988 const uint8_t *controls)
989{ 989{
990 vu->vu_controls = kmem_alloc(sizeof(*vu->vu_controls) * size, KM_SLEEP); 990 vu->vu_controls = kmem_alloc(sizeof(*vu->vu_controls) * size, KM_SLEEP);
991 if (vu->vu_controls == NULL) 991 if (vu->vu_controls == NULL)
992 return USBD_NOMEM; 992 return USBD_NOMEM;
993 993
994 vu->vu_control_size = size; 994 vu->vu_control_size = size;
995 memcpy(vu->vu_controls, controls, size); 995 memcpy(vu->vu_controls, controls, size);
996 996
997 return USBD_NORMAL_COMPLETION; 997 return USBD_NORMAL_COMPLETION;
998} 998}
999 999
1000static void 1000static void
1001uvideo_unit_free_controls(struct uvideo_unit *vu) 1001uvideo_unit_free_controls(struct uvideo_unit *vu)
1002{ 1002{
1003 kmem_free(vu->vu_controls, 1003 kmem_free(vu->vu_controls,
1004 sizeof(*vu->vu_controls) * vu->vu_control_size); 1004 sizeof(*vu->vu_controls) * vu->vu_control_size);
1005 vu->vu_controls = NULL; 1005 vu->vu_controls = NULL;
1006 vu->vu_control_size = 0; 1006 vu->vu_control_size = 0;
1007} 1007}
1008 1008
1009 1009
1010/* Initialize a stream from a Video Streaming interface 1010/* Initialize a stream from a Video Streaming interface
1011 * descriptor. Adds the stream to the stream_list in uvideo_softc. 1011 * descriptor. Adds the stream to the stream_list in uvideo_softc.
1012 * This should be called once for new streams, and 1012 * This should be called once for new streams, and
1013 * uvideo_stream_init_desc() should then be called for this and each 1013 * uvideo_stream_init_desc() should then be called for this and each
1014 * additional interface with the same interface number. */ 1014 * additional interface with the same interface number. */
1015static usbd_status 1015static usbd_status
1016uvideo_stream_init(struct uvideo_stream *vs, 1016uvideo_stream_init(struct uvideo_stream *vs,
1017 struct uvideo_softc *sc, 1017 struct uvideo_softc *sc,
1018 const usb_interface_descriptor_t *ifdesc, 1018 const usb_interface_descriptor_t *ifdesc,
1019 uint8_t idx) 1019 uint8_t idx)
1020{ 1020{
1021 uWord len; 1021 uWord len;
1022 usbd_status err; 1022 usbd_status err;
1023 1023
1024 SLIST_INSERT_HEAD(&sc->sc_stream_list, vs, entries); 1024 SLIST_INSERT_HEAD(&sc->sc_stream_list, vs, entries);
1025 memset(vs, 0, sizeof(*vs)); 1025 memset(vs, 0, sizeof(*vs));
1026 vs->vs_parent = sc; 1026 vs->vs_parent = sc;
1027 vs->vs_ifaceno = ifdesc->bInterfaceNumber; 1027 vs->vs_ifaceno = ifdesc->bInterfaceNumber;
1028 vs->vs_subtype = 0; 1028 vs->vs_subtype = 0;
1029 SIMPLEQ_INIT(&vs->vs_formats); 1029 SIMPLEQ_INIT(&vs->vs_formats);
1030 SIMPLEQ_INIT(&vs->vs_pixel_formats); 1030 SIMPLEQ_INIT(&vs->vs_pixel_formats);
1031 vs->vs_default_format = NULL; 1031 vs->vs_default_format = NULL;
1032 vs->vs_current_format.priv = -1; 1032 vs->vs_current_format.priv = -1;
1033 vs->vs_xfer_type = 0; 1033 vs->vs_xfer_type = 0;
1034 1034
1035 err = usbd_device2interface_handle(sc->sc_udev, idx, &vs->vs_iface); 1035 err = usbd_device2interface_handle(sc->sc_udev, idx, &vs->vs_iface);
1036 if (err != USBD_NORMAL_COMPLETION) { 1036 if (err != USBD_NORMAL_COMPLETION) {
1037 DPRINTF(("uvideo_stream_init: " 1037 DPRINTF(("uvideo_stream_init: "
1038 "error getting vs interface: " 1038 "error getting vs interface: "
1039 "%s (%d)\n", 1039 "%s (%d)\n",
1040 usbd_errstr(err), err)); 1040 usbd_errstr(err), err));
1041 return err; 1041 return err;
1042 } 1042 }
1043 1043
1044 /* For Xbox Live Vision camera, linux-uvc folk say we need to 1044 /* For Xbox Live Vision camera, linux-uvc folk say we need to
1045 * set an alternate interface and wait ~3 seconds prior to 1045 * set an alternate interface and wait ~3 seconds prior to
1046 * doing the format probe/commit. We set to alternate 1046 * doing the format probe/commit. We set to alternate
1047 * interface 0, which is the default, zero bandwidth 1047 * interface 0, which is the default, zero bandwidth
1048 * interface. This should not have adverse affects on other 1048 * interface. This should not have adverse affects on other
1049 * cameras. Errors are ignored. */ 1049 * cameras. Errors are ignored. */
1050 err = usbd_set_interface(vs->vs_iface, 0); 1050 err = usbd_set_interface(vs->vs_iface, 0);
1051 if (err != USBD_NORMAL_COMPLETION) { 1051 if (err != USBD_NORMAL_COMPLETION) {
1052 DPRINTF(("uvideo_stream_init: error setting alt interface: " 1052 DPRINTF(("uvideo_stream_init: error setting alt interface: "
1053 "%s (%d)\n", 1053 "%s (%d)\n",
1054 usbd_errstr(err), err)); 1054 usbd_errstr(err), err));
1055 } 1055 }
1056 1056
1057 /* Initialize probe and commit data size. This value is 1057 /* Initialize probe and commit data size. This value is
1058 * dependent on the version of the spec the hardware 1058 * dependent on the version of the spec the hardware
1059 * implements. */ 1059 * implements. */
1060 err = uvideo_stream_probe(vs, UR_GET_LEN, len); 1060 err = uvideo_stream_probe(vs, UR_GET_LEN, len);
1061 if (err != USBD_NORMAL_COMPLETION) { 1061 if (err != USBD_NORMAL_COMPLETION) {
1062 DPRINTF(("uvideo_stream_init: " 1062 DPRINTF(("uvideo_stream_init: "
1063 "error getting probe data len: " 1063 "error getting probe data len: "
1064 "%s (%d)\n", 1064 "%s (%d)\n",
1065 usbd_errstr(err), err)); 1065 usbd_errstr(err), err));
1066 vs->vs_probelen = 26; /* conservative v1.0 length */ 1066 vs->vs_probelen = 26; /* conservative v1.0 length */
1067 } else { 1067 } else {
1068 DPRINTFN(15,("uvideo_stream_init: probelen=%d\n", UGETW(len))); 1068 DPRINTFN(15,("uvideo_stream_init: probelen=%d\n", UGETW(len)));
1069 vs->vs_probelen = UGETW(len); 1069 vs->vs_probelen = UGETW(len);
1070 } 1070 }
1071  1071
1072 return USBD_NORMAL_COMPLETION; 1072 return USBD_NORMAL_COMPLETION;
1073} 1073}
1074 1074
1075/* Further stream initialization based on a Video Streaming interface 1075/* Further stream initialization based on a Video Streaming interface
1076 * descriptor and following descriptors belonging to that interface. 1076 * descriptor and following descriptors belonging to that interface.
1077 * Iterates through all descriptors belonging to this particular 1077 * Iterates through all descriptors belonging to this particular
1078 * interface descriptor, modifying the iterator. This may be called 1078 * interface descriptor, modifying the iterator. This may be called
1079 * multiple times because there may be several alternate interfaces 1079 * multiple times because there may be several alternate interfaces
1080 * associated with the same interface number. */ 1080 * associated with the same interface number. */
1081static usbd_status 1081static usbd_status
1082uvideo_stream_init_desc(struct uvideo_stream *vs, 1082uvideo_stream_init_desc(struct uvideo_stream *vs,
1083 const usb_interface_descriptor_t *ifdesc, 1083 const usb_interface_descriptor_t *ifdesc,
1084 usbd_desc_iter_t *iter) 1084 usbd_desc_iter_t *iter)
1085{ 1085{
1086 const usb_descriptor_t *desc; 1086 const usb_descriptor_t *desc;
1087 const uvideo_descriptor_t *uvdesc; 1087 const uvideo_descriptor_t *uvdesc;
1088 struct uvideo_bulk_xfer *bx; 1088 struct uvideo_bulk_xfer *bx;
1089 struct uvideo_isoc_xfer *ix; 1089 struct uvideo_isoc_xfer *ix;
1090 struct uvideo_alternate *alt; 1090 struct uvideo_alternate *alt;
1091 uint8_t xfer_type; 1091 uint8_t xfer_type;
1092 int i; 1092 int i;
1093 1093
1094 /* Iterate until the next interface descriptor. All 1094 /* Iterate until the next interface descriptor. All
1095 * descriptors until then belong to this streaming 1095 * descriptors until then belong to this streaming
1096 * interface. */ 1096 * interface. */
1097 while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) { 1097 while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) {
1098 uvdesc = (const uvideo_descriptor_t *)desc; 1098 uvdesc = (const uvideo_descriptor_t *)desc;
1099  1099
1100 switch (uvdesc->bDescriptorType) { 1100 switch (uvdesc->bDescriptorType) {
1101 case UDESC_ENDPOINT: 1101 case UDESC_ENDPOINT:
1102 xfer_type = UE_GET_XFERTYPE(GET(usb_endpoint_descriptor_t, 1102 xfer_type = UE_GET_XFERTYPE(GET(usb_endpoint_descriptor_t,
1103 desc, bmAttributes)); 1103 desc, bmAttributes));
1104 if (xfer_type == UE_BULK) { 1104 if (xfer_type == UE_BULK) {
1105 bx = &vs->vs_xfer.bulk; 1105 bx = &vs->vs_xfer.bulk;
1106 if (vs->vs_xfer_type == 0) { 1106 if (vs->vs_xfer_type == 0) {
1107 DPRINTFN(15, ("uvideo_attach: " 1107 DPRINTFN(15, ("uvideo_attach: "
1108 "BULK stream *\n")); 1108 "BULK stream *\n"));
1109 vs->vs_xfer_type = UE_BULK; 1109 vs->vs_xfer_type = UE_BULK;
1110 bx->bx_endpt = 1110 bx->bx_endpt =
1111 GET(usb_endpoint_descriptor_t, 1111 GET(usb_endpoint_descriptor_t,
1112 desc, bEndpointAddress); 1112 desc, bEndpointAddress);
1113 } 1113 }
1114 } else if (xfer_type == UE_ISOCHRONOUS) { 1114 } else if (xfer_type == UE_ISOCHRONOUS) {
1115 ix = &vs->vs_xfer.isoc; 1115 ix = &vs->vs_xfer.isoc;
1116 for (i = 0; i < UVIDEO_NXFERS; i++) { 1116 for (i = 0; i < UVIDEO_NXFERS; i++) {
1117 ix->ix_i[i].i_ix = ix; 1117 ix->ix_i[i].i_ix = ix;
1118 ix->ix_i[i].i_vs = vs; 1118 ix->ix_i[i].i_vs = vs;
1119 } 1119 }
1120 if (vs->vs_xfer_type == 0) { 1120 if (vs->vs_xfer_type == 0) {
1121 DPRINTFN(15, ("uvideo_attach: " 1121 DPRINTFN(15, ("uvideo_attach: "
1122 "ISOC stream *\n")); 1122 "ISOC stream *\n"));
1123 SLIST_INIT(&ix->ix_altlist); 1123 SLIST_INIT(&ix->ix_altlist);
1124 vs->vs_xfer_type = UE_ISOCHRONOUS; 1124 vs->vs_xfer_type = UE_ISOCHRONOUS;
1125 ix->ix_endpt = 1125 ix->ix_endpt =
1126 GET(usb_endpoint_descriptor_t, 1126 GET(usb_endpoint_descriptor_t,
1127 desc, bEndpointAddress); 1127 desc, bEndpointAddress);
1128 } 1128 }
1129 1129
1130 alt = kmem_alloc(sizeof(*alt), KM_NOSLEEP); 1130 alt = kmem_alloc(sizeof(*alt), KM_NOSLEEP);
1131 if (alt == NULL) 1131 if (alt == NULL)
1132 return USBD_NOMEM; 1132 return USBD_NOMEM;
1133 1133
1134 alt->altno = ifdesc->bAlternateSetting; 1134 alt->altno = ifdesc->bAlternateSetting;
1135 alt->interval = 1135 alt->interval =
1136 GET(usb_endpoint_descriptor_t, 1136 GET(usb_endpoint_descriptor_t,
1137 desc, bInterval); 1137 desc, bInterval);
1138 alt->max_packet_size = 1138 alt->max_packet_size =
1139 UGETW(GET(usb_endpoint_descriptor_t, 1139 UGETW(GET(usb_endpoint_descriptor_t,
1140 desc, wMaxPacketSize)); 1140 desc, wMaxPacketSize));
1141 SLIST_INSERT_HEAD(&ix->ix_altlist, 1141 SLIST_INSERT_HEAD(&ix->ix_altlist,
1142 alt, entries); 1142 alt, entries);
1143 } 1143 }
1144 break; 1144 break;
1145 case UDESC_CS_INTERFACE: 1145 case UDESC_CS_INTERFACE:
1146 if (ifdesc->bAlternateSetting != 0) { 1146 if (ifdesc->bAlternateSetting != 0) {
1147 DPRINTF(("uvideo_stream_init_alternate: " 1147 DPRINTF(("uvideo_stream_init_alternate: "
1148 "unexpected class-specific descriptor " 1148 "unexpected class-specific descriptor "
1149 "len=%d type=0x%02x subtype=0x%02x\n", 1149 "len=%d type=0x%02x subtype=0x%02x\n",
1150 uvdesc->bLength, 1150 uvdesc->bLength,
1151 uvdesc->bDescriptorType, 1151 uvdesc->bDescriptorType,
1152 uvdesc->bDescriptorSubtype)); 1152 uvdesc->bDescriptorSubtype));
1153 break; 1153 break;
1154 } 1154 }
1155 1155
1156 switch (uvdesc->bDescriptorSubtype) { 1156 switch (uvdesc->bDescriptorSubtype) {
1157 case UDESC_VS_INPUT_HEADER: 1157 case UDESC_VS_INPUT_HEADER:
1158 vs->vs_subtype = UDESC_VS_INPUT_HEADER; 1158 vs->vs_subtype = UDESC_VS_INPUT_HEADER;
1159 break; 1159 break;
1160 case UDESC_VS_OUTPUT_HEADER: 1160 case UDESC_VS_OUTPUT_HEADER:
1161 /* TODO: handle output stream */ 1161 /* TODO: handle output stream */
1162 DPRINTF(("uvideo: VS output not implemented\n")); 1162 DPRINTF(("uvideo: VS output not implemented\n"));
1163 vs->vs_subtype = UDESC_VS_OUTPUT_HEADER; 1163 vs->vs_subtype = UDESC_VS_OUTPUT_HEADER;
1164 return USBD_INVAL; 1164 return USBD_INVAL;
1165 case UDESC_VS_FORMAT_UNCOMPRESSED: 1165 case UDESC_VS_FORMAT_UNCOMPRESSED:
1166 case UDESC_VS_FORMAT_FRAME_BASED: 1166 case UDESC_VS_FORMAT_FRAME_BASED:
1167 case UDESC_VS_FORMAT_MJPEG: 1167 case UDESC_VS_FORMAT_MJPEG:
1168 uvideo_stream_init_frame_based_format(vs, 1168 uvideo_stream_init_frame_based_format(vs,
1169 uvdesc, 1169 uvdesc,
1170 iter); 1170 iter);
1171 break; 1171 break;
1172 case UDESC_VS_FORMAT_MPEG2TS: 1172 case UDESC_VS_FORMAT_MPEG2TS:
1173 case UDESC_VS_FORMAT_DV: 1173 case UDESC_VS_FORMAT_DV:
1174 case UDESC_VS_FORMAT_STREAM_BASED: 1174 case UDESC_VS_FORMAT_STREAM_BASED:
1175 default: 1175 default:
1176 DPRINTF(("uvideo: unimplemented VS CS " 1176 DPRINTF(("uvideo: unimplemented VS CS "
1177 "descriptor len=%d type=0x%02x " 1177 "descriptor len=%d type=0x%02x "
1178 "subtype=0x%02x\n", 1178 "subtype=0x%02x\n",
1179 uvdesc->bLength, 1179 uvdesc->bLength,
1180 uvdesc->bDescriptorType, 1180 uvdesc->bDescriptorType,
1181 uvdesc->bDescriptorSubtype)); 1181 uvdesc->bDescriptorSubtype));
1182 break; 1182 break;
1183 } 1183 }
1184 break; 1184 break;
1185 default: 1185 default:
1186 DPRINTF(("uvideo_stream_init_desc: " 1186 DPRINTF(("uvideo_stream_init_desc: "
1187 "unknown descriptor " 1187 "unknown descriptor "
1188 "len=%d type=0x%02x\n", 1188 "len=%d type=0x%02x\n",
1189 uvdesc->bLength, 1189 uvdesc->bLength,
1190 uvdesc->bDescriptorType)); 1190 uvdesc->bDescriptorType));
1191 break; 1191 break;
1192 } 1192 }
1193 } 1193 }
1194 1194
1195 return USBD_NORMAL_COMPLETION; 1195 return USBD_NORMAL_COMPLETION;
1196} 1196}
1197 1197
1198/* Finialize and free memory associated with this stream. */ 1198/* Finialize and free memory associated with this stream. */
1199static void 1199static void
1200uvideo_stream_free(struct uvideo_stream *vs) 1200uvideo_stream_free(struct uvideo_stream *vs)
1201{ 1201{
1202 struct uvideo_alternate *alt; 1202 struct uvideo_alternate *alt;
1203 struct uvideo_pixel_format *pixel_format; 1203 struct uvideo_pixel_format *pixel_format;
1204 struct uvideo_format *format; 1204 struct uvideo_format *format;
1205 1205
1206 /* free linked list of alternate interfaces */ 1206 /* free linked list of alternate interfaces */
1207 if (vs->vs_xfer_type == UE_ISOCHRONOUS) { 1207 if (vs->vs_xfer_type == UE_ISOCHRONOUS) {
1208 while (!SLIST_EMPTY(&vs->vs_xfer.isoc.ix_altlist)) { 1208 while (!SLIST_EMPTY(&vs->vs_xfer.isoc.ix_altlist)) {
1209 alt = SLIST_FIRST(&vs->vs_xfer.isoc.ix_altlist); 1209 alt = SLIST_FIRST(&vs->vs_xfer.isoc.ix_altlist);
1210 SLIST_REMOVE_HEAD(&vs->vs_xfer.isoc.ix_altlist, 1210 SLIST_REMOVE_HEAD(&vs->vs_xfer.isoc.ix_altlist,
1211 entries); 1211 entries);
1212 kmem_free(alt, sizeof(*alt)); 1212 kmem_free(alt, sizeof(*alt));
1213 } 1213 }
1214 } 1214 }
1215 1215
1216 /* free linked-list of formats and pixel formats */ 1216 /* free linked-list of formats and pixel formats */
1217 while ((format = SIMPLEQ_FIRST(&vs->vs_formats)) != NULL) { 1217 while ((format = SIMPLEQ_FIRST(&vs->vs_formats)) != NULL) {
1218 SIMPLEQ_REMOVE_HEAD(&vs->vs_formats, entries); 1218 SIMPLEQ_REMOVE_HEAD(&vs->vs_formats, entries);
1219 kmem_free(format, sizeof(struct uvideo_format)); 1219 kmem_free(format, sizeof(struct uvideo_format));
1220 } 1220 }
1221 while ((pixel_format = SIMPLEQ_FIRST(&vs->vs_pixel_formats)) != NULL) { 1221 while ((pixel_format = SIMPLEQ_FIRST(&vs->vs_pixel_formats)) != NULL) {
1222 SIMPLEQ_REMOVE_HEAD(&vs->vs_pixel_formats, entries); 1222 SIMPLEQ_REMOVE_HEAD(&vs->vs_pixel_formats, entries);
1223 kmem_free(pixel_format, sizeof(struct uvideo_pixel_format)); 1223 kmem_free(pixel_format, sizeof(struct uvideo_pixel_format));
1224 } 1224 }
1225 1225
1226 kmem_free(vs, sizeof(*vs)); 1226 kmem_free(vs, sizeof(*vs));
1227} 1227}
1228 1228
1229 1229
1230static usbd_status 1230static usbd_status
1231uvideo_stream_init_frame_based_format(struct uvideo_stream *vs, 1231uvideo_stream_init_frame_based_format(struct uvideo_stream *vs,
1232 const uvideo_descriptor_t *format_desc, 1232 const uvideo_descriptor_t *format_desc,
1233 usbd_desc_iter_t *iter) 1233 usbd_desc_iter_t *iter)
1234{ 1234{
1235 struct uvideo_pixel_format *pformat, *pfiter; 1235 struct uvideo_pixel_format *pformat, *pfiter;
1236 enum video_pixel_format pixel_format; 1236 enum video_pixel_format pixel_format;
1237 struct uvideo_format *format; 1237 struct uvideo_format *format;
1238 const uvideo_descriptor_t *uvdesc; 1238 const uvideo_descriptor_t *uvdesc;
1239 uint8_t subtype, default_index, index; 1239 uint8_t subtype, default_index, index;
1240 uint32_t frame_interval; 1240 uint32_t frame_interval;
1241 const usb_guid_t *guid; 1241 const usb_guid_t *guid;
1242 1242
1243 pixel_format = VIDEO_FORMAT_UNDEFINED; 1243 pixel_format = VIDEO_FORMAT_UNDEFINED;
1244 1244
1245 switch (format_desc->bDescriptorSubtype) { 1245 switch (format_desc->bDescriptorSubtype) {
1246 case UDESC_VS_FORMAT_UNCOMPRESSED: 1246 case UDESC_VS_FORMAT_UNCOMPRESSED:
1247 subtype = UDESC_VS_FRAME_UNCOMPRESSED; 1247 subtype = UDESC_VS_FRAME_UNCOMPRESSED;
1248 default_index = GET(uvideo_vs_format_uncompressed_descriptor_t, 1248 default_index = GET(uvideo_vs_format_uncompressed_descriptor_t,
1249 format_desc, 1249 format_desc,
1250 bDefaultFrameIndex); 1250 bDefaultFrameIndex);
1251 guid = GETP(uvideo_vs_format_uncompressed_descriptor_t, 1251 guid = GETP(uvideo_vs_format_uncompressed_descriptor_t,
1252 format_desc, 1252 format_desc,
1253 guidFormat); 1253 guidFormat);
1254 if (usb_guid_cmp(guid, &uvideo_guid_format_yuy2) == 0) 1254 if (usb_guid_cmp(guid, &uvideo_guid_format_yuy2) == 0)
1255 pixel_format = VIDEO_FORMAT_YUY2; 1255 pixel_format = VIDEO_FORMAT_YUY2;
1256 else if (usb_guid_cmp(guid, &uvideo_guid_format_nv12) == 0) 1256 else if (usb_guid_cmp(guid, &uvideo_guid_format_nv12) == 0)
1257 pixel_format = VIDEO_FORMAT_NV12; 1257 pixel_format = VIDEO_FORMAT_NV12;
 1258 else if (usb_guid_cmp(guid, &uvideo_guid_format_uyvy) == 0)
 1259 pixel_format = VIDEO_FORMAT_UYVY;
1258 break; 1260 break;
1259 case UDESC_VS_FORMAT_FRAME_BASED: 1261 case UDESC_VS_FORMAT_FRAME_BASED:
1260 subtype = UDESC_VS_FRAME_FRAME_BASED; 1262 subtype = UDESC_VS_FRAME_FRAME_BASED;
1261 default_index = GET(uvideo_format_frame_based_descriptor_t, 1263 default_index = GET(uvideo_format_frame_based_descriptor_t,
1262 format_desc, 1264 format_desc,
1263 bDefaultFrameIndex); 1265 bDefaultFrameIndex);
1264 break; 1266 break;
1265 case UDESC_VS_FORMAT_MJPEG: 1267 case UDESC_VS_FORMAT_MJPEG:
1266 subtype = UDESC_VS_FRAME_MJPEG; 1268 subtype = UDESC_VS_FRAME_MJPEG;
1267 default_index = GET(uvideo_vs_format_mjpeg_descriptor_t, 1269 default_index = GET(uvideo_vs_format_mjpeg_descriptor_t,
1268 format_desc, 1270 format_desc,
1269 bDefaultFrameIndex); 1271 bDefaultFrameIndex);
1270 pixel_format = VIDEO_FORMAT_MJPEG; 1272 pixel_format = VIDEO_FORMAT_MJPEG;
1271 break; 1273 break;
1272 default: 1274 default:
1273 DPRINTF(("uvideo: unknown frame based format %d\n", 1275 DPRINTF(("uvideo: unknown frame based format %d\n",
1274 format_desc->bDescriptorSubtype)); 1276 format_desc->bDescriptorSubtype));
1275 return USBD_INVAL; 1277 return USBD_INVAL;
1276 } 1278 }
1277 1279
1278 pformat = NULL; 1280 pformat = NULL;
1279 SIMPLEQ_FOREACH(pfiter, &vs->vs_pixel_formats, entries) { 1281 SIMPLEQ_FOREACH(pfiter, &vs->vs_pixel_formats, entries) {
1280 if (pfiter->pixel_format == pixel_format) { 1282 if (pfiter->pixel_format == pixel_format) {
1281 pformat = pfiter; 1283 pformat = pfiter;
1282 break; 1284 break;
1283 } 1285 }
1284 } 1286 }
1285 if (pixel_format != VIDEO_FORMAT_UNDEFINED && pformat == NULL) { 1287 if (pixel_format != VIDEO_FORMAT_UNDEFINED && pformat == NULL) {
1286 pformat = kmem_zalloc(sizeof(*pformat), KM_SLEEP); 1288 pformat = kmem_zalloc(sizeof(*pformat), KM_SLEEP);
1287 pformat->pixel_format = pixel_format; 1289 pformat->pixel_format = pixel_format;
1288 DPRINTF(("uvideo: Adding pixel format %d\n", 1290 DPRINTF(("uvideo: Adding pixel format %d\n",
1289 pixel_format)); 1291 pixel_format));
1290 SIMPLEQ_INSERT_TAIL(&vs->vs_pixel_formats, 1292 SIMPLEQ_INSERT_TAIL(&vs->vs_pixel_formats,
1291 pformat, entries); 1293 pformat, entries);
1292 } 1294 }
1293 1295
1294 /* Iterate through frame descriptors directly following the 1296 /* Iterate through frame descriptors directly following the
1295 * format descriptor, and add a format to the format list for 1297 * format descriptor, and add a format to the format list for
1296 * each frame descriptor. */ 1298 * each frame descriptor. */
1297 while ((uvdesc = (const uvideo_descriptor_t *) usb_desc_iter_peek_next(iter)) && 1299 while ((uvdesc = (const uvideo_descriptor_t *) usb_desc_iter_peek_next(iter)) &&
1298 (uvdesc != NULL) && (uvdesc->bDescriptorSubtype == subtype)) 1300 (uvdesc != NULL) && (uvdesc->bDescriptorSubtype == subtype))
1299 { 1301 {
1300 uvdesc = (const uvideo_descriptor_t *) usb_desc_iter_next(iter); 1302 uvdesc = (const uvideo_descriptor_t *) usb_desc_iter_next(iter);
1301 1303
1302 format = kmem_zalloc(sizeof(struct uvideo_format), KM_SLEEP); 1304 format = kmem_zalloc(sizeof(struct uvideo_format), KM_SLEEP);
1303 if (format == NULL) { 1305 if (format == NULL) {
1304 DPRINTF(("uvideo: failed to alloc video format\n")); 1306 DPRINTF(("uvideo: failed to alloc video format\n"));
1305 return USBD_NOMEM; 1307 return USBD_NOMEM;
1306 } 1308 }
1307  1309
1308 format->format.pixel_format = pixel_format; 1310 format->format.pixel_format = pixel_format;
1309 1311
1310 switch (format_desc->bDescriptorSubtype) { 1312 switch (format_desc->bDescriptorSubtype) {
1311 case UDESC_VS_FORMAT_UNCOMPRESSED: 1313 case UDESC_VS_FORMAT_UNCOMPRESSED:
1312#ifdef UVIDEO_DEBUG 1314#ifdef UVIDEO_DEBUG
1313 if (pixel_format == VIDEO_FORMAT_UNDEFINED && 1315 if (pixel_format == VIDEO_FORMAT_UNDEFINED &&
1314 uvideodebug) { 1316 uvideodebug) {
1315 guid = GETP( 1317 guid = GETP(
1316 uvideo_vs_format_uncompressed_descriptor_t, 1318 uvideo_vs_format_uncompressed_descriptor_t,
1317 format_desc, 1319 format_desc,
1318 guidFormat); 1320 guidFormat);
1319 1321
1320 DPRINTF(("uvideo: format undefined ")); 1322 DPRINTF(("uvideo: format undefined "));
1321 usb_guid_print(guid); 1323 usb_guid_print(guid);
1322 DPRINTF(("\n")); 1324 DPRINTF(("\n"));
1323 } 1325 }
1324#endif 1326#endif
1325 1327
1326 UVIDEO_FORMAT_INIT_FRAME_BASED( 1328 UVIDEO_FORMAT_INIT_FRAME_BASED(
1327 uvideo_vs_format_uncompressed_descriptor_t, 1329 uvideo_vs_format_uncompressed_descriptor_t,
1328 format_desc, 1330 format_desc,
1329 uvideo_vs_frame_uncompressed_descriptor_t, 1331 uvideo_vs_frame_uncompressed_descriptor_t,
1330 uvdesc, 1332 uvdesc,
1331 format); 1333 format);
1332 format->format.sample_size = 1334 format->format.sample_size =
1333 UGETDW( 1335 UGETDW(
1334 GET(uvideo_vs_frame_uncompressed_descriptor_t, 1336 GET(uvideo_vs_frame_uncompressed_descriptor_t,
1335 uvdesc, dwMaxVideoFrameBufferSize)); 1337 uvdesc, dwMaxVideoFrameBufferSize));
1336 format->format.stride = 1338 format->format.stride =
1337 format->format.sample_size / format->format.height; 1339 format->format.sample_size / format->format.height;
1338 index = GET(uvideo_vs_frame_uncompressed_descriptor_t, 1340 index = GET(uvideo_vs_frame_uncompressed_descriptor_t,
1339 uvdesc, 1341 uvdesc,
1340 bFrameIndex); 1342 bFrameIndex);
1341 frame_interval = 1343 frame_interval =
1342 UGETDW( 1344 UGETDW(
1343 GET(uvideo_vs_frame_uncompressed_descriptor_t, 1345 GET(uvideo_vs_frame_uncompressed_descriptor_t,
1344 uvdesc, 1346 uvdesc,
1345 dwDefaultFrameInterval)); 1347 dwDefaultFrameInterval));
1346 break; 1348 break;
1347 case UDESC_VS_FORMAT_MJPEG: 1349 case UDESC_VS_FORMAT_MJPEG:
1348 UVIDEO_FORMAT_INIT_FRAME_BASED( 1350 UVIDEO_FORMAT_INIT_FRAME_BASED(
1349 uvideo_vs_format_mjpeg_descriptor_t, 1351 uvideo_vs_format_mjpeg_descriptor_t,
1350 format_desc, 1352 format_desc,
1351 uvideo_vs_frame_mjpeg_descriptor_t, 1353 uvideo_vs_frame_mjpeg_descriptor_t,
1352 uvdesc, 1354 uvdesc,
1353 format); 1355 format);
1354 format->format.sample_size = 1356 format->format.sample_size =
1355 UGETDW( 1357 UGETDW(
1356 GET(uvideo_vs_frame_mjpeg_descriptor_t, 1358 GET(uvideo_vs_frame_mjpeg_descriptor_t,
1357 uvdesc, dwMaxVideoFrameBufferSize)); 1359 uvdesc, dwMaxVideoFrameBufferSize));
1358 format->format.stride = 1360 format->format.stride =
1359 format->format.sample_size / format->format.height; 1361 format->format.sample_size / format->format.height;
1360 index = GET(uvideo_vs_frame_mjpeg_descriptor_t, 1362 index = GET(uvideo_vs_frame_mjpeg_descriptor_t,
1361 uvdesc, 1363 uvdesc,
1362 bFrameIndex); 1364 bFrameIndex);
1363 frame_interval = 1365 frame_interval =
1364 UGETDW( 1366 UGETDW(
1365 GET(uvideo_vs_frame_mjpeg_descriptor_t, 1367 GET(uvideo_vs_frame_mjpeg_descriptor_t,
1366 uvdesc, 1368 uvdesc,
1367 dwDefaultFrameInterval)); 1369 dwDefaultFrameInterval));
1368 break; 1370 break;
1369 case UDESC_VS_FORMAT_FRAME_BASED: 1371 case UDESC_VS_FORMAT_FRAME_BASED:
1370 format->format.pixel_format = VIDEO_FORMAT_UNDEFINED; 1372 format->format.pixel_format = VIDEO_FORMAT_UNDEFINED;
1371 UVIDEO_FORMAT_INIT_FRAME_BASED( 1373 UVIDEO_FORMAT_INIT_FRAME_BASED(
1372 uvideo_format_frame_based_descriptor_t, 1374 uvideo_format_frame_based_descriptor_t,
1373 format_desc, 1375 format_desc,
1374 uvideo_frame_frame_based_descriptor_t, 1376 uvideo_frame_frame_based_descriptor_t,
1375 uvdesc, 1377 uvdesc,
1376 format); 1378 format);
1377 index = GET(uvideo_frame_frame_based_descriptor_t, 1379 index = GET(uvideo_frame_frame_based_descriptor_t,
1378 uvdesc, 1380 uvdesc,
1379 bFrameIndex); 1381 bFrameIndex);
1380 format->format.stride = 1382 format->format.stride =
1381 UGETDW( 1383 UGETDW(
1382 GET(uvideo_frame_frame_based_descriptor_t, 1384 GET(uvideo_frame_frame_based_descriptor_t,
1383 uvdesc, dwBytesPerLine)); 1385 uvdesc, dwBytesPerLine));
1384 format->format.sample_size = 1386 format->format.sample_size =
1385 format->format.stride * format->format.height; 1387 format->format.stride * format->format.height;
1386 frame_interval = 1388 frame_interval =
1387 UGETDW( 1389 UGETDW(
1388 GET(uvideo_frame_frame_based_descriptor_t, 1390 GET(uvideo_frame_frame_based_descriptor_t,
1389 uvdesc, dwDefaultFrameInterval)); 1391 uvdesc, dwDefaultFrameInterval));
1390 break; 1392 break;
1391 default: 1393 default:
1392 /* shouldn't ever get here */ 1394 /* shouldn't ever get here */
1393 DPRINTF(("uvideo: unknown frame based format %d\n", 1395 DPRINTF(("uvideo: unknown frame based format %d\n",
1394 format_desc->bDescriptorSubtype)); 1396 format_desc->bDescriptorSubtype));
1395 kmem_free(format, sizeof(struct uvideo_format)); 1397 kmem_free(format, sizeof(struct uvideo_format));
1396 return USBD_INVAL; 1398 return USBD_INVAL;
1397 } 1399 }
1398 1400
1399 DPRINTF(("uvideo: found format (index %d) type %d " 1401 DPRINTF(("uvideo: found format (index %d) type %d "
1400 "size %ux%u size %u stride %u interval %u\n", 1402 "size %ux%u size %u stride %u interval %u\n",
1401 index, format->format.pixel_format, format->format.width, 1403 index, format->format.pixel_format, format->format.width,
1402 format->format.height, format->format.sample_size, 1404 format->format.height, format->format.sample_size,
1403 format->format.stride, frame_interval)); 1405 format->format.stride, frame_interval));
1404 1406
1405 SIMPLEQ_INSERT_TAIL(&vs->vs_formats, format, entries); 1407 SIMPLEQ_INSERT_TAIL(&vs->vs_formats, format, entries);
1406 1408
1407 if (vs->vs_default_format == NULL && index == default_index 1409 if (vs->vs_default_format == NULL && index == default_index
1408#ifdef UVIDEO_DISABLE_MJPEG 1410#ifdef UVIDEO_DISABLE_MJPEG
1409 && subtype != UDESC_VS_FRAME_MJPEG 1411 && subtype != UDESC_VS_FRAME_MJPEG
1410#endif 1412#endif
1411 ) { 1413 ) {
1412 DPRINTF((" ^ picking this one\n")); 1414 DPRINTF((" ^ picking this one\n"));
1413 vs->vs_default_format = &format->format; 1415 vs->vs_default_format = &format->format;
1414 vs->vs_frame_interval = frame_interval; 1416 vs->vs_frame_interval = frame_interval;
1415 } 1417 }
1416 1418
1417 } 1419 }
1418  1420
1419 return USBD_NORMAL_COMPLETION; 1421 return USBD_NORMAL_COMPLETION;
1420} 1422}
1421 1423
1422static int 1424static int
1423uvideo_stream_start_xfer(struct uvideo_stream *vs) 1425uvideo_stream_start_xfer(struct uvideo_stream *vs)
1424{ 1426{
1425 struct uvideo_softc *sc = vs->vs_parent; 1427 struct uvideo_softc *sc = vs->vs_parent;
1426 struct uvideo_bulk_xfer *bx; 1428 struct uvideo_bulk_xfer *bx;
1427 struct uvideo_isoc_xfer *ix; 1429 struct uvideo_isoc_xfer *ix;
1428 uint32_t vframe_len; /* rough bytes per video frame */ 1430 uint32_t vframe_len; /* rough bytes per video frame */
1429 uint32_t uframe_len; /* bytes per usb frame (TODO: or microframe?) */ 1431 uint32_t uframe_len; /* bytes per usb frame (TODO: or microframe?) */
1430 uint32_t nframes; /* number of usb frames (TODO: or microframs?) */ 1432 uint32_t nframes; /* number of usb frames (TODO: or microframs?) */
1431 int i; 1433 int i;
1432 1434
1433 struct uvideo_alternate *alt, *alt_maybe; 1435 struct uvideo_alternate *alt, *alt_maybe;
1434 usbd_status err; 1436 usbd_status err;
1435 1437
1436 switch (vs->vs_xfer_type) { 1438 switch (vs->vs_xfer_type) {
1437 case UE_BULK: 1439 case UE_BULK:
1438 bx = &vs->vs_xfer.bulk; 1440 bx = &vs->vs_xfer.bulk;
1439 return 0; 1441 return 0;
1440 case UE_ISOCHRONOUS: 1442 case UE_ISOCHRONOUS:
1441 ix = &vs->vs_xfer.isoc; 1443 ix = &vs->vs_xfer.isoc;
1442 1444
1443 /* Choose an alternate interface most suitable for 1445 /* Choose an alternate interface most suitable for
1444 * this format. Choose the smallest size that can 1446 * this format. Choose the smallest size that can
1445 * contain max_payload_size. 1447 * contain max_payload_size.
1446 * 1448 *
1447 * It is assumed that the list is sorted in descending 1449 * It is assumed that the list is sorted in descending
1448 * order from largest to smallest packet size. 1450 * order from largest to smallest packet size.
1449 * 1451 *
1450 * TODO: what should the strategy be for choosing an 1452 * TODO: what should the strategy be for choosing an
1451 * alt interface? 1453 * alt interface?
1452 */ 1454 */
1453 alt = NULL; 1455 alt = NULL;
1454 SLIST_FOREACH(alt_maybe, &ix->ix_altlist, entries) { 1456 SLIST_FOREACH(alt_maybe, &ix->ix_altlist, entries) {
1455 /* TODO: define "packet" and "payload". I think 1457 /* TODO: define "packet" and "payload". I think
1456 * several packets can make up one payload which would 1458 * several packets can make up one payload which would
1457 * call into question this method of selecting an 1459 * call into question this method of selecting an
1458 * alternate interface... */ 1460 * alternate interface... */
1459 1461
1460 /* XXXJDM don't allow packet size > 1024 for now */ 1462 /* XXXJDM don't allow packet size > 1024 for now */
1461 if (alt_maybe->max_packet_size > 1024) 1463 if (alt_maybe->max_packet_size > 1024)
1462 continue; 1464 continue;
1463 1465
1464 if (alt == NULL || 1466 if (alt == NULL ||
1465 alt_maybe->max_packet_size >= alt->max_packet_size) 1467 alt_maybe->max_packet_size >= alt->max_packet_size)
1466 alt = alt_maybe; 1468 alt = alt_maybe;
1467 } 1469 }
1468  1470
1469 if (alt == NULL) { 1471 if (alt == NULL) {
1470 DPRINTF(("uvideo_stream_start_xfer: " 1472 DPRINTF(("uvideo_stream_start_xfer: "
1471 "no suitable alternate interface found\n")); 1473 "no suitable alternate interface found\n"));
1472 return EINVAL; 1474 return EINVAL;
1473 } 1475 }
1474 1476
1475 DPRINTFN(15,("uvideo_stream_start_xfer: " 1477 DPRINTFN(15,("uvideo_stream_start_xfer: "
1476 "choosing alternate interface " 1478 "choosing alternate interface "
1477 "%d wMaxPacketSize=%d bInterval=%d\n", 1479 "%d wMaxPacketSize=%d bInterval=%d\n",
1478 alt->altno, alt->max_packet_size, alt->interval)); 1480 alt->altno, alt->max_packet_size, alt->interval));
1479  1481
1480 err = usbd_set_interface(vs->vs_iface, alt->altno); 1482 err = usbd_set_interface(vs->vs_iface, alt->altno);
1481 if (err != USBD_NORMAL_COMPLETION) { 1483 if (err != USBD_NORMAL_COMPLETION) {
1482 DPRINTF(("uvideo_stream_start_xfer: " 1484 DPRINTF(("uvideo_stream_start_xfer: "
1483 "error setting alt interface: %s (%d)\n", 1485 "error setting alt interface: %s (%d)\n",
1484 usbd_errstr(err), err)); 1486 usbd_errstr(err), err));
1485 return EIO; 1487 return EIO;
1486 } 1488 }
1487 1489
1488 /* TODO: "packet" not same as frame */ 1490 /* TODO: "packet" not same as frame */
1489 vframe_len = vs->vs_current_format.sample_size; 1491 vframe_len = vs->vs_current_format.sample_size;
1490 uframe_len = alt->max_packet_size; 1492 uframe_len = alt->max_packet_size;
1491 nframes = (vframe_len + uframe_len - 1) / uframe_len; 1493 nframes = (vframe_len + uframe_len - 1) / uframe_len;
1492 DPRINTF(("uvideo_stream_start_xfer: nframes=%d\n", nframes)); 1494 DPRINTF(("uvideo_stream_start_xfer: nframes=%d\n", nframes));
1493  1495
1494 ix->ix_nframes = nframes; 1496 ix->ix_nframes = nframes;
1495 ix->ix_uframe_len = uframe_len; 1497 ix->ix_uframe_len = uframe_len;
1496 for (i = 0; i < UVIDEO_NXFERS; i++) { 1498 for (i = 0; i < UVIDEO_NXFERS; i++) {
1497 struct uvideo_isoc *isoc = &ix->ix_i[i]; 1499 struct uvideo_isoc *isoc = &ix->ix_i[i];
1498 isoc->i_frlengths = 1500 isoc->i_frlengths =
1499 kmem_alloc(sizeof(isoc->i_frlengths[0]) * nframes, 1501 kmem_alloc(sizeof(isoc->i_frlengths[0]) * nframes,
1500 KM_SLEEP); 1502 KM_SLEEP);
1501 if (isoc->i_frlengths == NULL) { 1503 if (isoc->i_frlengths == NULL) {
1502 DPRINTF(("uvideo: failed to alloc frlengths:" 1504 DPRINTF(("uvideo: failed to alloc frlengths:"
1503 "%s (%d)\n", 1505 "%s (%d)\n",
1504 usbd_errstr(err), err)); 1506 usbd_errstr(err), err));
1505 return ENOMEM; 1507 return ENOMEM;
1506 } 1508 }
1507 } 1509 }
1508  1510
1509 err = usbd_open_pipe(vs->vs_iface, ix->ix_endpt, 1511 err = usbd_open_pipe(vs->vs_iface, ix->ix_endpt,
1510 USBD_EXCLUSIVE_USE, &ix->ix_pipe); 1512 USBD_EXCLUSIVE_USE, &ix->ix_pipe);
1511 if (err != USBD_NORMAL_COMPLETION) { 1513 if (err != USBD_NORMAL_COMPLETION) {
1512 DPRINTF(("uvideo: error opening pipe: %s (%d)\n", 1514 DPRINTF(("uvideo: error opening pipe: %s (%d)\n",
1513 usbd_errstr(err), err)); 1515 usbd_errstr(err), err));
1514 return EIO; 1516 return EIO;
1515 } 1517 }
1516 1518
1517 for (i = 0; i < UVIDEO_NXFERS; i++) { 1519 for (i = 0; i < UVIDEO_NXFERS; i++) {
1518 struct uvideo_isoc *isoc = &ix->ix_i[i]; 1520 struct uvideo_isoc *isoc = &ix->ix_i[i];
1519 isoc->i_xfer = usbd_alloc_xfer(sc->sc_udev); 1521 isoc->i_xfer = usbd_alloc_xfer(sc->sc_udev);
1520 if (isoc->i_xfer == NULL) { 1522 if (isoc->i_xfer == NULL) {
1521 DPRINTF(("uvideo: failed to alloc xfer: %s" 1523 DPRINTF(("uvideo: failed to alloc xfer: %s"
1522 " (%d)\n", 1524 " (%d)\n",
1523 usbd_errstr(err), err)); 1525 usbd_errstr(err), err));
1524 return ENOMEM; 1526 return ENOMEM;
1525 } 1527 }
1526 1528
1527 isoc->i_buf = usbd_alloc_buffer(isoc->i_xfer, 1529 isoc->i_buf = usbd_alloc_buffer(isoc->i_xfer,
1528 nframes * uframe_len); 1530 nframes * uframe_len);
1529 if (isoc->i_xfer == NULL) { 1531 if (isoc->i_xfer == NULL) {
1530 DPRINTF(("uvideo: failed to alloc buf: %s" 1532 DPRINTF(("uvideo: failed to alloc buf: %s"
1531 " (%d)\n", 1533 " (%d)\n",
1532 usbd_errstr(err), err)); 1534 usbd_errstr(err), err));
1533 return ENOMEM; 1535 return ENOMEM;
1534 } 1536 }
1535 } 1537 }
1536 1538
1537 uvideo_stream_recv_isoc_start(vs); 1539 uvideo_stream_recv_isoc_start(vs);
1538 1540
1539 return 0; 1541 return 0;
1540 default: 1542 default:
1541 /* should never get here */ 1543 /* should never get here */
1542 DPRINTF(("uvideo_stream_start_xfer: unknown xfer type 0x%x\n", 1544 DPRINTF(("uvideo_stream_start_xfer: unknown xfer type 0x%x\n",
1543 vs->vs_xfer_type)); 1545 vs->vs_xfer_type));
1544 return EINVAL; 1546 return EINVAL;
1545 } 1547 }
1546} 1548}
1547 1549
1548static int 1550static int
1549uvideo_stream_stop_xfer(struct uvideo_stream *vs) 1551uvideo_stream_stop_xfer(struct uvideo_stream *vs)
1550{ 1552{
1551 struct uvideo_bulk_xfer *bx; 1553 struct uvideo_bulk_xfer *bx;
1552 struct uvideo_isoc_xfer *ix; 1554 struct uvideo_isoc_xfer *ix;
1553 usbd_status err; 1555 usbd_status err;
1554 int i; 1556 int i;
1555 1557
1556 switch (vs->vs_xfer_type) { 1558 switch (vs->vs_xfer_type) {
1557 case UE_BULK: 1559 case UE_BULK:
1558 bx = &vs->vs_xfer.bulk; 1560 bx = &vs->vs_xfer.bulk;
1559 return 0; 1561 return 0;
1560 case UE_ISOCHRONOUS: 1562 case UE_ISOCHRONOUS:
1561 ix = &vs->vs_xfer.isoc; 1563 ix = &vs->vs_xfer.isoc;
1562 if (ix->ix_pipe != NULL) { 1564 if (ix->ix_pipe != NULL) {
1563 usbd_abort_pipe(ix->ix_pipe); 1565 usbd_abort_pipe(ix->ix_pipe);
1564 usbd_close_pipe(ix->ix_pipe); 1566 usbd_close_pipe(ix->ix_pipe);
1565 ix->ix_pipe = NULL; 1567 ix->ix_pipe = NULL;
1566 } 1568 }
1567 1569
1568 for (i = 0; i < UVIDEO_NXFERS; i++) { 1570 for (i = 0; i < UVIDEO_NXFERS; i++) {
1569 struct uvideo_isoc *isoc = &ix->ix_i[i]; 1571 struct uvideo_isoc *isoc = &ix->ix_i[i];
1570 if (isoc->i_xfer != NULL) { 1572 if (isoc->i_xfer != NULL) {
1571 usbd_free_buffer(isoc->i_xfer); 1573 usbd_free_buffer(isoc->i_xfer);
1572 usbd_free_xfer(isoc->i_xfer); 1574 usbd_free_xfer(isoc->i_xfer);
1573 isoc->i_xfer = NULL; 1575 isoc->i_xfer = NULL;
1574 } 1576 }
1575 1577
1576 if (isoc->i_frlengths != NULL) { 1578 if (isoc->i_frlengths != NULL) {
1577 kmem_free(isoc->i_frlengths, 1579 kmem_free(isoc->i_frlengths,
1578 sizeof(isoc->i_frlengths[0]) * 1580 sizeof(isoc->i_frlengths[0]) *
1579 ix->ix_nframes); 1581 ix->ix_nframes);
1580 isoc->i_frlengths = NULL; 1582 isoc->i_frlengths = NULL;
1581 } 1583 }
1582 } 1584 }
1583 1585
1584 /* Give it some time to settle */ 1586 /* Give it some time to settle */
1585 usbd_delay_ms(vs->vs_parent->sc_udev, 1000); 1587 usbd_delay_ms(vs->vs_parent->sc_udev, 1000);
1586 1588
1587 /* Set to zero bandwidth alternate interface zero */ 1589 /* Set to zero bandwidth alternate interface zero */
1588 err = usbd_set_interface(vs->vs_iface, 0); 1590 err = usbd_set_interface(vs->vs_iface, 0);
1589 if (err != USBD_NORMAL_COMPLETION) { 1591 if (err != USBD_NORMAL_COMPLETION) {
1590 DPRINTF(("uvideo_stream_stop_transfer: " 1592 DPRINTF(("uvideo_stream_stop_transfer: "
1591 "error setting zero bandwidth interface: " 1593 "error setting zero bandwidth interface: "
1592 "%s (%d)\n", 1594 "%s (%d)\n",
1593 usbd_errstr(err), err)); 1595 usbd_errstr(err), err));
1594 return EIO; 1596 return EIO;
1595 } 1597 }
1596 1598
1597 return 0; 1599 return 0;
1598 default: 1600 default:
1599 /* should never get here */ 1601 /* should never get here */
1600 DPRINTF(("uvideo_stream_stop_xfer: unknown xfer type 0x%x\n", 1602 DPRINTF(("uvideo_stream_stop_xfer: unknown xfer type 0x%x\n",
1601 vs->vs_xfer_type)); 1603 vs->vs_xfer_type));
1602 return EINVAL; 1604 return EINVAL;
1603 } 1605 }
1604} 1606}
1605 1607
1606static usbd_status 1608static usbd_status
1607uvideo_stream_recv_isoc_start(struct uvideo_stream *vs) 1609uvideo_stream_recv_isoc_start(struct uvideo_stream *vs)
1608{ 1610{
1609 int i; 1611 int i;
1610 1612
1611 for (i = 0; i < UVIDEO_NXFERS; i++) 1613 for (i = 0; i < UVIDEO_NXFERS; i++)
1612 uvideo_stream_recv_isoc_start1(&vs->vs_xfer.isoc.ix_i[i]); 1614 uvideo_stream_recv_isoc_start1(&vs->vs_xfer.isoc.ix_i[i]);
1613 1615
1614 return USBD_NORMAL_COMPLETION; 1616 return USBD_NORMAL_COMPLETION;
1615} 1617}
1616 1618
1617/* Initiate a usb transfer. */ 1619/* Initiate a usb transfer. */
1618static usbd_status 1620static usbd_status
1619uvideo_stream_recv_isoc_start1(struct uvideo_isoc *isoc) 1621uvideo_stream_recv_isoc_start1(struct uvideo_isoc *isoc)
1620{ 1622{
1621 struct uvideo_isoc_xfer *ix; 1623 struct uvideo_isoc_xfer *ix;
1622 usbd_status err; 1624 usbd_status err;
1623 int i; 1625 int i;
1624 1626
1625 ix = isoc->i_ix; 1627 ix = isoc->i_ix;
1626  1628
1627 for (i = 0; i < ix->ix_nframes; ++i) 1629 for (i = 0; i < ix->ix_nframes; ++i)
1628 isoc->i_frlengths[i] = ix->ix_uframe_len; 1630 isoc->i_frlengths[i] = ix->ix_uframe_len;
1629 1631
1630 usbd_setup_isoc_xfer(isoc->i_xfer, 1632 usbd_setup_isoc_xfer(isoc->i_xfer,
1631 ix->ix_pipe, 1633 ix->ix_pipe,
1632 isoc, 1634 isoc,
1633 isoc->i_frlengths, 1635 isoc->i_frlengths,
1634 ix->ix_nframes, 1636 ix->ix_nframes,
1635 USBD_NO_COPY | USBD_SHORT_XFER_OK, 1637 USBD_NO_COPY | USBD_SHORT_XFER_OK,
1636 uvideo_stream_recv_isoc_complete); 1638 uvideo_stream_recv_isoc_complete);
1637 1639
1638 err = usbd_transfer(isoc->i_xfer); 1640 err = usbd_transfer(isoc->i_xfer);
1639 if (err != USBD_IN_PROGRESS) { 1641 if (err != USBD_IN_PROGRESS) {
1640 DPRINTF(("uvideo_stream_recv_start: " 1642 DPRINTF(("uvideo_stream_recv_start: "
1641 "usbd_transfer status=%s (%d)\n", 1643 "usbd_transfer status=%s (%d)\n",
1642 usbd_errstr(err), err)); 1644 usbd_errstr(err), err));
1643 } 1645 }
1644 return err; 1646 return err;
1645} 1647}
1646 1648
1647/* Callback on completion of usb isoc transfer */ 1649/* Callback on completion of usb isoc transfer */
1648static void 1650static void
1649uvideo_stream_recv_isoc_complete(usbd_xfer_handle xfer, 1651uvideo_stream_recv_isoc_complete(usbd_xfer_handle xfer,
1650 usbd_private_handle priv, 1652 usbd_private_handle priv,
1651 usbd_status status) 1653 usbd_status status)
1652{ 1654{
1653 struct uvideo_stream *vs; 1655 struct uvideo_stream *vs;
1654 struct uvideo_isoc_xfer *ix; 1656 struct uvideo_isoc_xfer *ix;
1655 struct uvideo_isoc *isoc; 1657 struct uvideo_isoc *isoc;
1656 int i; 1658 int i;
1657 uint32_t count; 1659 uint32_t count;
1658 const uvideo_payload_header_t *hdr; 1660 const uvideo_payload_header_t *hdr;
1659 uint8_t *buf; 1661 uint8_t *buf;
1660 struct video_payload payload; 1662 struct video_payload payload;
1661 1663
1662 isoc = priv; 1664 isoc = priv;
1663 vs = isoc->i_vs; 1665 vs = isoc->i_vs;
1664 ix = isoc->i_ix; 1666 ix = isoc->i_ix;
1665 1667
1666 if (status != USBD_NORMAL_COMPLETION) { 1668 if (status != USBD_NORMAL_COMPLETION) {
1667 DPRINTF(("uvideo_stream_recv_isoc_complete: status=%s (%d)\n", 1669 DPRINTF(("uvideo_stream_recv_isoc_complete: status=%s (%d)\n",
1668 usbd_errstr(status), status)); 1670 usbd_errstr(status), status));
1669  1671
1670 if (status == USBD_STALLED) 1672 if (status == USBD_STALLED)
1671 usbd_clear_endpoint_stall_async(ix->ix_pipe); 1673 usbd_clear_endpoint_stall_async(ix->ix_pipe);
1672 else 1674 else
1673 return; 1675 return;
1674 } else { 1676 } else {
1675 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 1677 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1676 1678
1677 if (count == 0) { 1679 if (count == 0) {
1678 /* DPRINTF(("uvideo: zero length transfer\n")); */ 1680 /* DPRINTF(("uvideo: zero length transfer\n")); */
1679 goto next; 1681 goto next;
1680 } 1682 }
1681  1683
1682 hdr = (const uvideo_payload_header_t *)isoc->i_buf; 1684 hdr = (const uvideo_payload_header_t *)isoc->i_buf;
1683  1685
1684 for (i = 0, buf = isoc->i_buf; 1686 for (i = 0, buf = isoc->i_buf;
1685 i < ix->ix_nframes; 1687 i < ix->ix_nframes;
1686 ++i, buf += ix->ix_uframe_len) 1688 ++i, buf += ix->ix_uframe_len)
1687 { 1689 {
1688 if (isoc->i_frlengths[i] < 1690 if (isoc->i_frlengths[i] <
1689 sizeof(uvideo_payload_header_t)) 1691 sizeof(uvideo_payload_header_t))
1690 continue; 1692 continue;
1691  1693
1692 hdr = (uvideo_payload_header_t *)buf; 1694 hdr = (uvideo_payload_header_t *)buf;
1693 if (hdr->bHeaderLength != UVIDEO_PAYLOAD_HEADER_SIZE) 1695 if (hdr->bHeaderLength != UVIDEO_PAYLOAD_HEADER_SIZE)
1694 continue; 1696 continue;
1695 if (hdr->bHeaderLength == isoc->i_frlengths[i] && 1697 if (hdr->bHeaderLength == isoc->i_frlengths[i] &&
1696 !(hdr->bmHeaderInfo & UV_END_OF_FRAME)) 1698 !(hdr->bmHeaderInfo & UV_END_OF_FRAME))
1697 continue; 1699 continue;
1698 if (hdr->bmHeaderInfo & UV_ERROR) { 1700 if (hdr->bmHeaderInfo & UV_ERROR) {
1699 DPRINTF(("uvideo: stream error\n")); 1701 DPRINTF(("uvideo: stream error\n"));
1700 break; 1702 break;
1701 } 1703 }
1702 1704
1703 payload.data = buf + hdr->bHeaderLength; 1705 payload.data = buf + hdr->bHeaderLength;
1704 payload.size = isoc->i_frlengths[i] - 1706 payload.size = isoc->i_frlengths[i] -
1705 hdr->bHeaderLength; 1707 hdr->bHeaderLength;
1706 payload.frameno = hdr->bmHeaderInfo & UV_FRAME_ID; 1708 payload.frameno = hdr->bmHeaderInfo & UV_FRAME_ID;
1707 payload.end_of_frame = 1709 payload.end_of_frame =
1708 hdr->bmHeaderInfo & UV_END_OF_FRAME; 1710 hdr->bmHeaderInfo & UV_END_OF_FRAME;
1709  1711
1710 video_submit_payload(vs->vs_parent->sc_videodev, 1712 video_submit_payload(vs->vs_parent->sc_videodev,
1711 &payload); 1713 &payload);
1712 } 1714 }
1713 } 1715 }
1714 1716
1715next: 1717next:
1716 uvideo_stream_recv_isoc_start1(isoc); 1718 uvideo_stream_recv_isoc_start1(isoc);
1717} 1719}
1718 1720
1719 1721
1720/* 1722/*
1721 * uvideo_open - probe and commit video format and start receiving 1723 * uvideo_open - probe and commit video format and start receiving
1722 * video data 1724 * video data
1723 */ 1725 */
1724static int 1726static int
1725uvideo_open(void *addr, int flags) 1727uvideo_open(void *addr, int flags)
1726{ 1728{
1727 struct uvideo_softc *sc; 1729 struct uvideo_softc *sc;
1728 struct uvideo_stream *vs; 1730 struct uvideo_stream *vs;
1729 struct video_format fmt; 1731 struct video_format fmt;
1730 1732
1731 sc = addr; 1733 sc = addr;
1732 vs = sc->sc_stream_in; 1734 vs = sc->sc_stream_in;
1733 1735
1734 DPRINTF(("uvideo_open: sc=%p\n", sc)); 1736 DPRINTF(("uvideo_open: sc=%p\n", sc));
1735 if (sc->sc_dying) 1737 if (sc->sc_dying)
1736 return EIO; 1738 return EIO;
1737 1739
1738 /* XXX select default format */ 1740 /* XXX select default format */
1739 fmt = *vs->vs_default_format; 1741 fmt = *vs->vs_default_format;
1740 return uvideo_set_format(addr, &fmt); 1742 return uvideo_set_format(addr, &fmt);
1741} 1743}
1742 1744
1743 1745
1744static void 1746static void
1745uvideo_close(void *addr) 1747uvideo_close(void *addr)
1746{ 1748{
1747 struct uvideo_softc *sc; 1749 struct uvideo_softc *sc;
1748 1750
1749 sc = addr; 1751 sc = addr;
1750  1752
1751 if (sc->sc_state != UVIDEO_STATE_CLOSED) { 1753 if (sc->sc_state != UVIDEO_STATE_CLOSED) {
1752 sc->sc_state = UVIDEO_STATE_CLOSED; 1754 sc->sc_state = UVIDEO_STATE_CLOSED;
1753 } 1755 }
1754} 1756}
1755 1757
1756static const char * 1758static const char *
1757uvideo_get_devname(void *addr) 1759uvideo_get_devname(void *addr)
1758{ 1760{
1759 struct uvideo_softc *sc = addr; 1761 struct uvideo_softc *sc = addr;
1760 return sc->sc_devname; 1762 return sc->sc_devname;
1761} 1763}
1762 1764
1763static int 1765static int
1764uvideo_enum_format(void *addr, uint32_t index, struct video_format *format) 1766uvideo_enum_format(void *addr, uint32_t index, struct video_format *format)
1765{ 1767{
1766 struct uvideo_softc *sc = addr; 1768 struct uvideo_softc *sc = addr;
1767 struct uvideo_stream *vs = sc->sc_stream_in; 1769 struct uvideo_stream *vs = sc->sc_stream_in;
1768 struct uvideo_pixel_format *pixel_format; 1770 struct uvideo_pixel_format *pixel_format;
1769 int off; 1771 int off;
1770 1772
1771 if (sc->sc_dying) 1773 if (sc->sc_dying)
1772 return EIO; 1774 return EIO;
1773 1775
1774 off = 0; 1776 off = 0;
1775 SIMPLEQ_FOREACH(pixel_format, &vs->vs_pixel_formats, entries) { 1777 SIMPLEQ_FOREACH(pixel_format, &vs->vs_pixel_formats, entries) {
1776 if (off++ != index) 1778 if (off++ != index)
1777 continue; 1779 continue;
1778 format->pixel_format = pixel_format->pixel_format; 1780 format->pixel_format = pixel_format->pixel_format;
1779 return 0; 1781 return 0;
1780 } 1782 }
1781 1783
1782 return EINVAL; 1784 return EINVAL;
1783} 1785}
1784 1786
1785/* 1787/*
1786 * uvideo_get_format 1788 * uvideo_get_format
1787 */ 1789 */
1788static int 1790static int
1789uvideo_get_format(void *addr, struct video_format *format) 1791uvideo_get_format(void *addr, struct video_format *format)
1790{ 1792{
1791 struct uvideo_softc *sc = addr; 1793 struct uvideo_softc *sc = addr;
1792 struct uvideo_stream *vs = sc->sc_stream_in; 1794 struct uvideo_stream *vs = sc->sc_stream_in;
1793 1795
1794 if (sc->sc_dying) 1796 if (sc->sc_dying)
1795 return EIO; 1797 return EIO;
1796 1798
1797 *format = vs->vs_current_format; 1799 *format = vs->vs_current_format;
1798 1800
1799 return 0; 1801 return 0;
1800}  1802}
1801 1803
1802/* 1804/*
1803 * uvideo_set_format - TODO: this is boken and does nothing 1805 * uvideo_set_format - TODO: this is boken and does nothing
1804 */ 1806 */
1805static int 1807static int
1806uvideo_set_format(void *addr, struct video_format *format) 1808uvideo_set_format(void *addr, struct video_format *format)
1807{ 1809{
1808 struct uvideo_softc *sc; 1810 struct uvideo_softc *sc;
1809 struct uvideo_stream *vs; 1811 struct uvideo_stream *vs;
1810 struct uvideo_format *uvfmt; 1812 struct uvideo_format *uvfmt;
1811 uvideo_probe_and_commit_data_t probe, maxprobe; 1813 uvideo_probe_and_commit_data_t probe, maxprobe;
1812 uint8_t ifaceno; 1814 uint8_t ifaceno;
1813 usbd_status err; 1815 usbd_status err;
1814 1816
1815 sc = addr; 1817 sc = addr;
1816 1818
1817 DPRINTF(("uvideo_set_format: sc=%p\n", sc)); 1819 DPRINTF(("uvideo_set_format: sc=%p\n", sc));
1818 if (sc->sc_dying) 1820 if (sc->sc_dying)
1819 return EIO; 1821 return EIO;
1820 1822
1821 vs = sc->sc_stream_in; 1823 vs = sc->sc_stream_in;
1822 ifaceno = vs->vs_ifaceno; 1824 ifaceno = vs->vs_ifaceno;
1823 1825
1824 uvfmt = uvideo_stream_guess_format(vs, format->pixel_format, 1826 uvfmt = uvideo_stream_guess_format(vs, format->pixel_format,
1825 format->width, format->height); 1827 format->width, format->height);
1826 if (uvfmt == NULL) { 1828 if (uvfmt == NULL) {
1827 DPRINTF(("uvideo: uvideo_stream_guess_format couldn't find " 1829 DPRINTF(("uvideo: uvideo_stream_guess_format couldn't find "
1828 "%dx%d format %d\n", format->width, format->height, 1830 "%dx%d format %d\n", format->width, format->height,
1829 format->pixel_format)); 1831 format->pixel_format));
1830 return EINVAL; 1832 return EINVAL;
1831 } 1833 }
1832 1834
1833 uvideo_init_probe_data(&probe); 1835 uvideo_init_probe_data(&probe);
1834 probe.bFormatIndex = UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt); 1836 probe.bFormatIndex = UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt);
1835 probe.bFrameIndex = UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt); 1837 probe.bFrameIndex = UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt);
1836 USETDW(probe.dwFrameInterval, vs->vs_frame_interval); /* XXX */ 1838 USETDW(probe.dwFrameInterval, vs->vs_frame_interval); /* XXX */
1837 1839
1838 maxprobe = probe; 1840 maxprobe = probe;
1839 err = uvideo_stream_probe(vs, UR_GET_MAX, &maxprobe); 1841 err = uvideo_stream_probe(vs, UR_GET_MAX, &maxprobe);
1840 if (err) { 1842 if (err) {
1841 DPRINTF(("uvideo: error probe/GET_MAX: %s (%d)\n", 1843 DPRINTF(("uvideo: error probe/GET_MAX: %s (%d)\n",
1842 usbd_errstr(err), err)); 1844 usbd_errstr(err), err));
1843 } else { 1845 } else {
1844 USETW(probe.wCompQuality, UGETW(maxprobe.wCompQuality)); 1846 USETW(probe.wCompQuality, UGETW(maxprobe.wCompQuality));
1845 } 1847 }
1846 1848
1847 err = uvideo_stream_probe(vs, UR_SET_CUR, &probe); 1849 err = uvideo_stream_probe(vs, UR_SET_CUR, &probe);
1848 if (err) { 1850 if (err) {
1849 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n", 1851 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n",
1850 usbd_errstr(err), err)); 1852 usbd_errstr(err), err));
1851 return EIO; 1853 return EIO;
1852 } 1854 }
1853 1855
1854 uvideo_init_probe_data(&probe); 1856 uvideo_init_probe_data(&probe);
1855 err = uvideo_stream_probe(vs, UR_GET_CUR, &probe); 1857 err = uvideo_stream_probe(vs, UR_GET_CUR, &probe);
1856 if (err) { 1858 if (err) {
1857 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n", 1859 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n",
1858 usbd_errstr(err), err)); 1860 usbd_errstr(err), err));
1859 return EIO; 1861 return EIO;
1860 } 1862 }
1861 1863
1862 if (probe.bFormatIndex != UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt)) { 1864 if (probe.bFormatIndex != UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt)) {
1863 DPRINTF(("uvideo: probe/GET_CUR returned format index %d " 1865 DPRINTF(("uvideo: probe/GET_CUR returned format index %d "
1864 "(expected %d)\n", probe.bFormatIndex, 1866 "(expected %d)\n", probe.bFormatIndex,
1865 UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt))); 1867 UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt)));
1866 probe.bFormatIndex = UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt); 1868 probe.bFormatIndex = UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt);
1867 } 1869 }
1868 if (probe.bFrameIndex != UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt)) { 1870 if (probe.bFrameIndex != UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt)) {
1869 DPRINTF(("uvideo: probe/GET_CUR returned frame index %d " 1871 DPRINTF(("uvideo: probe/GET_CUR returned frame index %d "
1870 "(expected %d)\n", probe.bFrameIndex, 1872 "(expected %d)\n", probe.bFrameIndex,
1871 UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt))); 1873 UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt)));
1872 probe.bFrameIndex = UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt); 1874 probe.bFrameIndex = UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt);
1873 } 1875 }
1874 USETDW(probe.dwFrameInterval, vs->vs_frame_interval); /* XXX */ 1876 USETDW(probe.dwFrameInterval, vs->vs_frame_interval); /* XXX */
1875 1877
1876 /* commit/SET_CUR. Fourth step is to set the alternate 1878 /* commit/SET_CUR. Fourth step is to set the alternate
1877 * interface. Currently the fourth step is in 1879 * interface. Currently the fourth step is in
1878 * uvideo_start_transfer. Maybe move it here? */ 1880 * uvideo_start_transfer. Maybe move it here? */
1879 err = uvideo_stream_commit(vs, UR_SET_CUR, &probe); 1881 err = uvideo_stream_commit(vs, UR_SET_CUR, &probe);
1880 if (err) { 1882 if (err) {
1881 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n", 1883 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n",
1882 usbd_errstr(err), err)); 1884 usbd_errstr(err), err));
1883 return EIO; 1885 return EIO;
1884 } 1886 }
1885 1887
1886 DPRINTFN(15, ("uvideo_set_format: committing to format: " 1888 DPRINTFN(15, ("uvideo_set_format: committing to format: "
1887 "bmHint=0x%04x bFormatIndex=%d bFrameIndex=%d " 1889 "bmHint=0x%04x bFormatIndex=%d bFrameIndex=%d "
1888 "dwFrameInterval=%u wKeyFrameRate=%d wPFrameRate=%d " 1890 "dwFrameInterval=%u wKeyFrameRate=%d wPFrameRate=%d "
1889 "wCompQuality=%d wCompWindowSize=%d wDelay=%d " 1891 "wCompQuality=%d wCompWindowSize=%d wDelay=%d "
1890 "dwMaxVideoFrameSize=%u dwMaxPayloadTransferSize=%u", 1892 "dwMaxVideoFrameSize=%u dwMaxPayloadTransferSize=%u",
1891 UGETW(probe.bmHint), 1893 UGETW(probe.bmHint),
1892 probe.bFormatIndex, 1894 probe.bFormatIndex,
1893 probe.bFrameIndex, 1895 probe.bFrameIndex,
1894 UGETDW(probe.dwFrameInterval), 1896 UGETDW(probe.dwFrameInterval),
1895 UGETW(probe.wKeyFrameRate), 1897 UGETW(probe.wKeyFrameRate),
1896 UGETW(probe.wPFrameRate), 1898 UGETW(probe.wPFrameRate),
1897 UGETW(probe.wCompQuality), 1899 UGETW(probe.wCompQuality),
1898 UGETW(probe.wCompWindowSize), 1900 UGETW(probe.wCompWindowSize),
1899 UGETW(probe.wDelay), 1901 UGETW(probe.wDelay),
1900 UGETDW(probe.dwMaxVideoFrameSize), 1902 UGETDW(probe.dwMaxVideoFrameSize),
1901 UGETDW(probe.dwMaxPayloadTransferSize))); 1903 UGETDW(probe.dwMaxPayloadTransferSize)));
1902 if (vs->vs_probelen == 34) { 1904 if (vs->vs_probelen == 34) {
1903 DPRINTFN(15, (" dwClockFrequency=%u bmFramingInfo=0x%02x " 1905 DPRINTFN(15, (" dwClockFrequency=%u bmFramingInfo=0x%02x "
1904 "bPreferedVersion=%d bMinVersion=%d " 1906 "bPreferedVersion=%d bMinVersion=%d "
1905 "bMaxVersion=%d", 1907 "bMaxVersion=%d",
1906 UGETDW(probe.dwClockFrequency), 1908 UGETDW(probe.dwClockFrequency),
1907 probe.bmFramingInfo, 1909 probe.bmFramingInfo,
1908 probe.bPreferedVersion, 1910 probe.bPreferedVersion,
1909 probe.bMinVersion, 1911 probe.bMinVersion,
1910 probe.bMaxVersion)); 1912 probe.bMaxVersion));
1911 } 1913 }
1912 DPRINTFN(15, ("\n")); 1914 DPRINTFN(15, ("\n"));
1913 1915
1914 vs->vs_frame_interval = UGETDW(probe.dwFrameInterval); 1916 vs->vs_frame_interval = UGETDW(probe.dwFrameInterval);
1915 vs->vs_max_payload_size = UGETDW(probe.dwMaxPayloadTransferSize); 1917 vs->vs_max_payload_size = UGETDW(probe.dwMaxPayloadTransferSize);
1916 1918
1917 *format = uvfmt->format; 1919 *format = uvfmt->format;
1918 vs->vs_current_format = *format; 1920 vs->vs_current_format = *format;
1919 DPRINTF(("uvideo_set_format: pixeltype is %d\n", format->pixel_format)); 1921 DPRINTF(("uvideo_set_format: pixeltype is %d\n", format->pixel_format));
1920  1922
1921 return 0; 1923 return 0;
1922} 1924}
1923 1925
1924static int 1926static int
1925uvideo_try_format(void *addr, struct video_format *format) 1927uvideo_try_format(void *addr, struct video_format *format)
1926{ 1928{
1927 struct uvideo_softc *sc = addr; 1929 struct uvideo_softc *sc = addr;
1928 struct uvideo_stream *vs = sc->sc_stream_in; 1930 struct uvideo_stream *vs = sc->sc_stream_in;
1929 struct uvideo_format *uvfmt; 1931 struct uvideo_format *uvfmt;
1930 1932
1931 uvfmt = uvideo_stream_guess_format(vs, format->pixel_format, 1933 uvfmt = uvideo_stream_guess_format(vs, format->pixel_format,
1932 format->width, format->height); 1934 format->width, format->height);
1933 if (uvfmt == NULL) 1935 if (uvfmt == NULL)
1934 return EINVAL; 1936 return EINVAL;
1935 1937
1936 *format = uvfmt->format; 1938 *format = uvfmt->format;
1937 return 0; 1939 return 0;
1938} 1940}
1939 1941
1940static int 1942static int
1941uvideo_start_transfer(void *addr) 1943uvideo_start_transfer(void *addr)
1942{ 1944{
1943 struct uvideo_softc *sc = addr; 1945 struct uvideo_softc *sc = addr;
1944 struct uvideo_stream *vs; 1946 struct uvideo_stream *vs;
1945 int s, err; 1947 int s, err;
1946 1948
1947 /* FIXME: this functions should be stream specific */ 1949 /* FIXME: this functions should be stream specific */
1948 vs = SLIST_FIRST(&sc->sc_stream_list); 1950 vs = SLIST_FIRST(&sc->sc_stream_list);
1949 s = splusb(); 1951 s = splusb();
1950 err = uvideo_stream_start_xfer(vs); 1952 err = uvideo_stream_start_xfer(vs);
1951 splx(s); 1953 splx(s);
1952 1954
1953 return err; 1955 return err;
1954} 1956}
1955 1957
1956static int 1958static int
1957uvideo_stop_transfer(void *addr) 1959uvideo_stop_transfer(void *addr)
1958{ 1960{
1959 struct uvideo_softc *sc; 1961 struct uvideo_softc *sc;
1960 int err, s; 1962 int err, s;
1961 1963
1962 sc = addr; 1964 sc = addr;
1963 1965
1964 s = splusb(); 1966 s = splusb();
1965 err = uvideo_stream_stop_xfer(sc->sc_stream_in); 1967 err = uvideo_stream_stop_xfer(sc->sc_stream_in);
1966 splx(s); 1968 splx(s);
1967 1969
1968 return err; 1970 return err;
1969} 1971}
1970 1972
1971 1973
1972static int 1974static int
1973uvideo_get_control_group(void *addr, struct video_control_group *group) 1975uvideo_get_control_group(void *addr, struct video_control_group *group)
1974{ 1976{
1975 struct uvideo_softc *sc; 1977 struct uvideo_softc *sc;
1976 usb_device_request_t req; 1978 usb_device_request_t req;
1977 usbd_status err; 1979 usbd_status err;
1978 uint8_t control_id, ent_id, data[16]; 1980 uint8_t control_id, ent_id, data[16];
1979 uint16_t len; 1981 uint16_t len;
1980 int s; 1982 int s;
1981 1983
1982 sc = addr; 1984 sc = addr;
1983 1985
1984 /* request setup */ 1986 /* request setup */
1985 switch (group->group_id) { 1987 switch (group->group_id) {
1986 case VIDEO_CONTROL_PANTILT_RELATIVE: 1988 case VIDEO_CONTROL_PANTILT_RELATIVE:
1987 if (group->length != 4) 1989 if (group->length != 4)
1988 return EINVAL; 1990 return EINVAL;
1989  1991
1990 return EINVAL; 1992 return EINVAL;
1991 case VIDEO_CONTROL_SHARPNESS: 1993 case VIDEO_CONTROL_SHARPNESS:
1992 if (group->length != 1) 1994 if (group->length != 1)
1993 return EINVAL; 1995 return EINVAL;
1994 1996
1995 control_id = UVIDEO_PU_SHARPNESS_CONTROL; 1997 control_id = UVIDEO_PU_SHARPNESS_CONTROL;
1996 ent_id = 2; /* TODO: hardcoded logitech processing unit */ 1998 ent_id = 2; /* TODO: hardcoded logitech processing unit */
1997 len = 2; 1999 len = 2;
1998 break; 2000 break;
1999 default: 2001 default:
2000 return EINVAL; 2002 return EINVAL;
2001 } 2003 }
2002 2004
2003 /* do request */ 2005 /* do request */
2004 req.bmRequestType = UVIDEO_REQUEST_TYPE_INTERFACE | 2006 req.bmRequestType = UVIDEO_REQUEST_TYPE_INTERFACE |
2005 UVIDEO_REQUEST_TYPE_CLASS_SPECIFIC | 2007 UVIDEO_REQUEST_TYPE_CLASS_SPECIFIC |
2006 UVIDEO_REQUEST_TYPE_GET; 2008 UVIDEO_REQUEST_TYPE_GET;
2007 req.bRequest = UR_GET_CUR; 2009 req.bRequest = UR_GET_CUR;
2008 USETW(req.wValue, control_id << 8); 2010 USETW(req.wValue, control_id << 8);
2009 USETW(req.wIndex, (ent_id << 8) | sc->sc_ifaceno); 2011 USETW(req.wIndex, (ent_id << 8) | sc->sc_ifaceno);
2010 USETW(req.wLength, len); 2012 USETW(req.wLength, len);
2011 2013
2012 s = splusb(); 2014 s = splusb();
2013 err = usbd_do_request(sc->sc_udev, &req, data); 2015 err = usbd_do_request(sc->sc_udev, &req, data);
2014 splx(s); 2016 splx(s);
2015 if (err != USBD_NORMAL_COMPLETION) { 2017 if (err != USBD_NORMAL_COMPLETION) {
2016 DPRINTF(("uvideo_set_control: error %s (%d)\n", 2018 DPRINTF(("uvideo_set_control: error %s (%d)\n",
2017 usbd_errstr(err), err)); 2019 usbd_errstr(err), err));
2018 return EIO; /* TODO: more detail here? */ 2020 return EIO; /* TODO: more detail here? */
2019 } 2021 }
2020 2022
2021 /* extract request data */ 2023 /* extract request data */
2022 switch (group->group_id) { 2024 switch (group->group_id) {
2023 case VIDEO_CONTROL_SHARPNESS: 2025 case VIDEO_CONTROL_SHARPNESS:
2024 group->control[0].value = UGETW(data); 2026 group->control[0].value = UGETW(data);
2025 break; 2027 break;
2026 default: 2028 default:
2027 return EINVAL; 2029 return EINVAL;
2028 } 2030 }
2029 2031
2030 return 0; 2032 return 0;
2031} 2033}
2032 2034
2033 2035
2034static int 2036static int
2035uvideo_set_control_group(void *addr, const struct video_control_group *group) 2037uvideo_set_control_group(void *addr, const struct video_control_group *group)
2036{ 2038{
2037 struct uvideo_softc *sc; 2039 struct uvideo_softc *sc;
2038 usb_device_request_t req; 2040 usb_device_request_t req;
2039 usbd_status err; 2041 usbd_status err;
2040 uint8_t control_id, ent_id, data[16]; /* long enough for all controls */ 2042 uint8_t control_id, ent_id, data[16]; /* long enough for all controls */
2041 uint16_t len; 2043 uint16_t len;
2042 int s; 2044 int s;
2043 2045
2044 sc = addr; 2046 sc = addr;
2045  2047
2046 switch (group->group_id) { 2048 switch (group->group_id) {
2047 case VIDEO_CONTROL_PANTILT_RELATIVE: 2049 case VIDEO_CONTROL_PANTILT_RELATIVE:
2048 if (group->length != 4) 2050 if (group->length != 4)
2049 return EINVAL; 2051 return EINVAL;
2050  2052
2051 if (group->control[0].value != 0 || 2053 if (group->control[0].value != 0 ||
2052 group->control[0].value != 1 || 2054 group->control[0].value != 1 ||
2053 group->control[0].value != 0xff) 2055 group->control[0].value != 0xff)
2054 return ERANGE; 2056 return ERANGE;
2055  2057
2056 if (group->control[2].value != 0 || 2058 if (group->control[2].value != 0 ||
2057 group->control[2].value != 1 || 2059 group->control[2].value != 1 ||
2058 group->control[2].value != 0xff) 2060 group->control[2].value != 0xff)
2059 return ERANGE; 2061 return ERANGE;
2060 2062
2061 control_id = UVIDEO_CT_PANTILT_RELATIVE_CONTROL; 2063 control_id = UVIDEO_CT_PANTILT_RELATIVE_CONTROL;
2062 ent_id = 1; /* TODO: hardcoded logitech camera terminal */ 2064 ent_id = 1; /* TODO: hardcoded logitech camera terminal */
2063 len = 4; 2065 len = 4;
2064 data[0] = group->control[0].value; 2066 data[0] = group->control[0].value;
2065 data[1] = group->control[1].value; 2067 data[1] = group->control[1].value;
2066 data[2] = group->control[2].value; 2068 data[2] = group->control[2].value;
2067 data[3] = group->control[3].value; 2069 data[3] = group->control[3].value;
2068 break; 2070 break;
2069 case VIDEO_CONTROL_BRIGHTNESS: 2071 case VIDEO_CONTROL_BRIGHTNESS:
2070 if (group->length != 1) 2072 if (group->length != 1)
2071 return EINVAL; 2073 return EINVAL;
2072 control_id = UVIDEO_PU_BRIGHTNESS_CONTROL; 2074 control_id = UVIDEO_PU_BRIGHTNESS_CONTROL;
2073 ent_id = 2; 2075 ent_id = 2;
2074 len = 2; 2076 len = 2;
2075 USETW(data, group->control[0].value); 2077 USETW(data, group->control[0].value);
2076 break; 2078 break;
2077 case VIDEO_CONTROL_GAIN: 2079 case VIDEO_CONTROL_GAIN:
2078 if (group->length != 1) 2080 if (group->length != 1)
2079 return EINVAL; 2081 return EINVAL;
2080 control_id = UVIDEO_PU_GAIN_CONTROL; 2082 control_id = UVIDEO_PU_GAIN_CONTROL;
2081 ent_id = 2; 2083 ent_id = 2;
2082 len = 2; 2084 len = 2;
2083 USETW(data, group->control[0].value); 2085 USETW(data, group->control[0].value);
2084 break; 2086 break;
2085 case VIDEO_CONTROL_SHARPNESS: 2087 case VIDEO_CONTROL_SHARPNESS:
2086 if (group->length != 1) 2088 if (group->length != 1)
2087 return EINVAL; 2089 return EINVAL;
2088 control_id = UVIDEO_PU_SHARPNESS_CONTROL; 2090 control_id = UVIDEO_PU_SHARPNESS_CONTROL;
2089 ent_id = 2; /* TODO: hardcoded logitech processing unit */ 2091 ent_id = 2; /* TODO: hardcoded logitech processing unit */
2090 len = 2; 2092 len = 2;
2091 USETW(data, group->control[0].value); 2093 USETW(data, group->control[0].value);
2092 break; 2094 break;
2093 default: 2095 default:
2094 return EINVAL; 2096 return EINVAL;
2095 } 2097 }
2096 2098
2097 req.bmRequestType = UVIDEO_REQUEST_TYPE_INTERFACE | 2099 req.bmRequestType = UVIDEO_REQUEST_TYPE_INTERFACE |
2098 UVIDEO_REQUEST_TYPE_CLASS_SPECIFIC | 2100 UVIDEO_REQUEST_TYPE_CLASS_SPECIFIC |
2099 UVIDEO_REQUEST_TYPE_SET; 2101 UVIDEO_REQUEST_TYPE_SET;
2100 req.bRequest = UR_SET_CUR; 2102 req.bRequest = UR_SET_CUR;
2101 USETW(req.wValue, control_id << 8); 2103 USETW(req.wValue, control_id << 8);
2102 USETW(req.wIndex, (ent_id << 8) | sc->sc_ifaceno); 2104 USETW(req.wIndex, (ent_id << 8) | sc->sc_ifaceno);
2103 USETW(req.wLength, len); 2105 USETW(req.wLength, len);
2104 2106
2105 s = splusb(); 2107 s = splusb();
2106 err = usbd_do_request(sc->sc_udev, &req, data); 2108 err = usbd_do_request(sc->sc_udev, &req, data);
2107 splx(s); 2109 splx(s);
2108 if (err != USBD_NORMAL_COMPLETION) { 2110 if (err != USBD_NORMAL_COMPLETION) {
2109 DPRINTF(("uvideo_set_control: error %s (%d)\n", 2111 DPRINTF(("uvideo_set_control: error %s (%d)\n",
2110 usbd_errstr(err), err)); 2112 usbd_errstr(err), err));
2111 return EIO; /* TODO: more detail here? */ 2113 return EIO; /* TODO: more detail here? */
2112 } 2114 }
2113 2115
2114 return 0; 2116 return 0;
2115} 2117}
2116 2118
2117static usbd_status 2119static usbd_status
2118uvideo_stream_probe_and_commit(struct uvideo_stream *vs, 2120uvideo_stream_probe_and_commit(struct uvideo_stream *vs,
2119 uint8_t action, uint8_t control, 2121 uint8_t action, uint8_t control,
2120 void *data) 2122 void *data)
2121{ 2123{
2122 usb_device_request_t req; 2124 usb_device_request_t req;
2123  2125
2124 switch (action) { 2126 switch (action) {
2125 case UR_SET_CUR: 2127 case UR_SET_CUR:
2126 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 2128 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
2127 USETW(req.wLength, vs->vs_probelen); 2129 USETW(req.wLength, vs->vs_probelen);
2128 break; 2130 break;
2129 case UR_GET_CUR: 2131 case UR_GET_CUR:
2130 case UR_GET_MIN: 2132 case UR_GET_MIN:
2131 case UR_GET_MAX: 2133 case UR_GET_MAX:
2132 case UR_GET_DEF: 2134 case UR_GET_DEF:
2133 req.bmRequestType = UT_READ_CLASS_INTERFACE; 2135 req.bmRequestType = UT_READ_CLASS_INTERFACE;
2134 USETW(req.wLength, vs->vs_probelen); 2136 USETW(req.wLength, vs->vs_probelen);
2135 break; 2137 break;
2136 case UR_GET_INFO: 2138 case UR_GET_INFO:
2137 req.bmRequestType = UT_READ_CLASS_INTERFACE; 2139 req.bmRequestType = UT_READ_CLASS_INTERFACE;
2138 USETW(req.wLength, sizeof(uByte)); 2140 USETW(req.wLength, sizeof(uByte));
2139 break; 2141 break;
2140 case UR_GET_LEN: 2142 case UR_GET_LEN:
2141 req.bmRequestType = UT_READ_CLASS_INTERFACE; 2143 req.bmRequestType = UT_READ_CLASS_INTERFACE;
2142 USETW(req.wLength, sizeof(uWord)); /* is this right? */ 2144 USETW(req.wLength, sizeof(uWord)); /* is this right? */
2143 break; 2145 break;
2144 default: 2146 default:
2145 DPRINTF(("uvideo_probe_and_commit: " 2147 DPRINTF(("uvideo_probe_and_commit: "
2146 "unknown request action %d\n", action)); 2148 "unknown request action %d\n", action));
2147 return USBD_NOT_STARTED; 2149 return USBD_NOT_STARTED;
2148 } 2150 }
2149  2151
2150 req.bRequest = action; 2152 req.bRequest = action;
2151 USETW2(req.wValue, control, 0); 2153 USETW2(req.wValue, control, 0);
2152 USETW2(req.wIndex, 0, vs->vs_ifaceno); 2154 USETW2(req.wIndex, 0, vs->vs_ifaceno);
2153 2155
2154 return (usbd_do_request_flags(vs->vs_parent->sc_udev, &req, data, 2156 return (usbd_do_request_flags(vs->vs_parent->sc_udev, &req, data,
2155 0, 0, 2157 0, 0,
2156 USBD_DEFAULT_TIMEOUT)); 2158 USBD_DEFAULT_TIMEOUT));
2157} 2159}
2158 2160
2159static void 2161static void
2160uvideo_init_probe_data(uvideo_probe_and_commit_data_t *probe) 2162uvideo_init_probe_data(uvideo_probe_and_commit_data_t *probe)
2161{ 2163{
2162 /* all zeroes tells camera to choose what it wants */ 2164 /* all zeroes tells camera to choose what it wants */
2163 memset(probe, 0, sizeof(*probe)); 2165 memset(probe, 0, sizeof(*probe));
2164} 2166}
2165 2167
2166 2168
2167#ifdef _MODULE 2169#ifdef _MODULE
2168 2170
2169MODULE(MODULE_CLASS_DRIVER, uvideo, NULL); 2171MODULE(MODULE_CLASS_DRIVER, uvideo, NULL);
2170static const struct cfiattrdata videobuscf_iattrdata = { 2172static const struct cfiattrdata videobuscf_iattrdata = {
2171 "videobus", 0, {  2173 "videobus", 0, {
2172 { NULL, NULL, 0 }, 2174 { NULL, NULL, 0 },
2173 } 2175 }
2174}; 2176};
2175static const struct cfiattrdata * const uvideo_attrs[] = { 2177static const struct cfiattrdata * const uvideo_attrs[] = {
2176 &videobuscf_iattrdata, NULL 2178 &videobuscf_iattrdata, NULL
2177};  2179};
2178CFDRIVER_DECL(uvideo, DV_DULL, uvideo_attrs); 2180CFDRIVER_DECL(uvideo, DV_DULL, uvideo_attrs);
2179extern struct cfattach uvideo_ca; 2181extern struct cfattach uvideo_ca;
2180extern struct cfattach uvideo_ca; 2182extern struct cfattach uvideo_ca;
2181static int uvideoloc[6] = { -1, -1, -1, -1, -1, -1 }; 2183static int uvideoloc[6] = { -1, -1, -1, -1, -1, -1 };
2182static struct cfparent uhubparent = { 2184static struct cfparent uhubparent = {
2183 "usbifif", NULL, DVUNIT_ANY 2185 "usbifif", NULL, DVUNIT_ANY
2184}; 2186};
2185static struct cfdata uvideo_cfdata[] = { 2187static struct cfdata uvideo_cfdata[] = {
2186 { 2188 {
2187 .cf_name = "uvideo", 2189 .cf_name = "uvideo",
2188 .cf_atname = "uvideo", 2190 .cf_atname = "uvideo",
2189 .cf_unit = 0, 2191 .cf_unit = 0,
2190 .cf_fstate = FSTATE_STAR, 2192 .cf_fstate = FSTATE_STAR,
2191 .cf_loc = uvideoloc, 2193 .cf_loc = uvideoloc,
2192 .cf_flags = 0, 2194 .cf_flags = 0,
2193 .cf_pspec = &uhubparent, 2195 .cf_pspec = &uhubparent,
2194 }, 2196 },
2195 { NULL } 2197 { NULL }
2196}; 2198};
2197 2199
2198static int 2200static int
2199uvideo_modcmd(modcmd_t cmd, void *arg) 2201uvideo_modcmd(modcmd_t cmd, void *arg)
2200{ 2202{
2201 int err; 2203 int err;
2202 2204
2203  2205
2204 switch (cmd) { 2206 switch (cmd) {
2205 case MODULE_CMD_INIT: 2207 case MODULE_CMD_INIT:
2206 DPRINTF(("uvideo: attempting to load\n")); 2208 DPRINTF(("uvideo: attempting to load\n"));
2207 2209
2208 err = config_cfdriver_attach(&uvideo_cd); 2210 err = config_cfdriver_attach(&uvideo_cd);
2209 if (err) 2211 if (err)
2210 return err; 2212 return err;
2211 err = config_cfattach_attach("uvideo", &uvideo_ca); 2213 err = config_cfattach_attach("uvideo", &uvideo_ca);
2212 if (err) { 2214 if (err) {
2213 config_cfdriver_detach(&uvideo_cd); 2215 config_cfdriver_detach(&uvideo_cd);
2214 return err; 2216 return err;
2215 } 2217 }
2216 err = config_cfdata_attach(uvideo_cfdata, 1); 2218 err = config_cfdata_attach(uvideo_cfdata, 1);
2217 if (err) { 2219 if (err) {
2218 config_cfattach_detach("uvideo", &uvideo_ca); 2220 config_cfattach_detach("uvideo", &uvideo_ca);
2219 config_cfdriver_detach(&uvideo_cd); 2221 config_cfdriver_detach(&uvideo_cd);
2220 return err; 2222 return err;
2221 } 2223 }
2222 DPRINTF(("uvideo: loaded module\n")); 2224 DPRINTF(("uvideo: loaded module\n"));
2223 return 0; 2225 return 0;
2224 case MODULE_CMD_FINI: 2226 case MODULE_CMD_FINI:
2225 DPRINTF(("uvideo: attempting to unload module\n")); 2227 DPRINTF(("uvideo: attempting to unload module\n"));
2226 err = config_cfdata_detach(uvideo_cfdata); 2228 err = config_cfdata_detach(uvideo_cfdata);
2227 if (err) 2229 if (err)
2228 return err; 2230 return err;
2229 config_cfattach_detach("uvideo", &uvideo_ca); 2231 config_cfattach_detach("uvideo", &uvideo_ca);
2230 config_cfdriver_detach(&uvideo_cd); 2232 config_cfdriver_detach(&uvideo_cd);
2231 DPRINTF(("uvideo: module unload\n")); 2233 DPRINTF(("uvideo: module unload\n"));
2232 return 0; 2234 return 0;
2233 default: 2235 default:
2234 return ENOTTY; 2236 return ENOTTY;
2235 } 2237 }
2236} 2238}
2237 2239
2238#endif /* _MODULE */ 2240#endif /* _MODULE */
2239 2241
2240 2242
2241#ifdef UVIDEO_DEBUG 2243#ifdef UVIDEO_DEBUG
2242/* Some functions to print out descriptors. Mostly useless other than 2244/* Some functions to print out descriptors. Mostly useless other than
2243 * debugging/exploration purposes. */ 2245 * debugging/exploration purposes. */
2244 2246
2245 2247
2246static void 2248static void
2247print_bitmap(const uByte *start, uByte nbytes) 2249print_bitmap(const uByte *start, uByte nbytes)
2248{ 2250{
2249 int byte, bit; 2251 int byte, bit;
2250 2252
2251 /* most significant first */ 2253 /* most significant first */
2252 for (byte = nbytes-1; byte >= 0; --byte) { 2254 for (byte = nbytes-1; byte >= 0; --byte) {
2253 if (byte < nbytes-1) printf("-"); 2255 if (byte < nbytes-1) printf("-");
2254 for (bit = 7; bit >= 0; --bit) 2256 for (bit = 7; bit >= 0; --bit)
2255 printf("%01d", (start[byte] >> bit) &1); 2257 printf("%01d", (start[byte] >> bit) &1);
2256 } 2258 }

cvs diff -r1.1 -r1.2 src/sys/dev/usb/uvideoreg.h (switch to unified diff)

--- src/sys/dev/usb/uvideoreg.h 2008/09/09 01:13:42 1.1
+++ src/sys/dev/usb/uvideoreg.h 2008/09/20 18:17:56 1.2
@@ -1,712 +1,719 @@ @@ -1,712 +1,719 @@
1/* $NetBSD: uvideoreg.h,v 1.1 2008/09/09 01:13:42 jmcneill Exp $ */ 1/* $NetBSD: uvideoreg.h,v 1.2 2008/09/20 18:17:56 jmcneill Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2008 Patrick Mahoney 4 * Copyright (c) 2008 Patrick Mahoney
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code was written by Patrick Mahoney (pat@polycrystal.org) as 7 * This code was written by Patrick Mahoney (pat@polycrystal.org) as
8 * part of Google Summer of Code 2008. 8 * part of Google Summer of Code 2008.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software 18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement: 19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD 20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors. 21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its 22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived 23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission. 24 * from this software without specific prior written permission.
25 * 25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE. 36 * POSSIBILITY OF SUCH DAMAGE.
37 */ 37 */
38 38
39#define UVIDEO_VERSION 0x001 39#define UVIDEO_VERSION 0x001
40 40
41/* This is the standard GUID / UUID. In USB, it comes in the usual 41/* This is the standard GUID / UUID. In USB, it comes in the usual
42 * little-endian packed format. */ 42 * little-endian packed format. */
43 43
44typedef struct { 44typedef struct {
45 uDWord data1; 45 uDWord data1;
46 uWord data2; 46 uWord data2;
47 uWord data3; 47 uWord data3;
48 uByte data4[8]; 48 uByte data4[8];
49} UPACKED usb_guid_t; 49} UPACKED usb_guid_t;
50 50
51typedef struct { 51typedef struct {
52 uint32_t data1; 52 uint32_t data1;
53 uint16_t data2; 53 uint16_t data2;
54 uint16_t data3; 54 uint16_t data3;
55 uint8_t data4[8]; 55 uint8_t data4[8];
56} guid_t; 56} guid_t;
57#define GUID_LEN 16 57#define GUID_LEN 16
58 58
59/* 59/*
60 * Video Control descriptors 60 * Video Control descriptors
61 */ 61 */
62 62
63#define UDESC_VC_HEADER 0x01 63#define UDESC_VC_HEADER 0x01
64#define UDESC_INPUT_TERMINAL 0x02 64#define UDESC_INPUT_TERMINAL 0x02
65#define UDESC_OUTPUT_TERMINAL 0x03 65#define UDESC_OUTPUT_TERMINAL 0x03
66#define UDESC_SELECTOR_UNIT 0x04 66#define UDESC_SELECTOR_UNIT 0x04
67#define UDESC_PROCESSING_UNIT 0x05 67#define UDESC_PROCESSING_UNIT 0x05
68#define UDESC_EXTENSION_UNIT 0x06 68#define UDESC_EXTENSION_UNIT 0x06
69 69
70#define UDESC_VC_INTERRUPT_ENDPOINT 0x03 70#define UDESC_VC_INTERRUPT_ENDPOINT 0x03
71 71
72/* Terminal Types */ 72/* Terminal Types */
73#define UVDIEO_TT_VENDOR_SPECIFIC 0x0100 73#define UVDIEO_TT_VENDOR_SPECIFIC 0x0100
74#define UVIDEO_TT_STREAMING 0x0101 74#define UVIDEO_TT_STREAMING 0x0101
75 75
76/* Input Terminal Types */ 76/* Input Terminal Types */
77#define UVIDEO_ITT_VENDOR_SPECIFIC 0x0200 77#define UVIDEO_ITT_VENDOR_SPECIFIC 0x0200
78#define UVIDEO_ITT_CAMERA 0x0201 78#define UVIDEO_ITT_CAMERA 0x0201
79#define UVIDEO_ITT_MEDIA_TRANSPORT_INPUT 0x0202 79#define UVIDEO_ITT_MEDIA_TRANSPORT_INPUT 0x0202
80 80
81/* Output Terminal Types */ 81/* Output Terminal Types */
82#define UVIDEO_OTT_VENDOR_SPECIFIC 0x0300 82#define UVIDEO_OTT_VENDOR_SPECIFIC 0x0300
83#define UVIDEO_OTT_DISPLAY 0x0301 83#define UVIDEO_OTT_DISPLAY 0x0301
84#define UVIDEO_OTT_MEDIA_TRANSPORT_OUTPUT 0x0302 84#define UVIDEO_OTT_MEDIA_TRANSPORT_OUTPUT 0x0302
85 85
86/* generic descriptor with Subtype */ 86/* generic descriptor with Subtype */
87typedef struct { 87typedef struct {
88 uByte bLength; 88 uByte bLength;
89 uByte bDescriptorType; 89 uByte bDescriptorType;
90 uByte bDescriptorSubtype; 90 uByte bDescriptorSubtype;
91} uvideo_descriptor_t; 91} uvideo_descriptor_t;
92 92
93/* Class-specific Video Control Interface Header Descriptor */ 93/* Class-specific Video Control Interface Header Descriptor */
94typedef struct { 94typedef struct {
95 uByte bLength; 95 uByte bLength;
96 uByte bDescriptorType; 96 uByte bDescriptorType;
97 uByte bDescriptorSubtype; 97 uByte bDescriptorSubtype;
98 uWord bcdUVC; 98 uWord bcdUVC;
99 uWord wTotalLength; 99 uWord wTotalLength;
100 uDWord dwClockFrequency; 100 uDWord dwClockFrequency;
101 uByte bInCollection; 101 uByte bInCollection;
102 /* followed by n bytes where n is equal to value of bInCollection */ 102 /* followed by n bytes where n is equal to value of bInCollection */
103 uByte baInterfaceNr[]; 103 uByte baInterfaceNr[];
104} UPACKED uvideo_vc_header_descriptor_t; 104} UPACKED uvideo_vc_header_descriptor_t;
105 105
106/* Input Terminal Descriptor */ 106/* Input Terminal Descriptor */
107typedef struct { 107typedef struct {
108 uByte bLength; 108 uByte bLength;
109 uByte bDescriptorType; 109 uByte bDescriptorType;
110 uByte bDescriptorSubtype; 110 uByte bDescriptorSubtype;
111 uByte bTerminalID; 111 uByte bTerminalID;
112 uWord wTerminalType; 112 uWord wTerminalType;
113 uByte bAssocTerminal; 113 uByte bAssocTerminal;
114 uByte iTerminal; 114 uByte iTerminal;
115 /* possibly more, depending on Terminal type */ 115 /* possibly more, depending on Terminal type */
116} UPACKED uvideo_input_terminal_descriptor_t; 116} UPACKED uvideo_input_terminal_descriptor_t;
117 117
118/* Output Terminal Descriptor */ 118/* Output Terminal Descriptor */
119typedef struct { 119typedef struct {
120 uByte bLength; 120 uByte bLength;
121 uByte bDescriptorType; 121 uByte bDescriptorType;
122 uByte bDescriptorSubtype; 122 uByte bDescriptorSubtype;
123 uByte bTerminalID; 123 uByte bTerminalID;
124 uWord wTerminalType; 124 uWord wTerminalType;
125 uByte bAssocTerminal; 125 uByte bAssocTerminal;
126 uByte bSourceID; 126 uByte bSourceID;
127 uByte iTerminal; 127 uByte iTerminal;
128} UPACKED uvideo_output_terminal_descriptor_t; 128} UPACKED uvideo_output_terminal_descriptor_t;
129 129
130/* Camera Terminal Descriptor */ 130/* Camera Terminal Descriptor */
131typedef struct { 131typedef struct {
132 uByte bLength; 132 uByte bLength;
133 uByte bDescriptorType; 133 uByte bDescriptorType;
134 uByte bDescriptorSubtype; /* UDESC_VC_INPUT_TERMINAL */ 134 uByte bDescriptorSubtype; /* UDESC_VC_INPUT_TERMINAL */
135 uByte bTerminalID; 135 uByte bTerminalID;
136 uWord wTerminalType; /* UVIDEO_ITT_CAMERA */ 136 uWord wTerminalType; /* UVIDEO_ITT_CAMERA */
137 uByte bAssocTerminal; 137 uByte bAssocTerminal;
138 uByte iTerminal; 138 uByte iTerminal;
139 uWord wObjectiveFocalLengthMin; 139 uWord wObjectiveFocalLengthMin;
140 uWord wObjectiveFocalLengthMax; 140 uWord wObjectiveFocalLengthMax;
141 uWord wOcularFocalLength; 141 uWord wOcularFocalLength;
142 uByte bControlSize; 142 uByte bControlSize;
143 uByte bmControls[]; 143 uByte bmControls[];
144} UPACKED uvideo_camera_terminal_descriptor_t; 144} UPACKED uvideo_camera_terminal_descriptor_t;
145 145
146/* bmControls fields of uvideo_camera_terminal_descriptor_t */ 146/* bmControls fields of uvideo_camera_terminal_descriptor_t */
147#define UVIDEO_CAMERA_CONTROL_SCANNING_MODE (1<<0) 147#define UVIDEO_CAMERA_CONTROL_SCANNING_MODE (1<<0)
148#define UVIDEO_CAMERA_CONTROL_AUTO_EXPOSURE_MODE (1<<1) 148#define UVIDEO_CAMERA_CONTROL_AUTO_EXPOSURE_MODE (1<<1)
149#define UVIDEO_CAMERA_CONTROL_AUTO_EXPOSURE_PRIO (1<<2) 149#define UVIDEO_CAMERA_CONTROL_AUTO_EXPOSURE_PRIO (1<<2)
150#define UVIDEO_CAMERA_CONTROL_EXPOSURE_TIME_ABSOLUTE (1<<3) 150#define UVIDEO_CAMERA_CONTROL_EXPOSURE_TIME_ABSOLUTE (1<<3)
151#define UVIDEO_CAMERA_CONTROL_EXPOSURE_TIME_RELATIVE (1<<4) 151#define UVIDEO_CAMERA_CONTROL_EXPOSURE_TIME_RELATIVE (1<<4)
152#define UVIDEO_CAMERA_CONTROL_FOCUS_ABSOLUTE (1<<5) 152#define UVIDEO_CAMERA_CONTROL_FOCUS_ABSOLUTE (1<<5)
153#define UVIDEO_CAMERA_CONTROL_FOCUS_RELATIVE (1<<6) 153#define UVIDEO_CAMERA_CONTROL_FOCUS_RELATIVE (1<<6)
154#define UVIDEO_CAMERA_CONTROL_IRIS_ABSOLUTE (1<<7) 154#define UVIDEO_CAMERA_CONTROL_IRIS_ABSOLUTE (1<<7)
155#define UVIDEO_CAMERA_CONTROL_IRIS_RELATIVE (1<<8) 155#define UVIDEO_CAMERA_CONTROL_IRIS_RELATIVE (1<<8)
156#define UVIDEO_CAMERA_CONTROL_ZOOM_ABSOLUTE (1<<9) 156#define UVIDEO_CAMERA_CONTROL_ZOOM_ABSOLUTE (1<<9)
157#define UVIDEO_CAMERA_CONTROL_ZOOM_RELATIVE (1<<10) 157#define UVIDEO_CAMERA_CONTROL_ZOOM_RELATIVE (1<<10)
158#define UVIDEO_CAMERA_CONTROL_PANTILT_ABSOLUTE (1<<11) 158#define UVIDEO_CAMERA_CONTROL_PANTILT_ABSOLUTE (1<<11)
159#define UVIDEO_CAMERA_CONTROL_PANTILT_RELATIVE (1<<12) 159#define UVIDEO_CAMERA_CONTROL_PANTILT_RELATIVE (1<<12)
160#define UVIDEO_CAMERA_CONTROL_ROLL_ABSOLUTE (1<<13) 160#define UVIDEO_CAMERA_CONTROL_ROLL_ABSOLUTE (1<<13)
161#define UVIDEO_CAMERA_CONTROL_ROLL_RELATIVE (1<<14) 161#define UVIDEO_CAMERA_CONTROL_ROLL_RELATIVE (1<<14)
162/* 15,16 reserved */ 162/* 15,16 reserved */
163#define UVIDEO_CAMERA_CONTROL_FOCUS_AUTO (1<<17) 163#define UVIDEO_CAMERA_CONTROL_FOCUS_AUTO (1<<17)
164#define UVIDEO_CAMERA_CONTROL_PRIVACY (1<<18) 164#define UVIDEO_CAMERA_CONTROL_PRIVACY (1<<18)
165 165
166typedef struct { 166typedef struct {
167 uByte bLength; 167 uByte bLength;
168 uByte bDescriptorType; 168 uByte bDescriptorType;
169 uByte bDescriptorSubtype; 169 uByte bDescriptorSubtype;
170 uByte bUnitID; 170 uByte bUnitID;
171 uByte bNrInPins; 171 uByte bNrInPins;
172 uByte baSourceID[]; 172 uByte baSourceID[];
173 /* The position of the next field is baSourceID[0] + bNrInPins 173 /* The position of the next field is baSourceID[0] + bNrInPins
174 * and should be accessed via a function. */ 174 * and should be accessed via a function. */
175/* uByte iSelector */ 175/* uByte iSelector */
176} UPACKED uvideo_selector_unit_descriptor_t; 176} UPACKED uvideo_selector_unit_descriptor_t;
177 177
178typedef struct { 178typedef struct {
179 uByte bLength; 179 uByte bLength;
180 uByte bDescriptorType; 180 uByte bDescriptorType;
181 uByte bDescriptorSubtype; 181 uByte bDescriptorSubtype;
182 uByte bUnitID; 182 uByte bUnitID;
183 uByte bSourceID; 183 uByte bSourceID;
184 uWord wMaxMultiplier; 184 uWord wMaxMultiplier;
185 uByte bControlSize; 185 uByte bControlSize;
186 uByte bmControls[]; 186 uByte bmControls[];
187/* uByte iProcessing */ 187/* uByte iProcessing */
188/* uByte bmVideoStandards */ 188/* uByte bmVideoStandards */
189#define PU_GET_VIDEO_STANDARDS(desc) \ 189#define PU_GET_VIDEO_STANDARDS(desc) \
190 (*((desc)->bmControls + (desc)->bControlSize)) 190 (*((desc)->bmControls + (desc)->bControlSize))
191#define UVIDEO_STANDARD_NONE (1<<0) 191#define UVIDEO_STANDARD_NONE (1<<0)
192#define UVIDEO_STANDARD_NTSC_525_60 (1<<1) 192#define UVIDEO_STANDARD_NTSC_525_60 (1<<1)
193#define UVIDEO_STANDARD_PAL_625_50 (1<<2) 193#define UVIDEO_STANDARD_PAL_625_50 (1<<2)
194#define UVIDEO_STANDARD_SECAM_625_50 (1<<3) 194#define UVIDEO_STANDARD_SECAM_625_50 (1<<3)
195#define UVIDEO_STANDARD_NTSC_625_50 (1<<4) 195#define UVIDEO_STANDARD_NTSC_625_50 (1<<4)
196#define UVIDEO_STANDARD_PAL_525_60 (1<<5) 196#define UVIDEO_STANDARD_PAL_525_60 (1<<5)
197} UPACKED uvideo_processing_unit_descriptor_t; 197} UPACKED uvideo_processing_unit_descriptor_t;
198 198
199typedef struct { 199typedef struct {
200 uByte bLength; 200 uByte bLength;
201 uByte bDescriptorType; 201 uByte bDescriptorType;
202 uByte bDescriptorSubtype; 202 uByte bDescriptorSubtype;
203 uByte bUnitID; 203 uByte bUnitID;
204 usb_guid_t guidExtensionCode; 204 usb_guid_t guidExtensionCode;
205 uByte bNumControls; 205 uByte bNumControls;
206 uByte bNrInPins; 206 uByte bNrInPins;
207 uByte baSourceID[]; 207 uByte baSourceID[];
208/* uByte bControlSize */ 208/* uByte bControlSize */
209/* uByte bmControls */ 209/* uByte bmControls */
210#define XU_GET_CONTROL_SIZE(desc) \ 210#define XU_GET_CONTROL_SIZE(desc) \
211 (*((desc)->baSourceID + (desc)->bNrInPins)) 211 (*((desc)->baSourceID + (desc)->bNrInPins))
212#define XU_GET_CONTROLS(desc) \ 212#define XU_GET_CONTROLS(desc) \
213 ((desc)->baSourceID + (desc)->bNrInPins + 1) 213 ((desc)->baSourceID + (desc)->bNrInPins + 1)
214/* uByte iExtension */ 214/* uByte iExtension */
215} UPACKED uvideo_extension_unit_descriptor_t; 215} UPACKED uvideo_extension_unit_descriptor_t;
216 216
217typedef struct { 217typedef struct {
218 uByte bLength; 218 uByte bLength;
219 uByte bDescriptorType; /* UDESC_ENDPOINT */ 219 uByte bDescriptorType; /* UDESC_ENDPOINT */
220 uByte bDescriptorSubtype; 220 uByte bDescriptorSubtype;
221 uWord wMaxTransferSize; 221 uWord wMaxTransferSize;
222} UPACKED uvideo_vc_interrupt_endpoint_descriptor_t; 222} UPACKED uvideo_vc_interrupt_endpoint_descriptor_t;
223 223
224 224
225 225
226/* 226/*
227 * Video Streaming descriptors 227 * Video Streaming descriptors
228 */ 228 */
229 229
230#define UDESC_VS_INPUT_HEADER 0x01 230#define UDESC_VS_INPUT_HEADER 0x01
231#define UDESC_VS_OUTPUT_HEADER 0x02 231#define UDESC_VS_OUTPUT_HEADER 0x02
232#define UDESC_VS_STILL_IMAGE_FRAME 0x03 232#define UDESC_VS_STILL_IMAGE_FRAME 0x03
233#define UDESC_VS_FORMAT_UNCOMPRESSED 0x04 233#define UDESC_VS_FORMAT_UNCOMPRESSED 0x04
234#define UDESC_VS_FRAME_UNCOMPRESSED 0x05 234#define UDESC_VS_FRAME_UNCOMPRESSED 0x05
235#define UDESC_VS_FORMAT_MJPEG 0x06 235#define UDESC_VS_FORMAT_MJPEG 0x06
236#define UDESC_VS_FRAME_MJPEG 0x07 236#define UDESC_VS_FRAME_MJPEG 0x07
237/* reserved in spec v1.1 0x08 */ 237/* reserved in spec v1.1 0x08 */
238/* reserved in spec v1.1 0x09 */ 238/* reserved in spec v1.1 0x09 */
239#define UDESC_VS_FORMAT_MPEG2TS 0x0A 239#define UDESC_VS_FORMAT_MPEG2TS 0x0A
240/* reserved in spec v 1.1 0x0B */ 240/* reserved in spec v 1.1 0x0B */
241#define UDESC_VS_FORMAT_DV 0x0C 241#define UDESC_VS_FORMAT_DV 0x0C
242#define UDESC_VS_COLORFORMAT 0x0D 242#define UDESC_VS_COLORFORMAT 0x0D
243/* reserved in spec v1.1 0x0E */ 243/* reserved in spec v1.1 0x0E */
244/* reserved in spec v1.1 0x0F */ 244/* reserved in spec v1.1 0x0F */
245#define UDESC_VS_FORMAT_FRAME_BASED 0x10 245#define UDESC_VS_FORMAT_FRAME_BASED 0x10
246#define UDESC_VS_FRAME_FRAME_BASED 0x11 246#define UDESC_VS_FRAME_FRAME_BASED 0x11
247#define UDESC_VS_FORMAT_STREAM_BASED 0x12 247#define UDESC_VS_FORMAT_STREAM_BASED 0x12
248 248
249/* Copy protection state */ 249/* Copy protection state */
250#define UVIDEO_NO_RESTRICTIONS 0 250#define UVIDEO_NO_RESTRICTIONS 0
251#define UVIDEO_RESTRICT_DUP 1 251#define UVIDEO_RESTRICT_DUP 1
252 252
253typedef struct { 253typedef struct {
254 uByte bLength; 254 uByte bLength;
255 uByte bDescriptorType; 255 uByte bDescriptorType;
256 uByte bDescriptorSubtype; 256 uByte bDescriptorSubtype;
257 uByte bNumFormats; 257 uByte bNumFormats;
258 uWord wTotalLength; 258 uWord wTotalLength;
259 uByte bEndpointAddress; 259 uByte bEndpointAddress;
260 uByte bmInfo; 260 uByte bmInfo;
261 uByte bTerminalLink; 261 uByte bTerminalLink;
262 uByte bStillCaptureMethod; 262 uByte bStillCaptureMethod;
263 uByte bTriggerSupport; 263 uByte bTriggerSupport;
264 uByte bTriggerUsage; 264 uByte bTriggerUsage;
265 uByte bControlSize; 265 uByte bControlSize;
266 uByte bmaControls[]; 266 uByte bmaControls[];
267#define UVIDEO_VS_KEYFRAME_RATE (1<<0) 267#define UVIDEO_VS_KEYFRAME_RATE (1<<0)
268#define UVIDEO_VS_PFRAME_RATE (1<<1) 268#define UVIDEO_VS_PFRAME_RATE (1<<1)
269#define UVIDEO_VS_COMP_QUALITY (1<<2) 269#define UVIDEO_VS_COMP_QUALITY (1<<2)
270#define UVIDEO_VS_COMP_WINDOW_SIZE (1<<3) 270#define UVIDEO_VS_COMP_WINDOW_SIZE (1<<3)
271#define UVIDEO_VS_GENERATE_KEYFRAME (1<<4) 271#define UVIDEO_VS_GENERATE_KEYFRAME (1<<4)
272#define UVIDEO_VS_UPDATE_FRAME_SEGMENT (1<<5) 272#define UVIDEO_VS_UPDATE_FRAME_SEGMENT (1<<5)
273} UPACKED uvideo_vs_input_header_descriptor_t; 273} UPACKED uvideo_vs_input_header_descriptor_t;
274 274
275typedef struct { 275typedef struct {
276 uByte bLength; 276 uByte bLength;
277 uByte bDescriptorType; 277 uByte bDescriptorType;
278 uByte bDescriptorSubtype; 278 uByte bDescriptorSubtype;
279 uByte bNumFormats; 279 uByte bNumFormats;
280 uWord wTotalLength; 280 uWord wTotalLength;
281 uByte bEndpointAddress; 281 uByte bEndpointAddress;
282 uByte bTerminalLink; 282 uByte bTerminalLink;
283 uByte bControlSize; 283 uByte bControlSize;
284 uByte bmaControls[]; 284 uByte bmaControls[];
285} UPACKED uvideo_vs_output_header_descriptor_t; 285} UPACKED uvideo_vs_output_header_descriptor_t;
286 286
287 287
288typedef struct { 288typedef struct {
289 uWord wWidth; 289 uWord wWidth;
290 uWord wHeight; 290 uWord wHeight;
291} UPACKED uvideo_still_image_frame_dimensions_t; 291} UPACKED uvideo_still_image_frame_dimensions_t;
292 292
293typedef struct { 293typedef struct {
294 uByte bLength; 294 uByte bLength;
295 uByte bDescriptorType; 295 uByte bDescriptorType;
296 uByte bDescriptorSubtype; 296 uByte bDescriptorSubtype;
297 uByte bEndpointAddress; 297 uByte bEndpointAddress;
298 uByte bNumImageSizePatterns; 298 uByte bNumImageSizePatterns;
299 uvideo_still_image_frame_dimensions_t wwaDimensions[]; 299 uvideo_still_image_frame_dimensions_t wwaDimensions[];
300 /* position dependent on size of previous item */ 300 /* position dependent on size of previous item */
301 /* uByte bNumCompressionPattern */ 301 /* uByte bNumCompressionPattern */
302 /* uByte bCompression[] */ 302 /* uByte bCompression[] */
303} UPACKED uvideo_still_image_frame_descriptor_t; 303} UPACKED uvideo_still_image_frame_descriptor_t;
304 304
305 305
306/* Color matching information */ 306/* Color matching information */
307 307
308/* bColroPrimaries */ 308/* bColroPrimaries */
309#define UVIDEO_COLOR_PRIMARIES_UNSPECIFIED 0 309#define UVIDEO_COLOR_PRIMARIES_UNSPECIFIED 0
310#define UVIDEO_COLOR_PRIMARIES_sRGB 1 /* same as BT709 */ 310#define UVIDEO_COLOR_PRIMARIES_sRGB 1 /* same as BT709 */
311#define UVIDEO_COLOR_PRIMARIES_BT709 1 /* default */ 311#define UVIDEO_COLOR_PRIMARIES_BT709 1 /* default */
312#define UVIDEO_COLOR_PRIMARIES_BT470_2_M 2 312#define UVIDEO_COLOR_PRIMARIES_BT470_2_M 2
313#define UVIDEO_COLOR_PRIMARIES_BT470_2_BG 3 313#define UVIDEO_COLOR_PRIMARIES_BT470_2_BG 3
314#define UVIDEO_COLOR_PRIMARIES_SMPTE_170M 4 314#define UVIDEO_COLOR_PRIMARIES_SMPTE_170M 4
315#define UVIDEO_COLOR_PRIMARIES_SMPTE_240M 5 315#define UVIDEO_COLOR_PRIMARIES_SMPTE_240M 5
316 316
317/* bTransferCharacteristics */ 317/* bTransferCharacteristics */
318#define UVIDEO_GAMMA_FUNCTION_UNSPECIFIED 0 318#define UVIDEO_GAMMA_FUNCTION_UNSPECIFIED 0
319#define UVIDEO_GAMMA_FUNCTION_BT709 1 /* default */ 319#define UVIDEO_GAMMA_FUNCTION_BT709 1 /* default */
320#define UVIDEO_GAMMA_FUNCTION_BT470_2_M 2 320#define UVIDEO_GAMMA_FUNCTION_BT470_2_M 2
321#define UVIDEO_GAMMA_FUNCTION_BT470_2_BG 3 321#define UVIDEO_GAMMA_FUNCTION_BT470_2_BG 3
322#define UVIDEO_GAMMA_FUNCTION_SMPTE_170M 4 322#define UVIDEO_GAMMA_FUNCTION_SMPTE_170M 4
323#define UVIDEO_GAMMA_FUNCTION_SMPTE_240M 5 323#define UVIDEO_GAMMA_FUNCTION_SMPTE_240M 5
324#define UVIDEO_GAMMA_FUNCTION_LINEAR 6  324#define UVIDEO_GAMMA_FUNCTION_LINEAR 6
325#define UVIDEO_GAMMA_FUNCTION_sRGB 7 /* similar to BT709 */ 325#define UVIDEO_GAMMA_FUNCTION_sRGB 7 /* similar to BT709 */
326 326
327/* bMatrixCoefficients */ 327/* bMatrixCoefficients */
328#define UVIDEO_LUMA_CHROMA_MATRIX_UNSPECIFIED 0 328#define UVIDEO_LUMA_CHROMA_MATRIX_UNSPECIFIED 0
329#define UVIDEO_LUMA_CHROMA_MATRIX_BT709 1 329#define UVIDEO_LUMA_CHROMA_MATRIX_BT709 1
330#define UVIDEO_LUMA_CHROMA_MATRIX_FCC 2 330#define UVIDEO_LUMA_CHROMA_MATRIX_FCC 2
331#define UVIDEO_LUMA_CHROMA_MATRIX_BT470_2_BG 3 331#define UVIDEO_LUMA_CHROMA_MATRIX_BT470_2_BG 3
332#define UVIDEO_LUMA_CHROMA_MATRIX_SMPTE_170M 4 /* default */ 332#define UVIDEO_LUMA_CHROMA_MATRIX_SMPTE_170M 4 /* default */
333#define UVIDEO_LUMA_CHROMA_MATRIX_SMPTE_240M 5 333#define UVIDEO_LUMA_CHROMA_MATRIX_SMPTE_240M 5
334 334
335typedef struct { 335typedef struct {
336 uByte bLength; 336 uByte bLength;
337 uByte bDescriptorType; 337 uByte bDescriptorType;
338 uByte bDescriptorSubtype; 338 uByte bDescriptorSubtype;
339 uByte bColorPrimaries; 339 uByte bColorPrimaries;
340 uByte bTransferCharacteristics; 340 uByte bTransferCharacteristics;
341 uByte bMatrixCoefficients; 341 uByte bMatrixCoefficients;
342} UPACKED uvideo_color_matching_descriptor_t; 342} UPACKED uvideo_color_matching_descriptor_t;
343 343
344/* 344/*
345 * Format and Frame descriptors 345 * Format and Frame descriptors
346 */ 346 */
347 347
348#define UVIDEO_FRAME_CAP_STILL_IMAGE 1<<0 348#define UVIDEO_FRAME_CAP_STILL_IMAGE 1<<0
349#define UVIDEO_FRAME_CAP_FIXED_RATE 1<<1 349#define UVIDEO_FRAME_CAP_FIXED_RATE 1<<1
350 350
351#define UVIDEO_FRAME_INTERVAL_CONTINUOUS 0 351#define UVIDEO_FRAME_INTERVAL_CONTINUOUS 0
352 352
353/* TODO: interlace flags */ 353/* TODO: interlace flags */
354 354
355 355
356typedef struct { 356typedef struct {
357 uDWord dwMinFrameInterval; 357 uDWord dwMinFrameInterval;
358 uDWord dwMaxFrameInterval; 358 uDWord dwMaxFrameInterval;
359 uDWord dwFrameIntervalStep; 359 uDWord dwFrameIntervalStep;
360} UPACKED uvideo_frame_interval_continuous_t; 360} UPACKED uvideo_frame_interval_continuous_t;
361 361
362typedef struct { 362typedef struct {
363 uDWord dwFrameInterval[1]; /* length depends on bFrameIntervalType */ 363 uDWord dwFrameInterval[1]; /* length depends on bFrameIntervalType */
364} UPACKED uvideo_frame_interval_discrete_t; 364} UPACKED uvideo_frame_interval_discrete_t;
365 365
366typedef union { 366typedef union {
367 uvideo_frame_interval_continuous_t continuous; 367 uvideo_frame_interval_continuous_t continuous;
368 uvideo_frame_interval_discrete_t discrete; 368 uvideo_frame_interval_discrete_t discrete;
369} uvideo_frame_interval_t; 369} uvideo_frame_interval_t;
370 370
371/* generic format descriptor header */ 371/* generic format descriptor header */
372typedef struct { 372typedef struct {
373 uByte bLength; 373 uByte bLength;
374 uByte bDescriptorType; 374 uByte bDescriptorType;
375 uByte bDescriptorSubtype; 375 uByte bDescriptorSubtype;
376 uByte bFormatIndex; 376 uByte bFormatIndex;
377} UPACKED uvideo_vs_format_descriptor_t; 377} UPACKED uvideo_vs_format_descriptor_t;
378 378
379/* generic frame descriptor header */ 379/* generic frame descriptor header */
380typedef struct { 380typedef struct {
381 uByte bLength; 381 uByte bLength;
382 uByte bDescriptorType; 382 uByte bDescriptorType;
383 uByte bDescriptorSubtype; 383 uByte bDescriptorSubtype;
384 uByte bFrameIndex; 384 uByte bFrameIndex;
385} UPACKED uvideo_vs_frame_descriptor_t; 385} UPACKED uvideo_vs_frame_descriptor_t;
386 386
387 387
388/* uncompressed format and frame descriptors */ 388/* uncompressed format and frame descriptors */
389static const guid_t uvideo_guid_format_yuy2 = { 389static const guid_t uvideo_guid_format_yuy2 = {
390 0x32595559, 390 0x32595559,
391 0x0000, 391 0x0000,
392 0x0010, 392 0x0010,
393 {0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71} 393 {0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}
394}; 394};
395 395
396static const guid_t uvideo_guid_format_nv12 = { 396static const guid_t uvideo_guid_format_nv12 = {
397 0x3231564E, 397 0x3231564E,
398 0x0000, 398 0x0000,
399 0x0010, 399 0x0010,
400 {0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71} 400 {0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}
401}; 401};
402 402
 403static const guid_t uvideo_guid_format_uyvy = {
 404 0x59565955,
 405 0x0000,
 406 0x0010,
 407 {0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}
 408};
 409
403typedef struct { 410typedef struct {
404 uByte bLength; 411 uByte bLength;
405 uByte bDescriptorType; 412 uByte bDescriptorType;
406 uByte bDescriptorSubtype; 413 uByte bDescriptorSubtype;
407 uByte bFormatIndex; 414 uByte bFormatIndex;
408 uByte bNumFrameDescriptors; 415 uByte bNumFrameDescriptors;
409 usb_guid_t guidFormat; 416 usb_guid_t guidFormat;
410 uByte bBitsPerPixel; 417 uByte bBitsPerPixel;
411 uByte bDefaultFrameIndex; 418 uByte bDefaultFrameIndex;
412 uByte bAspectRatioX; 419 uByte bAspectRatioX;
413 uByte bAspectRatioY; 420 uByte bAspectRatioY;
414 uByte bmInterlaceFlags; 421 uByte bmInterlaceFlags;
415 uByte bCopyProtect; 422 uByte bCopyProtect;
416} UPACKED uvideo_vs_format_uncompressed_descriptor_t; 423} UPACKED uvideo_vs_format_uncompressed_descriptor_t;
417 424
418typedef struct { 425typedef struct {
419 uByte bLength; 426 uByte bLength;
420 uByte bDescriptorType; 427 uByte bDescriptorType;
421 uByte bDescriptorSubtype; 428 uByte bDescriptorSubtype;
422 uByte bFrameIndex; 429 uByte bFrameIndex;
423 uByte bmCapabilities; 430 uByte bmCapabilities;
424 uWord wWidth; 431 uWord wWidth;
425 uWord wHeight; 432 uWord wHeight;
426 uDWord dwMinBitRate; 433 uDWord dwMinBitRate;
427 uDWord dwMaxBitRate; 434 uDWord dwMaxBitRate;
428 uDWord dwMaxVideoFrameBufferSize; 435 uDWord dwMaxVideoFrameBufferSize;
429 uDWord dwDefaultFrameInterval; 436 uDWord dwDefaultFrameInterval;
430 uByte bFrameIntervalType; 437 uByte bFrameIntervalType;
431 uvideo_frame_interval_t uFrameInterval; 438 uvideo_frame_interval_t uFrameInterval;
432} UPACKED uvideo_vs_frame_uncompressed_descriptor_t; 439} UPACKED uvideo_vs_frame_uncompressed_descriptor_t;
433 440
434 441
435/* Frame based Format and Frame descriptors. This is for generic 442/* Frame based Format and Frame descriptors. This is for generic
436 * frame based payloads not covered by other types (e.g, uncompressed 443 * frame based payloads not covered by other types (e.g, uncompressed
437 * or MJPEG). */ 444 * or MJPEG). */
438 445
439typedef struct { 446typedef struct {
440 uByte bLength; 447 uByte bLength;
441 uByte bDescriptorType; 448 uByte bDescriptorType;
442 uByte bDescriptorSubtype; 449 uByte bDescriptorSubtype;
443 uByte bFormatIndex; 450 uByte bFormatIndex;
444 uByte bNumFrameDescriptors; 451 uByte bNumFrameDescriptors;
445 usb_guid_t guidFormat; 452 usb_guid_t guidFormat;
446 uByte bBitsPerPixel; 453 uByte bBitsPerPixel;
447 uByte bDefaultFrameIndex; 454 uByte bDefaultFrameIndex;
448 uByte bAspectRatioX; 455 uByte bAspectRatioX;
449 uByte bAspectRatioY; 456 uByte bAspectRatioY;
450 uByte bmInterlaceFlags; 457 uByte bmInterlaceFlags;
451 uByte bCopyProtect; 458 uByte bCopyProtect;
452} UPACKED uvideo_format_frame_based_descriptor_t; 459} UPACKED uvideo_format_frame_based_descriptor_t;
453 460
454typedef struct { 461typedef struct {
455 uByte bLength; 462 uByte bLength;
456 uByte bDescriptorType; 463 uByte bDescriptorType;
457 uByte bDescriptorSubtype; 464 uByte bDescriptorSubtype;
458 uByte bFrameIndex; 465 uByte bFrameIndex;
459 uByte bmCapabilities; 466 uByte bmCapabilities;
460 uWord wWidth; 467 uWord wWidth;
461 uWord wHeight; 468 uWord wHeight;
462 uDWord dwMinBitRate; 469 uDWord dwMinBitRate;
463 uDWord dwMaxBitRate; 470 uDWord dwMaxBitRate;
464 uDWord dwDefaultFrameInterval; 471 uDWord dwDefaultFrameInterval;
465 uByte bFrameIntervalType; 472 uByte bFrameIntervalType;
466 uDWord dwBytesPerLine; 473 uDWord dwBytesPerLine;
467 uvideo_frame_interval_t uFrameInterval; 474 uvideo_frame_interval_t uFrameInterval;
468} UPACKED uvideo_frame_frame_based_descriptor_t; 475} UPACKED uvideo_frame_frame_based_descriptor_t;
469 476
470 477
471/* MJPEG format and frame descriptors */ 478/* MJPEG format and frame descriptors */
472 479
473typedef struct { 480typedef struct {
474 uByte bLength; 481 uByte bLength;
475 uByte bDescriptorType; 482 uByte bDescriptorType;
476 uByte bDescriptorSubtype; 483 uByte bDescriptorSubtype;
477 uByte bFormatIndex; 484 uByte bFormatIndex;
478 uByte bNumFrameDescriptors; 485 uByte bNumFrameDescriptors;
479 uByte bmFlags; 486 uByte bmFlags;
480#define UVIDEO_NO_FIXED_SIZE_SAMPLES 0 487#define UVIDEO_NO_FIXED_SIZE_SAMPLES 0
481#define UVIDEO_FIXED_SIZE_SAMPLES 1 488#define UVIDEO_FIXED_SIZE_SAMPLES 1
482 uByte bDefaultFrameIndex; 489 uByte bDefaultFrameIndex;
483 uByte bAspectRatioX; 490 uByte bAspectRatioX;
484 uByte bAspectRatioY; 491 uByte bAspectRatioY;
485 uByte bmInterlaceFlags; 492 uByte bmInterlaceFlags;
486 uByte bCopyProtect; 493 uByte bCopyProtect;
487} UPACKED uvideo_vs_format_mjpeg_descriptor_t; 494} UPACKED uvideo_vs_format_mjpeg_descriptor_t;
488 495
489typedef struct { 496typedef struct {
490 uByte bLength; 497 uByte bLength;
491 uByte bDescriptorType; 498 uByte bDescriptorType;
492 uByte bDescriptorSubtype; 499 uByte bDescriptorSubtype;
493 uByte bFrameIndex; 500 uByte bFrameIndex;
494 uByte bmCapabilities; 501 uByte bmCapabilities;
495 uWord wWidth; 502 uWord wWidth;
496 uWord wHeight; 503 uWord wHeight;
497 uDWord dwMinBitRate; 504 uDWord dwMinBitRate;
498 uDWord dwMaxBitRate; 505 uDWord dwMaxBitRate;
499 uDWord dwMaxVideoFrameBufferSize; 506 uDWord dwMaxVideoFrameBufferSize;
500 uDWord dwDefaultFrameInterval; 507 uDWord dwDefaultFrameInterval;
501 uByte bFrameIntervalType; 508 uByte bFrameIntervalType;
502 uvideo_frame_interval_t uFrameInterval; 509 uvideo_frame_interval_t uFrameInterval;
503} UPACKED uvideo_vs_frame_mjpeg_descriptor_t; 510} UPACKED uvideo_vs_frame_mjpeg_descriptor_t;
504 511
505 512
506typedef struct { 513typedef struct {
507 uByte bLength; 514 uByte bLength;
508 uByte bDescriptorType; 515 uByte bDescriptorType;
509 uByte bDescriptorSubtype; 516 uByte bDescriptorSubtype;
510 uByte bFormatIndex; 517 uByte bFormatIndex;
511 uDWord dwMaxVideoFrameBufferSize; 518 uDWord dwMaxVideoFrameBufferSize;
512 uByte bFormatType; 519 uByte bFormatType;
513#define UVIDEO_GET_DV_FREQ(ubyte) (((ubyte)>>7) & 1) 520#define UVIDEO_GET_DV_FREQ(ubyte) (((ubyte)>>7) & 1)
514#define UVIDEO_DV_FORMAT_FREQ_50HZ 0 521#define UVIDEO_DV_FORMAT_FREQ_50HZ 0
515#define UVIDEO_DV_FORMAT_FREQ_60HZ 1 522#define UVIDEO_DV_FORMAT_FREQ_60HZ 1
516#define UVIDEO_GET_DV_FORMAT(ubyte) ((ubyte) & 0x3f) 523#define UVIDEO_GET_DV_FORMAT(ubyte) ((ubyte) & 0x3f)
517#define UVIDEO_DV_FORMAT_SD_DV 0 524#define UVIDEO_DV_FORMAT_SD_DV 0
518#define UVIDEO_DV_FORMAT_SDL_DV 1 525#define UVIDEO_DV_FORMAT_SDL_DV 1
519#define UVIDEO_DV_FORMAT_HD_DV 2 526#define UVIDEO_DV_FORMAT_HD_DV 2
520} UPACKED uvideo_vs_format_dv_descriptor_t; 527} UPACKED uvideo_vs_format_dv_descriptor_t;
521 528
522 529
523 530
524/* 531/*
525 * Video Control requests 532 * Video Control requests
526 */ 533 */
527 534
528/* Pseudo bitmasks that only work when bitwise OR onto a zeroed value */ 535/* Pseudo bitmasks that only work when bitwise OR onto a zeroed value */
529#define UVIDEO_REQUEST_TYPE_INTERFACE (0x0001) 536#define UVIDEO_REQUEST_TYPE_INTERFACE (0x0001)
530#define UVIDEO_REQUEST_TYPE_ENDPOINT (0x0010) 537#define UVIDEO_REQUEST_TYPE_ENDPOINT (0x0010)
531#define UVIDEO_REQUEST_TYPE_CLASS_SPECIFIC (0x01 << 5) 538#define UVIDEO_REQUEST_TYPE_CLASS_SPECIFIC (0x01 << 5)
532#define UVIDEO_REQUEST_TYPE_SET (0x0 << 7) 539#define UVIDEO_REQUEST_TYPE_SET (0x0 << 7)
533#define UVIDEO_REQUEST_TYPE_GET (0x1 << 7) 540#define UVIDEO_REQUEST_TYPE_GET (0x1 << 7)
534 541
535typedef enum { 542typedef enum {
536 UVIDEO_REQUEST_DESC_INTERFACE, 543 UVIDEO_REQUEST_DESC_INTERFACE,
537 UVIDEO_REQUEST_DESC_ENDPOINT 544 UVIDEO_REQUEST_DESC_ENDPOINT
538} uvideo_request_descriptor; 545} uvideo_request_descriptor;
539 546
540typedef enum { 547typedef enum {
541 UR_RC_UNDEFINED = 0x00, 548 UR_RC_UNDEFINED = 0x00,
542 UR_SET_CUR = 0x01, 549 UR_SET_CUR = 0x01,
543 UR_GET_CUR = 0x81, 550 UR_GET_CUR = 0x81,
544 UR_GET_MIN = 0x82, 551 UR_GET_MIN = 0x82,
545 UR_GET_MAX = 0x83, 552 UR_GET_MAX = 0x83,
546 UR_GET_RES = 0x84, 553 UR_GET_RES = 0x84,
547 UR_GET_LEN = 0x85, 554 UR_GET_LEN = 0x85,
548 UR_GET_INFO = 0x86, 555 UR_GET_INFO = 0x86,
549 UR_GET_DEF = 0x87, 556 UR_GET_DEF = 0x87,
550} uvideo_request; 557} uvideo_request;
551 558
552/* camera terminal control selectors */ 559/* camera terminal control selectors */
553#define UVIDEO_CT_CONTROL_UNDEFINED 0x00 560#define UVIDEO_CT_CONTROL_UNDEFINED 0x00
554#define UVIDEO_CT_SCANNING_MODE_CONTROL 0x01 561#define UVIDEO_CT_SCANNING_MODE_CONTROL 0x01
555#define UVIDEO_CT_AE_MODE_CONTROL 0x02 562#define UVIDEO_CT_AE_MODE_CONTROL 0x02
556#define UVIDEO_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 563#define UVIDEO_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04
557#define UVIDEO_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 564#define UVIDEO_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05
558#define UVIDEO_CT_FOCUS_ABSOLUTE_CONTROL 0x06 565#define UVIDEO_CT_FOCUS_ABSOLUTE_CONTROL 0x06
559#define UVIDEO_CT_FOCUS_RELATIVE_CONTROL 0x07 566#define UVIDEO_CT_FOCUS_RELATIVE_CONTROL 0x07
560#define UVIDEO_CT_IRIS_ABSOLUTE_CONTROL 0x09 567#define UVIDEO_CT_IRIS_ABSOLUTE_CONTROL 0x09
561#define UVIDEO_CT_IRIS_RELATIVE_CONTROL 0x0A 568#define UVIDEO_CT_IRIS_RELATIVE_CONTROL 0x0A
562#define UVIDEO_CT_ZOOM_ABSOLUTE_CONTROL 0x0B 569#define UVIDEO_CT_ZOOM_ABSOLUTE_CONTROL 0x0B
563#define UVIDEO_CT_ZOOM_RELATIVE_CONTROL 0x0C 570#define UVIDEO_CT_ZOOM_RELATIVE_CONTROL 0x0C
564#define UVIDEO_CT_PANTILT_ABSOLUTE_CONTROL 0x0D 571#define UVIDEO_CT_PANTILT_ABSOLUTE_CONTROL 0x0D
565#define UVIDEO_CT_PANTILT_RELATIVE_CONTROL 0x0E 572#define UVIDEO_CT_PANTILT_RELATIVE_CONTROL 0x0E
566#define UVIDEO_CT_ROLL_ABSOLUTE_CONTROL 0x0F 573#define UVIDEO_CT_ROLL_ABSOLUTE_CONTROL 0x0F
567#define UVIDEO_CT_ROLL_RELATIVE_CONTROL 0x10 574#define UVIDEO_CT_ROLL_RELATIVE_CONTROL 0x10
568#define UVIDEO_CT_PRIVACY_CONTROL 0x11 575#define UVIDEO_CT_PRIVACY_CONTROL 0x11
569 576
570/* processing unit control selectors */ 577/* processing unit control selectors */
571#define UVIDEO_PU_CONTROL_UNDEFINED 0x00 578#define UVIDEO_PU_CONTROL_UNDEFINED 0x00
572#define UVIDEO_PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 579#define UVIDEO_PU_BACKLIGHT_COMPENSATION_CONTROL 0x01
573#define UVIDEO_PU_BRIGHTNESS_CONTROL 0x02 580#define UVIDEO_PU_BRIGHTNESS_CONTROL 0x02
574#define UVIDEO_PU_CONTRAST_CONTROL 0x03 581#define UVIDEO_PU_CONTRAST_CONTROL 0x03
575#define UVIDEO_PU_GAIN_CONTROL 0x04 582#define UVIDEO_PU_GAIN_CONTROL 0x04
576#define UVIDEO_PU_POWER_LINE_FREQUENCY_CONTROL 0x05 583#define UVIDEO_PU_POWER_LINE_FREQUENCY_CONTROL 0x05
577#define UVIDEO_PU_HUE_CONTROL 0x06 584#define UVIDEO_PU_HUE_CONTROL 0x06
578#define UVIDEO_PU_SATURATION_CONTROL 0x07 585#define UVIDEO_PU_SATURATION_CONTROL 0x07
579#define UVIDEO_PU_SHARPNESS_CONTROL 0x08 586#define UVIDEO_PU_SHARPNESS_CONTROL 0x08
580#define UVIDEO_PU_GAMMA_CONTROL 0x09 587#define UVIDEO_PU_GAMMA_CONTROL 0x09
581#define UVIDEO_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0A 588#define UVIDEO_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0A
582#define UVIDEO_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0B 589#define UVIDEO_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0B
583#define UVIDEO_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0C 590#define UVIDEO_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0C
584#define UVIDEO_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0D 591#define UVIDEO_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0D
585#define UVIDEO_PU_DIGITAL_MULTIPLIER_CONTROL 0x0E 592#define UVIDEO_PU_DIGITAL_MULTIPLIER_CONTROL 0x0E
586#define UVIDEO_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0F 593#define UVIDEO_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0F
587#define UVIDEO_PU_HUE_AUTO_CONTROL 0x10 594#define UVIDEO_PU_HUE_AUTO_CONTROL 0x10
588#define UVIDEO_PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 595#define UVIDEO_PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11
589#define UVIDEO_PU_ANALOG_LOCK_STATUS_CONTROL 0x12 596#define UVIDEO_PU_ANALOG_LOCK_STATUS_CONTROL 0x12
590 597
591/* extension unit control selectors */ 598/* extension unit control selectors */
592#define UVIDEO_XU_CONTROL_UNDEFINED 0x00 599#define UVIDEO_XU_CONTROL_UNDEFINED 0x00
593 600
594/* VideoStreaming Interface control selectors */ 601/* VideoStreaming Interface control selectors */
595#define UVIDEO_VS_CONTROL_UNDEFINED 0x00 602#define UVIDEO_VS_CONTROL_UNDEFINED 0x00
596#define UVIDEO_VS_PROBE_CONTROL 0x01 603#define UVIDEO_VS_PROBE_CONTROL 0x01
597#define UVIDEO_VS_COMMIT_CONTROL 0x02 604#define UVIDEO_VS_COMMIT_CONTROL 0x02
598#define UVIDEO_VS_STILL_PROBE_CONTROL 0x03 605#define UVIDEO_VS_STILL_PROBE_CONTROL 0x03
599#define UVIDEO_VS_STILL_COMMIT_CONTROL 0x04 606#define UVIDEO_VS_STILL_COMMIT_CONTROL 0x04
600#define UVIDEO_VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 607#define UVIDEO_VS_STILL_IMAGE_TRIGGER_CONTROL 0x05
601#define UVIDEO_VS_STREAM_ERROR_CODE_CONTROL 0x06 608#define UVIDEO_VS_STREAM_ERROR_CODE_CONTROL 0x06
602#define UVIDEO_VS_GENERATE_KEY_FRAME_CONTROL 0x07 609#define UVIDEO_VS_GENERATE_KEY_FRAME_CONTROL 0x07
603#define UVIDEO_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 610#define UVIDEO_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08
604#define UVIDEO_VS_SYNCH_DELAY_CONTROL 0x09 611#define UVIDEO_VS_SYNCH_DELAY_CONTROL 0x09
605 612
606/* bitmask result of GET_INFO on a control */ 613/* bitmask result of GET_INFO on a control */
607#define UVIDEO_CONTROL_INFO_SUPPORTS_GET (1<<0) 614#define UVIDEO_CONTROL_INFO_SUPPORTS_GET (1<<0)
608#define UVIDEO_CONTROL_INFO_SUPPORTS_SET (1<<1) 615#define UVIDEO_CONTROL_INFO_SUPPORTS_SET (1<<1)
609#define UVIDEO_CONTROL_INFO_DISABLED (1<<2) 616#define UVIDEO_CONTROL_INFO_DISABLED (1<<2)
610#define UVIDEO_CONTROL_INFO_AUTOUPDATE (1<<3) 617#define UVIDEO_CONTROL_INFO_AUTOUPDATE (1<<3)
611#define UVIDEO_CONTROL_INFO_ASYNC (1<<4) 618#define UVIDEO_CONTROL_INFO_ASYNC (1<<4)
612 619
613 620
614/* Video Probe and Commit Controls request data */ 621/* Video Probe and Commit Controls request data */
615typedef struct { 622typedef struct {
616 uWord bmHint; 623 uWord bmHint;
617#define UVIDEO_HINT_FRAME_INTERVAL (1<<0) 624#define UVIDEO_HINT_FRAME_INTERVAL (1<<0)
618#define UVIDEO_HINT_KEYFRAME_RATE (1<<1) 625#define UVIDEO_HINT_KEYFRAME_RATE (1<<1)
619#define UVIDEO_HINT_PFRAME_RATE (1<<2) 626#define UVIDEO_HINT_PFRAME_RATE (1<<2)
620#define UVIDEO_HINT_COMP_QUALITY (1<<3) 627#define UVIDEO_HINT_COMP_QUALITY (1<<3)
621#define UVIDEO_HINT_COMP_WINDOW_SIZE (1<<4) 628#define UVIDEO_HINT_COMP_WINDOW_SIZE (1<<4)
622 uByte bFormatIndex; 629 uByte bFormatIndex;
623 uByte bFrameIndex; 630 uByte bFrameIndex;
624 uDWord dwFrameInterval; 631 uDWord dwFrameInterval;
625#define UVIDEO_100NS_PER_MS 10000 632#define UVIDEO_100NS_PER_MS 10000
626#define UVIDEO_FRAME_INTERVAL_UNITS_PER_USB_FRAME UVIDEO_100NS_PER_MS 633#define UVIDEO_FRAME_INTERVAL_UNITS_PER_USB_FRAME UVIDEO_100NS_PER_MS
627 uWord wKeyFrameRate; 634 uWord wKeyFrameRate;
628 uWord wPFrameRate; 635 uWord wPFrameRate;
629 uWord wCompQuality; 636 uWord wCompQuality;
630 uWord wCompWindowSize; 637 uWord wCompWindowSize;
631 uWord wDelay; 638 uWord wDelay;
632 uDWord dwMaxVideoFrameSize; 639 uDWord dwMaxVideoFrameSize;
633 uDWord dwMaxPayloadTransferSize; 640 uDWord dwMaxPayloadTransferSize;
634 /* Following fields are not in v1.0 of UVC. Will have to do 641 /* Following fields are not in v1.0 of UVC. Will have to do
635 * UR_GET_LEN to discover the length of this descriptor. */ 642 * UR_GET_LEN to discover the length of this descriptor. */
636 uDWord dwClockFrequency; 643 uDWord dwClockFrequency;
637 uByte bmFramingInfo; 644 uByte bmFramingInfo;
638#define UVIDEO_FRAMING_INFO_FID (1<<0) 645#define UVIDEO_FRAMING_INFO_FID (1<<0)
639#define UVIDEO_FRAMING_INFO_EOF (1<<1) 646#define UVIDEO_FRAMING_INFO_EOF (1<<1)
640 uByte bPreferedVersion; 647 uByte bPreferedVersion;
641 uByte bMinVersion; 648 uByte bMinVersion;
642 uByte bMaxVersion; 649 uByte bMaxVersion;
643} UPACKED uvideo_probe_and_commit_data_t; 650} UPACKED uvideo_probe_and_commit_data_t;
644 651
645/* Video Still Probe and Still Commit Controls request data */ 652/* Video Still Probe and Still Commit Controls request data */
646typedef struct { 653typedef struct {
647 uByte bFormatIndex; 654 uByte bFormatIndex;
648 uByte bFrameIndex; 655 uByte bFrameIndex;
649 uByte bCompressionIndex; 656 uByte bCompressionIndex;
650 uDWord dwMaxVideoFrameSize; 657 uDWord dwMaxVideoFrameSize;
651 uDWord dwMaxPayloadTransferSize; 658 uDWord dwMaxPayloadTransferSize;
652} UPACKED uvideo_still_probe_and_still_commit_data_t; 659} UPACKED uvideo_still_probe_and_still_commit_data_t;
653#define UVIDEO_STILL_PROBE_AND_STILL_COMMIT_DATA_SIZE 11; 660#define UVIDEO_STILL_PROBE_AND_STILL_COMMIT_DATA_SIZE 11;
654 661
655 662
656 663
657/* common header for Video Control and Video Stream status */ 664/* common header for Video Control and Video Stream status */
658typedef struct { 665typedef struct {
659 uByte bStatusType; 666 uByte bStatusType;
660#define UV_STATUS_TYPE_CONTROL 0x02 667#define UV_STATUS_TYPE_CONTROL 0x02
661#define UV_STATUS_TYPE_STREAM 0x04 668#define UV_STATUS_TYPE_STREAM 0x04
662 uByte bOriginator; 669 uByte bOriginator;
663} UPACKED uvideo_status_t; 670} UPACKED uvideo_status_t;
664 671
665typedef struct { 672typedef struct {
666 uByte bStatusType; 673 uByte bStatusType;
667 uByte bOriginator; 674 uByte bOriginator;
668 uByte bEvent; 675 uByte bEvent;
669#define UV_CONTROL_CHANGE 0x00 /* any other value is Reserved */ 676#define UV_CONTROL_CHANGE 0x00 /* any other value is Reserved */
670 uByte bSelector; 677 uByte bSelector;
671 uByte bAttribute; 678 uByte bAttribute;
672#define UV_CONTROL_VALUE_CHANGE 0x00 679#define UV_CONTROL_VALUE_CHANGE 0x00
673#define UV_CONTROL_INFO_CHANGE 0x01 680#define UV_CONTROL_INFO_CHANGE 0x01
674#define UV_CONTROL_FAILURE_CHANGE 0x02 681#define UV_CONTROL_FAILURE_CHANGE 0x02
675 uByte bValue; 682 uByte bValue;
676} UPACKED uvideo_control_status_t; 683} UPACKED uvideo_control_status_t;
677 684
678typedef struct { 685typedef struct {
679 uByte bStatusType; 686 uByte bStatusType;
680 uByte bOriginator; 687 uByte bOriginator;
681 uByte bEvent; 688 uByte bEvent;
682#define UV_BUTTON_PRESS 0x00 /* any other value is Stream Error */ 689#define UV_BUTTON_PRESS 0x00 /* any other value is Stream Error */
683 uByte bValue; 690 uByte bValue;
684#define UV_BUTTON_RELEASED 0x00 691#define UV_BUTTON_RELEASED 0x00
685#define UV_BUTTON_PRESSED 0x01 692#define UV_BUTTON_PRESSED 0x01
686} UPACKED uvideo_streaming_status_t; 693} UPACKED uvideo_streaming_status_t;
687 694
688typedef struct { 695typedef struct {
689 uByte bHeaderLength; 696 uByte bHeaderLength;
690 uByte bmHeaderInfo; 697 uByte bmHeaderInfo;
691#define UV_FRAME_ID 1<<0 698#define UV_FRAME_ID 1<<0
692#define UV_END_OF_FRAME 1<<1 699#define UV_END_OF_FRAME 1<<1
693#define UV_PRES_TIME 1<<2 700#define UV_PRES_TIME 1<<2
694#define UV_SRC_CLOCK 1<<3 701#define UV_SRC_CLOCK 1<<3
695/* D4: Reserved */ 702/* D4: Reserved */
696#define UV_STILL_IMAGE 1<<5 703#define UV_STILL_IMAGE 1<<5
697#define UV_ERROR 1<<6 704#define UV_ERROR 1<<6
698#define UV_END_OF_HDR 1<<7 705#define UV_END_OF_HDR 1<<7
699/* other fields depend on which bits are set above and have no fixed offset */ 706/* other fields depend on which bits are set above and have no fixed offset */
700/* uDWord dwPresentationTime; */ 707/* uDWord dwPresentationTime; */
701#define UVIDEO_PTS_SIZE 4 708#define UVIDEO_PTS_SIZE 4
702/* uByte scrSourceClock[UVIDEO_SOURCE_CLOCK_SIZE]; */ 709/* uByte scrSourceClock[UVIDEO_SOURCE_CLOCK_SIZE]; */
703#define UVIDEO_SOURCE_CLOCK_SIZE 6 710#define UVIDEO_SOURCE_CLOCK_SIZE 6
704#define UV_GET_SOURCE_TIME_CLOCK(sc) (UGETDW(sc)) 711#define UV_GET_SOURCE_TIME_CLOCK(sc) (UGETDW(sc))
705/* bits 42..32 */ 712/* bits 42..32 */
706#define UV_GET_SOF_COUNTER(sc) (((sc)[4] | ((sc)[5] << 8)) &0x7ff) 713#define UV_GET_SOF_COUNTER(sc) (((sc)[4] | ((sc)[5] << 8)) &0x7ff)
707} UPACKED uvideo_payload_header_t; 714} UPACKED uvideo_payload_header_t;
708 715
709/* Note: this might be larger depending on presence of source clock, 716/* Note: this might be larger depending on presence of source clock,
710 SOF counter, or other things... bHeaderLength is actual length. */ 717 SOF counter, or other things... bHeaderLength is actual length. */
711#define UVIDEO_PAYLOAD_HEADER_SIZE 12 718#define UVIDEO_PAYLOAD_HEADER_SIZE 12
712 719