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