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