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