Thu Mar 3 06:22:40 2022 UTC ()
uvideo(4): Fix zero initialization of uvideo_stream.

Just use kmem_zalloc; don't memset it to zero, especially not after
we just inserted it into the list, with the side effect of deleting
the rest of the list!


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

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

--- src/sys/dev/usb/uvideo.c 2022/03/03 06:22:03 1.66
+++ src/sys/dev/usb/uvideo.c 2022/03/03 06:22:40 1.67
@@ -1,2033 +1,2032 @@ @@ -1,2033 +1,2032 @@
1/* $NetBSD: uvideo.c,v 1.66 2022/03/03 06:22:03 riastradh Exp $ */ 1/* $NetBSD: uvideo.c,v 1.67 2022/03/03 06:22:40 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.66 2022/03/03 06:22:03 riastradh Exp $"); 45__KERNEL_RCSID(0, "$NetBSD: uvideo.c,v 1.67 2022/03/03 06:22:40 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_zalloc(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__, 1028 DPRINTF(("%s: %s ifaceno=%d vs=%p\n", __func__,
1029 device_xname(sc->sc_dev), 1029 device_xname(sc->sc_dev),
1030 ifdesc->bInterfaceNumber, 1030 ifdesc->bInterfaceNumber,
1031 vs)); 1031 vs));
1032 1032
1033 SLIST_INSERT_HEAD(&sc->sc_stream_list, vs, entries); 1033 SLIST_INSERT_HEAD(&sc->sc_stream_list, vs, entries);
1034 memset(vs, 0, sizeof(*vs)); 
1035 vs->vs_parent = sc; 1034 vs->vs_parent = sc;
1036 vs->vs_ifaceno = ifdesc->bInterfaceNumber; 1035 vs->vs_ifaceno = ifdesc->bInterfaceNumber;
1037 vs->vs_subtype = 0; 1036 vs->vs_subtype = 0;
1038 SIMPLEQ_INIT(&vs->vs_formats); 1037 SIMPLEQ_INIT(&vs->vs_formats);
1039 SIMPLEQ_INIT(&vs->vs_pixel_formats); 1038 SIMPLEQ_INIT(&vs->vs_pixel_formats);
1040 vs->vs_default_format = NULL; 1039 vs->vs_default_format = NULL;
1041 vs->vs_current_format.priv = -1; 1040 vs->vs_current_format.priv = -1;
1042 vs->vs_xfer_type = 0; 1041 vs->vs_xfer_type = 0;
1043 1042
1044 err = usbd_device2interface_handle(sc->sc_udev, vs->vs_ifaceno, 1043 err = usbd_device2interface_handle(sc->sc_udev, vs->vs_ifaceno,
1045 &vs->vs_iface); 1044 &vs->vs_iface);
1046 if (err != USBD_NORMAL_COMPLETION) { 1045 if (err != USBD_NORMAL_COMPLETION) {
1047 DPRINTF(("uvideo_stream_init: " 1046 DPRINTF(("uvideo_stream_init: "
1048 "error getting vs interface: " 1047 "error getting vs interface: "
1049 "%s (%d)\n", 1048 "%s (%d)\n",
1050 usbd_errstr(err), err)); 1049 usbd_errstr(err), err));
1051 return err; 1050 return err;
1052 } 1051 }
1053 1052
1054 /* For Xbox Live Vision camera, linux-uvc folk say we need to 1053 /* For Xbox Live Vision camera, linux-uvc folk say we need to
1055 * set an alternate interface and wait ~3 seconds prior to 1054 * set an alternate interface and wait ~3 seconds prior to
1056 * doing the format probe/commit. We set to alternate 1055 * doing the format probe/commit. We set to alternate
1057 * interface 0, which is the default, zero bandwidth 1056 * interface 0, which is the default, zero bandwidth
1058 * interface. This should not have adverse affects on other 1057 * interface. This should not have adverse affects on other
1059 * cameras. Errors are ignored. */ 1058 * cameras. Errors are ignored. */
1060 err = usbd_set_interface(vs->vs_iface, 0); 1059 err = usbd_set_interface(vs->vs_iface, 0);
1061 if (err != USBD_NORMAL_COMPLETION) { 1060 if (err != USBD_NORMAL_COMPLETION) {
1062 DPRINTF(("uvideo_stream_init: error setting alt interface: " 1061 DPRINTF(("uvideo_stream_init: error setting alt interface: "
1063 "%s (%d)\n", 1062 "%s (%d)\n",
1064 usbd_errstr(err), err)); 1063 usbd_errstr(err), err));
1065 } 1064 }
1066 1065
1067 /* Initialize probe and commit data size. This value is 1066 /* Initialize probe and commit data size. This value is
1068 * dependent on the version of the spec the hardware 1067 * dependent on the version of the spec the hardware
1069 * implements. */ 1068 * implements. */
1070 err = uvideo_stream_probe(vs, UR_GET_LEN, &len); 1069 err = uvideo_stream_probe(vs, UR_GET_LEN, &len);
1071 if (err != USBD_NORMAL_COMPLETION) { 1070 if (err != USBD_NORMAL_COMPLETION) {
1072 DPRINTF(("uvideo_stream_init: " 1071 DPRINTF(("uvideo_stream_init: "
1073 "error getting probe data len: " 1072 "error getting probe data len: "
1074 "%s (%d)\n", 1073 "%s (%d)\n",
1075 usbd_errstr(err), err)); 1074 usbd_errstr(err), err));
1076 vs->vs_probelen = 26; /* conservative v1.0 length */ 1075 vs->vs_probelen = 26; /* conservative v1.0 length */
1077 } else if (UGETW(len) <= sizeof(uvideo_probe_and_commit_data_t)) { 1076 } else if (UGETW(len) <= sizeof(uvideo_probe_and_commit_data_t)) {
1078 DPRINTFN(15,("uvideo_stream_init: probelen=%d\n", UGETW(len))); 1077 DPRINTFN(15,("uvideo_stream_init: probelen=%d\n", UGETW(len)));
1079 vs->vs_probelen = UGETW(len); 1078 vs->vs_probelen = UGETW(len);
1080 } else { 1079 } else {
1081 DPRINTFN(15,("uvideo_stream_init: device returned invalid probe" 1080 DPRINTFN(15,("uvideo_stream_init: device returned invalid probe"
1082 " len %d, using default\n", UGETW(len))); 1081 " len %d, using default\n", UGETW(len)));
1083 vs->vs_probelen = 26; 1082 vs->vs_probelen = 26;
1084 } 1083 }
1085 1084
1086 return USBD_NORMAL_COMPLETION; 1085 return USBD_NORMAL_COMPLETION;
1087} 1086}
1088 1087
1089/* Further stream initialization based on a Video Streaming interface 1088/* Further stream initialization based on a Video Streaming interface
1090 * descriptor and following descriptors belonging to that interface. 1089 * descriptor and following descriptors belonging to that interface.
1091 * Iterates through all descriptors belonging to this particular 1090 * Iterates through all descriptors belonging to this particular
1092 * interface descriptor, modifying the iterator. This may be called 1091 * interface descriptor, modifying the iterator. This may be called
1093 * multiple times because there may be several alternate interfaces 1092 * multiple times because there may be several alternate interfaces
1094 * associated with the same interface number. */ 1093 * associated with the same interface number. */
1095/* 1094/*
1096 * XXX XXX XXX: This function accesses descriptors in an unsafe manner. 1095 * XXX XXX XXX: This function accesses descriptors in an unsafe manner.
1097 */ 1096 */
1098static usbd_status 1097static usbd_status
1099uvideo_stream_init_desc(struct uvideo_stream *vs, 1098uvideo_stream_init_desc(struct uvideo_stream *vs,
1100 const usb_interface_descriptor_t *ifdesc, 1099 const usb_interface_descriptor_t *ifdesc,
1101 usbd_desc_iter_t *iter) 1100 usbd_desc_iter_t *iter)
1102{ 1101{
1103 const usb_descriptor_t *desc; 1102 const usb_descriptor_t *desc;
1104 const uvideo_descriptor_t *uvdesc; 1103 const uvideo_descriptor_t *uvdesc;
1105 struct uvideo_bulk_xfer *bx; 1104 struct uvideo_bulk_xfer *bx;
1106 struct uvideo_isoc_xfer *ix; 1105 struct uvideo_isoc_xfer *ix;
1107 struct uvideo_alternate *alt; 1106 struct uvideo_alternate *alt;
1108 uint8_t xfer_type, xfer_dir; 1107 uint8_t xfer_type, xfer_dir;
1109 uint8_t bmAttributes, bEndpointAddress; 1108 uint8_t bmAttributes, bEndpointAddress;
1110 int i; 1109 int i;
1111 1110
1112 DPRINTF(("%s: bInterfaceNumber=%d bAlternateSetting=%d\n", __func__, 1111 DPRINTF(("%s: bInterfaceNumber=%d bAlternateSetting=%d\n", __func__,
1113 ifdesc->bInterfaceNumber, ifdesc->bAlternateSetting)); 1112 ifdesc->bInterfaceNumber, ifdesc->bAlternateSetting));
1114 1113
1115 /* Iterate until the next interface descriptor. All 1114 /* Iterate until the next interface descriptor. All
1116 * descriptors until then belong to this streaming 1115 * descriptors until then belong to this streaming
1117 * interface. */ 1116 * interface. */
1118 while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) { 1117 while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) {
1119 uvdesc = (const uvideo_descriptor_t *)desc; 1118 uvdesc = (const uvideo_descriptor_t *)desc;
1120 1119
1121 switch (uvdesc->bDescriptorType) { 1120 switch (uvdesc->bDescriptorType) {
1122 case UDESC_ENDPOINT: 1121 case UDESC_ENDPOINT:
1123 bmAttributes = GET(usb_endpoint_descriptor_t, 1122 bmAttributes = GET(usb_endpoint_descriptor_t,
1124 desc, bmAttributes); 1123 desc, bmAttributes);
1125 bEndpointAddress = GET(usb_endpoint_descriptor_t, 1124 bEndpointAddress = GET(usb_endpoint_descriptor_t,
1126 desc, bEndpointAddress); 1125 desc, bEndpointAddress);
1127 xfer_type = UE_GET_XFERTYPE(bmAttributes); 1126 xfer_type = UE_GET_XFERTYPE(bmAttributes);
1128 xfer_dir = UE_GET_DIR(bEndpointAddress); 1127 xfer_dir = UE_GET_DIR(bEndpointAddress);
1129 if (xfer_type == UE_BULK && xfer_dir == UE_DIR_IN) { 1128 if (xfer_type == UE_BULK && xfer_dir == UE_DIR_IN) {
1130 bx = &vs->vs_xfer.bulk; 1129 bx = &vs->vs_xfer.bulk;
1131 if (vs->vs_xfer_type == 0) { 1130 if (vs->vs_xfer_type == 0) {
1132 DPRINTFN(15, ("uvideo_attach: " 1131 DPRINTFN(15, ("uvideo_attach: "
1133 "BULK stream *\n")); 1132 "BULK stream *\n"));
1134 vs->vs_xfer_type = UE_BULK; 1133 vs->vs_xfer_type = UE_BULK;
1135 bx->bx_endpt = bEndpointAddress; 1134 bx->bx_endpt = bEndpointAddress;
1136 DPRINTF(("uvideo_attach: BULK " 1135 DPRINTF(("uvideo_attach: BULK "
1137 "endpoint %x\n", 1136 "endpoint %x\n",
1138 bx->bx_endpt)); 1137 bx->bx_endpt));
1139 bx->bx_running = false; 1138 bx->bx_running = false;
1140 cv_init(&bx->bx_cv, 1139 cv_init(&bx->bx_cv,
1141 device_xname(vs->vs_parent->sc_dev) 1140 device_xname(vs->vs_parent->sc_dev)
1142 ); 1141 );
1143 mutex_init(&bx->bx_lock, 1142 mutex_init(&bx->bx_lock,
1144 MUTEX_DEFAULT, IPL_NONE); 1143 MUTEX_DEFAULT, IPL_NONE);
1145 } 1144 }
1146 } else if (xfer_type == UE_ISOCHRONOUS) { 1145 } else if (xfer_type == UE_ISOCHRONOUS) {
1147 ix = &vs->vs_xfer.isoc; 1146 ix = &vs->vs_xfer.isoc;
1148 for (i = 0; i < UVIDEO_NXFERS; i++) { 1147 for (i = 0; i < UVIDEO_NXFERS; i++) {
1149 ix->ix_i[i].i_ix = ix; 1148 ix->ix_i[i].i_ix = ix;
1150 ix->ix_i[i].i_vs = vs; 1149 ix->ix_i[i].i_vs = vs;
1151 } 1150 }
1152 if (vs->vs_xfer_type == 0) { 1151 if (vs->vs_xfer_type == 0) {
1153 DPRINTFN(15, ("uvideo_attach: " 1152 DPRINTFN(15, ("uvideo_attach: "
1154 "ISOC stream *\n")); 1153 "ISOC stream *\n"));
1155 SLIST_INIT(&ix->ix_altlist); 1154 SLIST_INIT(&ix->ix_altlist);
1156 vs->vs_xfer_type = UE_ISOCHRONOUS; 1155 vs->vs_xfer_type = UE_ISOCHRONOUS;
1157 ix->ix_endpt = 1156 ix->ix_endpt =
1158 GET(usb_endpoint_descriptor_t, 1157 GET(usb_endpoint_descriptor_t,
1159 desc, bEndpointAddress); 1158 desc, bEndpointAddress);
1160 } 1159 }
1161 1160
1162 alt = kmem_alloc(sizeof(*alt), KM_SLEEP); 1161 alt = kmem_alloc(sizeof(*alt), KM_SLEEP);
1163 alt->altno = ifdesc->bAlternateSetting; 1162 alt->altno = ifdesc->bAlternateSetting;
1164 alt->interval = 1163 alt->interval =
1165 GET(usb_endpoint_descriptor_t, 1164 GET(usb_endpoint_descriptor_t,
1166 desc, bInterval); 1165 desc, bInterval);
1167 1166
1168 alt->max_packet_size = 1167 alt->max_packet_size =
1169 UE_GET_SIZE(UGETW(GET(usb_endpoint_descriptor_t, 1168 UE_GET_SIZE(UGETW(GET(usb_endpoint_descriptor_t,
1170 desc, wMaxPacketSize))); 1169 desc, wMaxPacketSize)));
1171 alt->max_packet_size *= 1170 alt->max_packet_size *=
1172 (UE_GET_TRANS(UGETW(GET( 1171 (UE_GET_TRANS(UGETW(GET(
1173 usb_endpoint_descriptor_t, desc, 1172 usb_endpoint_descriptor_t, desc,
1174 wMaxPacketSize)))) + 1; 1173 wMaxPacketSize)))) + 1;
1175 1174
1176 SLIST_INSERT_HEAD(&ix->ix_altlist, 1175 SLIST_INSERT_HEAD(&ix->ix_altlist,
1177 alt, entries); 1176 alt, entries);
1178 } 1177 }
1179 break; 1178 break;
1180 case UDESC_CS_INTERFACE: 1179 case UDESC_CS_INTERFACE:
1181 if (ifdesc->bAlternateSetting != 0) { 1180 if (ifdesc->bAlternateSetting != 0) {
1182 DPRINTF(("uvideo_stream_init_alternate: " 1181 DPRINTF(("uvideo_stream_init_alternate: "
1183 "unexpected class-specific descriptor " 1182 "unexpected class-specific descriptor "
1184 "len=%d type=0x%02x subtype=0x%02x\n", 1183 "len=%d type=0x%02x subtype=0x%02x\n",
1185 uvdesc->bLength, 1184 uvdesc->bLength,
1186 uvdesc->bDescriptorType, 1185 uvdesc->bDescriptorType,
1187 uvdesc->bDescriptorSubtype)); 1186 uvdesc->bDescriptorSubtype));
1188 break; 1187 break;
1189 } 1188 }
1190 1189
1191 switch (uvdesc->bDescriptorSubtype) { 1190 switch (uvdesc->bDescriptorSubtype) {
1192 case UDESC_VS_INPUT_HEADER: 1191 case UDESC_VS_INPUT_HEADER:
1193 vs->vs_subtype = UDESC_VS_INPUT_HEADER; 1192 vs->vs_subtype = UDESC_VS_INPUT_HEADER;
1194 break; 1193 break;
1195 case UDESC_VS_OUTPUT_HEADER: 1194 case UDESC_VS_OUTPUT_HEADER:
1196 /* TODO: handle output stream */ 1195 /* TODO: handle output stream */
1197 DPRINTF(("uvideo: VS output not implemented\n")); 1196 DPRINTF(("uvideo: VS output not implemented\n"));
1198 vs->vs_subtype = UDESC_VS_OUTPUT_HEADER; 1197 vs->vs_subtype = UDESC_VS_OUTPUT_HEADER;
1199 return USBD_INVAL; 1198 return USBD_INVAL;
1200 case UDESC_VS_FORMAT_UNCOMPRESSED: 1199 case UDESC_VS_FORMAT_UNCOMPRESSED:
1201 case UDESC_VS_FORMAT_FRAME_BASED: 1200 case UDESC_VS_FORMAT_FRAME_BASED:
1202 case UDESC_VS_FORMAT_MJPEG: 1201 case UDESC_VS_FORMAT_MJPEG:
1203 uvideo_stream_init_frame_based_format(vs, 1202 uvideo_stream_init_frame_based_format(vs,
1204 uvdesc, 1203 uvdesc,
1205 iter); 1204 iter);
1206 break; 1205 break;
1207 case UDESC_VS_FORMAT_MPEG2TS: 1206 case UDESC_VS_FORMAT_MPEG2TS:
1208 case UDESC_VS_FORMAT_DV: 1207 case UDESC_VS_FORMAT_DV:
1209 case UDESC_VS_FORMAT_STREAM_BASED: 1208 case UDESC_VS_FORMAT_STREAM_BASED:
1210 default: 1209 default:
1211 DPRINTF(("uvideo: unimplemented VS CS " 1210 DPRINTF(("uvideo: unimplemented VS CS "
1212 "descriptor len=%d type=0x%02x " 1211 "descriptor len=%d type=0x%02x "
1213 "subtype=0x%02x\n", 1212 "subtype=0x%02x\n",
1214 uvdesc->bLength, 1213 uvdesc->bLength,
1215 uvdesc->bDescriptorType, 1214 uvdesc->bDescriptorType,
1216 uvdesc->bDescriptorSubtype)); 1215 uvdesc->bDescriptorSubtype));
1217 break; 1216 break;
1218 } 1217 }
1219 break; 1218 break;
1220 default: 1219 default:
1221 DPRINTF(("uvideo_stream_init_desc: " 1220 DPRINTF(("uvideo_stream_init_desc: "
1222 "unknown descriptor " 1221 "unknown descriptor "
1223 "len=%d type=0x%02x\n", 1222 "len=%d type=0x%02x\n",
1224 uvdesc->bLength, 1223 uvdesc->bLength,
1225 uvdesc->bDescriptorType)); 1224 uvdesc->bDescriptorType));
1226 break; 1225 break;
1227 } 1226 }
1228 } 1227 }
1229 1228
1230 DPRINTF(("%s: bInterfaceNumber=%d bAlternateSetting=%d done\n", 1229 DPRINTF(("%s: bInterfaceNumber=%d bAlternateSetting=%d done\n",
1231 __func__, 1230 __func__,
1232 ifdesc->bInterfaceNumber, ifdesc->bAlternateSetting)); 1231 ifdesc->bInterfaceNumber, ifdesc->bAlternateSetting));
1233 1232
1234 return USBD_NORMAL_COMPLETION; 1233 return USBD_NORMAL_COMPLETION;
1235} 1234}
1236 1235
1237/* Finialize and free memory associated with this stream. */ 1236/* Finialize and free memory associated with this stream. */
1238static void 1237static void
1239uvideo_stream_free(struct uvideo_stream *vs) 1238uvideo_stream_free(struct uvideo_stream *vs)
1240{ 1239{
1241 struct uvideo_alternate *alt; 1240 struct uvideo_alternate *alt;
1242 struct uvideo_pixel_format *pixel_format; 1241 struct uvideo_pixel_format *pixel_format;
1243 struct uvideo_format *format; 1242 struct uvideo_format *format;
1244 1243
1245 /* free linked list of alternate interfaces */ 1244 /* free linked list of alternate interfaces */
1246 if (vs->vs_xfer_type == UE_ISOCHRONOUS) { 1245 if (vs->vs_xfer_type == UE_ISOCHRONOUS) {
1247 while (!SLIST_EMPTY(&vs->vs_xfer.isoc.ix_altlist)) { 1246 while (!SLIST_EMPTY(&vs->vs_xfer.isoc.ix_altlist)) {
1248 alt = SLIST_FIRST(&vs->vs_xfer.isoc.ix_altlist); 1247 alt = SLIST_FIRST(&vs->vs_xfer.isoc.ix_altlist);
1249 SLIST_REMOVE_HEAD(&vs->vs_xfer.isoc.ix_altlist, 1248 SLIST_REMOVE_HEAD(&vs->vs_xfer.isoc.ix_altlist,
1250 entries); 1249 entries);
1251 kmem_free(alt, sizeof(*alt)); 1250 kmem_free(alt, sizeof(*alt));
1252 } 1251 }
1253 } 1252 }
1254 1253
1255 /* free linked-list of formats and pixel formats */ 1254 /* free linked-list of formats and pixel formats */
1256 while ((format = SIMPLEQ_FIRST(&vs->vs_formats)) != NULL) { 1255 while ((format = SIMPLEQ_FIRST(&vs->vs_formats)) != NULL) {
1257 SIMPLEQ_REMOVE_HEAD(&vs->vs_formats, entries); 1256 SIMPLEQ_REMOVE_HEAD(&vs->vs_formats, entries);
1258 kmem_free(format, sizeof(struct uvideo_format)); 1257 kmem_free(format, sizeof(struct uvideo_format));
1259 } 1258 }
1260 while ((pixel_format = SIMPLEQ_FIRST(&vs->vs_pixel_formats)) != NULL) { 1259 while ((pixel_format = SIMPLEQ_FIRST(&vs->vs_pixel_formats)) != NULL) {
1261 SIMPLEQ_REMOVE_HEAD(&vs->vs_pixel_formats, entries); 1260 SIMPLEQ_REMOVE_HEAD(&vs->vs_pixel_formats, entries);
1262 kmem_free(pixel_format, sizeof(struct uvideo_pixel_format)); 1261 kmem_free(pixel_format, sizeof(struct uvideo_pixel_format));
1263 } 1262 }
1264 1263
1265 kmem_free(vs, sizeof(*vs)); 1264 kmem_free(vs, sizeof(*vs));
1266} 1265}
1267 1266
1268 1267
1269static usbd_status 1268static usbd_status
1270uvideo_stream_init_frame_based_format(struct uvideo_stream *vs, 1269uvideo_stream_init_frame_based_format(struct uvideo_stream *vs,
1271 const uvideo_descriptor_t *format_desc, 1270 const uvideo_descriptor_t *format_desc,
1272 usbd_desc_iter_t *iter) 1271 usbd_desc_iter_t *iter)
1273{ 1272{
1274 struct uvideo_pixel_format *pformat, *pfiter; 1273 struct uvideo_pixel_format *pformat, *pfiter;
1275 enum video_pixel_format pixel_format; 1274 enum video_pixel_format pixel_format;
1276 struct uvideo_format *format; 1275 struct uvideo_format *format;
1277 const uvideo_descriptor_t *uvdesc; 1276 const uvideo_descriptor_t *uvdesc;
1278 uint8_t subtype, default_index, index; 1277 uint8_t subtype, default_index, index;
1279 uint32_t frame_interval; 1278 uint32_t frame_interval;
1280 const usb_guid_t *guid; 1279 const usb_guid_t *guid;
1281 1280
1282 DPRINTF(("%s: ifaceno=%d subtype=%d probelen=%d\n", __func__, 1281 DPRINTF(("%s: ifaceno=%d subtype=%d probelen=%d\n", __func__,
1283 vs->vs_ifaceno, vs->vs_subtype, vs->vs_probelen)); 1282 vs->vs_ifaceno, vs->vs_subtype, vs->vs_probelen));
1284 1283
1285 pixel_format = VIDEO_FORMAT_UNDEFINED; 1284 pixel_format = VIDEO_FORMAT_UNDEFINED;
1286 1285
1287 switch (format_desc->bDescriptorSubtype) { 1286 switch (format_desc->bDescriptorSubtype) {
1288 case UDESC_VS_FORMAT_UNCOMPRESSED: 1287 case UDESC_VS_FORMAT_UNCOMPRESSED:
1289 DPRINTF(("%s: uncompressed\n", __func__)); 1288 DPRINTF(("%s: uncompressed\n", __func__));
1290 subtype = UDESC_VS_FRAME_UNCOMPRESSED; 1289 subtype = UDESC_VS_FRAME_UNCOMPRESSED;
1291 default_index = GET(uvideo_vs_format_uncompressed_descriptor_t, 1290 default_index = GET(uvideo_vs_format_uncompressed_descriptor_t,
1292 format_desc, 1291 format_desc,
1293 bDefaultFrameIndex); 1292 bDefaultFrameIndex);
1294 guid = GETP(uvideo_vs_format_uncompressed_descriptor_t, 1293 guid = GETP(uvideo_vs_format_uncompressed_descriptor_t,
1295 format_desc, 1294 format_desc,
1296 guidFormat); 1295 guidFormat);
1297 if (usb_guid_cmp(guid, &uvideo_guid_format_yuy2) == 0) 1296 if (usb_guid_cmp(guid, &uvideo_guid_format_yuy2) == 0)
1298 pixel_format = VIDEO_FORMAT_YUY2; 1297 pixel_format = VIDEO_FORMAT_YUY2;
1299 else if (usb_guid_cmp(guid, &uvideo_guid_format_nv12) == 0) 1298 else if (usb_guid_cmp(guid, &uvideo_guid_format_nv12) == 0)
1300 pixel_format = VIDEO_FORMAT_NV12; 1299 pixel_format = VIDEO_FORMAT_NV12;
1301 else if (usb_guid_cmp(guid, &uvideo_guid_format_uyvy) == 0) 1300 else if (usb_guid_cmp(guid, &uvideo_guid_format_uyvy) == 0)
1302 pixel_format = VIDEO_FORMAT_UYVY; 1301 pixel_format = VIDEO_FORMAT_UYVY;
1303 else { 1302 else {
1304#ifdef UVIDEO_DEBUG 1303#ifdef UVIDEO_DEBUG
1305 DPRINTF(("%s: unknown format: ", __func__)); 1304 DPRINTF(("%s: unknown format: ", __func__));
1306 usb_guid_print(guid); 1305 usb_guid_print(guid);
1307 DPRINTF(("\n")); 1306 DPRINTF(("\n"));
1308#endif 1307#endif
1309 } 1308 }
1310 break; 1309 break;
1311 case UDESC_VS_FORMAT_FRAME_BASED: 1310 case UDESC_VS_FORMAT_FRAME_BASED:
1312 DPRINTF(("%s: frame-based\n", __func__)); 1311 DPRINTF(("%s: frame-based\n", __func__));
1313 subtype = UDESC_VS_FRAME_FRAME_BASED; 1312 subtype = UDESC_VS_FRAME_FRAME_BASED;
1314 default_index = GET(uvideo_format_frame_based_descriptor_t, 1313 default_index = GET(uvideo_format_frame_based_descriptor_t,
1315 format_desc, 1314 format_desc,
1316 bDefaultFrameIndex); 1315 bDefaultFrameIndex);
1317 break; 1316 break;
1318 case UDESC_VS_FORMAT_MJPEG: 1317 case UDESC_VS_FORMAT_MJPEG:
1319 DPRINTF(("%s: mjpeg\n", __func__)); 1318 DPRINTF(("%s: mjpeg\n", __func__));
1320 subtype = UDESC_VS_FRAME_MJPEG; 1319 subtype = UDESC_VS_FRAME_MJPEG;
1321 default_index = GET(uvideo_vs_format_mjpeg_descriptor_t, 1320 default_index = GET(uvideo_vs_format_mjpeg_descriptor_t,
1322 format_desc, 1321 format_desc,
1323 bDefaultFrameIndex); 1322 bDefaultFrameIndex);
1324 pixel_format = VIDEO_FORMAT_MJPEG; 1323 pixel_format = VIDEO_FORMAT_MJPEG;
1325 break; 1324 break;
1326 default: 1325 default:
1327 DPRINTF(("uvideo: unknown frame based format %d\n", 1326 DPRINTF(("uvideo: unknown frame based format %d\n",
1328 format_desc->bDescriptorSubtype)); 1327 format_desc->bDescriptorSubtype));
1329 return USBD_INVAL; 1328 return USBD_INVAL;
1330 } 1329 }
1331 1330
1332 pformat = NULL; 1331 pformat = NULL;
1333 SIMPLEQ_FOREACH(pfiter, &vs->vs_pixel_formats, entries) { 1332 SIMPLEQ_FOREACH(pfiter, &vs->vs_pixel_formats, entries) {
1334 if (pfiter->pixel_format == pixel_format) { 1333 if (pfiter->pixel_format == pixel_format) {
1335 pformat = pfiter; 1334 pformat = pfiter;
1336 break; 1335 break;
1337 } 1336 }
1338 } 1337 }
1339 if (pixel_format != VIDEO_FORMAT_UNDEFINED && pformat == NULL) { 1338 if (pixel_format != VIDEO_FORMAT_UNDEFINED && pformat == NULL) {
1340 pformat = kmem_zalloc(sizeof(*pformat), KM_SLEEP); 1339 pformat = kmem_zalloc(sizeof(*pformat), KM_SLEEP);
1341 pformat->pixel_format = pixel_format; 1340 pformat->pixel_format = pixel_format;
1342 DPRINTF(("uvideo: Adding pixel format %d\n", 1341 DPRINTF(("uvideo: Adding pixel format %d\n",
1343 pixel_format)); 1342 pixel_format));
1344 SIMPLEQ_INSERT_TAIL(&vs->vs_pixel_formats, 1343 SIMPLEQ_INSERT_TAIL(&vs->vs_pixel_formats,
1345 pformat, entries); 1344 pformat, entries);
1346 } 1345 }
1347 1346
1348 /* Iterate through frame descriptors directly following the 1347 /* Iterate through frame descriptors directly following the
1349 * format descriptor, and add a format to the format list for 1348 * format descriptor, and add a format to the format list for
1350 * each frame descriptor. */ 1349 * each frame descriptor. */
1351 while ((uvdesc = (const uvideo_descriptor_t *)usb_desc_iter_peek(iter)) && 1350 while ((uvdesc = (const uvideo_descriptor_t *)usb_desc_iter_peek(iter)) &&
1352 (uvdesc != NULL) && (uvdesc->bDescriptorSubtype == subtype)) 1351 (uvdesc != NULL) && (uvdesc->bDescriptorSubtype == subtype))
1353 { 1352 {
1354 uvdesc = (const uvideo_descriptor_t *) usb_desc_iter_next(iter); 1353 uvdesc = (const uvideo_descriptor_t *) usb_desc_iter_next(iter);
1355 1354
1356 format = kmem_zalloc(sizeof(struct uvideo_format), KM_SLEEP); 1355 format = kmem_zalloc(sizeof(struct uvideo_format), KM_SLEEP);
1357 format->format.pixel_format = pixel_format; 1356 format->format.pixel_format = pixel_format;
1358 1357
1359 switch (format_desc->bDescriptorSubtype) { 1358 switch (format_desc->bDescriptorSubtype) {
1360 case UDESC_VS_FORMAT_UNCOMPRESSED: 1359 case UDESC_VS_FORMAT_UNCOMPRESSED:
1361#ifdef UVIDEO_DEBUG 1360#ifdef UVIDEO_DEBUG
1362 if (pixel_format == VIDEO_FORMAT_UNDEFINED && 1361 if (pixel_format == VIDEO_FORMAT_UNDEFINED &&
1363 uvideodebug) { 1362 uvideodebug) {
1364 guid = GETP( 1363 guid = GETP(
1365 uvideo_vs_format_uncompressed_descriptor_t, 1364 uvideo_vs_format_uncompressed_descriptor_t,
1366 format_desc, 1365 format_desc,
1367 guidFormat); 1366 guidFormat);
1368 1367
1369 DPRINTF(("uvideo: format undefined ")); 1368 DPRINTF(("uvideo: format undefined "));
1370 usb_guid_print(guid); 1369 usb_guid_print(guid);
1371 DPRINTF(("\n")); 1370 DPRINTF(("\n"));
1372 } 1371 }
1373#endif 1372#endif
1374 1373
1375 UVIDEO_FORMAT_INIT_FRAME_BASED( 1374 UVIDEO_FORMAT_INIT_FRAME_BASED(
1376 uvideo_vs_format_uncompressed_descriptor_t, 1375 uvideo_vs_format_uncompressed_descriptor_t,
1377 format_desc, 1376 format_desc,
1378 uvideo_vs_frame_uncompressed_descriptor_t, 1377 uvideo_vs_frame_uncompressed_descriptor_t,
1379 uvdesc, 1378 uvdesc,
1380 format); 1379 format);
1381 format->format.sample_size = 1380 format->format.sample_size =
1382 UGETDW( 1381 UGETDW(
1383 GET(uvideo_vs_frame_uncompressed_descriptor_t, 1382 GET(uvideo_vs_frame_uncompressed_descriptor_t,
1384 uvdesc, dwMaxVideoFrameBufferSize)); 1383 uvdesc, dwMaxVideoFrameBufferSize));
1385 format->format.stride = 1384 format->format.stride =
1386 format->format.sample_size / format->format.height; 1385 format->format.sample_size / format->format.height;
1387 index = GET(uvideo_vs_frame_uncompressed_descriptor_t, 1386 index = GET(uvideo_vs_frame_uncompressed_descriptor_t,
1388 uvdesc, 1387 uvdesc,
1389 bFrameIndex); 1388 bFrameIndex);
1390 frame_interval = 1389 frame_interval =
1391 UGETDW( 1390 UGETDW(
1392 GET(uvideo_vs_frame_uncompressed_descriptor_t, 1391 GET(uvideo_vs_frame_uncompressed_descriptor_t,
1393 uvdesc, 1392 uvdesc,
1394 dwDefaultFrameInterval)); 1393 dwDefaultFrameInterval));
1395 break; 1394 break;
1396 case UDESC_VS_FORMAT_MJPEG: 1395 case UDESC_VS_FORMAT_MJPEG:
1397 UVIDEO_FORMAT_INIT_FRAME_BASED( 1396 UVIDEO_FORMAT_INIT_FRAME_BASED(
1398 uvideo_vs_format_mjpeg_descriptor_t, 1397 uvideo_vs_format_mjpeg_descriptor_t,
1399 format_desc, 1398 format_desc,
1400 uvideo_vs_frame_mjpeg_descriptor_t, 1399 uvideo_vs_frame_mjpeg_descriptor_t,
1401 uvdesc, 1400 uvdesc,
1402 format); 1401 format);
1403 format->format.sample_size = 1402 format->format.sample_size =
1404 UGETDW( 1403 UGETDW(
1405 GET(uvideo_vs_frame_mjpeg_descriptor_t, 1404 GET(uvideo_vs_frame_mjpeg_descriptor_t,
1406 uvdesc, dwMaxVideoFrameBufferSize)); 1405 uvdesc, dwMaxVideoFrameBufferSize));
1407 format->format.stride = 1406 format->format.stride =
1408 format->format.sample_size / format->format.height; 1407 format->format.sample_size / format->format.height;
1409 index = GET(uvideo_vs_frame_mjpeg_descriptor_t, 1408 index = GET(uvideo_vs_frame_mjpeg_descriptor_t,
1410 uvdesc, 1409 uvdesc,
1411 bFrameIndex); 1410 bFrameIndex);
1412 frame_interval = 1411 frame_interval =
1413 UGETDW( 1412 UGETDW(
1414 GET(uvideo_vs_frame_mjpeg_descriptor_t, 1413 GET(uvideo_vs_frame_mjpeg_descriptor_t,
1415 uvdesc, 1414 uvdesc,
1416 dwDefaultFrameInterval)); 1415 dwDefaultFrameInterval));
1417 break; 1416 break;
1418 case UDESC_VS_FORMAT_FRAME_BASED: 1417 case UDESC_VS_FORMAT_FRAME_BASED:
1419 format->format.pixel_format = VIDEO_FORMAT_UNDEFINED; 1418 format->format.pixel_format = VIDEO_FORMAT_UNDEFINED;
1420 UVIDEO_FORMAT_INIT_FRAME_BASED( 1419 UVIDEO_FORMAT_INIT_FRAME_BASED(
1421 uvideo_format_frame_based_descriptor_t, 1420 uvideo_format_frame_based_descriptor_t,
1422 format_desc, 1421 format_desc,
1423 uvideo_frame_frame_based_descriptor_t, 1422 uvideo_frame_frame_based_descriptor_t,
1424 uvdesc, 1423 uvdesc,
1425 format); 1424 format);
1426 index = GET(uvideo_frame_frame_based_descriptor_t, 1425 index = GET(uvideo_frame_frame_based_descriptor_t,
1427 uvdesc, 1426 uvdesc,
1428 bFrameIndex); 1427 bFrameIndex);
1429 format->format.stride = 1428 format->format.stride =
1430 UGETDW( 1429 UGETDW(
1431 GET(uvideo_frame_frame_based_descriptor_t, 1430 GET(uvideo_frame_frame_based_descriptor_t,
1432 uvdesc, dwBytesPerLine)); 1431 uvdesc, dwBytesPerLine));
1433 format->format.sample_size = 1432 format->format.sample_size =
1434 format->format.stride * format->format.height; 1433 format->format.stride * format->format.height;
1435 frame_interval = 1434 frame_interval =
1436 UGETDW( 1435 UGETDW(
1437 GET(uvideo_frame_frame_based_descriptor_t, 1436 GET(uvideo_frame_frame_based_descriptor_t,
1438 uvdesc, dwDefaultFrameInterval)); 1437 uvdesc, dwDefaultFrameInterval));
1439 break; 1438 break;
1440 default: 1439 default:
1441 /* shouldn't ever get here */ 1440 /* shouldn't ever get here */
1442 DPRINTF(("uvideo: unknown frame based format %d\n", 1441 DPRINTF(("uvideo: unknown frame based format %d\n",
1443 format_desc->bDescriptorSubtype)); 1442 format_desc->bDescriptorSubtype));
1444 kmem_free(format, sizeof(struct uvideo_format)); 1443 kmem_free(format, sizeof(struct uvideo_format));
1445 return USBD_INVAL; 1444 return USBD_INVAL;
1446 } 1445 }
1447 1446
1448 DPRINTF(("uvideo: found format (index %d) type %d " 1447 DPRINTF(("uvideo: found format (index %d) type %d "
1449 "size %ux%u size %u stride %u interval %u\n", 1448 "size %ux%u size %u stride %u interval %u\n",
1450 index, format->format.pixel_format, format->format.width, 1449 index, format->format.pixel_format, format->format.width,
1451 format->format.height, format->format.sample_size, 1450 format->format.height, format->format.sample_size,
1452 format->format.stride, frame_interval)); 1451 format->format.stride, frame_interval));
1453 1452
1454 SIMPLEQ_INSERT_TAIL(&vs->vs_formats, format, entries); 1453 SIMPLEQ_INSERT_TAIL(&vs->vs_formats, format, entries);
1455 1454
1456 if (vs->vs_default_format == NULL && index == default_index 1455 if (vs->vs_default_format == NULL && index == default_index
1457#ifdef UVIDEO_DISABLE_MJPEG 1456#ifdef UVIDEO_DISABLE_MJPEG
1458 && subtype != UDESC_VS_FRAME_MJPEG 1457 && subtype != UDESC_VS_FRAME_MJPEG
1459#endif 1458#endif
1460 ) { 1459 ) {
1461 DPRINTF((" ^ picking this one\n")); 1460 DPRINTF((" ^ picking this one\n"));
1462 vs->vs_default_format = &format->format; 1461 vs->vs_default_format = &format->format;
1463 vs->vs_frame_interval = frame_interval; 1462 vs->vs_frame_interval = frame_interval;
1464 } 1463 }
1465 1464
1466 } 1465 }
1467 1466
1468 return USBD_NORMAL_COMPLETION; 1467 return USBD_NORMAL_COMPLETION;
1469} 1468}
1470 1469
1471static int 1470static int
1472uvideo_stream_start_xfer(struct uvideo_stream *vs) 1471uvideo_stream_start_xfer(struct uvideo_stream *vs)
1473{ 1472{
1474 struct uvideo_softc *sc = vs->vs_parent; 1473 struct uvideo_softc *sc = vs->vs_parent;
1475 struct uvideo_bulk_xfer *bx; 1474 struct uvideo_bulk_xfer *bx;
1476 struct uvideo_isoc_xfer *ix; 1475 struct uvideo_isoc_xfer *ix;
1477 uint32_t vframe_len; /* rough bytes per video frame */ 1476 uint32_t vframe_len; /* rough bytes per video frame */
1478 uint32_t uframe_len; /* bytes per usb frame (TODO: or microframe?) */ 1477 uint32_t uframe_len; /* bytes per usb frame (TODO: or microframe?) */
1479 uint32_t nframes; /* number of usb frames (TODO: or microframs?) */ 1478 uint32_t nframes; /* number of usb frames (TODO: or microframs?) */
1480 int i, ret; 1479 int i, ret;
1481 int error; 1480 int error;
1482 1481
1483 struct uvideo_alternate *alt, *alt_maybe; 1482 struct uvideo_alternate *alt, *alt_maybe;
1484 usbd_status err; 1483 usbd_status err;
1485 1484
1486 switch (vs->vs_xfer_type) { 1485 switch (vs->vs_xfer_type) {
1487 case UE_BULK: 1486 case UE_BULK:
1488 ret = 0; 1487 ret = 0;
1489 bx = &vs->vs_xfer.bulk; 1488 bx = &vs->vs_xfer.bulk;
1490 1489
1491 err = usbd_open_pipe(vs->vs_iface, bx->bx_endpt, 0, 1490 err = usbd_open_pipe(vs->vs_iface, bx->bx_endpt, 0,
1492 &bx->bx_pipe); 1491 &bx->bx_pipe);
1493 if (err != USBD_NORMAL_COMPLETION) { 1492 if (err != USBD_NORMAL_COMPLETION) {
1494 DPRINTF(("uvideo: error opening pipe: %s (%d)\n", 1493 DPRINTF(("uvideo: error opening pipe: %s (%d)\n",
1495 usbd_errstr(err), err)); 1494 usbd_errstr(err), err));
1496 return EIO; 1495 return EIO;
1497 } 1496 }
1498 DPRINTF(("uvideo: pipe %p\n", bx->bx_pipe)); 1497 DPRINTF(("uvideo: pipe %p\n", bx->bx_pipe));
1499 1498
1500 error = usbd_create_xfer(bx->bx_pipe, vs->vs_max_payload_size, 1499 error = usbd_create_xfer(bx->bx_pipe, vs->vs_max_payload_size,
1501 0, 0, &bx->bx_xfer); 1500 0, 0, &bx->bx_xfer);
1502 if (error) { 1501 if (error) {
1503 DPRINTF(("uvideo: couldn't allocate xfer\n")); 1502 DPRINTF(("uvideo: couldn't allocate xfer\n"));
1504 return error; 1503 return error;
1505 } 1504 }
1506 DPRINTF(("uvideo: xfer %p\n", bx->bx_xfer)); 1505 DPRINTF(("uvideo: xfer %p\n", bx->bx_xfer));
1507 1506
1508 bx->bx_buflen = vs->vs_max_payload_size; 1507 bx->bx_buflen = vs->vs_max_payload_size;
1509 bx->bx_buffer = usbd_get_buffer(bx->bx_xfer); 1508 bx->bx_buffer = usbd_get_buffer(bx->bx_xfer);
1510 1509
1511 mutex_enter(&bx->bx_lock); 1510 mutex_enter(&bx->bx_lock);
1512 if (bx->bx_running == false) { 1511 if (bx->bx_running == false) {
1513 bx->bx_running = true; 1512 bx->bx_running = true;
1514 ret = kthread_create(PRI_UVIDEO, 0, NULL, 1513 ret = kthread_create(PRI_UVIDEO, 0, NULL,
1515 uvideo_stream_recv_bulk_transfer, vs, 1514 uvideo_stream_recv_bulk_transfer, vs,
1516 NULL, "%s", device_xname(sc->sc_dev)); 1515 NULL, "%s", device_xname(sc->sc_dev));
1517 if (ret) { 1516 if (ret) {
1518 DPRINTF(("uvideo: couldn't create kthread:" 1517 DPRINTF(("uvideo: couldn't create kthread:"
1519 " %d\n", err)); 1518 " %d\n", err));
1520 bx->bx_running = false; 1519 bx->bx_running = false;
1521 mutex_exit(&bx->bx_lock); 1520 mutex_exit(&bx->bx_lock);
1522 return err; 1521 return err;
1523 } 1522 }
1524 } else 1523 } else
1525 aprint_error_dev(sc->sc_dev, 1524 aprint_error_dev(sc->sc_dev,
1526 "transfer already in progress\n"); 1525 "transfer already in progress\n");
1527 mutex_exit(&bx->bx_lock); 1526 mutex_exit(&bx->bx_lock);
1528 1527
1529 DPRINTF(("uvideo: thread created\n")); 1528 DPRINTF(("uvideo: thread created\n"));
1530 1529
1531 return 0; 1530 return 0;
1532 case UE_ISOCHRONOUS: 1531 case UE_ISOCHRONOUS:
1533 ix = &vs->vs_xfer.isoc; 1532 ix = &vs->vs_xfer.isoc;
1534 1533
1535 /* Choose an alternate interface most suitable for 1534 /* Choose an alternate interface most suitable for
1536 * this format. Choose the smallest size that can 1535 * this format. Choose the smallest size that can
1537 * contain max_payload_size. 1536 * contain max_payload_size.
1538 * 1537 *
1539 * It is assumed that the list is sorted in descending 1538 * It is assumed that the list is sorted in descending
1540 * order from largest to smallest packet size. 1539 * order from largest to smallest packet size.
1541 * 1540 *
1542 * TODO: what should the strategy be for choosing an 1541 * TODO: what should the strategy be for choosing an
1543 * alt interface? 1542 * alt interface?
1544 */ 1543 */
1545 alt = NULL; 1544 alt = NULL;
1546 SLIST_FOREACH(alt_maybe, &ix->ix_altlist, entries) { 1545 SLIST_FOREACH(alt_maybe, &ix->ix_altlist, entries) {
1547 /* TODO: define "packet" and "payload". I think 1546 /* TODO: define "packet" and "payload". I think
1548 * several packets can make up one payload which would 1547 * several packets can make up one payload which would
1549 * call into question this method of selecting an 1548 * call into question this method of selecting an
1550 * alternate interface... */ 1549 * alternate interface... */
1551 1550
1552 if (alt_maybe->max_packet_size > vs->vs_max_payload_size) 1551 if (alt_maybe->max_packet_size > vs->vs_max_payload_size)
1553 continue; 1552 continue;
1554 1553
1555 if (alt == NULL || 1554 if (alt == NULL ||
1556 alt_maybe->max_packet_size >= alt->max_packet_size) 1555 alt_maybe->max_packet_size >= alt->max_packet_size)
1557 alt = alt_maybe; 1556 alt = alt_maybe;
1558 } 1557 }
1559 1558
1560 if (alt == NULL) { 1559 if (alt == NULL) {
1561 DPRINTF(("uvideo_stream_start_xfer: " 1560 DPRINTF(("uvideo_stream_start_xfer: "
1562 "no suitable alternate interface found\n")); 1561 "no suitable alternate interface found\n"));
1563 return EINVAL; 1562 return EINVAL;
1564 } 1563 }
1565 1564
1566 DPRINTFN(15,("uvideo_stream_start_xfer: " 1565 DPRINTFN(15,("uvideo_stream_start_xfer: "
1567 "choosing alternate interface " 1566 "choosing alternate interface "
1568 "%d wMaxPacketSize=%d bInterval=%d\n", 1567 "%d wMaxPacketSize=%d bInterval=%d\n",
1569 alt->altno, alt->max_packet_size, alt->interval)); 1568 alt->altno, alt->max_packet_size, alt->interval));
1570 1569
1571 err = usbd_set_interface(vs->vs_iface, alt->altno); 1570 err = usbd_set_interface(vs->vs_iface, alt->altno);
1572 if (err != USBD_NORMAL_COMPLETION) { 1571 if (err != USBD_NORMAL_COMPLETION) {
1573 DPRINTF(("uvideo_stream_start_xfer: " 1572 DPRINTF(("uvideo_stream_start_xfer: "
1574 "error setting alt interface: %s (%d)\n", 1573 "error setting alt interface: %s (%d)\n",
1575 usbd_errstr(err), err)); 1574 usbd_errstr(err), err));
1576 return EIO; 1575 return EIO;
1577 } 1576 }
1578 1577
1579 /* TODO: "packet" not same as frame */ 1578 /* TODO: "packet" not same as frame */
1580 vframe_len = vs->vs_current_format.sample_size; 1579 vframe_len = vs->vs_current_format.sample_size;
1581 uframe_len = alt->max_packet_size; 1580 uframe_len = alt->max_packet_size;
1582 nframes = (vframe_len + uframe_len - 1) / uframe_len; 1581 nframes = (vframe_len + uframe_len - 1) / uframe_len;
1583 nframes = (nframes + 7) & ~7; /*round up for ehci inefficiency*/ 1582 nframes = (nframes + 7) & ~7; /*round up for ehci inefficiency*/
1584 nframes = uimin(UVIDEO_NFRAMES_MAX, nframes); 1583 nframes = uimin(UVIDEO_NFRAMES_MAX, nframes);
1585 DPRINTF(("uvideo_stream_start_xfer: nframes=%d\n", nframes)); 1584 DPRINTF(("uvideo_stream_start_xfer: nframes=%d\n", nframes));
1586 1585
1587 ix->ix_nframes = nframes; 1586 ix->ix_nframes = nframes;
1588 ix->ix_uframe_len = uframe_len; 1587 ix->ix_uframe_len = uframe_len;
1589 for (i = 0; i < UVIDEO_NXFERS; i++) { 1588 for (i = 0; i < UVIDEO_NXFERS; i++) {
1590 struct uvideo_isoc *isoc = &ix->ix_i[i]; 1589 struct uvideo_isoc *isoc = &ix->ix_i[i];
1591 isoc->i_frlengths = 1590 isoc->i_frlengths =
1592 kmem_alloc(sizeof(isoc->i_frlengths[0]) * nframes, 1591 kmem_alloc(sizeof(isoc->i_frlengths[0]) * nframes,
1593 KM_SLEEP); 1592 KM_SLEEP);
1594 } 1593 }
1595 1594
1596 err = usbd_open_pipe(vs->vs_iface, ix->ix_endpt, 1595 err = usbd_open_pipe(vs->vs_iface, ix->ix_endpt,
1597 USBD_EXCLUSIVE_USE, &ix->ix_pipe); 1596 USBD_EXCLUSIVE_USE, &ix->ix_pipe);
1598 if (err != USBD_NORMAL_COMPLETION) { 1597 if (err != USBD_NORMAL_COMPLETION) {
1599 DPRINTF(("uvideo: error opening pipe: %s (%d)\n", 1598 DPRINTF(("uvideo: error opening pipe: %s (%d)\n",
1600 usbd_errstr(err), err)); 1599 usbd_errstr(err), err));
1601 return EIO; 1600 return EIO;
1602 } 1601 }
1603 1602
1604 for (i = 0; i < UVIDEO_NXFERS; i++) { 1603 for (i = 0; i < UVIDEO_NXFERS; i++) {
1605 struct uvideo_isoc *isoc = &ix->ix_i[i]; 1604 struct uvideo_isoc *isoc = &ix->ix_i[i];
1606 error = usbd_create_xfer(ix->ix_pipe, 1605 error = usbd_create_xfer(ix->ix_pipe,
1607 nframes * uframe_len, 0, ix->ix_nframes, 1606 nframes * uframe_len, 0, ix->ix_nframes,
1608 &isoc->i_xfer); 1607 &isoc->i_xfer);
1609 if (error) { 1608 if (error) {
1610 DPRINTF(("uvideo: " 1609 DPRINTF(("uvideo: "
1611 "couldn't allocate xfer (%d)\n", error)); 1610 "couldn't allocate xfer (%d)\n", error));
1612 return error; 1611 return error;
1613 } 1612 }
1614 1613
1615 isoc->i_buf = usbd_get_buffer(isoc->i_xfer); 1614 isoc->i_buf = usbd_get_buffer(isoc->i_xfer);
1616 } 1615 }
1617 1616
1618 uvideo_stream_recv_isoc_start(vs); 1617 uvideo_stream_recv_isoc_start(vs);
1619 1618
1620 return 0; 1619 return 0;
1621 default: 1620 default:
1622 /* should never get here */ 1621 /* should never get here */
1623 DPRINTF(("uvideo_stream_start_xfer: unknown xfer type %#x\n", 1622 DPRINTF(("uvideo_stream_start_xfer: unknown xfer type %#x\n",
1624 vs->vs_xfer_type)); 1623 vs->vs_xfer_type));
1625 return EINVAL; 1624 return EINVAL;
1626 } 1625 }
1627} 1626}
1628 1627
1629static int 1628static int
1630uvideo_stream_stop_xfer(struct uvideo_stream *vs) 1629uvideo_stream_stop_xfer(struct uvideo_stream *vs)
1631{ 1630{
1632 struct uvideo_bulk_xfer *bx; 1631 struct uvideo_bulk_xfer *bx;
1633 struct uvideo_isoc_xfer *ix; 1632 struct uvideo_isoc_xfer *ix;
1634 usbd_status err; 1633 usbd_status err;
1635 int i; 1634 int i;
1636 1635
1637 switch (vs->vs_xfer_type) { 1636 switch (vs->vs_xfer_type) {
1638 case UE_BULK: 1637 case UE_BULK:
1639 bx = &vs->vs_xfer.bulk; 1638 bx = &vs->vs_xfer.bulk;
1640 1639
1641 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: " 1640 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: "
1642 "waiting for thread to complete\n")); 1641 "waiting for thread to complete\n"));
1643 mutex_enter(&bx->bx_lock); 1642 mutex_enter(&bx->bx_lock);
1644 if (bx->bx_running == true) { 1643 if (bx->bx_running == true) {
1645 bx->bx_running = false; 1644 bx->bx_running = false;
1646 cv_wait_sig(&bx->bx_cv, &bx->bx_lock); 1645 cv_wait_sig(&bx->bx_cv, &bx->bx_lock);
1647 } 1646 }
1648 mutex_exit(&bx->bx_lock); 1647 mutex_exit(&bx->bx_lock);
1649 1648
1650 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: cleaning up\n")); 1649 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: cleaning up\n"));
1651 1650
1652 if (bx->bx_pipe) { 1651 if (bx->bx_pipe) {
1653 usbd_abort_pipe(bx->bx_pipe); 1652 usbd_abort_pipe(bx->bx_pipe);
1654 } 1653 }
1655 1654
1656 if (bx->bx_xfer) { 1655 if (bx->bx_xfer) {
1657 usbd_destroy_xfer(bx->bx_xfer); 1656 usbd_destroy_xfer(bx->bx_xfer);
1658 bx->bx_xfer = NULL; 1657 bx->bx_xfer = NULL;
1659 } 1658 }
1660 1659
1661 if (bx->bx_pipe) { 1660 if (bx->bx_pipe) {
1662 usbd_close_pipe(bx->bx_pipe); 1661 usbd_close_pipe(bx->bx_pipe);
1663 bx->bx_pipe = NULL; 1662 bx->bx_pipe = NULL;
1664 } 1663 }
1665 1664
1666 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: done\n")); 1665 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: done\n"));
1667 1666
1668 return 0; 1667 return 0;
1669 case UE_ISOCHRONOUS: 1668 case UE_ISOCHRONOUS:
1670 ix = &vs->vs_xfer.isoc; 1669 ix = &vs->vs_xfer.isoc;
1671 if (ix->ix_pipe != NULL) { 1670 if (ix->ix_pipe != NULL) {
1672 usbd_abort_pipe(ix->ix_pipe); 1671 usbd_abort_pipe(ix->ix_pipe);
1673 } 1672 }
1674 1673
1675 for (i = 0; i < UVIDEO_NXFERS; i++) { 1674 for (i = 0; i < UVIDEO_NXFERS; i++) {
1676 struct uvideo_isoc *isoc = &ix->ix_i[i]; 1675 struct uvideo_isoc *isoc = &ix->ix_i[i];
1677 if (isoc->i_xfer != NULL) { 1676 if (isoc->i_xfer != NULL) {
1678 usbd_destroy_xfer(isoc->i_xfer); 1677 usbd_destroy_xfer(isoc->i_xfer);
1679 isoc->i_xfer = NULL; 1678 isoc->i_xfer = NULL;
1680 } 1679 }
1681 } 1680 }
1682 1681
1683 if (ix->ix_pipe != NULL) { 1682 if (ix->ix_pipe != NULL) {
1684 usbd_close_pipe(ix->ix_pipe); 1683 usbd_close_pipe(ix->ix_pipe);
1685 ix->ix_pipe = NULL; 1684 ix->ix_pipe = NULL;
1686 } 1685 }
1687 1686
1688 for (i = 0; i < UVIDEO_NXFERS; i++) { 1687 for (i = 0; i < UVIDEO_NXFERS; i++) {
1689 struct uvideo_isoc *isoc = &ix->ix_i[i]; 1688 struct uvideo_isoc *isoc = &ix->ix_i[i];
1690 if (isoc->i_frlengths != NULL) { 1689 if (isoc->i_frlengths != NULL) {
1691 kmem_free(isoc->i_frlengths, 1690 kmem_free(isoc->i_frlengths,
1692 sizeof(isoc->i_frlengths[0]) * 1691 sizeof(isoc->i_frlengths[0]) *
1693 ix->ix_nframes); 1692 ix->ix_nframes);
1694 isoc->i_frlengths = NULL; 1693 isoc->i_frlengths = NULL;
1695 } 1694 }
1696 } 1695 }
1697 1696
1698 /* Give it some time to settle */ 1697 /* Give it some time to settle */
1699 usbd_delay_ms(vs->vs_parent->sc_udev, 1000); 1698 usbd_delay_ms(vs->vs_parent->sc_udev, 1000);
1700 1699
1701 /* Set to zero bandwidth alternate interface zero */ 1700 /* Set to zero bandwidth alternate interface zero */
1702 err = usbd_set_interface(vs->vs_iface, 0); 1701 err = usbd_set_interface(vs->vs_iface, 0);
1703 if (err != USBD_NORMAL_COMPLETION) { 1702 if (err != USBD_NORMAL_COMPLETION) {
1704 DPRINTF(("uvideo_stream_stop_transfer: " 1703 DPRINTF(("uvideo_stream_stop_transfer: "
1705 "error setting zero bandwidth interface: " 1704 "error setting zero bandwidth interface: "
1706 "%s (%d)\n", 1705 "%s (%d)\n",
1707 usbd_errstr(err), err)); 1706 usbd_errstr(err), err));
1708 return EIO; 1707 return EIO;
1709 } 1708 }
1710 1709
1711 return 0; 1710 return 0;
1712 default: 1711 default:
1713 /* should never get here */ 1712 /* should never get here */
1714 DPRINTF(("uvideo_stream_stop_xfer: unknown xfer type %#x\n", 1713 DPRINTF(("uvideo_stream_stop_xfer: unknown xfer type %#x\n",
1715 vs->vs_xfer_type)); 1714 vs->vs_xfer_type));
1716 return EINVAL; 1715 return EINVAL;
1717 } 1716 }
1718} 1717}
1719 1718
1720static usbd_status 1719static usbd_status
1721uvideo_stream_recv_isoc_start(struct uvideo_stream *vs) 1720uvideo_stream_recv_isoc_start(struct uvideo_stream *vs)
1722{ 1721{
1723 int i; 1722 int i;
1724 1723
1725 for (i = 0; i < UVIDEO_NXFERS; i++) 1724 for (i = 0; i < UVIDEO_NXFERS; i++)
1726 uvideo_stream_recv_isoc_start1(&vs->vs_xfer.isoc.ix_i[i]); 1725 uvideo_stream_recv_isoc_start1(&vs->vs_xfer.isoc.ix_i[i]);
1727 1726
1728 return USBD_NORMAL_COMPLETION; 1727 return USBD_NORMAL_COMPLETION;
1729} 1728}
1730 1729
1731/* Initiate a usb transfer. */ 1730/* Initiate a usb transfer. */
1732static usbd_status 1731static usbd_status
1733uvideo_stream_recv_isoc_start1(struct uvideo_isoc *isoc) 1732uvideo_stream_recv_isoc_start1(struct uvideo_isoc *isoc)
1734{ 1733{
1735 struct uvideo_isoc_xfer *ix; 1734 struct uvideo_isoc_xfer *ix;
1736 usbd_status err; 1735 usbd_status err;
1737 int i; 1736 int i;
1738 1737
1739 ix = isoc->i_ix; 1738 ix = isoc->i_ix;
1740 1739
1741 for (i = 0; i < ix->ix_nframes; ++i) 1740 for (i = 0; i < ix->ix_nframes; ++i)
1742 isoc->i_frlengths[i] = ix->ix_uframe_len; 1741 isoc->i_frlengths[i] = ix->ix_uframe_len;
1743 1742
1744 usbd_setup_isoc_xfer(isoc->i_xfer, 1743 usbd_setup_isoc_xfer(isoc->i_xfer,
1745 isoc, 1744 isoc,
1746 isoc->i_frlengths, 1745 isoc->i_frlengths,
1747 ix->ix_nframes, 1746 ix->ix_nframes,
1748 USBD_SHORT_XFER_OK, 1747 USBD_SHORT_XFER_OK,
1749 uvideo_stream_recv_isoc_complete); 1748 uvideo_stream_recv_isoc_complete);
1750 1749
1751 err = usbd_transfer(isoc->i_xfer); 1750 err = usbd_transfer(isoc->i_xfer);
1752 if (err != USBD_IN_PROGRESS) { 1751 if (err != USBD_IN_PROGRESS) {
1753 DPRINTF(("uvideo_stream_recv_start: " 1752 DPRINTF(("uvideo_stream_recv_start: "
1754 "usbd_transfer status=%s (%d)\n", 1753 "usbd_transfer status=%s (%d)\n",
1755 usbd_errstr(err), err)); 1754 usbd_errstr(err), err));
1756 } 1755 }
1757 return err; 1756 return err;
1758} 1757}
1759 1758
1760static usbd_status 1759static usbd_status
1761uvideo_stream_recv_process(struct uvideo_stream *vs, uint8_t *buf, uint32_t len) 1760uvideo_stream_recv_process(struct uvideo_stream *vs, uint8_t *buf, uint32_t len)
1762{ 1761{
1763 uvideo_payload_header_t *hdr; 1762 uvideo_payload_header_t *hdr;
1764 struct video_payload payload; 1763 struct video_payload payload;
1765 1764
1766 if (len < sizeof(uvideo_payload_header_t)) { 1765 if (len < sizeof(uvideo_payload_header_t)) {
1767 DPRINTF(("uvideo_stream_recv_process: len %d < payload hdr\n", 1766 DPRINTF(("uvideo_stream_recv_process: len %d < payload hdr\n",
1768 len)); 1767 len));
1769 return USBD_SHORT_XFER; 1768 return USBD_SHORT_XFER;
1770 } 1769 }
1771 1770
1772 hdr = (uvideo_payload_header_t *)buf; 1771 hdr = (uvideo_payload_header_t *)buf;
1773 1772
1774 if (hdr->bHeaderLength > UVIDEO_PAYLOAD_HEADER_SIZE || 1773 if (hdr->bHeaderLength > UVIDEO_PAYLOAD_HEADER_SIZE ||
1775 hdr->bHeaderLength < sizeof(uvideo_payload_header_t)) 1774 hdr->bHeaderLength < sizeof(uvideo_payload_header_t))
1776 return USBD_INVAL; 1775 return USBD_INVAL;
1777 if (hdr->bHeaderLength == len && !(hdr->bmHeaderInfo & UV_END_OF_FRAME)) 1776 if (hdr->bHeaderLength == len && !(hdr->bmHeaderInfo & UV_END_OF_FRAME))
1778 return USBD_INVAL; 1777 return USBD_INVAL;
1779 if (hdr->bmHeaderInfo & UV_ERROR) 1778 if (hdr->bmHeaderInfo & UV_ERROR)
1780 return USBD_IOERROR; 1779 return USBD_IOERROR;
1781 1780
1782 payload.data = buf + hdr->bHeaderLength; 1781 payload.data = buf + hdr->bHeaderLength;
1783 payload.size = len - hdr->bHeaderLength; 1782 payload.size = len - hdr->bHeaderLength;
1784 payload.frameno = hdr->bmHeaderInfo & UV_FRAME_ID; 1783 payload.frameno = hdr->bmHeaderInfo & UV_FRAME_ID;
1785 payload.end_of_frame = hdr->bmHeaderInfo & UV_END_OF_FRAME; 1784 payload.end_of_frame = hdr->bmHeaderInfo & UV_END_OF_FRAME;
1786 1785
1787 video_submit_payload(vs->vs_parent->sc_videodev, &payload); 1786 video_submit_payload(vs->vs_parent->sc_videodev, &payload);
1788 1787
1789 return USBD_NORMAL_COMPLETION; 1788 return USBD_NORMAL_COMPLETION;
1790} 1789}
1791 1790
1792/* Callback on completion of usb isoc transfer */ 1791/* Callback on completion of usb isoc transfer */
1793static void 1792static void
1794uvideo_stream_recv_isoc_complete(struct usbd_xfer *xfer, 1793uvideo_stream_recv_isoc_complete(struct usbd_xfer *xfer,
1795 void *priv, 1794 void *priv,
1796 usbd_status status) 1795 usbd_status status)
1797{ 1796{
1798 struct uvideo_stream *vs; 1797 struct uvideo_stream *vs;
1799 struct uvideo_isoc_xfer *ix; 1798 struct uvideo_isoc_xfer *ix;
1800 struct uvideo_isoc *isoc; 1799 struct uvideo_isoc *isoc;
1801 int i; 1800 int i;
1802 uint32_t count; 1801 uint32_t count;
1803 uint8_t *buf; 1802 uint8_t *buf;
1804 1803
1805 isoc = priv; 1804 isoc = priv;
1806 vs = isoc->i_vs; 1805 vs = isoc->i_vs;
1807 ix = isoc->i_ix; 1806 ix = isoc->i_ix;
1808 1807
1809 if (status != USBD_NORMAL_COMPLETION) { 1808 if (status != USBD_NORMAL_COMPLETION) {
1810 DPRINTF(("uvideo_stream_recv_isoc_complete: status=%s (%d)\n", 1809 DPRINTF(("uvideo_stream_recv_isoc_complete: status=%s (%d)\n",
1811 usbd_errstr(status), status)); 1810 usbd_errstr(status), status));
1812 1811
1813 if (status == USBD_STALLED) 1812 if (status == USBD_STALLED)
1814 usbd_clear_endpoint_stall_async(ix->ix_pipe); 1813 usbd_clear_endpoint_stall_async(ix->ix_pipe);
1815 else 1814 else
1816 return; 1815 return;
1817 } else { 1816 } else {
1818 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 1817 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1819 1818
1820 if (count == 0) { 1819 if (count == 0) {
1821 /* DPRINTF(("uvideo: zero length transfer\n")); */ 1820 /* DPRINTF(("uvideo: zero length transfer\n")); */
1822 goto next; 1821 goto next;
1823 } 1822 }
1824 1823
1825 1824
1826 for (i = 0, buf = isoc->i_buf; 1825 for (i = 0, buf = isoc->i_buf;
1827 i < ix->ix_nframes; 1826 i < ix->ix_nframes;
1828 ++i, buf += ix->ix_uframe_len) 1827 ++i, buf += ix->ix_uframe_len)
1829 { 1828 {
1830 status = uvideo_stream_recv_process(vs, buf, 1829 status = uvideo_stream_recv_process(vs, buf,
1831 isoc->i_frlengths[i]); 1830 isoc->i_frlengths[i]);
1832 if (status == USBD_IOERROR) 1831 if (status == USBD_IOERROR)
1833 break; 1832 break;
1834 } 1833 }
1835 } 1834 }
1836 1835
1837next: 1836next:
1838 uvideo_stream_recv_isoc_start1(isoc); 1837 uvideo_stream_recv_isoc_start1(isoc);
1839} 1838}
1840 1839
1841static void 1840static void
1842uvideo_stream_recv_bulk_transfer(void *addr) 1841uvideo_stream_recv_bulk_transfer(void *addr)
1843{ 1842{
1844 struct uvideo_stream *vs = addr; 1843 struct uvideo_stream *vs = addr;
1845 struct uvideo_bulk_xfer *bx = &vs->vs_xfer.bulk; 1844 struct uvideo_bulk_xfer *bx = &vs->vs_xfer.bulk;
1846 usbd_status err; 1845 usbd_status err;
1847 uint32_t len; 1846 uint32_t len;
1848 1847
1849 DPRINTF(("uvideo_stream_recv_bulk_transfer: " 1848 DPRINTF(("uvideo_stream_recv_bulk_transfer: "
1850 "vs %p sc %p bx %p buffer %p\n", vs, vs->vs_parent, bx, 1849 "vs %p sc %p bx %p buffer %p\n", vs, vs->vs_parent, bx,
1851 bx->bx_buffer)); 1850 bx->bx_buffer));
1852 1851
1853 while (bx->bx_running) { 1852 while (bx->bx_running) {
1854 len = bx->bx_buflen; 1853 len = bx->bx_buflen;
1855 err = usbd_bulk_transfer(bx->bx_xfer, bx->bx_pipe, 1854 err = usbd_bulk_transfer(bx->bx_xfer, bx->bx_pipe,
1856 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, 1855 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT,
1857 bx->bx_buffer, &len); 1856 bx->bx_buffer, &len);
1858 1857
1859 if (err == USBD_NORMAL_COMPLETION) { 1858 if (err == USBD_NORMAL_COMPLETION) {
1860 uvideo_stream_recv_process(vs, bx->bx_buffer, len); 1859 uvideo_stream_recv_process(vs, bx->bx_buffer, len);
1861 } else { 1860 } else {
1862 DPRINTF(("uvideo_stream_recv_bulk_transfer: %s\n", 1861 DPRINTF(("uvideo_stream_recv_bulk_transfer: %s\n",
1863 usbd_errstr(err))); 1862 usbd_errstr(err)));
1864 } 1863 }
1865 } 1864 }
1866 1865
1867 DPRINTF(("uvideo_stream_recv_bulk_transfer: notify complete\n")); 1866 DPRINTF(("uvideo_stream_recv_bulk_transfer: notify complete\n"));
1868 1867
1869 mutex_enter(&bx->bx_lock); 1868 mutex_enter(&bx->bx_lock);
1870 cv_broadcast(&bx->bx_cv); 1869 cv_broadcast(&bx->bx_cv);
1871 mutex_exit(&bx->bx_lock); 1870 mutex_exit(&bx->bx_lock);
1872 1871
1873 DPRINTF(("uvideo_stream_recv_bulk_transfer: return\n")); 1872 DPRINTF(("uvideo_stream_recv_bulk_transfer: return\n"));
1874 1873
1875 kthread_exit(0); 1874 kthread_exit(0);
1876} 1875}
1877 1876
1878/* 1877/*
1879 * uvideo_open - probe and commit video format and start receiving 1878 * uvideo_open - probe and commit video format and start receiving
1880 * video data 1879 * video data
1881 */ 1880 */
1882static int 1881static int
1883uvideo_open(void *addr, int flags) 1882uvideo_open(void *addr, int flags)
1884{ 1883{
1885 struct uvideo_softc *sc; 1884 struct uvideo_softc *sc;
1886 struct uvideo_stream *vs; 1885 struct uvideo_stream *vs;
1887 struct video_format fmt; 1886 struct video_format fmt;
1888 1887
1889 sc = addr; 1888 sc = addr;
1890 vs = sc->sc_stream_in; 1889 vs = sc->sc_stream_in;
1891 1890
1892 DPRINTF(("uvideo_open: sc=%p\n", sc)); 1891 DPRINTF(("uvideo_open: sc=%p\n", sc));
1893 if (sc->sc_dying) 1892 if (sc->sc_dying)
1894 return EIO; 1893 return EIO;
1895 1894
1896 /* XXX select default format */ 1895 /* XXX select default format */
1897 fmt = *vs->vs_default_format; 1896 fmt = *vs->vs_default_format;
1898 return uvideo_set_format(addr, &fmt); 1897 return uvideo_set_format(addr, &fmt);
1899} 1898}
1900 1899
1901 1900
1902static void 1901static void
1903uvideo_close(void *addr) 1902uvideo_close(void *addr)
1904{ 1903{
1905 struct uvideo_softc *sc; 1904 struct uvideo_softc *sc;
1906 1905
1907 sc = addr; 1906 sc = addr;
1908 1907
1909 uvideo_stop_transfer(addr); 1908 uvideo_stop_transfer(addr);
1910 1909
1911 if (sc->sc_state != UVIDEO_STATE_CLOSED) { 1910 if (sc->sc_state != UVIDEO_STATE_CLOSED) {
1912 sc->sc_state = UVIDEO_STATE_CLOSED; 1911 sc->sc_state = UVIDEO_STATE_CLOSED;
1913 } 1912 }
1914} 1913}
1915 1914
1916static const char * 1915static const char *
1917uvideo_get_devname(void *addr) 1916uvideo_get_devname(void *addr)
1918{ 1917{
1919 struct uvideo_softc *sc = addr; 1918 struct uvideo_softc *sc = addr;
1920 return sc->sc_devname; 1919 return sc->sc_devname;
1921} 1920}
1922 1921
1923static const char * 1922static const char *
1924uvideo_get_businfo(void *addr) 1923uvideo_get_businfo(void *addr)
1925{ 1924{
1926 struct uvideo_softc *sc = addr; 1925 struct uvideo_softc *sc = addr;
1927 return sc->sc_businfo; 1926 return sc->sc_businfo;
1928} 1927}
1929 1928
1930static int 1929static int
1931uvideo_enum_format(void *addr, uint32_t index, struct video_format *format) 1930uvideo_enum_format(void *addr, uint32_t index, struct video_format *format)
1932{ 1931{
1933 struct uvideo_softc *sc = addr; 1932 struct uvideo_softc *sc = addr;
1934 struct uvideo_stream *vs = sc->sc_stream_in; 1933 struct uvideo_stream *vs = sc->sc_stream_in;
1935 struct uvideo_format *video_format; 1934 struct uvideo_format *video_format;
1936 int off; 1935 int off;
1937 1936
1938 if (sc->sc_dying) 1937 if (sc->sc_dying)
1939 return EIO; 1938 return EIO;
1940 1939
1941 off = 0; 1940 off = 0;
1942 SIMPLEQ_FOREACH(video_format, &vs->vs_formats, entries) { 1941 SIMPLEQ_FOREACH(video_format, &vs->vs_formats, entries) {
1943 if (off++ != index) 1942 if (off++ != index)
1944 continue; 1943 continue;
1945 format->pixel_format = video_format->format.pixel_format; 1944 format->pixel_format = video_format->format.pixel_format;
1946 format->width = video_format->format.width; 1945 format->width = video_format->format.width;
1947 format->height = video_format->format.height; 1946 format->height = video_format->format.height;
1948 return 0; 1947 return 0;
1949 } 1948 }
1950 1949
1951 return EINVAL; 1950 return EINVAL;
1952} 1951}
1953 1952
1954/* 1953/*
1955 * uvideo_get_format 1954 * uvideo_get_format
1956 */ 1955 */
1957static int 1956static int
1958uvideo_get_format(void *addr, struct video_format *format) 1957uvideo_get_format(void *addr, struct video_format *format)
1959{ 1958{
1960 struct uvideo_softc *sc = addr; 1959 struct uvideo_softc *sc = addr;
1961 struct uvideo_stream *vs = sc->sc_stream_in; 1960 struct uvideo_stream *vs = sc->sc_stream_in;
1962 1961
1963 if (sc->sc_dying) 1962 if (sc->sc_dying)
1964 return EIO; 1963 return EIO;
1965 1964
1966 *format = vs->vs_current_format; 1965 *format = vs->vs_current_format;
1967 1966
1968 return 0; 1967 return 0;
1969} 1968}
1970 1969
1971/* 1970/*
1972 * uvideo_set_format - TODO: this is broken and does nothing 1971 * uvideo_set_format - TODO: this is broken and does nothing
1973 */ 1972 */
1974static int 1973static int
1975uvideo_set_format(void *addr, struct video_format *format) 1974uvideo_set_format(void *addr, struct video_format *format)
1976{ 1975{
1977 struct uvideo_softc *sc; 1976 struct uvideo_softc *sc;
1978 struct uvideo_stream *vs; 1977 struct uvideo_stream *vs;
1979 struct uvideo_format *uvfmt; 1978 struct uvideo_format *uvfmt;
1980 uvideo_probe_and_commit_data_t probe, maxprobe; 1979 uvideo_probe_and_commit_data_t probe, maxprobe;
1981 usbd_status err; 1980 usbd_status err;
1982 1981
1983 sc = addr; 1982 sc = addr;
1984 1983
1985 DPRINTF(("uvideo_set_format: sc=%p\n", sc)); 1984 DPRINTF(("uvideo_set_format: sc=%p\n", sc));
1986 if (sc->sc_dying) 1985 if (sc->sc_dying)
1987 return EIO; 1986 return EIO;
1988 1987
1989 vs = sc->sc_stream_in; 1988 vs = sc->sc_stream_in;
1990 1989
1991 uvfmt = uvideo_stream_guess_format(vs, format->pixel_format, 1990 uvfmt = uvideo_stream_guess_format(vs, format->pixel_format,
1992 format->width, format->height); 1991 format->width, format->height);
1993 if (uvfmt == NULL) { 1992 if (uvfmt == NULL) {
1994 DPRINTF(("uvideo: uvideo_stream_guess_format couldn't find " 1993 DPRINTF(("uvideo: uvideo_stream_guess_format couldn't find "
1995 "%dx%d format %d\n", format->width, format->height, 1994 "%dx%d format %d\n", format->width, format->height,
1996 format->pixel_format)); 1995 format->pixel_format));
1997 return EINVAL; 1996 return EINVAL;
1998 } 1997 }
1999 1998
2000 uvideo_init_probe_data(&probe); 1999 uvideo_init_probe_data(&probe);
2001 probe.bFormatIndex = UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt); 2000 probe.bFormatIndex = UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt);
2002 probe.bFrameIndex = UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt); 2001 probe.bFrameIndex = UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt);
2003 USETDW(probe.dwFrameInterval, vs->vs_frame_interval); /* XXX */ 2002 USETDW(probe.dwFrameInterval, vs->vs_frame_interval); /* XXX */
2004 2003
2005 maxprobe = probe; 2004 maxprobe = probe;
2006 err = uvideo_stream_probe(vs, UR_GET_MAX, &maxprobe); 2005 err = uvideo_stream_probe(vs, UR_GET_MAX, &maxprobe);
2007 if (err) { 2006 if (err) {
2008 DPRINTF(("uvideo: error probe/GET_MAX: %s (%d)\n", 2007 DPRINTF(("uvideo: error probe/GET_MAX: %s (%d)\n",
2009 usbd_errstr(err), err)); 2008 usbd_errstr(err), err));
2010 } else { 2009 } else {
2011 USETW(probe.wCompQuality, UGETW(maxprobe.wCompQuality)); 2010 USETW(probe.wCompQuality, UGETW(maxprobe.wCompQuality));
2012 } 2011 }
2013 2012
2014 err = uvideo_stream_probe(vs, UR_SET_CUR, &probe); 2013 err = uvideo_stream_probe(vs, UR_SET_CUR, &probe);
2015 if (err) { 2014 if (err) {
2016 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n", 2015 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n",
2017 usbd_errstr(err), err)); 2016 usbd_errstr(err), err));
2018 return EIO; 2017 return EIO;
2019 } 2018 }
2020 2019
2021 uvideo_init_probe_data(&probe); 2020 uvideo_init_probe_data(&probe);
2022 err = uvideo_stream_probe(vs, UR_GET_CUR, &probe); 2021 err = uvideo_stream_probe(vs, UR_GET_CUR, &probe);
2023 if (err) { 2022 if (err) {
2024 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n", 2023 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n",
2025 usbd_errstr(err), err)); 2024 usbd_errstr(err), err));
2026 return EIO; 2025 return EIO;
2027 } 2026 }
2028 2027
2029 if (probe.bFormatIndex != UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt)) { 2028 if (probe.bFormatIndex != UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt)) {
2030 DPRINTF(("uvideo: probe/GET_CUR returned format index %d " 2029 DPRINTF(("uvideo: probe/GET_CUR returned format index %d "
2031 "(expected %d)\n", probe.bFormatIndex, 2030 "(expected %d)\n", probe.bFormatIndex,
2032 UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt))); 2031 UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt)));
2033 probe.bFormatIndex = UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt); 2032 probe.bFormatIndex = UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt);