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