1 /* $NetBSD: uvideo.c,v 1.29 2009/03/09 15:59:33 uebayasi Exp $ */
4 * Copyright (c) 2008 Patrick Mahoney
7 * This code was written by Patrick Mahoney (pat@polycrystal.org) as
8 * part of Google Summer of Code 2008.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
41 * http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_1.zip
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: uvideo.c,v 1.29 2009/03/09 15:59:33 uebayasi Exp $");
48 #include <sys/module.h>
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/kernel.h>
54 /* #include <sys/malloc.h> */
56 #include <sys/device.h>
57 #include <sys/ioctl.h>
60 #include <sys/select.h>
63 #include <sys/vnode.h>
65 #include <sys/queue.h> /* SLIST */
66 #include <sys/kthread.h>
68 #include <sys/videoio.h>
69 #include <dev/video_if.h>
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>
76 #include <dev/usb/uvideoreg.h>
79 #include "opt_uvideo.h"
82 #define UVIDEO_NXFERS 3
83 #define PRI_UVIDEO PRI_BIO
85 /* #define UVIDEO_DISABLE_MJPEG */
88 #define DPRINTF(x) do { if (uvideodebug) logprintf x; } while (0)
89 #define DPRINTFN(n,x) do { if (uvideodebug>(n)) logprintf x; } while (0)
102 struct uvideo_camera_terminal
{
103 uint16_t ct_objective_focal_min
;
104 uint16_t ct_objective_focal_max
;
105 uint16_t ct_ocular_focal_length
;
108 struct uvideo_processing_unit
{
109 uint16_t pu_max_multiplier
; /* digital zoom */
110 uint8_t pu_video_standards
;
113 struct uvideo_extension_unit
{
117 /* For simplicity, we consider a Terminal a special case of Unit
118 * rather than a separate entity. */
125 uint8_t vu_src_id
; /* vu_nsrcs = 1 */
126 uint8_t *vu_src_id_ary
; /* vu_nsrcs > 1 */
129 /* fields for individual unit/terminal types */
131 struct uvideo_camera_terminal vu_camera
;
132 struct uvideo_processing_unit vu_processing
;
133 struct uvideo_extension_unit vu_extension
;
136 /* Used by camera terminal, processing and extention units. */
137 uint8_t vu_control_size
; /* number of bytes in vu_controls */
138 uint8_t *vu_controls
; /* array of bytes. bits are
139 * numbered from 0 at least
141 * (8*vu_control_size - 1)*/
144 struct uvideo_alternate
{
147 uint16_t max_packet_size
;
148 SLIST_ENTRY(uvideo_alternate
) entries
;
150 SLIST_HEAD(altlist
, uvideo_alternate
);
152 #define UVIDEO_FORMAT_GET_FORMAT_INDEX(fmt) \
153 ((fmt)->format.priv & 0xff)
154 #define UVIDEO_FORMAT_GET_FRAME_INDEX(fmt) \
155 (((fmt)->format.priv >> 8) & 0xff)
156 /* TODO: find a better way to set bytes within this 32 bit value? */
157 #define UVIDEO_FORMAT_SET_FORMAT_INDEX(fmt, index) do { \
158 (fmt)->format.priv &= ~0xff; \
159 (fmt)->format.priv |= ((index) & 0xff); \
161 #define UVIDEO_FORMAT_SET_FRAME_INDEX(fmt, index) do { \
162 (fmt)->format.priv &= ~(0xff << 8); \
163 ((fmt)->format.priv |= (((index) & 0xff) << 8)); \
166 struct uvideo_pixel_format
{
167 enum video_pixel_format pixel_format
;
168 SIMPLEQ_ENTRY(uvideo_pixel_format
) entries
;
170 SIMPLEQ_HEAD(uvideo_pixel_format_list
, uvideo_pixel_format
);
172 struct uvideo_format
{
173 struct video_format format
;
174 SIMPLEQ_ENTRY(uvideo_format
) entries
;
176 SIMPLEQ_HEAD(uvideo_format_list
, uvideo_format
);
178 struct uvideo_isoc_xfer
;
179 struct uvideo_stream
;
182 struct uvideo_isoc_xfer
*i_ix
;
183 struct uvideo_stream
*i_vs
;
184 usbd_xfer_handle i_xfer
;
186 uint16_t *i_frlengths
;
189 struct uvideo_isoc_xfer
{
191 usbd_pipe_handle ix_pipe
;
192 struct uvideo_isoc ix_i
[UVIDEO_NXFERS
];
194 uint32_t ix_uframe_len
;
196 struct altlist ix_altlist
;
199 struct uvideo_bulk_xfer
{
201 usbd_pipe_handle bx_pipe
;
202 usbd_xfer_handle bx_xfer
;
210 struct uvideo_stream
{
211 struct uvideo_softc
*vs_parent
;
212 usbd_interface_handle vs_iface
;
214 uint8_t vs_subtype
; /* input or output */
215 uint16_t vs_probelen
; /* length of probe and
216 * commit data; varies
217 * depending on version
219 struct uvideo_format_list vs_formats
;
220 struct uvideo_pixel_format_list vs_pixel_formats
;
221 struct video_format
*vs_default_format
;
222 struct video_format vs_current_format
;
224 /* usb transfer details */
225 uint8_t vs_xfer_type
;
227 struct uvideo_bulk_xfer bulk
;
228 struct uvideo_isoc_xfer isoc
;
231 int vs_frameno
; /* toggles between 0 and 1 */
233 /* current video format */
234 uint32_t vs_max_payload_size
;
235 uint32_t vs_frame_interval
;
236 SLIST_ENTRY(uvideo_stream
) entries
;
238 SLIST_HEAD(uvideo_stream_list
, uvideo_stream
);
240 struct uvideo_softc
{
241 USBBASEDEVICE sc_dev
; /* base device */
242 usbd_device_handle sc_udev
; /* device */
243 usbd_interface_handle sc_iface
; /* interface handle */
244 int sc_ifaceno
; /* interface number */
247 device_ptr_t sc_videodev
;
250 uvideo_state sc_state
;
253 struct uvideo_unit
**sc_unit
;
255 struct uvideo_stream
*sc_stream_in
;
257 struct uvideo_stream_list sc_stream_list
;
260 int uvideo_match(device_t
, cfdata_t
, void *);
261 void uvideo_attach(device_t
, device_t
, void *);
262 int uvideo_detach(device_t
, int);
263 void uvideo_childdet(device_t
, device_t
);
264 int uvideo_activate(device_t
, enum devact
);
266 static int uvideo_open(void *, int);
267 static void uvideo_close(void *);
268 static const char * uvideo_get_devname(void *);
270 static int uvideo_enum_format(void *, uint32_t, struct video_format
*);
271 static int uvideo_get_format(void *, struct video_format
*);
272 static int uvideo_set_format(void *, struct video_format
*);
273 static int uvideo_try_format(void *, struct video_format
*);
274 static int uvideo_start_transfer(void *);
275 static int uvideo_stop_transfer(void *);
277 static int uvideo_get_control_group(void *,
278 struct video_control_group
*);
279 static int uvideo_set_control_group(void *,
280 const struct video_control_group
*);
282 static usbd_status
uvideo_init_control(
283 struct uvideo_softc
*,
284 const usb_interface_descriptor_t
*,
286 static usbd_status
uvideo_init_collection(
287 struct uvideo_softc
*,
288 const usb_interface_descriptor_t
*,
291 /* Functions for unit & terminal descriptors */
292 static struct uvideo_unit
* uvideo_unit_alloc(const uvideo_descriptor_t
*);
293 static usbd_status
uvideo_unit_init(struct uvideo_unit
*,
294 const uvideo_descriptor_t
*);
295 static void uvideo_unit_free(struct uvideo_unit
*);
296 static usbd_status
uvideo_unit_alloc_controls(struct uvideo_unit
*,
299 static void uvideo_unit_free_controls(struct uvideo_unit
*);
300 static usbd_status
uvideo_unit_alloc_sources(struct uvideo_unit
*,
303 static void uvideo_unit_free_sources(struct uvideo_unit
*);
308 /* Functions for uvideo_stream, primary unit associated with a video
309 * driver or device file. */
310 static struct uvideo_stream
* uvideo_find_stream(struct uvideo_softc
*,
313 static struct uvideo_format
* uvideo_stream_find_format(
314 struct uvideo_stream
*,
317 static struct uvideo_format
* uvideo_stream_guess_format(
318 struct uvideo_stream
*,
319 enum video_pixel_format
, uint32_t, uint32_t);
320 static struct uvideo_stream
* uvideo_stream_alloc(void);
321 static usbd_status
uvideo_stream_init(
322 struct uvideo_stream
*stream
,
323 struct uvideo_softc
*sc
,
324 const usb_interface_descriptor_t
*ifdesc
,
326 static usbd_status
uvideo_stream_init_desc(
327 struct uvideo_stream
*,
328 const usb_interface_descriptor_t
*ifdesc
,
329 usbd_desc_iter_t
*iter
);
330 static usbd_status
uvideo_stream_init_frame_based_format(
331 struct uvideo_stream
*,
332 const uvideo_descriptor_t
*,
334 static void uvideo_stream_free(struct uvideo_stream
*);
336 static int uvideo_stream_start_xfer(struct uvideo_stream
*);
337 static int uvideo_stream_stop_xfer(struct uvideo_stream
*);
338 static usbd_status
uvideo_stream_recv_process(struct uvideo_stream
*,
339 uint8_t *, uint32_t);
340 static usbd_status
uvideo_stream_recv_isoc_start(struct uvideo_stream
*);
341 static usbd_status
uvideo_stream_recv_isoc_start1(struct uvideo_isoc
*);
342 static void uvideo_stream_recv_isoc_complete(usbd_xfer_handle
,
345 static void uvideo_stream_recv_bulk_transfer(void *);
347 /* format probe and commit */
348 #define uvideo_stream_probe(vs, act, data) \
349 (uvideo_stream_probe_and_commit((vs), (act), \
350 UVIDEO_VS_PROBE_CONTROL, (data)))
351 #define uvideo_stream_commit(vs, act, data) \
352 (uvideo_stream_probe_and_commit((vs), (act), \
353 UVIDEO_VS_COMMIT_CONTROL, (data)))
354 static usbd_status
uvideo_stream_probe_and_commit(struct uvideo_stream
*,
357 static void uvideo_init_probe_data(uvideo_probe_and_commit_data_t
*);
360 static const usb_descriptor_t
* usb_desc_iter_peek_next(usbd_desc_iter_t
*);
361 static const usb_interface_descriptor_t
* usb_desc_iter_next_interface(
363 static const usb_descriptor_t
* usb_desc_iter_next_non_interface(
366 static int usb_guid_cmp(const usb_guid_t
*, const guid_t
*);
369 CFATTACH_DECL2_NEW(uvideo
, sizeof(struct uvideo_softc
),
370 uvideo_match
, uvideo_attach
, uvideo_detach
, uvideo_activate
, NULL
,
373 extern struct cfdriver uvideo_cd
;
376 static const struct video_hw_if uvideo_hw_if
= {
378 .close
= uvideo_close
,
379 .get_devname
= uvideo_get_devname
,
380 .enum_format
= uvideo_enum_format
,
381 .get_format
= uvideo_get_format
,
382 .set_format
= uvideo_set_format
,
383 .try_format
= uvideo_try_format
,
384 .start_transfer
= uvideo_start_transfer
,
385 .stop_transfer
= uvideo_stop_transfer
,
386 .control_iter_init
= NULL
,
387 .control_iter_next
= NULL
,
388 .get_control_desc_group
= NULL
,
389 .get_control_group
= uvideo_get_control_group
,
390 .set_control_group
= uvideo_set_control_group
,
394 /* Some functions to print out descriptors. Mostly useless other than
395 * debugging/exploration purposes. */
396 static void usb_guid_print(const usb_guid_t
*);
397 static void print_descriptor(const usb_descriptor_t
*);
398 static void print_interface_descriptor(const usb_interface_descriptor_t
*);
399 static void print_endpoint_descriptor(const usb_endpoint_descriptor_t
*);
401 static void print_vc_descriptor(const usb_descriptor_t
*);
402 static void print_vs_descriptor(const usb_descriptor_t
*);
404 static void print_vc_header_descriptor(
405 const uvideo_vc_header_descriptor_t
*);
406 static void print_input_terminal_descriptor(
407 const uvideo_input_terminal_descriptor_t
*);
408 static void print_output_terminal_descriptor(
409 const uvideo_output_terminal_descriptor_t
*);
410 static void print_camera_terminal_descriptor(
411 const uvideo_camera_terminal_descriptor_t
*);
412 static void print_selector_unit_descriptor(
413 const uvideo_selector_unit_descriptor_t
*);
414 static void print_processing_unit_descriptor(
415 const uvideo_processing_unit_descriptor_t
*);
416 static void print_extension_unit_descriptor(
417 const uvideo_extension_unit_descriptor_t
*);
418 static void print_interrupt_endpoint_descriptor(
419 const uvideo_vc_interrupt_endpoint_descriptor_t
*);
421 static void print_vs_input_header_descriptor(
422 const uvideo_vs_input_header_descriptor_t
*);
423 static void print_vs_output_header_descriptor(
424 const uvideo_vs_output_header_descriptor_t
*);
426 static void print_vs_format_uncompressed_descriptor(
427 const uvideo_vs_format_uncompressed_descriptor_t
*);
428 static void print_vs_frame_uncompressed_descriptor(
429 const uvideo_vs_frame_uncompressed_descriptor_t
*);
430 static void print_vs_format_mjpeg_descriptor(
431 const uvideo_vs_format_mjpeg_descriptor_t
*);
432 static void print_vs_frame_mjpeg_descriptor(
433 const uvideo_vs_frame_mjpeg_descriptor_t
*);
434 static void print_vs_format_dv_descriptor(
435 const uvideo_vs_format_dv_descriptor_t
*);
436 #endif /* !UVIDEO_DEBUG */
438 #define GET(type, descp, field) (((const type *)(descp))->field)
439 #define GETP(type, descp, field) (&(((const type *)(descp))->field))
441 /* Given a format descriptor and frame descriptor, copy values common
442 * to all formats into a struct uvideo_format. */
443 #define UVIDEO_FORMAT_INIT_FRAME_BASED(format_type, format_desc, \
444 frame_type, frame_desc, \
447 UVIDEO_FORMAT_SET_FORMAT_INDEX( \
449 GET(format_type, format_desc, bFormatIndex)); \
450 UVIDEO_FORMAT_SET_FRAME_INDEX( \
452 GET(frame_type, frame_desc, bFrameIndex)); \
453 format->format.width = \
454 UGETW(GET(frame_type, frame_desc, wWidth)); \
455 format->format.height = \
456 UGETW(GET(frame_type, frame_desc, wHeight)); \
457 format->format.aspect_x = \
458 GET(format_type, format_desc, bAspectRatioX); \
459 format->format.aspect_y = \
460 GET(format_type, format_desc, bAspectRatioY); \
466 USB_IFMATCH_START(uvideo
, uaa
);
468 /* TODO: May need to change in the future to work with
469 * Interface Association Descriptor. */
471 /* Trigger on the Video Control Interface which must be present */
472 if (uaa
->class == UICLASS_VIDEO
&&
473 uaa
->subclass
== UISUBCLASS_VIDEOCONTROL
)
474 return UMATCH_IFACECLASS_IFACESUBCLASS
;
481 USB_IFATTACH_START(uvideo
, sc
, uaa
);
482 usbd_desc_iter_t iter
;
483 const usb_interface_descriptor_t
*ifdesc
;
484 struct uvideo_stream
*vs
;
490 sc
->sc_devname
= usbd_devinfo_alloc(uaa
->device
, 0);
493 aprint_normal(": %s\n", sc
->sc_devname
);
495 sc
->sc_udev
= uaa
->device
;
496 sc
->sc_iface
= uaa
->iface
;
497 sc
->sc_ifaceno
= uaa
->ifaceno
;
499 sc
->sc_state
= UVIDEO_STATE_CLOSED
;
500 SLIST_INIT(&sc
->sc_stream_list
);
503 /* Debugging dump of descriptors. TODO: move this to userspace
504 * via a custom IOCTL or something. */
505 const usb_descriptor_t
*desc
;
506 usb_desc_iter_init(sc
->sc_udev
, &iter
);
507 while ((desc
= usb_desc_iter_next(&iter
)) != NULL
) {
508 /* print out all descriptors */
509 printf("uvideo_attach: ");
510 print_descriptor(desc
);
512 #endif /* !UVIDEO_DEBUG */
514 /* iterate through interface descriptors and initialize softc */
515 usb_desc_iter_init(sc
->sc_udev
, &iter
);
517 (ifdesc
= usb_desc_iter_next_interface(&iter
)) != NULL
;
520 if (ifdesc
->bInterfaceClass
!= UICLASS_VIDEO
) {
521 DPRINTFN(50, ("uvideo_attach: "
522 "ignoring non-uvc interface: "
523 "len=%d type=0x%02x "
524 "class=0x%02x subclass=0x%02x\n",
526 ifdesc
->bDescriptorType
,
527 ifdesc
->bInterfaceClass
,
528 ifdesc
->bInterfaceSubClass
));
532 switch (ifdesc
->bInterfaceSubClass
) {
533 case UISUBCLASS_VIDEOCONTROL
:
534 err
= uvideo_init_control(sc
, ifdesc
, &iter
);
535 if (err
!= USBD_NORMAL_COMPLETION
) {
536 DPRINTF(("uvideo_attach: error with interface "
538 "descriptor len=%d type=0x%02x: "
540 ifdesc
->bInterfaceNumber
,
542 ifdesc
->bDescriptorType
,
543 usbd_errstr(err
), err
));
546 case UISUBCLASS_VIDEOSTREAMING
:
547 vs
= uvideo_find_stream(sc
, ifdesc
->bInterfaceNumber
);
549 vs
= uvideo_stream_alloc();
551 DPRINTF(("uvideo_attach: "
552 "failed to alloc stream\n"));
556 err
= uvideo_stream_init(vs
, sc
, ifdesc
,
558 if (err
!= USBD_NORMAL_COMPLETION
) {
559 DPRINTF(("uvideo_attach: "
560 "error initializing stream: "
562 usbd_errstr(err
), err
));
566 err
= uvideo_stream_init_desc(vs
, ifdesc
, &iter
);
567 if (err
!= USBD_NORMAL_COMPLETION
) {
568 DPRINTF(("uvideo_attach: "
569 "error initializing stream descriptor: "
571 usbd_errstr(err
), err
));
574 /* TODO: for now, set (each) stream to stream_in. */
575 sc
->sc_stream_in
= vs
;
577 case UISUBCLASS_VIDEOCOLLECTION
:
578 err
= uvideo_init_collection(sc
, ifdesc
, &iter
);
579 if (err
!= USBD_NORMAL_COMPLETION
) {
580 DPRINTF(("uvideo_attach: error with interface "
581 "%d, VideoCollection, "
582 "descriptor len=%d type=0x%02x: "
584 ifdesc
->bInterfaceNumber
,
586 ifdesc
->bDescriptorType
,
587 usbd_errstr(err
), err
));
592 DPRINTF(("uvideo_attach: unknown UICLASS_VIDEO "
594 ifdesc
->bInterfaceSubClass
));
601 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH
, sc
->sc_udev
,
604 if (!pmf_device_register(self
, NULL
, NULL
))
605 aprint_error_dev(self
, "couldn't establish power handler\n");
607 sc
->sc_videodev
= video_attach_mi(&uvideo_hw_if
, sc
->sc_dev
);
608 DPRINTF(("uvideo_attach: attached video driver at %p\n",
611 USB_ATTACH_SUCCESS_RETURN
;
614 if (err
!= USBD_NORMAL_COMPLETION
) {
615 DPRINTF(("uvideo_attach: error: %s (%d)\n",
616 usbd_errstr(err
), err
));
618 USB_ATTACH_ERROR_RETURN
;
623 uvideo_activate(device_t self
, enum devact act
)
625 struct uvideo_softc
*sc
= device_private(self
);
628 case DVACT_DEACTIVATE
:
629 DPRINTF(("uvideo_activate: deactivating\n"));
638 /* Detach child (video interface) */
640 uvideo_childdet(device_t self
, device_t child
)
642 struct uvideo_softc
*sc
= device_private(self
);
644 KASSERT(sc
->sc_videodev
== child
);
645 sc
->sc_videodev
= NULL
;
650 uvideo_detach(device_t self
, int flags
)
652 struct uvideo_softc
*sc
;
653 struct uvideo_stream
*vs
;
656 sc
= device_private(self
);
661 pmf_device_deregister(self
);
663 usbd_devinfo_free(sc
->sc_devname
);
665 /* TODO: close the device if it is currently opened? Or will
666 * close be called automatically? */
668 while (!SLIST_EMPTY(&sc
->sc_stream_list
)) {
669 vs
= SLIST_FIRST(&sc
->sc_stream_list
);
670 SLIST_REMOVE_HEAD(&sc
->sc_stream_list
, entries
);
671 uvideo_stream_free(vs
);
674 /* Wait for outstanding request to complete. TODO: what is
675 * appropriate here? */
676 usbd_delay_ms(sc
->sc_udev
, 1000);
678 DPRINTFN(15, ("uvideo: detaching from %s\n",
679 USBDEVNAME(sc
->sc_dev
)));
681 if (sc
->sc_videodev
!= NULL
)
682 rv
= config_detach(sc
->sc_videodev
, flags
);
684 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH
, sc
->sc_udev
,
690 /* Search the stream list for a stream matching the interface number.
691 * This is an O(n) search, but most devices should have only one or at
692 * most two streams. */
693 static struct uvideo_stream
*
694 uvideo_find_stream(struct uvideo_softc
*sc
, uint8_t ifaceno
)
696 struct uvideo_stream
*vs
;
698 SLIST_FOREACH(vs
, &sc
->sc_stream_list
, entries
) {
699 if (vs
->vs_ifaceno
== ifaceno
)
706 /* Search the format list for the given format and frame index. This
707 * might be improved through indexing, but the format and frame count
708 * is unknown ahead of time (only after iterating through the
709 * usb device descriptors). */
711 static struct uvideo_format
*
712 uvideo_stream_find_format(struct uvideo_stream
*vs
,
713 uint8_t format_index
, uint8_t frame_index
)
715 struct uvideo_format
*format
;
717 SIMPLEQ_FOREACH(format
, &vs
->vs_formats
, entries
) {
718 if (UVIDEO_FORMAT_GET_FORMAT_INDEX(format
) == format_index
&&
719 UVIDEO_FORMAT_GET_FRAME_INDEX(format
) == frame_index
)
726 static struct uvideo_format
*
727 uvideo_stream_guess_format(struct uvideo_stream
*vs
,
728 enum video_pixel_format pixel_format
,
729 uint32_t width
, uint32_t height
)
731 struct uvideo_format
*format
, *gformat
= NULL
;
733 SIMPLEQ_FOREACH(format
, &vs
->vs_formats
, entries
) {
734 if (format
->format
.pixel_format
!= pixel_format
)
736 if (format
->format
.width
<= width
&&
737 format
->format
.height
<= height
) {
738 if (gformat
== NULL
||
739 (gformat
->format
.width
< format
->format
.width
&&
740 gformat
->format
.height
< format
->format
.height
))
748 static struct uvideo_stream
*
749 uvideo_stream_alloc(void)
751 return (kmem_alloc(sizeof(struct uvideo_stream
), KM_NOSLEEP
));
756 uvideo_init_control(struct uvideo_softc
*sc
,
757 const usb_interface_descriptor_t
*ifdesc
,
758 usbd_desc_iter_t
*iter
)
760 const usb_descriptor_t
*desc
;
761 const uvideo_descriptor_t
*uvdesc
;
762 usbd_desc_iter_t orig
;
763 uint8_t i
, j
, nunits
;
765 /* save original iterator state */
766 memcpy(&orig
, iter
, sizeof(orig
));
768 /* count number of units and terminals */
770 while ((desc
= usb_desc_iter_next_non_interface(iter
)) != NULL
) {
771 uvdesc
= (const uvideo_descriptor_t
*)desc
;
773 if (uvdesc
->bDescriptorType
!= UDESC_CS_INTERFACE
)
775 if (uvdesc
->bDescriptorSubtype
< UDESC_INPUT_TERMINAL
||
776 uvdesc
->bDescriptorSubtype
> UDESC_EXTENSION_UNIT
)
782 DPRINTF(("uvideo_init_control: no units\n"));
783 return USBD_NORMAL_COMPLETION
;
786 /* allocate space for units */
787 sc
->sc_nunits
= nunits
;
788 sc
->sc_unit
= kmem_alloc(sizeof(*sc
->sc_unit
) * nunits
, KM_SLEEP
);
789 if (sc
->sc_unit
== NULL
)
792 /* restore original iterator state */
793 memcpy(iter
, &orig
, sizeof(orig
));
795 /* iterate again, initializing the units */
797 while ((desc
= usb_desc_iter_next_non_interface(iter
)) != NULL
) {
798 uvdesc
= (const uvideo_descriptor_t
*)desc
;
800 if (uvdesc
->bDescriptorType
!= UDESC_CS_INTERFACE
)
802 if (uvdesc
->bDescriptorSubtype
< UDESC_INPUT_TERMINAL
||
803 uvdesc
->bDescriptorSubtype
> UDESC_EXTENSION_UNIT
)
806 sc
->sc_unit
[i
] = uvideo_unit_alloc(uvdesc
);
807 /* TODO: free other units before returning? */
808 if (sc
->sc_unit
[i
] == NULL
)
813 return USBD_NORMAL_COMPLETION
;
816 if (sc
->sc_unit
!= NULL
) {
817 for (j
= 0; j
< i
; ++j
) {
818 uvideo_unit_free(sc
->sc_unit
[j
]);
819 sc
->sc_unit
[j
] = NULL
;
821 kmem_free(sc
->sc_unit
, sizeof(*sc
->sc_unit
) * nunits
);
830 uvideo_init_collection(struct uvideo_softc
*sc
,
831 const usb_interface_descriptor_t
*ifdesc
,
832 usbd_desc_iter_t
*iter
)
834 DPRINTF(("uvideo: ignoring Video Collection\n"));
835 return USBD_NORMAL_COMPLETION
;
838 /* Allocates space for and initializes a uvideo unit based on the
839 * given descriptor. Returns NULL with bad descriptor or ENOMEM. */
840 static struct uvideo_unit
*
841 uvideo_unit_alloc(const uvideo_descriptor_t
*desc
)
843 struct uvideo_unit
*vu
;
846 if (desc
->bDescriptorType
!= UDESC_CS_INTERFACE
)
849 vu
= kmem_alloc(sizeof(*vu
), KM_SLEEP
);
853 err
= uvideo_unit_init(vu
, desc
);
854 if (err
!= USBD_NORMAL_COMPLETION
) {
855 DPRINTF(("uvideo_unit_alloc: error initializing unit: "
856 "%s (%d)\n", usbd_errstr(err
), err
));
857 kmem_free(vu
, sizeof(*vu
));
865 uvideo_unit_init(struct uvideo_unit
*vu
, const uvideo_descriptor_t
*desc
)
867 struct uvideo_camera_terminal
*ct
;
868 struct uvideo_processing_unit
*pu
;
869 struct uvideo_extension_unit
*xu
;
871 const uvideo_input_terminal_descriptor_t
*input
;
872 const uvideo_output_terminal_descriptor_t
*output
;
873 const uvideo_camera_terminal_descriptor_t
*camera
;
874 const uvideo_selector_unit_descriptor_t
*selector
;
875 const uvideo_processing_unit_descriptor_t
*processing
;
876 const uvideo_extension_unit_descriptor_t
*extension
;
878 memset(vu
, 0, sizeof(*vu
));
880 switch (desc
->bDescriptorSubtype
) {
881 case UDESC_INPUT_TERMINAL
:
882 input
= (const uvideo_input_terminal_descriptor_t
*)desc
;
883 switch (UGETW(input
->wTerminalType
)) {
884 case UVIDEO_ITT_CAMERA
:
886 (const uvideo_camera_terminal_descriptor_t
*)desc
;
887 ct
= &vu
->u
.vu_camera
;
889 ct
->ct_objective_focal_min
=
890 UGETW(camera
->wObjectiveFocalLengthMin
);
891 ct
->ct_objective_focal_max
=
892 UGETW(camera
->wObjectiveFocalLengthMax
);
893 ct
->ct_ocular_focal_length
=
894 UGETW(camera
->wOcularFocalLength
);
896 uvideo_unit_alloc_controls(vu
, camera
->bControlSize
,
900 DPRINTF(("uvideo_unit_init: "
901 "unknown input terminal type 0x%04x\n",
902 UGETW(input
->wTerminalType
)));
906 case UDESC_OUTPUT_TERMINAL
:
907 output
= (const uvideo_output_terminal_descriptor_t
*)desc
;
909 case UDESC_SELECTOR_UNIT
:
910 selector
= (const uvideo_selector_unit_descriptor_t
*)desc
;
912 uvideo_unit_alloc_sources(vu
, selector
->bNrInPins
,
913 selector
->baSourceID
);
915 case UDESC_PROCESSING_UNIT
:
916 processing
= (const uvideo_processing_unit_descriptor_t
*)desc
;
917 pu
= &vu
->u
.vu_processing
;
919 pu
->pu_video_standards
= PU_GET_VIDEO_STANDARDS(processing
);
920 pu
->pu_max_multiplier
= UGETW(processing
->wMaxMultiplier
);
922 uvideo_unit_alloc_sources(vu
, 1, &processing
->bSourceID
);
923 uvideo_unit_alloc_controls(vu
, processing
->bControlSize
,
924 processing
->bmControls
);
926 case UDESC_EXTENSION_UNIT
:
927 extension
= (const uvideo_extension_unit_descriptor_t
*)desc
;
928 xu
= &vu
->u
.vu_extension
;
929 /* TODO: copy guid */
931 uvideo_unit_alloc_sources(vu
, extension
->bNrInPins
,
932 extension
->baSourceID
);
933 uvideo_unit_alloc_controls(vu
, XU_GET_CONTROL_SIZE(extension
),
934 XU_GET_CONTROLS(extension
));
937 DPRINTF(("uvideo_unit_alloc: unknown descriptor "
938 "type=0x%02x subtype=0x%02x\n",
939 desc
->bDescriptorType
, desc
->bDescriptorSubtype
));
943 return USBD_NORMAL_COMPLETION
;
947 uvideo_unit_free(struct uvideo_unit
*vu
)
949 uvideo_unit_free_sources(vu
);
950 uvideo_unit_free_controls(vu
);
951 kmem_free(vu
, sizeof(*vu
));
955 uvideo_unit_alloc_sources(struct uvideo_unit
*vu
,
956 uint8_t nsrcs
, const uint8_t *src_ids
)
958 vu
->vu_nsrcs
= nsrcs
;
962 } else if (nsrcs
== 1) {
963 vu
->s
.vu_src_id
= src_ids
[0];
965 vu
->s
.vu_src_id_ary
=
966 kmem_alloc(sizeof(*vu
->s
.vu_src_id_ary
) * nsrcs
, KM_SLEEP
);
967 if (vu
->s
.vu_src_id_ary
== NULL
) {
972 memcpy(vu
->s
.vu_src_id_ary
, src_ids
, nsrcs
);
975 return USBD_NORMAL_COMPLETION
;
979 uvideo_unit_free_sources(struct uvideo_unit
*vu
)
981 if (vu
->vu_nsrcs
== 1)
984 kmem_free(vu
->s
.vu_src_id_ary
,
985 sizeof(*vu
->s
.vu_src_id_ary
) * vu
->vu_nsrcs
);
987 vu
->s
.vu_src_id_ary
= NULL
;
991 uvideo_unit_alloc_controls(struct uvideo_unit
*vu
, uint8_t size
,
992 const uint8_t *controls
)
994 vu
->vu_controls
= kmem_alloc(sizeof(*vu
->vu_controls
) * size
, KM_SLEEP
);
995 if (vu
->vu_controls
== NULL
)
998 vu
->vu_control_size
= size
;
999 memcpy(vu
->vu_controls
, controls
, size
);
1001 return USBD_NORMAL_COMPLETION
;
1005 uvideo_unit_free_controls(struct uvideo_unit
*vu
)
1007 kmem_free(vu
->vu_controls
,
1008 sizeof(*vu
->vu_controls
) * vu
->vu_control_size
);
1009 vu
->vu_controls
= NULL
;
1010 vu
->vu_control_size
= 0;
1014 /* Initialize a stream from a Video Streaming interface
1015 * descriptor. Adds the stream to the stream_list in uvideo_softc.
1016 * This should be called once for new streams, and
1017 * uvideo_stream_init_desc() should then be called for this and each
1018 * additional interface with the same interface number. */
1020 uvideo_stream_init(struct uvideo_stream
*vs
,
1021 struct uvideo_softc
*sc
,
1022 const usb_interface_descriptor_t
*ifdesc
,
1028 SLIST_INSERT_HEAD(&sc
->sc_stream_list
, vs
, entries
);
1029 memset(vs
, 0, sizeof(*vs
));
1031 vs
->vs_ifaceno
= ifdesc
->bInterfaceNumber
;
1033 SIMPLEQ_INIT(&vs
->vs_formats
);
1034 SIMPLEQ_INIT(&vs
->vs_pixel_formats
);
1035 vs
->vs_default_format
= NULL
;
1036 vs
->vs_current_format
.priv
= -1;
1037 vs
->vs_xfer_type
= 0;
1039 err
= usbd_device2interface_handle(sc
->sc_udev
, idx
, &vs
->vs_iface
);
1040 if (err
!= USBD_NORMAL_COMPLETION
) {
1041 DPRINTF(("uvideo_stream_init: "
1042 "error getting vs interface: "
1044 usbd_errstr(err
), err
));
1048 /* For Xbox Live Vision camera, linux-uvc folk say we need to
1049 * set an alternate interface and wait ~3 seconds prior to
1050 * doing the format probe/commit. We set to alternate
1051 * interface 0, which is the default, zero bandwidth
1052 * interface. This should not have adverse affects on other
1053 * cameras. Errors are ignored. */
1054 err
= usbd_set_interface(vs
->vs_iface
, 0);
1055 if (err
!= USBD_NORMAL_COMPLETION
) {
1056 DPRINTF(("uvideo_stream_init: error setting alt interface: "
1058 usbd_errstr(err
), err
));
1061 /* Initialize probe and commit data size. This value is
1062 * dependent on the version of the spec the hardware
1064 err
= uvideo_stream_probe(vs
, UR_GET_LEN
, &len
);
1065 if (err
!= USBD_NORMAL_COMPLETION
) {
1066 DPRINTF(("uvideo_stream_init: "
1067 "error getting probe data len: "
1069 usbd_errstr(err
), err
));
1070 vs
->vs_probelen
= 26; /* conservative v1.0 length */
1071 } else if (UGETW(len
) <= sizeof(uvideo_probe_and_commit_data_t
)) {
1072 DPRINTFN(15,("uvideo_stream_init: probelen=%d\n", UGETW(len
)));
1073 vs
->vs_probelen
= UGETW(len
);
1075 DPRINTFN(15,("uvideo_stream_init: device returned invalid probe"
1076 " len %d, using default\n", UGETW(len
)));
1077 vs
->vs_probelen
= 26;
1080 return USBD_NORMAL_COMPLETION
;
1083 /* Further stream initialization based on a Video Streaming interface
1084 * descriptor and following descriptors belonging to that interface.
1085 * Iterates through all descriptors belonging to this particular
1086 * interface descriptor, modifying the iterator. This may be called
1087 * multiple times because there may be several alternate interfaces
1088 * associated with the same interface number. */
1090 uvideo_stream_init_desc(struct uvideo_stream
*vs
,
1091 const usb_interface_descriptor_t
*ifdesc
,
1092 usbd_desc_iter_t
*iter
)
1094 const usb_descriptor_t
*desc
;
1095 const uvideo_descriptor_t
*uvdesc
;
1096 struct uvideo_bulk_xfer
*bx
;
1097 struct uvideo_isoc_xfer
*ix
;
1098 struct uvideo_alternate
*alt
;
1099 uint8_t xfer_type
, xfer_dir
;
1100 uint8_t bmAttributes
, bEndpointAddress
;
1103 /* Iterate until the next interface descriptor. All
1104 * descriptors until then belong to this streaming
1106 while ((desc
= usb_desc_iter_next_non_interface(iter
)) != NULL
) {
1107 uvdesc
= (const uvideo_descriptor_t
*)desc
;
1109 switch (uvdesc
->bDescriptorType
) {
1110 case UDESC_ENDPOINT
:
1111 bmAttributes
= GET(usb_endpoint_descriptor_t
,
1112 desc
, bmAttributes
);
1113 bEndpointAddress
= GET(usb_endpoint_descriptor_t
,
1114 desc
, bEndpointAddress
);
1115 xfer_type
= UE_GET_XFERTYPE(bmAttributes
);
1116 xfer_dir
= UE_GET_DIR(bEndpointAddress
);
1117 if (xfer_type
== UE_BULK
&& xfer_dir
== UE_DIR_IN
) {
1118 bx
= &vs
->vs_xfer
.bulk
;
1119 if (vs
->vs_xfer_type
== 0) {
1120 DPRINTFN(15, ("uvideo_attach: "
1121 "BULK stream *\n"));
1122 vs
->vs_xfer_type
= UE_BULK
;
1123 bx
->bx_endpt
= bEndpointAddress
;
1124 DPRINTF(("uvideo_attach: BULK "
1127 bx
->bx_running
= false;
1129 device_xname(vs
->vs_parent
->sc_dev
)
1131 mutex_init(&bx
->bx_lock
,
1132 MUTEX_DEFAULT
, IPL_NONE
);
1134 } else if (xfer_type
== UE_ISOCHRONOUS
) {
1135 ix
= &vs
->vs_xfer
.isoc
;
1136 for (i
= 0; i
< UVIDEO_NXFERS
; i
++) {
1137 ix
->ix_i
[i
].i_ix
= ix
;
1138 ix
->ix_i
[i
].i_vs
= vs
;
1140 if (vs
->vs_xfer_type
== 0) {
1141 DPRINTFN(15, ("uvideo_attach: "
1142 "ISOC stream *\n"));
1143 SLIST_INIT(&ix
->ix_altlist
);
1144 vs
->vs_xfer_type
= UE_ISOCHRONOUS
;
1146 GET(usb_endpoint_descriptor_t
,
1147 desc
, bEndpointAddress
);
1150 alt
= kmem_alloc(sizeof(*alt
), KM_NOSLEEP
);
1154 alt
->altno
= ifdesc
->bAlternateSetting
;
1156 GET(usb_endpoint_descriptor_t
,
1159 alt
->max_packet_size
=
1160 UE_GET_SIZE(UGETW(GET(usb_endpoint_descriptor_t
,
1161 desc
, wMaxPacketSize
)));
1162 alt
->max_packet_size
*=
1163 (UE_GET_TRANS(UGETW(GET(
1164 usb_endpoint_descriptor_t
, desc
,
1165 wMaxPacketSize
)))) + 1;
1167 SLIST_INSERT_HEAD(&ix
->ix_altlist
,
1171 case UDESC_CS_INTERFACE
:
1172 if (ifdesc
->bAlternateSetting
!= 0) {
1173 DPRINTF(("uvideo_stream_init_alternate: "
1174 "unexpected class-specific descriptor "
1175 "len=%d type=0x%02x subtype=0x%02x\n",
1177 uvdesc
->bDescriptorType
,
1178 uvdesc
->bDescriptorSubtype
));
1182 switch (uvdesc
->bDescriptorSubtype
) {
1183 case UDESC_VS_INPUT_HEADER
:
1184 vs
->vs_subtype
= UDESC_VS_INPUT_HEADER
;
1186 case UDESC_VS_OUTPUT_HEADER
:
1187 /* TODO: handle output stream */
1188 DPRINTF(("uvideo: VS output not implemented\n"));
1189 vs
->vs_subtype
= UDESC_VS_OUTPUT_HEADER
;
1191 case UDESC_VS_FORMAT_UNCOMPRESSED
:
1192 case UDESC_VS_FORMAT_FRAME_BASED
:
1193 case UDESC_VS_FORMAT_MJPEG
:
1194 uvideo_stream_init_frame_based_format(vs
,
1198 case UDESC_VS_FORMAT_MPEG2TS
:
1199 case UDESC_VS_FORMAT_DV
:
1200 case UDESC_VS_FORMAT_STREAM_BASED
:
1202 DPRINTF(("uvideo: unimplemented VS CS "
1203 "descriptor len=%d type=0x%02x "
1206 uvdesc
->bDescriptorType
,
1207 uvdesc
->bDescriptorSubtype
));
1212 DPRINTF(("uvideo_stream_init_desc: "
1213 "unknown descriptor "
1214 "len=%d type=0x%02x\n",
1216 uvdesc
->bDescriptorType
));
1221 return USBD_NORMAL_COMPLETION
;
1224 /* Finialize and free memory associated with this stream. */
1226 uvideo_stream_free(struct uvideo_stream
*vs
)
1228 struct uvideo_alternate
*alt
;
1229 struct uvideo_pixel_format
*pixel_format
;
1230 struct uvideo_format
*format
;
1232 /* free linked list of alternate interfaces */
1233 if (vs
->vs_xfer_type
== UE_ISOCHRONOUS
) {
1234 while (!SLIST_EMPTY(&vs
->vs_xfer
.isoc
.ix_altlist
)) {
1235 alt
= SLIST_FIRST(&vs
->vs_xfer
.isoc
.ix_altlist
);
1236 SLIST_REMOVE_HEAD(&vs
->vs_xfer
.isoc
.ix_altlist
,
1238 kmem_free(alt
, sizeof(*alt
));
1242 /* free linked-list of formats and pixel formats */
1243 while ((format
= SIMPLEQ_FIRST(&vs
->vs_formats
)) != NULL
) {
1244 SIMPLEQ_REMOVE_HEAD(&vs
->vs_formats
, entries
);
1245 kmem_free(format
, sizeof(struct uvideo_format
));
1247 while ((pixel_format
= SIMPLEQ_FIRST(&vs
->vs_pixel_formats
)) != NULL
) {
1248 SIMPLEQ_REMOVE_HEAD(&vs
->vs_pixel_formats
, entries
);
1249 kmem_free(pixel_format
, sizeof(struct uvideo_pixel_format
));
1252 kmem_free(vs
, sizeof(*vs
));
1257 uvideo_stream_init_frame_based_format(struct uvideo_stream
*vs
,
1258 const uvideo_descriptor_t
*format_desc
,
1259 usbd_desc_iter_t
*iter
)
1261 struct uvideo_pixel_format
*pformat
, *pfiter
;
1262 enum video_pixel_format pixel_format
;
1263 struct uvideo_format
*format
;
1264 const uvideo_descriptor_t
*uvdesc
;
1265 uint8_t subtype
, default_index
, index
;
1266 uint32_t frame_interval
;
1267 const usb_guid_t
*guid
;
1269 pixel_format
= VIDEO_FORMAT_UNDEFINED
;
1271 switch (format_desc
->bDescriptorSubtype
) {
1272 case UDESC_VS_FORMAT_UNCOMPRESSED
:
1273 subtype
= UDESC_VS_FRAME_UNCOMPRESSED
;
1274 default_index
= GET(uvideo_vs_format_uncompressed_descriptor_t
,
1276 bDefaultFrameIndex
);
1277 guid
= GETP(uvideo_vs_format_uncompressed_descriptor_t
,
1280 if (usb_guid_cmp(guid
, &uvideo_guid_format_yuy2
) == 0)
1281 pixel_format
= VIDEO_FORMAT_YUY2
;
1282 else if (usb_guid_cmp(guid
, &uvideo_guid_format_nv12
) == 0)
1283 pixel_format
= VIDEO_FORMAT_NV12
;
1284 else if (usb_guid_cmp(guid
, &uvideo_guid_format_uyvy
) == 0)
1285 pixel_format
= VIDEO_FORMAT_UYVY
;
1287 case UDESC_VS_FORMAT_FRAME_BASED
:
1288 subtype
= UDESC_VS_FRAME_FRAME_BASED
;
1289 default_index
= GET(uvideo_format_frame_based_descriptor_t
,
1291 bDefaultFrameIndex
);
1293 case UDESC_VS_FORMAT_MJPEG
:
1294 subtype
= UDESC_VS_FRAME_MJPEG
;
1295 default_index
= GET(uvideo_vs_format_mjpeg_descriptor_t
,
1297 bDefaultFrameIndex
);
1298 pixel_format
= VIDEO_FORMAT_MJPEG
;
1301 DPRINTF(("uvideo: unknown frame based format %d\n",
1302 format_desc
->bDescriptorSubtype
));
1307 SIMPLEQ_FOREACH(pfiter
, &vs
->vs_pixel_formats
, entries
) {
1308 if (pfiter
->pixel_format
== pixel_format
) {
1313 if (pixel_format
!= VIDEO_FORMAT_UNDEFINED
&& pformat
== NULL
) {
1314 pformat
= kmem_zalloc(sizeof(*pformat
), KM_SLEEP
);
1315 pformat
->pixel_format
= pixel_format
;
1316 DPRINTF(("uvideo: Adding pixel format %d\n",
1318 SIMPLEQ_INSERT_TAIL(&vs
->vs_pixel_formats
,
1322 /* Iterate through frame descriptors directly following the
1323 * format descriptor, and add a format to the format list for
1324 * each frame descriptor. */
1325 while ((uvdesc
= (const uvideo_descriptor_t
*) usb_desc_iter_peek_next(iter
)) &&
1326 (uvdesc
!= NULL
) && (uvdesc
->bDescriptorSubtype
== subtype
))
1328 uvdesc
= (const uvideo_descriptor_t
*) usb_desc_iter_next(iter
);
1330 format
= kmem_zalloc(sizeof(struct uvideo_format
), KM_SLEEP
);
1331 if (format
== NULL
) {
1332 DPRINTF(("uvideo: failed to alloc video format\n"));
1336 format
->format
.pixel_format
= pixel_format
;
1338 switch (format_desc
->bDescriptorSubtype
) {
1339 case UDESC_VS_FORMAT_UNCOMPRESSED
:
1341 if (pixel_format
== VIDEO_FORMAT_UNDEFINED
&&
1344 uvideo_vs_format_uncompressed_descriptor_t
,
1348 DPRINTF(("uvideo: format undefined "));
1349 usb_guid_print(guid
);
1354 UVIDEO_FORMAT_INIT_FRAME_BASED(
1355 uvideo_vs_format_uncompressed_descriptor_t
,
1357 uvideo_vs_frame_uncompressed_descriptor_t
,
1360 format
->format
.sample_size
=
1362 GET(uvideo_vs_frame_uncompressed_descriptor_t
,
1363 uvdesc
, dwMaxVideoFrameBufferSize
));
1364 format
->format
.stride
=
1365 format
->format
.sample_size
/ format
->format
.height
;
1366 index
= GET(uvideo_vs_frame_uncompressed_descriptor_t
,
1371 GET(uvideo_vs_frame_uncompressed_descriptor_t
,
1373 dwDefaultFrameInterval
));
1375 case UDESC_VS_FORMAT_MJPEG
:
1376 UVIDEO_FORMAT_INIT_FRAME_BASED(
1377 uvideo_vs_format_mjpeg_descriptor_t
,
1379 uvideo_vs_frame_mjpeg_descriptor_t
,
1382 format
->format
.sample_size
=
1384 GET(uvideo_vs_frame_mjpeg_descriptor_t
,
1385 uvdesc
, dwMaxVideoFrameBufferSize
));
1386 format
->format
.stride
=
1387 format
->format
.sample_size
/ format
->format
.height
;
1388 index
= GET(uvideo_vs_frame_mjpeg_descriptor_t
,
1393 GET(uvideo_vs_frame_mjpeg_descriptor_t
,
1395 dwDefaultFrameInterval
));
1397 case UDESC_VS_FORMAT_FRAME_BASED
:
1398 format
->format
.pixel_format
= VIDEO_FORMAT_UNDEFINED
;
1399 UVIDEO_FORMAT_INIT_FRAME_BASED(
1400 uvideo_format_frame_based_descriptor_t
,
1402 uvideo_frame_frame_based_descriptor_t
,
1405 index
= GET(uvideo_frame_frame_based_descriptor_t
,
1408 format
->format
.stride
=
1410 GET(uvideo_frame_frame_based_descriptor_t
,
1411 uvdesc
, dwBytesPerLine
));
1412 format
->format
.sample_size
=
1413 format
->format
.stride
* format
->format
.height
;
1416 GET(uvideo_frame_frame_based_descriptor_t
,
1417 uvdesc
, dwDefaultFrameInterval
));
1420 /* shouldn't ever get here */
1421 DPRINTF(("uvideo: unknown frame based format %d\n",
1422 format_desc
->bDescriptorSubtype
));
1423 kmem_free(format
, sizeof(struct uvideo_format
));
1427 DPRINTF(("uvideo: found format (index %d) type %d "
1428 "size %ux%u size %u stride %u interval %u\n",
1429 index
, format
->format
.pixel_format
, format
->format
.width
,
1430 format
->format
.height
, format
->format
.sample_size
,
1431 format
->format
.stride
, frame_interval
));
1433 SIMPLEQ_INSERT_TAIL(&vs
->vs_formats
, format
, entries
);
1435 if (vs
->vs_default_format
== NULL
&& index
== default_index
1436 #ifdef UVIDEO_DISABLE_MJPEG
1437 && subtype
!= UDESC_VS_FRAME_MJPEG
1440 DPRINTF((" ^ picking this one\n"));
1441 vs
->vs_default_format
= &format
->format
;
1442 vs
->vs_frame_interval
= frame_interval
;
1447 return USBD_NORMAL_COMPLETION
;
1451 uvideo_stream_start_xfer(struct uvideo_stream
*vs
)
1453 struct uvideo_softc
*sc
= vs
->vs_parent
;
1454 struct uvideo_bulk_xfer
*bx
;
1455 struct uvideo_isoc_xfer
*ix
;
1456 uint32_t vframe_len
; /* rough bytes per video frame */
1457 uint32_t uframe_len
; /* bytes per usb frame (TODO: or microframe?) */
1458 uint32_t nframes
; /* number of usb frames (TODO: or microframs?) */
1461 struct uvideo_alternate
*alt
, *alt_maybe
;
1464 switch (vs
->vs_xfer_type
) {
1467 bx
= &vs
->vs_xfer
.bulk
;
1469 bx
->bx_xfer
= usbd_alloc_xfer(sc
->sc_udev
);
1470 if (bx
->bx_xfer
== NULL
) {
1471 DPRINTF(("uvideo: couldn't allocate xfer\n"));
1474 DPRINTF(("uvideo: xfer %p\n", bx
->bx_xfer
));
1476 bx
->bx_buflen
= vs
->vs_max_payload_size
;
1478 DPRINTF(("uvideo: allocating %u byte buffer\n", bx
->bx_buflen
));
1479 bx
->bx_buffer
= usbd_alloc_buffer(bx
->bx_xfer
, bx
->bx_buflen
);
1481 if (bx
->bx_buffer
== NULL
) {
1482 DPRINTF(("uvideo: couldn't allocate buffer\n"));
1486 err
= usbd_open_pipe(vs
->vs_iface
, bx
->bx_endpt
, 0,
1488 if (err
!= USBD_NORMAL_COMPLETION
) {
1489 DPRINTF(("uvideo: error opening pipe: %s (%d)\n",
1490 usbd_errstr(err
), err
));
1493 DPRINTF(("uvideo: pipe %p\n", bx
->bx_pipe
));
1495 mutex_enter(&bx
->bx_lock
);
1496 if (bx
->bx_running
== false) {
1497 bx
->bx_running
= true;
1498 ret
= kthread_create(PRI_UVIDEO
, 0, NULL
,
1499 uvideo_stream_recv_bulk_transfer
, vs
,
1500 NULL
, device_xname(sc
->sc_dev
));
1502 DPRINTF(("uvideo: couldn't create kthread:"
1504 bx
->bx_running
= false;
1505 mutex_exit(&bx
->bx_lock
);
1509 aprint_error_dev(sc
->sc_dev
,
1510 "transfer already in progress\n");
1511 mutex_exit(&bx
->bx_lock
);
1513 DPRINTF(("uvideo: thread created\n"));
1516 case UE_ISOCHRONOUS
:
1517 ix
= &vs
->vs_xfer
.isoc
;
1519 /* Choose an alternate interface most suitable for
1520 * this format. Choose the smallest size that can
1521 * contain max_payload_size.
1523 * It is assumed that the list is sorted in descending
1524 * order from largest to smallest packet size.
1526 * TODO: what should the strategy be for choosing an
1530 SLIST_FOREACH(alt_maybe
, &ix
->ix_altlist
, entries
) {
1531 /* TODO: define "packet" and "payload". I think
1532 * several packets can make up one payload which would
1533 * call into question this method of selecting an
1534 * alternate interface... */
1536 if (alt_maybe
->max_packet_size
> vs
->vs_max_payload_size
)
1540 alt_maybe
->max_packet_size
>= alt
->max_packet_size
)
1545 DPRINTF(("uvideo_stream_start_xfer: "
1546 "no suitable alternate interface found\n"));
1550 DPRINTFN(15,("uvideo_stream_start_xfer: "
1551 "choosing alternate interface "
1552 "%d wMaxPacketSize=%d bInterval=%d\n",
1553 alt
->altno
, alt
->max_packet_size
, alt
->interval
));
1555 err
= usbd_set_interface(vs
->vs_iface
, alt
->altno
);
1556 if (err
!= USBD_NORMAL_COMPLETION
) {
1557 DPRINTF(("uvideo_stream_start_xfer: "
1558 "error setting alt interface: %s (%d)\n",
1559 usbd_errstr(err
), err
));
1563 /* TODO: "packet" not same as frame */
1564 vframe_len
= vs
->vs_current_format
.sample_size
;
1565 uframe_len
= alt
->max_packet_size
;
1566 nframes
= (vframe_len
+ uframe_len
- 1) / uframe_len
;
1567 nframes
= (nframes
+ 7) & ~7; /*round up for ehci inefficiency*/
1568 DPRINTF(("uvideo_stream_start_xfer: nframes=%d\n", nframes
));
1570 ix
->ix_nframes
= nframes
;
1571 ix
->ix_uframe_len
= uframe_len
;
1572 for (i
= 0; i
< UVIDEO_NXFERS
; i
++) {
1573 struct uvideo_isoc
*isoc
= &ix
->ix_i
[i
];
1575 kmem_alloc(sizeof(isoc
->i_frlengths
[0]) * nframes
,
1577 if (isoc
->i_frlengths
== NULL
) {
1578 DPRINTF(("uvideo: failed to alloc frlengths:"
1580 usbd_errstr(err
), err
));
1585 err
= usbd_open_pipe(vs
->vs_iface
, ix
->ix_endpt
,
1586 USBD_EXCLUSIVE_USE
, &ix
->ix_pipe
);
1587 if (err
!= USBD_NORMAL_COMPLETION
) {
1588 DPRINTF(("uvideo: error opening pipe: %s (%d)\n",
1589 usbd_errstr(err
), err
));
1593 for (i
= 0; i
< UVIDEO_NXFERS
; i
++) {
1594 struct uvideo_isoc
*isoc
= &ix
->ix_i
[i
];
1595 isoc
->i_xfer
= usbd_alloc_xfer(sc
->sc_udev
);
1596 if (isoc
->i_xfer
== NULL
) {
1597 DPRINTF(("uvideo: failed to alloc xfer: %s"
1599 usbd_errstr(err
), err
));
1603 isoc
->i_buf
= usbd_alloc_buffer(isoc
->i_xfer
,
1604 nframes
* uframe_len
);
1606 if (isoc
->i_buf
== NULL
) {
1607 DPRINTF(("uvideo: failed to alloc buf: %s"
1609 usbd_errstr(err
), err
));
1614 uvideo_stream_recv_isoc_start(vs
);
1618 /* should never get here */
1619 DPRINTF(("uvideo_stream_start_xfer: unknown xfer type 0x%x\n",
1626 uvideo_stream_stop_xfer(struct uvideo_stream
*vs
)
1628 struct uvideo_bulk_xfer
*bx
;
1629 struct uvideo_isoc_xfer
*ix
;
1633 switch (vs
->vs_xfer_type
) {
1635 bx
= &vs
->vs_xfer
.bulk
;
1637 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: "
1638 "waiting for thread to complete\n"));
1639 mutex_enter(&bx
->bx_lock
);
1640 if (bx
->bx_running
== true) {
1641 bx
->bx_running
= false;
1642 cv_wait_sig(&bx
->bx_cv
, &bx
->bx_lock
);
1644 mutex_exit(&bx
->bx_lock
);
1646 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: cleaning up\n"));
1649 usbd_abort_pipe(bx
->bx_pipe
);
1650 usbd_close_pipe(bx
->bx_pipe
);
1655 usbd_free_xfer(bx
->bx_xfer
);
1659 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: done\n"));
1662 case UE_ISOCHRONOUS
:
1663 ix
= &vs
->vs_xfer
.isoc
;
1664 if (ix
->ix_pipe
!= NULL
) {
1665 usbd_abort_pipe(ix
->ix_pipe
);
1666 usbd_close_pipe(ix
->ix_pipe
);
1670 for (i
= 0; i
< UVIDEO_NXFERS
; i
++) {
1671 struct uvideo_isoc
*isoc
= &ix
->ix_i
[i
];
1672 if (isoc
->i_xfer
!= NULL
) {
1673 usbd_free_buffer(isoc
->i_xfer
);
1674 usbd_free_xfer(isoc
->i_xfer
);
1675 isoc
->i_xfer
= NULL
;
1678 if (isoc
->i_frlengths
!= NULL
) {
1679 kmem_free(isoc
->i_frlengths
,
1680 sizeof(isoc
->i_frlengths
[0]) *
1682 isoc
->i_frlengths
= NULL
;
1686 /* Give it some time to settle */
1687 usbd_delay_ms(vs
->vs_parent
->sc_udev
, 1000);
1689 /* Set to zero bandwidth alternate interface zero */
1690 err
= usbd_set_interface(vs
->vs_iface
, 0);
1691 if (err
!= USBD_NORMAL_COMPLETION
) {
1692 DPRINTF(("uvideo_stream_stop_transfer: "
1693 "error setting zero bandwidth interface: "
1695 usbd_errstr(err
), err
));
1701 /* should never get here */
1702 DPRINTF(("uvideo_stream_stop_xfer: unknown xfer type 0x%x\n",
1709 uvideo_stream_recv_isoc_start(struct uvideo_stream
*vs
)
1713 for (i
= 0; i
< UVIDEO_NXFERS
; i
++)
1714 uvideo_stream_recv_isoc_start1(&vs
->vs_xfer
.isoc
.ix_i
[i
]);
1716 return USBD_NORMAL_COMPLETION
;
1719 /* Initiate a usb transfer. */
1721 uvideo_stream_recv_isoc_start1(struct uvideo_isoc
*isoc
)
1723 struct uvideo_isoc_xfer
*ix
;
1729 for (i
= 0; i
< ix
->ix_nframes
; ++i
)
1730 isoc
->i_frlengths
[i
] = ix
->ix_uframe_len
;
1732 usbd_setup_isoc_xfer(isoc
->i_xfer
,
1737 USBD_NO_COPY
| USBD_SHORT_XFER_OK
,
1738 uvideo_stream_recv_isoc_complete
);
1740 err
= usbd_transfer(isoc
->i_xfer
);
1741 if (err
!= USBD_IN_PROGRESS
) {
1742 DPRINTF(("uvideo_stream_recv_start: "
1743 "usbd_transfer status=%s (%d)\n",
1744 usbd_errstr(err
), err
));
1750 uvideo_stream_recv_process(struct uvideo_stream
*vs
, uint8_t *buf
, uint32_t len
)
1752 uvideo_payload_header_t
*hdr
;
1753 struct video_payload payload
;
1755 if (len
< sizeof(uvideo_payload_header_t
)) {
1756 DPRINTF(("uvideo_stream_recv_process: len %d < payload hdr\n",
1758 return USBD_SHORT_XFER
;
1761 hdr
= (uvideo_payload_header_t
*)buf
;
1763 if (hdr
->bHeaderLength
> UVIDEO_PAYLOAD_HEADER_SIZE
||
1764 hdr
->bHeaderLength
< sizeof(uvideo_payload_header_t
))
1766 if (hdr
->bHeaderLength
== len
&& !(hdr
->bmHeaderInfo
& UV_END_OF_FRAME
))
1768 if (hdr
->bmHeaderInfo
& UV_ERROR
)
1769 return USBD_IOERROR
;
1771 payload
.data
= buf
+ hdr
->bHeaderLength
;
1772 payload
.size
= len
- hdr
->bHeaderLength
;
1773 payload
.frameno
= hdr
->bmHeaderInfo
& UV_FRAME_ID
;
1774 payload
.end_of_frame
= hdr
->bmHeaderInfo
& UV_END_OF_FRAME
;
1776 video_submit_payload(vs
->vs_parent
->sc_videodev
, &payload
);
1778 return USBD_NORMAL_COMPLETION
;
1781 /* Callback on completion of usb isoc transfer */
1783 uvideo_stream_recv_isoc_complete(usbd_xfer_handle xfer
,
1784 usbd_private_handle priv
,
1787 struct uvideo_stream
*vs
;
1788 struct uvideo_isoc_xfer
*ix
;
1789 struct uvideo_isoc
*isoc
;
1792 const uvideo_payload_header_t
*hdr
;
1799 if (status
!= USBD_NORMAL_COMPLETION
) {
1800 DPRINTF(("uvideo_stream_recv_isoc_complete: status=%s (%d)\n",
1801 usbd_errstr(status
), status
));
1803 if (status
== USBD_STALLED
)
1804 usbd_clear_endpoint_stall_async(ix
->ix_pipe
);
1808 usbd_get_xfer_status(xfer
, NULL
, NULL
, &count
, NULL
);
1811 /* DPRINTF(("uvideo: zero length transfer\n")); */
1815 hdr
= (const uvideo_payload_header_t
*)isoc
->i_buf
;
1817 for (i
= 0, buf
= isoc
->i_buf
;
1819 ++i
, buf
+= ix
->ix_uframe_len
)
1821 status
= uvideo_stream_recv_process(vs
, buf
,
1822 isoc
->i_frlengths
[i
]);
1823 if (status
== USBD_IOERROR
)
1829 uvideo_stream_recv_isoc_start1(isoc
);
1833 uvideo_stream_recv_bulk_transfer(void *addr
)
1835 struct uvideo_stream
*vs
= addr
;
1836 struct uvideo_bulk_xfer
*bx
= &vs
->vs_xfer
.bulk
;
1840 DPRINTF(("uvideo_stream_recv_bulk_transfer: "
1841 "vs %p sc %p bx %p buffer %p\n", vs
, vs
->vs_parent
, bx
,
1844 while (bx
->bx_running
) {
1845 len
= bx
->bx_buflen
;
1846 err
= usbd_bulk_transfer(bx
->bx_xfer
, bx
->bx_pipe
,
1847 USBD_SHORT_XFER_OK
| USBD_NO_COPY
,
1849 bx
->bx_buffer
, &len
, "uvideorb");
1851 if (err
== USBD_NORMAL_COMPLETION
) {
1852 uvideo_stream_recv_process(vs
, bx
->bx_buffer
, len
);
1854 DPRINTF(("uvideo_stream_recv_bulk_transfer: %s\n",
1859 DPRINTF(("uvideo_stream_recv_bulk_transfer: notify complete\n"));
1861 mutex_enter(&bx
->bx_lock
);
1862 cv_broadcast(&bx
->bx_cv
);
1863 mutex_exit(&bx
->bx_lock
);
1865 DPRINTF(("uvideo_stream_recv_bulk_transfer: return\n"));
1871 * uvideo_open - probe and commit video format and start receiving
1875 uvideo_open(void *addr
, int flags
)
1877 struct uvideo_softc
*sc
;
1878 struct uvideo_stream
*vs
;
1879 struct video_format fmt
;
1882 vs
= sc
->sc_stream_in
;
1884 DPRINTF(("uvideo_open: sc=%p\n", sc
));
1888 /* XXX select default format */
1889 fmt
= *vs
->vs_default_format
;
1890 return uvideo_set_format(addr
, &fmt
);
1895 uvideo_close(void *addr
)
1897 struct uvideo_softc
*sc
;
1901 if (sc
->sc_state
!= UVIDEO_STATE_CLOSED
) {
1902 sc
->sc_state
= UVIDEO_STATE_CLOSED
;
1907 uvideo_get_devname(void *addr
)
1909 struct uvideo_softc
*sc
= addr
;
1910 return sc
->sc_devname
;
1914 uvideo_enum_format(void *addr
, uint32_t index
, struct video_format
*format
)
1916 struct uvideo_softc
*sc
= addr
;
1917 struct uvideo_stream
*vs
= sc
->sc_stream_in
;
1918 struct uvideo_pixel_format
*pixel_format
;
1925 SIMPLEQ_FOREACH(pixel_format
, &vs
->vs_pixel_formats
, entries
) {
1928 format
->pixel_format
= pixel_format
->pixel_format
;
1939 uvideo_get_format(void *addr
, struct video_format
*format
)
1941 struct uvideo_softc
*sc
= addr
;
1942 struct uvideo_stream
*vs
= sc
->sc_stream_in
;
1947 *format
= vs
->vs_current_format
;
1953 * uvideo_set_format - TODO: this is boken and does nothing
1956 uvideo_set_format(void *addr
, struct video_format
*format
)
1958 struct uvideo_softc
*sc
;
1959 struct uvideo_stream
*vs
;
1960 struct uvideo_format
*uvfmt
;
1961 uvideo_probe_and_commit_data_t probe
, maxprobe
;
1967 DPRINTF(("uvideo_set_format: sc=%p\n", sc
));
1971 vs
= sc
->sc_stream_in
;
1972 ifaceno
= vs
->vs_ifaceno
;
1974 uvfmt
= uvideo_stream_guess_format(vs
, format
->pixel_format
,
1975 format
->width
, format
->height
);
1976 if (uvfmt
== NULL
) {
1977 DPRINTF(("uvideo: uvideo_stream_guess_format couldn't find "
1978 "%dx%d format %d\n", format
->width
, format
->height
,
1979 format
->pixel_format
));
1983 uvideo_init_probe_data(&probe
);
1984 probe
.bFormatIndex
= UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt
);
1985 probe
.bFrameIndex
= UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt
);
1986 USETDW(probe
.dwFrameInterval
, vs
->vs_frame_interval
); /* XXX */
1989 err
= uvideo_stream_probe(vs
, UR_GET_MAX
, &maxprobe
);
1991 DPRINTF(("uvideo: error probe/GET_MAX: %s (%d)\n",
1992 usbd_errstr(err
), err
));
1994 USETW(probe
.wCompQuality
, UGETW(maxprobe
.wCompQuality
));
1997 err
= uvideo_stream_probe(vs
, UR_SET_CUR
, &probe
);
1999 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n",
2000 usbd_errstr(err
), err
));
2004 uvideo_init_probe_data(&probe
);
2005 err
= uvideo_stream_probe(vs
, UR_GET_CUR
, &probe
);
2007 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n",
2008 usbd_errstr(err
), err
));
2012 if (probe
.bFormatIndex
!= UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt
)) {
2013 DPRINTF(("uvideo: probe/GET_CUR returned format index %d "
2014 "(expected %d)\n", probe
.bFormatIndex
,
2015 UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt
)));
2016 probe
.bFormatIndex
= UVIDEO_FORMAT_GET_FORMAT_INDEX(uvfmt
);
2018 if (probe
.bFrameIndex
!= UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt
)) {
2019 DPRINTF(("uvideo: probe/GET_CUR returned frame index %d "
2020 "(expected %d)\n", probe
.bFrameIndex
,
2021 UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt
)));
2022 probe
.bFrameIndex
= UVIDEO_FORMAT_GET_FRAME_INDEX(uvfmt
);
2024 USETDW(probe
.dwFrameInterval
, vs
->vs_frame_interval
); /* XXX */
2026 /* commit/SET_CUR. Fourth step is to set the alternate
2027 * interface. Currently the fourth step is in
2028 * uvideo_start_transfer. Maybe move it here? */
2029 err
= uvideo_stream_commit(vs
, UR_SET_CUR
, &probe
);
2031 DPRINTF(("uvideo: error commit/SET_CUR: %s (%d)\n",
2032 usbd_errstr(err
), err
));
2036 DPRINTFN(15, ("uvideo_set_format: committing to format: "
2037 "bmHint=0x%04x bFormatIndex=%d bFrameIndex=%d "
2038 "dwFrameInterval=%u wKeyFrameRate=%d wPFrameRate=%d "
2039 "wCompQuality=%d wCompWindowSize=%d wDelay=%d "
2040 "dwMaxVideoFrameSize=%u dwMaxPayloadTransferSize=%u",
2041 UGETW(probe
.bmHint
),
2044 UGETDW(probe
.dwFrameInterval
),
2045 UGETW(probe
.wKeyFrameRate
),
2046 UGETW(probe
.wPFrameRate
),
2047 UGETW(probe
.wCompQuality
),
2048 UGETW(probe
.wCompWindowSize
),
2049 UGETW(probe
.wDelay
),
2050 UGETDW(probe
.dwMaxVideoFrameSize
),
2051 UGETDW(probe
.dwMaxPayloadTransferSize
)));
2052 if (vs
->vs_probelen
== 34) {
2053 DPRINTFN(15, (" dwClockFrequency=%u bmFramingInfo=0x%02x "
2054 "bPreferedVersion=%d bMinVersion=%d "
2056 UGETDW(probe
.dwClockFrequency
),
2057 probe
.bmFramingInfo
,
2058 probe
.bPreferedVersion
,
2060 probe
.bMaxVersion
));
2062 DPRINTFN(15, ("\n"));
2064 vs
->vs_frame_interval
= UGETDW(probe
.dwFrameInterval
);
2065 vs
->vs_max_payload_size
= UGETDW(probe
.dwMaxPayloadTransferSize
);
2067 *format
= uvfmt
->format
;
2068 vs
->vs_current_format
= *format
;
2069 DPRINTF(("uvideo_set_format: pixeltype is %d\n", format
->pixel_format
));
2075 uvideo_try_format(void *addr
, struct video_format
*format
)
2077 struct uvideo_softc
*sc
= addr
;
2078 struct uvideo_stream
*vs
= sc
->sc_stream_in
;
2079 struct uvideo_format
*uvfmt
;
2081 uvfmt
= uvideo_stream_guess_format(vs
, format
->pixel_format
,
2082 format
->width
, format
->height
);
2086 *format
= uvfmt
->format
;
2091 uvideo_start_transfer(void *addr
)
2093 struct uvideo_softc
*sc
= addr
;
2094 struct uvideo_stream
*vs
;
2097 /* FIXME: this functions should be stream specific */
2098 vs
= SLIST_FIRST(&sc
->sc_stream_list
);
2100 err
= uvideo_stream_start_xfer(vs
);
2107 uvideo_stop_transfer(void *addr
)
2109 struct uvideo_softc
*sc
;
2115 err
= uvideo_stream_stop_xfer(sc
->sc_stream_in
);
2123 uvideo_get_control_group(void *addr
, struct video_control_group
*group
)
2125 struct uvideo_softc
*sc
;
2126 usb_device_request_t req
;
2128 uint8_t control_id
, ent_id
, data
[16];
2135 switch (group
->group_id
) {
2136 case VIDEO_CONTROL_PANTILT_RELATIVE
:
2137 if (group
->length
!= 4)
2141 case VIDEO_CONTROL_SHARPNESS
:
2142 if (group
->length
!= 1)
2145 control_id
= UVIDEO_PU_SHARPNESS_CONTROL
;
2146 ent_id
= 2; /* TODO: hardcoded logitech processing unit */
2154 req
.bmRequestType
= UVIDEO_REQUEST_TYPE_INTERFACE
|
2155 UVIDEO_REQUEST_TYPE_CLASS_SPECIFIC
|
2156 UVIDEO_REQUEST_TYPE_GET
;
2157 req
.bRequest
= UR_GET_CUR
;
2158 USETW(req
.wValue
, control_id
<< 8);
2159 USETW(req
.wIndex
, (ent_id
<< 8) | sc
->sc_ifaceno
);
2160 USETW(req
.wLength
, len
);
2163 err
= usbd_do_request(sc
->sc_udev
, &req
, data
);
2165 if (err
!= USBD_NORMAL_COMPLETION
) {
2166 DPRINTF(("uvideo_set_control: error %s (%d)\n",
2167 usbd_errstr(err
), err
));
2168 return EIO
; /* TODO: more detail here? */
2171 /* extract request data */
2172 switch (group
->group_id
) {
2173 case VIDEO_CONTROL_SHARPNESS
:
2174 group
->control
[0].value
= UGETW(data
);
2185 uvideo_set_control_group(void *addr
, const struct video_control_group
*group
)
2187 struct uvideo_softc
*sc
;
2188 usb_device_request_t req
;
2190 uint8_t control_id
, ent_id
, data
[16]; /* long enough for all controls */
2196 switch (group
->group_id
) {
2197 case VIDEO_CONTROL_PANTILT_RELATIVE
:
2198 if (group
->length
!= 4)
2201 if (group
->control
[0].value
!= 0 ||
2202 group
->control
[0].value
!= 1 ||
2203 group
->control
[0].value
!= 0xff)
2206 if (group
->control
[2].value
!= 0 ||
2207 group
->control
[2].value
!= 1 ||
2208 group
->control
[2].value
!= 0xff)
2211 control_id
= UVIDEO_CT_PANTILT_RELATIVE_CONTROL
;
2212 ent_id
= 1; /* TODO: hardcoded logitech camera terminal */
2214 data
[0] = group
->control
[0].value
;
2215 data
[1] = group
->control
[1].value
;
2216 data
[2] = group
->control
[2].value
;
2217 data
[3] = group
->control
[3].value
;
2219 case VIDEO_CONTROL_BRIGHTNESS
:
2220 if (group
->length
!= 1)
2222 control_id
= UVIDEO_PU_BRIGHTNESS_CONTROL
;
2225 USETW(data
, group
->control
[0].value
);
2227 case VIDEO_CONTROL_GAIN
:
2228 if (group
->length
!= 1)
2230 control_id
= UVIDEO_PU_GAIN_CONTROL
;
2233 USETW(data
, group
->control
[0].value
);
2235 case VIDEO_CONTROL_SHARPNESS
:
2236 if (group
->length
!= 1)
2238 control_id
= UVIDEO_PU_SHARPNESS_CONTROL
;
2239 ent_id
= 2; /* TODO: hardcoded logitech processing unit */
2241 USETW(data
, group
->control
[0].value
);
2247 req
.bmRequestType
= UVIDEO_REQUEST_TYPE_INTERFACE
|
2248 UVIDEO_REQUEST_TYPE_CLASS_SPECIFIC
|
2249 UVIDEO_REQUEST_TYPE_SET
;
2250 req
.bRequest
= UR_SET_CUR
;
2251 USETW(req
.wValue
, control_id
<< 8);
2252 USETW(req
.wIndex
, (ent_id
<< 8) | sc
->sc_ifaceno
);
2253 USETW(req
.wLength
, len
);
2256 err
= usbd_do_request(sc
->sc_udev
, &req
, data
);
2258 if (err
!= USBD_NORMAL_COMPLETION
) {
2259 DPRINTF(("uvideo_set_control: error %s (%d)\n",
2260 usbd_errstr(err
), err
));
2261 return EIO
; /* TODO: more detail here? */
2268 uvideo_stream_probe_and_commit(struct uvideo_stream
*vs
,
2269 uint8_t action
, uint8_t control
,
2272 usb_device_request_t req
;
2276 req
.bmRequestType
= UT_WRITE_CLASS_INTERFACE
;
2277 USETW(req
.wLength
, vs
->vs_probelen
);
2283 req
.bmRequestType
= UT_READ_CLASS_INTERFACE
;
2284 USETW(req
.wLength
, vs
->vs_probelen
);
2287 req
.bmRequestType
= UT_READ_CLASS_INTERFACE
;
2288 USETW(req
.wLength
, sizeof(uByte
));
2291 req
.bmRequestType
= UT_READ_CLASS_INTERFACE
;
2292 USETW(req
.wLength
, sizeof(uWord
)); /* is this right? */
2295 DPRINTF(("uvideo_probe_and_commit: "
2296 "unknown request action %d\n", action
));
2297 return USBD_NOT_STARTED
;
2300 req
.bRequest
= action
;
2301 USETW2(req
.wValue
, control
, 0);
2302 USETW2(req
.wIndex
, 0, vs
->vs_ifaceno
);
2304 return (usbd_do_request_flags(vs
->vs_parent
->sc_udev
, &req
, data
,
2306 USBD_DEFAULT_TIMEOUT
));
2310 uvideo_init_probe_data(uvideo_probe_and_commit_data_t
*probe
)
2312 /* all zeroes tells camera to choose what it wants */
2313 memset(probe
, 0, sizeof(*probe
));
2319 MODULE(MODULE_CLASS_DRIVER
, uvideo
, NULL
);
2320 static const struct cfiattrdata videobuscf_iattrdata
= {
2325 static const struct cfiattrdata
* const uvideo_attrs
[] = {
2326 &videobuscf_iattrdata
, NULL
2328 CFDRIVER_DECL(uvideo
, DV_DULL
, uvideo_attrs
);
2329 extern struct cfattach uvideo_ca
;
2330 extern struct cfattach uvideo_ca
;
2331 static int uvideoloc
[6] = { -1, -1, -1, -1, -1, -1 };
2332 static struct cfparent uhubparent
= {
2333 "usbifif", NULL
, DVUNIT_ANY
2335 static struct cfdata uvideo_cfdata
[] = {
2337 .cf_name
= "uvideo",
2338 .cf_atname
= "uvideo",
2340 .cf_fstate
= FSTATE_STAR
,
2341 .cf_loc
= uvideoloc
,
2343 .cf_pspec
= &uhubparent
,
2349 uvideo_modcmd(modcmd_t cmd
, void *arg
)
2355 case MODULE_CMD_INIT
:
2356 DPRINTF(("uvideo: attempting to load\n"));
2358 err
= config_cfdriver_attach(&uvideo_cd
);
2361 err
= config_cfattach_attach("uvideo", &uvideo_ca
);
2363 config_cfdriver_detach(&uvideo_cd
);
2366 err
= config_cfdata_attach(uvideo_cfdata
, 1);
2368 config_cfattach_detach("uvideo", &uvideo_ca
);
2369 config_cfdriver_detach(&uvideo_cd
);
2372 DPRINTF(("uvideo: loaded module\n"));
2374 case MODULE_CMD_FINI
:
2375 DPRINTF(("uvideo: attempting to unload module\n"));
2376 err
= config_cfdata_detach(uvideo_cfdata
);
2379 config_cfattach_detach("uvideo", &uvideo_ca
);
2380 config_cfdriver_detach(&uvideo_cd
);
2381 DPRINTF(("uvideo: module unload\n"));
2388 #endif /* _MODULE */
2392 /* Some functions to print out descriptors. Mostly useless other than
2393 * debugging/exploration purposes. */
2397 print_bitmap(const uByte
*start
, uByte nbytes
)
2401 /* most significant first */
2402 for (byte
= nbytes
-1; byte
>= 0; --byte
) {
2403 if (byte
< nbytes
-1) printf("-");
2404 for (bit
= 7; bit
>= 0; --bit
)
2405 printf("%01d", (start
[byte
] >> bit
) &1);
2410 print_descriptor(const usb_descriptor_t
*desc
)
2412 static int current_class
= -1;
2413 static int current_subclass
= -1;
2415 if (desc
->bDescriptorType
== UDESC_INTERFACE
) {
2416 const usb_interface_descriptor_t
*id
;
2417 id
= (const usb_interface_descriptor_t
*)desc
;
2418 current_class
= id
->bInterfaceClass
;
2419 current_subclass
= id
->bInterfaceSubClass
;
2420 print_interface_descriptor(id
);
2425 printf(" "); /* indent */
2427 if (current_class
== UICLASS_VIDEO
) {
2428 switch (current_subclass
) {
2429 case UISUBCLASS_VIDEOCONTROL
:
2430 print_vc_descriptor(desc
);
2432 case UISUBCLASS_VIDEOSTREAMING
:
2433 print_vs_descriptor(desc
);
2435 case UISUBCLASS_VIDEOCOLLECTION
:
2436 printf("uvc collection: len=%d type=0x%02x",
2437 desc
->bLength
, desc
->bDescriptorType
);
2441 printf("non uvc descriptor len=%d type=0x%02x",
2442 desc
->bLength
, desc
->bDescriptorType
);
2449 print_vc_descriptor(const usb_descriptor_t
*desc
)
2451 const uvideo_descriptor_t
*vcdesc
;
2455 switch (desc
->bDescriptorType
) {
2456 case UDESC_ENDPOINT
:
2457 print_endpoint_descriptor(
2458 (const usb_endpoint_descriptor_t
*)desc
);
2460 case UDESC_CS_INTERFACE
:
2461 vcdesc
= (const uvideo_descriptor_t
*)desc
;
2462 switch (vcdesc
->bDescriptorSubtype
) {
2463 case UDESC_VC_HEADER
:
2464 print_vc_header_descriptor(
2465 (const uvideo_vc_header_descriptor_t
*)
2468 case UDESC_INPUT_TERMINAL
:
2470 ((const uvideo_input_terminal_descriptor_t
*)
2471 vcdesc
)->wTerminalType
)) {
2472 case UVIDEO_ITT_CAMERA
:
2473 print_camera_terminal_descriptor(
2474 (const uvideo_camera_terminal_descriptor_t
*)vcdesc
);
2477 print_input_terminal_descriptor(
2478 (const uvideo_input_terminal_descriptor_t
*)vcdesc
);
2482 case UDESC_OUTPUT_TERMINAL
:
2483 print_output_terminal_descriptor(
2484 (const uvideo_output_terminal_descriptor_t
*)
2487 case UDESC_SELECTOR_UNIT
:
2488 print_selector_unit_descriptor(
2489 (const uvideo_selector_unit_descriptor_t
*)
2492 case UDESC_PROCESSING_UNIT
:
2493 print_processing_unit_descriptor(
2494 (const uvideo_processing_unit_descriptor_t
*)
2497 case UDESC_EXTENSION_UNIT
:
2498 print_extension_unit_descriptor(
2499 (const uvideo_extension_unit_descriptor_t
*)
2503 printf("class specific interface "
2504 "len=%d type=0x%02x subtype=0x%02x",
2506 vcdesc
->bDescriptorType
,
2507 vcdesc
->bDescriptorSubtype
);
2511 case UDESC_CS_ENDPOINT
:
2512 vcdesc
= (const uvideo_descriptor_t
*)desc
;
2513 switch (vcdesc
->bDescriptorSubtype
) {
2514 case UDESC_VC_INTERRUPT_ENDPOINT
:
2515 print_interrupt_endpoint_descriptor(
2516 (const uvideo_vc_interrupt_endpoint_descriptor_t
*)
2520 printf("class specific endpoint "
2521 "len=%d type=0x%02x subtype=0x%02x",
2523 vcdesc
->bDescriptorType
,
2524 vcdesc
->bDescriptorSubtype
);
2529 printf("unknown: len=%d type=0x%02x",
2530 desc
->bLength
, desc
->bDescriptorType
);
2536 print_vs_descriptor(const usb_descriptor_t
*desc
)
2538 const uvideo_descriptor_t
* vsdesc
;
2541 switch (desc
->bDescriptorType
) {
2542 case UDESC_ENDPOINT
:
2543 print_endpoint_descriptor(
2544 (const usb_endpoint_descriptor_t
*)desc
);
2546 case UDESC_CS_INTERFACE
:
2547 vsdesc
= (const uvideo_descriptor_t
*)desc
;
2548 switch (vsdesc
->bDescriptorSubtype
) {
2549 case UDESC_VS_INPUT_HEADER
:
2550 print_vs_input_header_descriptor(
2551 (const uvideo_vs_input_header_descriptor_t
*)
2554 case UDESC_VS_OUTPUT_HEADER
:
2555 print_vs_output_header_descriptor(
2556 (const uvideo_vs_output_header_descriptor_t
*)
2559 case UDESC_VS_FORMAT_UNCOMPRESSED
:
2560 print_vs_format_uncompressed_descriptor(
2561 (const uvideo_vs_format_uncompressed_descriptor_t
*)
2564 case UDESC_VS_FRAME_UNCOMPRESSED
:
2565 print_vs_frame_uncompressed_descriptor(
2566 (const uvideo_vs_frame_uncompressed_descriptor_t
*)
2569 case UDESC_VS_FORMAT_MJPEG
:
2570 print_vs_format_mjpeg_descriptor(
2571 (const uvideo_vs_format_mjpeg_descriptor_t
*)
2574 case UDESC_VS_FRAME_MJPEG
:
2575 print_vs_frame_mjpeg_descriptor(
2576 (const uvideo_vs_frame_mjpeg_descriptor_t
*)
2579 case UDESC_VS_FORMAT_DV
:
2580 print_vs_format_dv_descriptor(
2581 (const uvideo_vs_format_dv_descriptor_t
*)
2585 printf("unknown cs interface: len=%d type=0x%02x "
2587 vsdesc
->bLength
, vsdesc
->bDescriptorType
,
2588 vsdesc
->bDescriptorSubtype
);
2592 printf("unknown: len=%d type=0x%02x",
2593 desc
->bLength
, desc
->bDescriptorType
);
2599 print_interface_descriptor(const usb_interface_descriptor_t
*id
)
2601 printf("Interface: Len=%d Type=0x%02x "
2602 "bInterfaceNumber=0x%02x "
2603 "bAlternateSetting=0x%02x bNumEndpoints=0x%02x "
2604 "bInterfaceClass=0x%02x bInterfaceSubClass=0x%02x "
2605 "bInterfaceProtocol=0x%02x iInterface=0x%02x",
2607 id
->bDescriptorType
,
2608 id
->bInterfaceNumber
,
2609 id
->bAlternateSetting
,
2611 id
->bInterfaceClass
,
2612 id
->bInterfaceSubClass
,
2613 id
->bInterfaceProtocol
,
2618 print_endpoint_descriptor(const usb_endpoint_descriptor_t
*desc
)
2620 printf("Endpoint: Len=%d Type=0x%02x "
2621 "bEndpointAddress=0x%02x ",
2623 desc
->bDescriptorType
,
2624 desc
->bEndpointAddress
);
2625 printf("bmAttributes=");
2626 print_bitmap(&desc
->bmAttributes
, 1);
2627 printf(" wMaxPacketSize=%d bInterval=%d",
2628 UGETW(desc
->wMaxPacketSize
),
2633 print_vc_header_descriptor(
2634 const uvideo_vc_header_descriptor_t
*desc
)
2636 printf("Interface Header: "
2637 "Len=%d Type=0x%02x Subtype=0x%02x "
2638 "bcdUVC=%d wTotalLength=%d "
2639 "dwClockFrequency=%u bInCollection=%d",
2641 desc
->bDescriptorType
,
2642 desc
->bDescriptorSubtype
,
2643 UGETW(desc
->bcdUVC
),
2644 UGETW(desc
->wTotalLength
),
2645 UGETDW(desc
->dwClockFrequency
),
2646 desc
->bInCollection
);
2650 print_input_terminal_descriptor(
2651 const uvideo_input_terminal_descriptor_t
*desc
)
2653 printf("Input Terminal: "
2654 "Len=%d Type=0x%02x Subtype=0x%02x "
2655 "bTerminalID=%d wTerminalType=%x bAssocTerminal=%d "
2658 desc
->bDescriptorType
,
2659 desc
->bDescriptorSubtype
,
2661 UGETW(desc
->wTerminalType
),
2662 desc
->bAssocTerminal
,
2667 print_output_terminal_descriptor(
2668 const uvideo_output_terminal_descriptor_t
*desc
)
2670 printf("Output Terminal: "
2671 "Len=%d Type=0x%02x Subtype=0x%02x "
2672 "bTerminalID=%d wTerminalType=%x bAssocTerminal=%d "
2673 "bSourceID=%d iTerminal=%d",
2675 desc
->bDescriptorType
,
2676 desc
->bDescriptorSubtype
,
2678 UGETW(desc
->wTerminalType
),
2679 desc
->bAssocTerminal
,
2685 print_camera_terminal_descriptor(
2686 const uvideo_camera_terminal_descriptor_t
*desc
)
2688 printf("Camera Terminal: "
2689 "Len=%d Type=0x%02x Subtype=0x%02x "
2690 "bTerminalID=%d wTerminalType=%x bAssocTerminal=%d "
2692 "wObjectiveFocalLengthMin/Max=%d/%d "
2693 "wOcularFocalLength=%d "
2696 desc
->bDescriptorType
,
2697 desc
->bDescriptorSubtype
,
2699 UGETW(desc
->wTerminalType
),
2700 desc
->bAssocTerminal
,
2702 UGETW(desc
->wObjectiveFocalLengthMin
),
2703 UGETW(desc
->wObjectiveFocalLengthMax
),
2704 UGETW(desc
->wOcularFocalLength
),
2705 desc
->bControlSize
);
2706 printf("bmControls=");
2707 print_bitmap(desc
->bmControls
, desc
->bControlSize
);
2711 print_selector_unit_descriptor(
2712 const uvideo_selector_unit_descriptor_t
*desc
)
2716 printf("Selector Unit: "
2717 "Len=%d Type=0x%02x Subtype=0x%02x "
2718 "bUnitID=%d bNrInPins=%d ",
2720 desc
->bDescriptorType
,
2721 desc
->bDescriptorSubtype
,
2724 printf("baSourceIDs=");
2725 b
= &desc
->baSourceID
[0];
2726 for (i
= 0; i
< desc
->bNrInPins
; ++i
)
2727 printf("%d ", *b
++);
2728 printf("iSelector=%d", *b
);
2732 print_processing_unit_descriptor(
2733 const uvideo_processing_unit_descriptor_t
*desc
)
2737 printf("Processing Unit: "
2738 "Len=%d Type=0x%02x Subtype=0x%02x "
2739 "bUnitID=%d bSourceID=%d wMaxMultiplier=%d bControlSize=%d ",
2741 desc
->bDescriptorType
,
2742 desc
->bDescriptorSubtype
,
2745 UGETW(desc
->wMaxMultiplier
),
2746 desc
->bControlSize
);
2747 printf("bmControls=");
2748 print_bitmap(desc
->bmControls
, desc
->bControlSize
);
2749 b
= &desc
->bControlSize
+ desc
->bControlSize
+ 1;
2750 printf(" iProcessing=%d bmVideoStandards=", *b
);
2756 print_extension_unit_descriptor(
2757 const uvideo_extension_unit_descriptor_t
*desc
)
2763 printf("Extension Unit: "
2764 "Len=%d Type=0x%02x Subtype=0x%02x "
2767 desc
->bDescriptorType
,
2768 desc
->bDescriptorSubtype
,
2771 printf("guidExtensionCode=");
2772 usb_guid_print(&desc
->guidExtensionCode
);
2775 printf("bNumControls=%d bNrInPins=%d ",
2779 printf("baSourceIDs=");
2780 byte
= &desc
->baSourceID
[0];
2781 for (i
= 0; i
< desc
->bNrInPins
; ++i
)
2782 printf("%d ", *byte
++);
2784 controlbytes
= *byte
++;
2785 printf("bControlSize=%d ", controlbytes
);
2786 printf("bmControls=");
2787 print_bitmap(byte
, controlbytes
);
2789 byte
+= controlbytes
;
2790 printf(" iExtension=%d", *byte
);
2794 print_interrupt_endpoint_descriptor(
2795 const uvideo_vc_interrupt_endpoint_descriptor_t
*desc
)
2797 printf("Interrupt Endpoint: "
2798 "Len=%d Type=0x%02x Subtype=0x%02x "
2799 "wMaxTransferSize=%d ",
2801 desc
->bDescriptorType
,
2802 desc
->bDescriptorSubtype
,
2803 UGETW(desc
->wMaxTransferSize
));
2808 print_vs_output_header_descriptor(
2809 const uvideo_vs_output_header_descriptor_t
*desc
)
2811 printf("Interface Output Header: "
2812 "Len=%d Type=0x%02x Subtype=0x%02x "
2813 "bNumFormats=%d wTotalLength=%d bEndpointAddress=%d "
2814 "bTerminalLink=%d bControlSize=%d",
2816 desc
->bDescriptorType
,
2817 desc
->bDescriptorSubtype
,
2819 UGETW(desc
->wTotalLength
),
2820 desc
->bEndpointAddress
,
2821 desc
->bTerminalLink
,
2822 desc
->bControlSize
);
2826 print_vs_input_header_descriptor(
2827 const uvideo_vs_input_header_descriptor_t
*desc
)
2829 printf("Interface Input Header: "
2830 "Len=%d Type=0x%02x Subtype=0x%02x "
2831 "bNumFormats=%d wTotalLength=%d bEndpointAddress=%d "
2832 "bmInfo=%x bTerminalLink=%d bStillCaptureMethod=%d "
2833 "bTriggerSupport=%d bTriggerUsage=%d bControlSize=%d ",
2835 desc
->bDescriptorType
,
2836 desc
->bDescriptorSubtype
,
2838 UGETW(desc
->wTotalLength
),
2839 desc
->bEndpointAddress
,
2841 desc
->bTerminalLink
,
2842 desc
->bStillCaptureMethod
,
2843 desc
->bTriggerSupport
,
2844 desc
->bTriggerUsage
,
2845 desc
->bControlSize
);
2846 print_bitmap(desc
->bmaControls
, desc
->bControlSize
);
2850 print_vs_format_uncompressed_descriptor(
2851 const uvideo_vs_format_uncompressed_descriptor_t
*desc
)
2853 printf("Format Uncompressed: "
2854 "Len=%d Type=0x%02x Subtype=0x%02x "
2855 "bFormatIndex=%d bNumFrameDescriptors=%d ",
2857 desc
->bDescriptorType
,
2858 desc
->bDescriptorSubtype
,
2860 desc
->bNumFrameDescriptors
);
2861 usb_guid_print(&desc
->guidFormat
);
2862 printf(" bBitsPerPixel=%d bDefaultFrameIndex=%d "
2863 "bAspectRatioX=%d bAspectRatioY=%d "
2864 "bmInterlaceFlags=0x%02x bCopyProtect=%d",
2865 desc
->bBitsPerPixel
,
2866 desc
->bDefaultFrameIndex
,
2867 desc
->bAspectRatioX
,
2868 desc
->bAspectRatioY
,
2869 desc
->bmInterlaceFlags
,
2870 desc
->bCopyProtect
);
2874 print_vs_frame_uncompressed_descriptor(
2875 const uvideo_vs_frame_uncompressed_descriptor_t
*desc
)
2877 printf("Frame Uncompressed: "
2878 "Len=%d Type=0x%02x Subtype=0x%02x "
2879 "bFrameIndex=%d bmCapabilities=0x%02x "
2880 "wWidth=%d wHeight=%d dwMinBitRate=%u dwMaxBitRate=%u "
2881 "dwMaxVideoFrameBufferSize=%u dwDefaultFrameInterval=%u "
2882 "bFrameIntervalType=%d",
2884 desc
->bDescriptorType
,
2885 desc
->bDescriptorSubtype
,
2887 desc
->bmCapabilities
,
2888 UGETW(desc
->wWidth
),
2889 UGETW(desc
->wHeight
),
2890 UGETDW(desc
->dwMinBitRate
),
2891 UGETDW(desc
->dwMaxBitRate
),
2892 UGETDW(desc
->dwMaxVideoFrameBufferSize
),
2893 UGETDW(desc
->dwDefaultFrameInterval
),
2894 desc
->bFrameIntervalType
);
2898 print_vs_format_mjpeg_descriptor(
2899 const uvideo_vs_format_mjpeg_descriptor_t
*desc
)
2901 printf("MJPEG format: "
2902 "Len=%d Type=0x%02x Subtype=0x%02x "
2903 "bFormatIndex=%d bNumFrameDescriptors=%d bmFlags=0x%02x "
2904 "bDefaultFrameIndex=%d bAspectRatioX=%d bAspectRatioY=%d "
2905 "bmInterlaceFlags=0x%02x bCopyProtect=%d",
2907 desc
->bDescriptorType
,
2908 desc
->bDescriptorSubtype
,
2910 desc
->bNumFrameDescriptors
,
2912 desc
->bDefaultFrameIndex
,
2913 desc
->bAspectRatioX
,
2914 desc
->bAspectRatioY
,
2915 desc
->bmInterlaceFlags
,
2916 desc
->bCopyProtect
);
2920 print_vs_frame_mjpeg_descriptor(
2921 const uvideo_vs_frame_mjpeg_descriptor_t
*desc
)
2923 printf("MJPEG frame: "
2924 "Len=%d Type=0x%02x Subtype=0x%02x "
2925 "bFrameIndex=%d bmCapabilities=0x%02x "
2926 "wWidth=%d wHeight=%d dwMinBitRate=%u dwMaxBitRate=%u "
2927 "dwMaxVideoFrameBufferSize=%u dwDefaultFrameInterval=%u "
2928 "bFrameIntervalType=%d",
2930 desc
->bDescriptorType
,
2931 desc
->bDescriptorSubtype
,
2933 desc
->bmCapabilities
,
2934 UGETW(desc
->wWidth
),
2935 UGETW(desc
->wHeight
),
2936 UGETDW(desc
->dwMinBitRate
),
2937 UGETDW(desc
->dwMaxBitRate
),
2938 UGETDW(desc
->dwMaxVideoFrameBufferSize
),
2939 UGETDW(desc
->dwDefaultFrameInterval
),
2940 desc
->bFrameIntervalType
);
2944 print_vs_format_dv_descriptor(
2945 const uvideo_vs_format_dv_descriptor_t
*desc
)
2947 printf("MJPEG format: "
2948 "Len=%d Type=0x%02x Subtype=0x%02x "
2949 "bFormatIndex=%d dwMaxVideoFrameBufferSize=%u "
2950 "bFormatType/Rate=%d bFormatType/Format=%d",
2952 desc
->bDescriptorType
,
2953 desc
->bDescriptorSubtype
,
2955 UGETDW(desc
->dwMaxVideoFrameBufferSize
),
2956 UVIDEO_GET_DV_FREQ(desc
->bFormatType
),
2957 UVIDEO_GET_DV_FORMAT(desc
->bFormatType
));
2960 #endif /* !UVIDEO_DEBUG */
2962 static const usb_descriptor_t
*
2963 usb_desc_iter_peek_next(usbd_desc_iter_t
*iter
)
2965 const usb_descriptor_t
*desc
;
2967 if (iter
->cur
+ sizeof(usb_descriptor_t
) >= iter
->end
) {
2968 if (iter
->cur
!= iter
->end
)
2969 printf("usb_desc_iter_peek_next: bad descriptor\n");
2972 desc
= (const usb_descriptor_t
*)iter
->cur
;
2973 if (desc
->bLength
== 0) {
2974 printf("usb_desc_iter_peek_next: descriptor length = 0\n");
2977 if (iter
->cur
+ desc
->bLength
> iter
->end
) {
2978 printf("usb_desc_iter_peek_next: descriptor length too large\n");
2984 /* Return the next interface descriptor, skipping over any other
2985 * descriptors. Returns NULL at the end or on error. */
2986 static const usb_interface_descriptor_t
*
2987 usb_desc_iter_next_interface(usbd_desc_iter_t
*iter
)
2989 const usb_descriptor_t
*desc
;
2991 while ((desc
= usb_desc_iter_peek_next(iter
)) != NULL
&&
2992 desc
->bDescriptorType
!= UDESC_INTERFACE
)
2994 usb_desc_iter_next(iter
);
2997 return (const usb_interface_descriptor_t
*)usb_desc_iter_next(iter
);
3000 /* Returns the next non-interface descriptor, returning NULL when the
3001 * next descriptor would be an interface descriptor. */
3002 static const usb_descriptor_t
*
3003 usb_desc_iter_next_non_interface(usbd_desc_iter_t
*iter
)
3005 const usb_descriptor_t
*desc
;
3007 if ((desc
= usb_desc_iter_peek_next(iter
)) != NULL
&&
3008 desc
->bDescriptorType
!= UDESC_INTERFACE
)
3010 return (usb_desc_iter_next(iter
));
3018 usb_guid_print(const usb_guid_t
*guid
)
3020 printf("%04X-%02X-%02X-",
3021 UGETDW(guid
->data1
),
3023 UGETW(guid
->data3
));
3027 printf("%02X%02X%02X%02X%02X%02X",
3035 #endif /* !UVIDEO_DEBUG */
3037 /* Returns less than zero, zero, or greater than zero if uguid is less
3038 * than, equal to, or greater than guid. */
3040 usb_guid_cmp(const usb_guid_t
*uguid
, const guid_t
*guid
)
3042 if (guid
->data1
> UGETDW(uguid
->data1
))
3044 else if (guid
->data1
< UGETDW(uguid
->data1
))
3047 if (guid
->data2
> UGETW(uguid
->data2
))
3049 else if (guid
->data2
< UGETW(uguid
->data2
))
3052 if (guid
->data3
> UGETW(uguid
->data3
))
3054 else if (guid
->data3
< UGETW(uguid
->data3
))
3057 return (memcmp(guid
->data4
, uguid
->data4
, 8));