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