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