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