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