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