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