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