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