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