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