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