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