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