Thu Mar 3 06:22:03 2022 UTC ()
uvideo(4): Sprinkle debug messages.


(riastradh)
diff -r1.65 -r1.66 src/sys/dev/usb/uvideo.c

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

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