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