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