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