LCOV - code coverage report
Current view: top level - dev/usb - uvideo.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1402 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 75 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: uvideo.c,v 1.199 2018/05/01 18:14:46 landry Exp $ */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2008 Robert Nagy <robert@openbsd.org>
       5             :  * Copyright (c) 2008 Marcus Glocker <mglocker@openbsd.org>
       6             :  *
       7             :  * Permission to use, copy, modify, and distribute this software for any
       8             :  * purpose with or without fee is hereby granted, provided that the above
       9             :  * copyright notice and this permission notice appear in all copies.
      10             :  *
      11             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      12             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      13             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      14             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      15             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      16             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      17             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      18             :  */
      19             : 
      20             : #include <sys/param.h>
      21             : #include <sys/systm.h>
      22             : #include <sys/kernel.h>
      23             : #include <sys/malloc.h>
      24             : #include <sys/device.h>
      25             : #include <sys/ioctl.h>
      26             : #include <sys/tty.h>
      27             : #include <sys/fcntl.h>
      28             : #include <sys/selinfo.h>
      29             : #include <sys/lock.h>
      30             : #include <sys/stat.h>
      31             : #include <sys/poll.h>
      32             : #include <sys/timeout.h>
      33             : #include <sys/kthread.h>
      34             : #include <sys/stdint.h>
      35             : 
      36             : #include <uvm/uvm_extern.h>
      37             : 
      38             : #include <machine/bus.h>
      39             : 
      40             : #include <dev/usb/usb.h>
      41             : #include <dev/usb/usbdi.h>
      42             : #include <dev/usb/usbdivar.h>
      43             : #include <dev/usb/usbdi_util.h>
      44             : #include <dev/usb/usbdevs.h>
      45             : #include <dev/usb/uvideo.h>
      46             : 
      47             : #include <dev/video_if.h>
      48             : 
      49             : #ifdef UVIDEO_DEBUG
      50             : int uvideo_debug = 1;
      51             : #define DPRINTF(l, x...) do { if ((l) <= uvideo_debug) printf(x); } while (0)
      52             : #else
      53             : #define DPRINTF(l, x...)
      54             : #endif
      55             : 
      56             : #define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
      57             : 
      58             : #define byteof(x) ((x) >> 3)
      59             : #define bitof(x)  (1L << ((x) & 0x7))
      60             : 
      61             : struct uvideo_softc {
      62             :         struct device                            sc_dev;
      63             :         struct usbd_device                      *sc_udev;
      64             :         int                                      sc_nifaces;
      65             :         struct usbd_interface                   **sc_ifaces;
      66             : 
      67             :         struct device                           *sc_videodev;
      68             : 
      69             :         int                                      sc_enabled;
      70             :         int                                      sc_max_fbuf_size;
      71             :         int                                      sc_negotiated_flag;
      72             :         int                                      sc_frame_rate;
      73             : 
      74             :         struct uvideo_frame_buffer               sc_frame_buffer;
      75             : 
      76             :         struct uvideo_mmap                       sc_mmap[UVIDEO_MAX_BUFFERS];
      77             :         uint8_t                                 *sc_mmap_buffer;
      78             :         size_t                                   sc_mmap_buffer_size;
      79             :         q_mmap                                   sc_mmap_q;
      80             :         int                                      sc_mmap_count;
      81             :         int                                      sc_mmap_flag;
      82             : 
      83             :         struct vnode                            *sc_vp;
      84             :         struct usb_task                          sc_task_write;
      85             : 
      86             :         int                                      sc_nframes;
      87             :         struct usb_video_probe_commit            sc_desc_probe;
      88             :         struct usb_video_header_desc_all         sc_desc_vc_header;
      89             :         struct usb_video_input_header_desc_all   sc_desc_vs_input_header;
      90             : 
      91             : #define UVIDEO_MAX_PU                            8
      92             :         int                                      sc_desc_vc_pu_num;
      93             :         struct usb_video_vc_processing_desc     *sc_desc_vc_pu_cur;
      94             :         struct usb_video_vc_processing_desc     *sc_desc_vc_pu[UVIDEO_MAX_PU];
      95             : 
      96             : #define UVIDEO_MAX_FORMAT                        8
      97             :         int                                      sc_fmtgrp_idx;
      98             :         int                                      sc_fmtgrp_num;
      99             :         struct uvideo_format_group              *sc_fmtgrp_cur;
     100             :         struct uvideo_format_group               sc_fmtgrp[UVIDEO_MAX_FORMAT];
     101             : 
     102             : #define UVIDEO_MAX_VS_NUM                        8
     103             :         struct uvideo_vs_iface                  *sc_vs_cur;
     104             :         struct uvideo_vs_iface                   sc_vs_coll[UVIDEO_MAX_VS_NUM];
     105             : 
     106             :         void                                    *sc_uplayer_arg;
     107             :         int                                     *sc_uplayer_fsize;
     108             :         uint8_t                                 *sc_uplayer_fbuffer;
     109             :         void                                     (*sc_uplayer_intr)(void *);
     110             : 
     111             :         struct uvideo_devs                      *sc_quirk;
     112             :         usbd_status                             (*sc_decode_stream_header)
     113             :                                                     (struct uvideo_softc *,
     114             :                                                     uint8_t *, int);
     115             : };
     116             : 
     117             : int             uvideo_enable(void *);
     118             : void            uvideo_disable(void *);
     119             : int             uvideo_open(void *, int, int *, uint8_t *, void (*)(void *),
     120             :                     void *arg);
     121             : int             uvideo_close(void *);
     122             : int             uvideo_match(struct device *, void *, void *);
     123             : void            uvideo_attach(struct device *, struct device *, void *);
     124             : void            uvideo_attach_hook(struct device *);
     125             : int             uvideo_detach(struct device *, int);
     126             : 
     127             : usbd_status     uvideo_vc_parse_desc(struct uvideo_softc *);
     128             : usbd_status     uvideo_vc_parse_desc_header(struct uvideo_softc *,
     129             :                     const usb_descriptor_t *);
     130             : usbd_status     uvideo_vc_parse_desc_pu(struct uvideo_softc *,
     131             :                     const usb_descriptor_t *);
     132             : usbd_status     uvideo_vc_get_ctrl(struct uvideo_softc *, uint8_t *, uint8_t,
     133             :                     uint8_t, uint16_t, uint16_t);
     134             : usbd_status     uvideo_vc_set_ctrl(struct uvideo_softc *, uint8_t *, uint8_t,
     135             :                     uint8_t, uint16_t, uint16_t);
     136             : int             uvideo_find_ctrl(struct uvideo_softc *, int);
     137             : int             uvideo_has_ctrl(struct usb_video_vc_processing_desc *, int);
     138             : 
     139             : usbd_status     uvideo_vs_parse_desc(struct uvideo_softc *,
     140             :                     usb_config_descriptor_t *);
     141             : usbd_status     uvideo_vs_parse_desc_input_header(struct uvideo_softc *,
     142             :                     const usb_descriptor_t *);
     143             : usbd_status     uvideo_vs_parse_desc_format(struct uvideo_softc *);
     144             : usbd_status     uvideo_vs_parse_desc_format_mjpeg(struct uvideo_softc *,
     145             :                     const usb_descriptor_t *);
     146             : usbd_status     uvideo_vs_parse_desc_format_uncompressed(struct uvideo_softc *,
     147             :                     const usb_descriptor_t *);
     148             : usbd_status     uvideo_vs_parse_desc_frame(struct uvideo_softc *);
     149             : usbd_status     uvideo_vs_parse_desc_frame_sub(struct uvideo_softc *,
     150             :                     const usb_descriptor_t *);
     151             : usbd_status     uvideo_vs_parse_desc_alt(struct uvideo_softc *, int, int, int);
     152             : usbd_status     uvideo_vs_set_alt(struct uvideo_softc *,
     153             :                     struct usbd_interface *, int);
     154             : int             uvideo_desc_len(const usb_descriptor_t *, int, int, int, int);
     155             : void            uvideo_find_res(struct uvideo_softc *, int, int, int,
     156             :                     struct uvideo_res *);
     157             : usbd_status     uvideo_vs_negotiation(struct uvideo_softc *, int);
     158             : usbd_status     uvideo_vs_set_probe(struct uvideo_softc *, uint8_t *);
     159             : usbd_status     uvideo_vs_get_probe(struct uvideo_softc *, uint8_t *, uint8_t);
     160             : usbd_status     uvideo_vs_set_commit(struct uvideo_softc *, uint8_t *);
     161             : usbd_status     uvideo_vs_alloc_frame(struct uvideo_softc *);
     162             : void            uvideo_vs_free_frame(struct uvideo_softc *);
     163             : usbd_status     uvideo_vs_alloc_isoc(struct uvideo_softc *);
     164             : usbd_status     uvideo_vs_alloc_bulk(struct uvideo_softc *);
     165             : void            uvideo_vs_free_isoc(struct uvideo_softc *);
     166             : void            uvideo_vs_free_bulk(struct uvideo_softc *);
     167             : usbd_status     uvideo_vs_open(struct uvideo_softc *);
     168             : void            uvideo_vs_close(struct uvideo_softc *);
     169             : usbd_status     uvideo_vs_init(struct uvideo_softc *);
     170             : int             uvideo_vs_start_bulk(struct uvideo_softc *);
     171             : void            uvideo_vs_start_bulk_thread(void *);
     172             : void            uvideo_vs_start_isoc(struct uvideo_softc *);
     173             : void            uvideo_vs_start_isoc_ixfer(struct uvideo_softc *,
     174             :                     struct uvideo_isoc_xfer *);
     175             : void            uvideo_vs_cb(struct usbd_xfer *, void *,
     176             :                     usbd_status);
     177             : usbd_status     uvideo_vs_decode_stream_header(struct uvideo_softc *,
     178             :                     uint8_t *, int); 
     179             : usbd_status     uvideo_vs_decode_stream_header_isight(struct uvideo_softc *,
     180             :                     uint8_t *, int);
     181             : int             uvideo_mmap_queue(struct uvideo_softc *, uint8_t *, int);
     182             : void            uvideo_read(struct uvideo_softc *, uint8_t *, int);
     183             : usbd_status     uvideo_usb_control(struct uvideo_softc *sc, uint8_t rt, uint8_t r,
     184             :                     uint16_t value, uint8_t *data, size_t length);
     185             : 
     186             : #ifdef UVIDEO_DEBUG
     187             : #include <sys/namei.h>
     188             : #include <sys/vnode.h>
     189             : 
     190             : void            uvideo_dump_desc_all(struct uvideo_softc *);
     191             : void            uvideo_dump_desc_vc_header(struct uvideo_softc *,
     192             :                     const usb_descriptor_t *);
     193             : void            uvideo_dump_desc_input_header(struct uvideo_softc *,
     194             :                     const usb_descriptor_t *);
     195             : void            uvideo_dump_desc_input(struct uvideo_softc *,
     196             :                     const usb_descriptor_t *);
     197             : void            uvideo_dump_desc_output(struct uvideo_softc *,
     198             :                     const usb_descriptor_t *);
     199             : void            uvideo_dump_desc_endpoint(struct uvideo_softc *,
     200             :                     const usb_descriptor_t *);
     201             : void            uvideo_dump_desc_interface(struct uvideo_softc *,
     202             :                     const usb_descriptor_t *);
     203             : void            uvideo_dump_desc_config(struct uvideo_softc *,
     204             :                     const usb_descriptor_t *);
     205             : void            uvideo_dump_desc_cs_endpoint(struct uvideo_softc *,
     206             :                     const usb_descriptor_t *);
     207             : void            uvideo_dump_desc_colorformat(struct uvideo_softc *,
     208             :                     const usb_descriptor_t *);
     209             : void            uvideo_dump_desc_format_mjpeg(struct uvideo_softc *,
     210             :                     const usb_descriptor_t *);
     211             : void            uvideo_dump_desc_format_uncompressed(struct uvideo_softc *,
     212             :                     const usb_descriptor_t *);
     213             : void            uvideo_dump_desc_frame(struct uvideo_softc *,
     214             :                     const usb_descriptor_t *);
     215             : void            uvideo_dump_desc_processing(struct uvideo_softc *,
     216             :                     const usb_descriptor_t *);
     217             : void            uvideo_dump_desc_extension(struct uvideo_softc *,
     218             :                     const usb_descriptor_t *);
     219             : void            uvideo_hexdump(void *, int, int);
     220             : int             uvideo_debug_file_open(struct uvideo_softc *);
     221             : void            uvideo_debug_file_write_frame(void *);
     222             : #endif
     223             : 
     224             : /*
     225             :  * IOCTL's
     226             :  */
     227             : int             uvideo_querycap(void *, struct v4l2_capability *);
     228             : int             uvideo_enum_fmt(void *, struct v4l2_fmtdesc *);
     229             : int             uvideo_enum_fsizes(void *, struct v4l2_frmsizeenum *);
     230             : int             uvideo_enum_fivals(void *, struct v4l2_frmivalenum *);
     231             : int             uvideo_s_fmt(void *, struct v4l2_format *);
     232             : int             uvideo_g_fmt(void *, struct v4l2_format *);
     233             : int             uvideo_s_parm(void *, struct v4l2_streamparm *);
     234             : int             uvideo_g_parm(void *, struct v4l2_streamparm *);
     235             : int             uvideo_enum_input(void *, struct v4l2_input *);
     236             : int             uvideo_s_input(void *, int);
     237             : int             uvideo_g_input(void *, int *);
     238             : int             uvideo_reqbufs(void *, struct v4l2_requestbuffers *);
     239             : int             uvideo_querybuf(void *, struct v4l2_buffer *);
     240             : int             uvideo_qbuf(void *, struct v4l2_buffer *);
     241             : int             uvideo_dqbuf(void *, struct v4l2_buffer *);
     242             : int             uvideo_streamon(void *, int);
     243             : int             uvideo_streamoff(void *, int);
     244             : int             uvideo_try_fmt(void *, struct v4l2_format *);
     245             : int             uvideo_queryctrl(void *, struct v4l2_queryctrl *);
     246             : int             uvideo_g_ctrl(void *, struct v4l2_control *);
     247             : int             uvideo_s_ctrl(void *, struct v4l2_control *);
     248             : 
     249             : /*
     250             :  * Other hardware interface related functions
     251             :  */
     252             : caddr_t         uvideo_mappage(void *, off_t, int);
     253             : int             uvideo_get_bufsize(void *);
     254             : int             uvideo_start_read(void *);
     255             : 
     256             : /*
     257             :  * Firmware
     258             :  */
     259             : usbd_status     uvideo_ucode_loader_ricoh(struct uvideo_softc *);
     260             : usbd_status     uvideo_ucode_loader_apple_isight(struct uvideo_softc *);
     261             : 
     262             : struct cfdriver uvideo_cd = {
     263             :         NULL, "uvideo", DV_DULL
     264             : };
     265             : 
     266             : const struct cfattach uvideo_ca = {
     267             :         sizeof(struct uvideo_softc), uvideo_match, uvideo_attach, uvideo_detach
     268             : };
     269             : 
     270             : struct video_hw_if uvideo_hw_if = {
     271             :         uvideo_open,            /* open */
     272             :         uvideo_close,           /* close */
     273             :         uvideo_querycap,        /* VIDIOC_QUERYCAP */
     274             :         uvideo_enum_fmt,        /* VIDIOC_ENUM_FMT */
     275             :         uvideo_enum_fsizes,     /* VIDIOC_ENUM_FRAMESIZES */
     276             :         uvideo_enum_fivals,     /* VIDIOC_ENUM_FRAMEINTERVALS */
     277             :         uvideo_s_fmt,           /* VIDIOC_S_FMT */
     278             :         uvideo_g_fmt,           /* VIDIOC_G_FMT */
     279             :         uvideo_s_parm,          /* VIDIOC_S_PARM */
     280             :         uvideo_g_parm,          /* VIDIOC_G_PARM */
     281             :         uvideo_enum_input,      /* VIDIOC_ENUMINPUT */
     282             :         uvideo_s_input,         /* VIDIOC_S_INPUT */
     283             :         uvideo_g_input,         /* VIDIOC_G_INPUT */
     284             :         uvideo_reqbufs,         /* VIDIOC_REQBUFS */
     285             :         uvideo_querybuf,        /* VIDIOC_QUERYBUF */
     286             :         uvideo_qbuf,            /* VIDIOC_QBUF */
     287             :         uvideo_dqbuf,           /* VIDIOC_DQBUF */
     288             :         uvideo_streamon,        /* VIDIOC_STREAMON */
     289             :         uvideo_streamoff,       /* VIDIOC_STREAMOFF */
     290             :         uvideo_try_fmt,         /* VIDIOC_TRY_FMT */
     291             :         uvideo_queryctrl,       /* VIDIOC_QUERYCTRL */
     292             :         uvideo_g_ctrl,          /* VIDIOC_G_CTRL */
     293             :         uvideo_s_ctrl,          /* VIDIOC_S_CTRL */
     294             :         uvideo_mappage,         /* mmap */
     295             :         uvideo_get_bufsize,     /* read */
     296             :         uvideo_start_read       /* start stream for read */
     297             : };
     298             : 
     299             : /*
     300             :  * Devices which either fail to declare themselves as UICLASS_VIDEO,
     301             :  * or which need firmware uploads or other quirk handling later on.
     302             :  */
     303             : #define UVIDEO_FLAG_ISIGHT_STREAM_HEADER        0x1
     304             : #define UVIDEO_FLAG_REATTACH                    0x2
     305             : #define UVIDEO_FLAG_VENDOR_CLASS                0x4
     306             : struct uvideo_devs {
     307             :         struct usb_devno         uv_dev;
     308             :         char                    *ucode_name;
     309             :         usbd_status              (*ucode_loader)(struct uvideo_softc *);
     310             :         int                      flags;
     311             : } uvideo_devs[] = {
     312             :         {
     313             :             /* Needs firmware */
     314             :             { USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC5 },
     315             :             "uvideo_r5u87x_05ca-1835",
     316             :             uvideo_ucode_loader_ricoh,
     317             :             0
     318             :         },
     319             :         {
     320             :             /* Needs firmware */
     321             :             { USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC4 },
     322             :             "uvideo_r5u87x_05ca-1836",
     323             :             uvideo_ucode_loader_ricoh,
     324             :             0
     325             :         },
     326             :         {
     327             :             /* Needs firmware */
     328             :             { USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC4_2 },
     329             :             "uvideo_r5u87x_05ca-1837",
     330             :             uvideo_ucode_loader_ricoh,
     331             :             0
     332             :         },
     333             :         {
     334             :             /* Needs firmware */
     335             :             { USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC6 },
     336             :             "uvideo_r5u87x_05ca-1839",
     337             :             uvideo_ucode_loader_ricoh,
     338             :             0
     339             :         },
     340             :         {
     341             :             /* Needs firmware */
     342             :             { USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC7 },
     343             :             "uvideo_r5u87x_05ca-183a",
     344             :             uvideo_ucode_loader_ricoh,
     345             :             0
     346             :         },
     347             :         {
     348             :             /* Needs firmware */
     349             :             { USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC8 },
     350             :             "uvideo_r5u87x_05ca-183b",
     351             :             uvideo_ucode_loader_ricoh,
     352             :             0
     353             :         },
     354             :         {
     355             :             /* Needs firmware */
     356             :             { USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC9 },
     357             :             "uvideo_r5u87x_05ca-183e",
     358             :             uvideo_ucode_loader_ricoh,
     359             :             0
     360             :         },
     361             :         {
     362             :             /* Needs firmware */
     363             :             { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_BLUETOOTH },
     364             :             "uvideo_isight_05ac-8300",
     365             :             uvideo_ucode_loader_apple_isight,
     366             :             UVIDEO_FLAG_REATTACH
     367             :         },
     368             :         {
     369             :             /* Has a non-standard streaming header protocol */
     370             :             { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_ISIGHT_1 },
     371             :             NULL,
     372             :             NULL,
     373             :             UVIDEO_FLAG_ISIGHT_STREAM_HEADER
     374             :         },
     375             :         {   /* Incorrectly reports as bInterfaceClass=UICLASS_VENDOR */
     376             :             { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMOEM_1 },
     377             :             NULL,
     378             :             NULL,
     379             :             UVIDEO_FLAG_VENDOR_CLASS
     380             :         },
     381             : };
     382             : #define uvideo_lookup(v, p) \
     383             :         ((struct uvideo_devs *)usb_lookup(uvideo_devs, v, p))
     384             : 
     385             : int
     386           0 : uvideo_enable(void *v)
     387             : {
     388           0 :         struct uvideo_softc *sc = v;
     389             : 
     390             :         DPRINTF(1, "%s: uvideo_enable sc=%p\n", DEVNAME(sc), sc);
     391             : 
     392           0 :         if (usbd_is_dying(sc->sc_udev))
     393           0 :                 return (EIO);
     394             : 
     395           0 :         if (sc->sc_enabled)
     396           0 :                 return (EBUSY);
     397             : 
     398           0 :         sc->sc_enabled = 1;
     399             : 
     400           0 :         return (0);
     401           0 : }
     402             : 
     403             : void
     404           0 : uvideo_disable(void *v)
     405             : {
     406           0 :         struct uvideo_softc *sc = v;
     407             : 
     408             :         DPRINTF(1, "%s: uvideo_disable sc=%p\n", DEVNAME(sc), sc);
     409             : 
     410           0 :         if (!sc->sc_enabled) {
     411           0 :                 printf("uvideo_disable: already disabled!\n");
     412           0 :                 return;
     413             :         }
     414             : 
     415           0 :         sc->sc_enabled = 0;
     416           0 : }
     417             : 
     418             : int
     419           0 : uvideo_open(void *addr, int flags, int *size, uint8_t *buffer,
     420             :     void (*intr)(void *), void *arg)
     421             : {
     422           0 :         struct uvideo_softc *sc = addr;
     423             : 
     424             :         DPRINTF(1, "%s: uvideo_open: sc=%p\n", DEVNAME(sc), sc);
     425             : 
     426           0 :         if (usbd_is_dying(sc->sc_udev))
     427           0 :                 return (EIO);
     428             : 
     429             :         /* pointers to upper video layer */
     430           0 :         sc->sc_uplayer_arg = arg;
     431           0 :         sc->sc_uplayer_fsize = size;
     432           0 :         sc->sc_uplayer_fbuffer = buffer;
     433           0 :         sc->sc_uplayer_intr = intr;
     434             : 
     435           0 :         sc->sc_mmap_flag = 0;
     436           0 :         sc->sc_negotiated_flag = 0;
     437             : 
     438           0 :         return (0);
     439           0 : }
     440             : 
     441             : int
     442           0 : uvideo_close(void *addr)
     443             : {
     444           0 :         struct uvideo_softc *sc = addr;
     445             : 
     446             :         DPRINTF(1, "%s: uvideo_close: sc=%p\n", DEVNAME(sc), sc);
     447             : 
     448             : #ifdef UVIDEO_DUMP
     449             :         usb_rem_task(sc->sc_udev, &sc->sc_task_write);
     450             : #endif
     451             :         /* close video stream pipe */
     452           0 :         uvideo_vs_close(sc);
     453             : 
     454             :         /* free video stream xfer buffer */
     455           0 :         if (sc->sc_vs_cur->bulk_endpoint)
     456           0 :                 uvideo_vs_free_bulk(sc);
     457             :         else
     458           0 :                 uvideo_vs_free_isoc(sc);
     459             : 
     460             :         /* free video stream frame buffer */
     461           0 :         uvideo_vs_free_frame(sc);
     462           0 :         return (0);
     463             : }
     464             : 
     465             : int
     466           0 : uvideo_match(struct device *parent, void *match, void *aux)
     467             : {
     468           0 :         struct usb_attach_arg *uaa = aux;
     469             :         usb_interface_descriptor_t *id;
     470             :         struct uvideo_devs *quirk;
     471             : 
     472           0 :         if (uaa->iface == NULL)
     473           0 :                 return (UMATCH_NONE);
     474             : 
     475           0 :         id = usbd_get_interface_descriptor(uaa->iface);
     476           0 :         if (id == NULL)
     477           0 :                 return (UMATCH_NONE);
     478             : 
     479           0 :         if (id->bInterfaceClass == UICLASS_VIDEO &&
     480           0 :             id->bInterfaceSubClass == UISUBCLASS_VIDEOCONTROL)
     481           0 :                 return (UMATCH_VENDOR_PRODUCT_CONF_IFACE);
     482             : 
     483             :         /* quirk devices which we want to attach */
     484           0 :         quirk = uvideo_lookup(uaa->vendor, uaa->product);
     485           0 :         if (quirk != NULL) {
     486           0 :                 if (quirk->flags & UVIDEO_FLAG_REATTACH)
     487           0 :                         return (UMATCH_VENDOR_PRODUCT_CONF_IFACE);
     488             : 
     489           0 :                 if (quirk->flags & UVIDEO_FLAG_VENDOR_CLASS &&
     490           0 :                     id->bInterfaceClass == UICLASS_VENDOR &&
     491           0 :                     id->bInterfaceSubClass == UISUBCLASS_VIDEOCONTROL)
     492           0 :                         return (UMATCH_VENDOR_PRODUCT_CONF_IFACE);
     493             :         }
     494             : 
     495           0 :         return (UMATCH_NONE);
     496           0 : }
     497             : 
     498             : void
     499           0 : uvideo_attach(struct device *parent, struct device *self, void *aux)
     500             : {
     501           0 :         struct uvideo_softc *sc = (struct uvideo_softc *)self;
     502           0 :         struct usb_attach_arg *uaa = aux;
     503             :         usb_interface_descriptor_t *id;
     504             :         int i;
     505             : 
     506           0 :         sc->sc_udev = uaa->device;
     507           0 :         sc->sc_nifaces = uaa->nifaces;
     508             :         /*
     509             :          * Claim all video interfaces.  Interfaces must be claimed during
     510             :          * attach, during attach hooks is too late.
     511             :          */
     512           0 :         for (i = 0; i < sc->sc_nifaces; i++) {
     513           0 :                 if (usbd_iface_claimed(sc->sc_udev, i))
     514             :                         continue;
     515           0 :                 id = usbd_get_interface_descriptor(&sc->sc_udev->ifaces[i]);
     516           0 :                 if (id == NULL)
     517             :                         continue;
     518           0 :                 if (id->bInterfaceClass == UICLASS_VIDEO)
     519           0 :                         usbd_claim_iface(sc->sc_udev, i);
     520             :         }
     521             : 
     522             :         /* maybe the device has quirks */
     523           0 :         sc->sc_quirk = uvideo_lookup(uaa->vendor, uaa->product);
     524             : 
     525           0 :         if (sc->sc_quirk && sc->sc_quirk->ucode_name)
     526           0 :                 config_mountroot(self, uvideo_attach_hook);
     527             :         else
     528           0 :                 uvideo_attach_hook(self);
     529           0 : }
     530             : 
     531             : void
     532           0 : uvideo_attach_hook(struct device *self)
     533             : {
     534           0 :         struct uvideo_softc *sc = (struct uvideo_softc *)self;
     535             :         usb_config_descriptor_t *cdesc;
     536             :         usbd_status error;
     537             : 
     538             :         /* maybe the device needs a firmware */
     539           0 :         if (sc->sc_quirk && sc->sc_quirk->ucode_name) {
     540           0 :                 error = (sc->sc_quirk->ucode_loader)(sc);
     541           0 :                 if (error != USBD_NORMAL_COMPLETION)
     542           0 :                         return;
     543             :         }
     544             : 
     545             :         /* map stream header decode function */
     546           0 :         if (sc->sc_quirk &&
     547           0 :             sc->sc_quirk->flags & UVIDEO_FLAG_ISIGHT_STREAM_HEADER) {
     548           0 :                 sc->sc_decode_stream_header =
     549             :                     uvideo_vs_decode_stream_header_isight;
     550           0 :         } else {
     551           0 :                 sc->sc_decode_stream_header =
     552             :                     uvideo_vs_decode_stream_header;
     553             :         }
     554             : 
     555             :         /* get the config descriptor */
     556           0 :         cdesc = usbd_get_config_descriptor(sc->sc_udev);
     557           0 :         if (cdesc == NULL) {
     558           0 :                 printf("%s: failed to get configuration descriptor\n",
     559           0 :                     DEVNAME(sc));
     560           0 :                 return;
     561             :         }
     562             : #ifdef UVIDEO_DEBUG
     563             :         uvideo_dump_desc_all(sc);
     564             : #endif
     565             :         /* parse video control descriptors */
     566           0 :         error = uvideo_vc_parse_desc(sc);
     567           0 :         if (error != USBD_NORMAL_COMPLETION)
     568           0 :                 return;
     569             : 
     570             :         /* parse video stream descriptors */
     571           0 :         error = uvideo_vs_parse_desc(sc, cdesc);
     572           0 :         if (error != USBD_NORMAL_COMPLETION)
     573           0 :                 return;
     574             : 
     575             :         /* set default video stream interface */
     576           0 :         error = usbd_set_interface(sc->sc_vs_cur->ifaceh, 0);
     577           0 :         if (error != USBD_NORMAL_COMPLETION)
     578           0 :                 return;
     579             : 
     580             :         /* do device negotiation without commit */
     581           0 :         error = uvideo_vs_negotiation(sc, 0);
     582           0 :         if (error != USBD_NORMAL_COMPLETION)
     583           0 :                 return;
     584             : 
     585             :         /* init mmap queue */
     586           0 :         SIMPLEQ_INIT(&sc->sc_mmap_q);
     587           0 :         sc->sc_mmap_count = 0;
     588             : 
     589             :         DPRINTF(1, "uvideo_attach: doing video_attach_mi\n");
     590           0 :         sc->sc_videodev = video_attach_mi(&uvideo_hw_if, sc, &sc->sc_dev);
     591           0 : }
     592             : 
     593             : int
     594           0 : uvideo_detach(struct device *self, int flags)
     595             : {
     596           0 :         struct uvideo_softc *sc = (struct uvideo_softc *)self;
     597             :         int rv = 0;
     598             : 
     599             :         /* Wait for outstanding requests to complete */
     600           0 :         usbd_delay_ms(sc->sc_udev, UVIDEO_NFRAMES_MAX);
     601             : 
     602           0 :         uvideo_vs_free_frame(sc);
     603             : 
     604           0 :         if (sc->sc_videodev != NULL)
     605           0 :                 rv = config_detach(sc->sc_videodev, flags);
     606             : 
     607           0 :         return (rv);
     608             : }
     609             : 
     610             : usbd_status
     611           0 : uvideo_vc_parse_desc(struct uvideo_softc *sc)
     612             : {
     613           0 :         struct usbd_desc_iter iter;
     614             :         const usb_descriptor_t *desc;
     615             :         int vc_header_found;
     616             :         usbd_status error;
     617             : 
     618             :         DPRINTF(1, "%s: %s\n", DEVNAME(sc), __func__);
     619             : 
     620             :         vc_header_found = 0;
     621             : 
     622           0 :         usbd_desc_iter_init(sc->sc_udev, &iter);
     623           0 :         desc = usbd_desc_iter_next(&iter);
     624           0 :         while (desc) {
     625           0 :                 if (desc->bDescriptorType != UDESC_CS_INTERFACE) {
     626           0 :                         desc = usbd_desc_iter_next(&iter);
     627           0 :                         continue;
     628             :                 }
     629             : 
     630           0 :                 switch (desc->bDescriptorSubtype) {
     631             :                 case UDESCSUB_VC_HEADER:
     632           0 :                         if (!uvideo_desc_len(desc, 12, 11, 1, 0))
     633             :                                 break;
     634           0 :                         if (vc_header_found) {
     635           0 :                                 printf("%s: too many VC_HEADERs!\n",
     636           0 :                                     DEVNAME(sc));
     637           0 :                                 return (USBD_INVAL);
     638             :                         }
     639           0 :                         error = uvideo_vc_parse_desc_header(sc, desc);
     640           0 :                         if (error != USBD_NORMAL_COMPLETION)
     641           0 :                                 return (error);
     642             :                         vc_header_found = 1;
     643           0 :                         break;
     644             :                 case UDESCSUB_VC_PROCESSING_UNIT:
     645             :                         /* XXX do correct length calculation */
     646           0 :                         if (desc->bLength <
     647             :                             sizeof(struct usb_video_frame_desc)) {
     648           0 :                                 (void)uvideo_vc_parse_desc_pu(sc, desc);
     649           0 :                         }
     650             :                         break;
     651             : 
     652             :                 /* TODO: which VC descriptors do we need else? */
     653             :                 }
     654             : 
     655           0 :                 desc = usbd_desc_iter_next(&iter);
     656             :         }
     657             : 
     658           0 :         if (vc_header_found == 0) {
     659           0 :                 printf("%s: no VC_HEADER found!\n", DEVNAME(sc));
     660           0 :                 return (USBD_INVAL);
     661             :         }
     662             : 
     663           0 :         return (USBD_NORMAL_COMPLETION);
     664           0 : }
     665             : 
     666             : usbd_status
     667           0 : uvideo_vc_parse_desc_header(struct uvideo_softc *sc,
     668             :     const usb_descriptor_t *desc)
     669             : {
     670             :         struct usb_video_header_desc *d;
     671             : 
     672           0 :         d = (struct usb_video_header_desc *)(uint8_t *)desc;
     673             : 
     674           0 :         if (d->bInCollection == 0) {
     675           0 :                 printf("%s: no VS interface found!\n",
     676           0 :                     DEVNAME(sc));
     677           0 :                 return (USBD_INVAL);
     678             :         }
     679             :         
     680           0 :         sc->sc_desc_vc_header.fix = d;
     681           0 :         sc->sc_desc_vc_header.baInterfaceNr = (uByte *)(d + 1);
     682             : 
     683           0 :         return (USBD_NORMAL_COMPLETION);
     684           0 : }
     685             : 
     686             : usbd_status
     687           0 : uvideo_vc_parse_desc_pu(struct uvideo_softc *sc,
     688             :     const usb_descriptor_t *desc)
     689             : {
     690             :         struct usb_video_vc_processing_desc *d;
     691             : 
     692             :         /* PU descriptor is variable sized */
     693           0 :         d = (void *)desc;
     694             : 
     695           0 :         if (sc->sc_desc_vc_pu_num == UVIDEO_MAX_PU) {
     696           0 :                 printf("%s: too many PU descriptors found!\n", DEVNAME(sc));
     697           0 :                 return (USBD_INVAL);
     698             :         }
     699             : 
     700           0 :         sc->sc_desc_vc_pu[sc->sc_desc_vc_pu_num] = d;
     701           0 :         sc->sc_desc_vc_pu_num++;
     702             : 
     703           0 :         return (USBD_NORMAL_COMPLETION);
     704           0 : }
     705             : 
     706             : usbd_status
     707           0 : uvideo_vc_get_ctrl(struct uvideo_softc *sc, uint8_t *ctrl_data,
     708             :     uint8_t request, uint8_t unitid, uint16_t ctrl_selector, uint16_t ctrl_len)
     709             : {
     710           0 :         usb_device_request_t req;
     711             :         usbd_status error;
     712             : 
     713           0 :         req.bmRequestType = UVIDEO_GET_IF;
     714           0 :         req.bRequest = request;
     715           0 :         USETW(req.wValue, (ctrl_selector << 8));
     716           0 :         USETW(req.wIndex, (unitid << 8));
     717           0 :         USETW(req.wLength, ctrl_len);
     718             : 
     719           0 :         error = usbd_do_request(sc->sc_udev, &req, ctrl_data);
     720           0 :         if (error) {
     721             :                 DPRINTF(1, "%s: %s: could not GET ctrl request: %s\n",
     722             :                     DEVNAME(sc), __func__, usbd_errstr(error));
     723           0 :                 return (USBD_INVAL);
     724             :         }
     725             : 
     726           0 :         return (USBD_NORMAL_COMPLETION);
     727           0 : }
     728             : 
     729             : usbd_status
     730           0 : uvideo_vc_set_ctrl(struct uvideo_softc *sc, uint8_t *ctrl_data,
     731             :     uint8_t request, uint8_t unitid, uint16_t ctrl_selector, uint16_t ctrl_len)
     732             : {
     733           0 :         usb_device_request_t req;
     734             :         usbd_status error;
     735             : 
     736           0 :         req.bmRequestType = UVIDEO_SET_IF;
     737           0 :         req.bRequest = request;
     738           0 :         USETW(req.wValue, (ctrl_selector << 8));
     739           0 :         USETW(req.wIndex, (unitid << 8));
     740           0 :         USETW(req.wLength, ctrl_len);
     741             : 
     742           0 :         error = usbd_do_request(sc->sc_udev, &req, ctrl_data);
     743           0 :         if (error) {
     744             :                 DPRINTF(1, "%s: %s: could not SET ctrl request: %s\n",
     745             :                     DEVNAME(sc), __func__, usbd_errstr(error));
     746           0 :                 return (USBD_INVAL);
     747             :         }
     748             : 
     749           0 :         return (USBD_NORMAL_COMPLETION);
     750           0 : }
     751             : 
     752             : int
     753           0 : uvideo_find_ctrl(struct uvideo_softc *sc, int id)
     754             : {
     755             :         int i, j, found;
     756             : 
     757           0 :         if (sc->sc_desc_vc_pu_num == 0) {
     758             :                 /* no processing unit descriptors found */
     759             :                 DPRINTF(1, "%s: %s: no processing unit descriptors found!\n",
     760             :                     DEVNAME(sc), __func__);
     761           0 :                 return (EINVAL);
     762             :         }
     763             : 
     764             :         /* do we support this control? */
     765           0 :         for (found = 0, i = 0; uvideo_ctrls[i].cid != 0; i++) {
     766           0 :                 if (id == uvideo_ctrls[i].cid) {
     767             :                         found = 1;
     768           0 :                         break;
     769             :                 }
     770             :         }
     771           0 :         if (found == 0) {
     772             :                 DPRINTF(1, "%s: %s: control not supported by driver!\n",
     773             :                     DEVNAME(sc), __func__);
     774           0 :                 return (EINVAL);
     775             :         }
     776             : 
     777             :         /* does the device support this control? */
     778           0 :         for (found = 0, j = 0; j < sc->sc_desc_vc_pu_num; j++) {
     779           0 :                 if (uvideo_has_ctrl(sc->sc_desc_vc_pu[j],
     780           0 :                     uvideo_ctrls[i].ctrl_bit) != 0) {
     781             :                         found = 1;
     782           0 :                         break; 
     783             :                 }
     784             :         }
     785           0 :         if (found == 0) {
     786             :                 DPRINTF(1, "%s: %s: control not supported by device!\n",
     787             :                     DEVNAME(sc), __func__);
     788           0 :                 return (EINVAL);
     789             :         }
     790           0 :         sc->sc_desc_vc_pu_cur = sc->sc_desc_vc_pu[j];
     791             : 
     792           0 :         return (i);
     793           0 : }
     794             : 
     795             : int
     796           0 : uvideo_has_ctrl(struct usb_video_vc_processing_desc *desc, int ctrl_bit)
     797             : {
     798           0 :         if (desc->bControlSize * 8 <= ctrl_bit)
     799           0 :                 return (0);
     800             : 
     801           0 :         return (desc->bmControls[byteof(ctrl_bit)] & bitof(ctrl_bit));
     802           0 : }
     803             : 
     804             : usbd_status
     805           0 : uvideo_vs_parse_desc(struct uvideo_softc *sc, usb_config_descriptor_t *cdesc)
     806             : {
     807           0 :         struct usbd_desc_iter iter;
     808             :         const usb_descriptor_t *desc;
     809             :         usb_interface_descriptor_t *id;
     810             :         int i, iface, numalts;
     811             :         usbd_status error;
     812             : 
     813             :         DPRINTF(1, "%s: number of total interfaces=%d\n",
     814             :             DEVNAME(sc), sc->sc_nifaces);
     815             :         DPRINTF(1, "%s: number of VS interfaces=%d\n",
     816             :             DEVNAME(sc), sc->sc_desc_vc_header.fix->bInCollection);
     817             : 
     818           0 :         usbd_desc_iter_init(sc->sc_udev, &iter);
     819           0 :         desc = usbd_desc_iter_next(&iter);
     820           0 :         while (desc) {
     821           0 :                 if (desc->bDescriptorType != UDESC_CS_INTERFACE) {
     822           0 :                         desc = usbd_desc_iter_next(&iter);
     823           0 :                         continue;
     824             :                 }
     825             : 
     826           0 :                 switch (desc->bDescriptorSubtype) {
     827             :                 case UDESCSUB_VS_INPUT_HEADER:
     828           0 :                         if (!uvideo_desc_len(desc, 13, 3, 0, 12))
     829             :                                 break;
     830           0 :                         error = uvideo_vs_parse_desc_input_header(sc, desc);
     831           0 :                         if (error != USBD_NORMAL_COMPLETION)
     832           0 :                                 return (error);
     833             :                         break;
     834             : 
     835             :                 /* TODO: which VS descriptors do we need else? */
     836             :                 }
     837             : 
     838           0 :                 desc = usbd_desc_iter_next(&iter);
     839             :         }
     840             : 
     841             :         /* parse video stream format descriptors */
     842           0 :         error = uvideo_vs_parse_desc_format(sc);
     843           0 :         if (error != USBD_NORMAL_COMPLETION)
     844           0 :                 return (error);
     845             : 
     846             :         /* parse video stream frame descriptors */
     847           0 :         error = uvideo_vs_parse_desc_frame(sc);
     848           0 :         if (error != USBD_NORMAL_COMPLETION)
     849           0 :                 return (error);
     850             : 
     851             :         /* parse interface collection */
     852           0 :         for (i = 0; i < sc->sc_desc_vc_header.fix->bInCollection; i++) {
     853           0 :                 iface = sc->sc_desc_vc_header.baInterfaceNr[i];
     854             : 
     855           0 :                 id = usbd_get_interface_descriptor(&sc->sc_udev->ifaces[iface]);
     856           0 :                 if (id == NULL) {
     857           0 :                         printf("%s: can't get VS interface %d!\n",
     858           0 :                             DEVNAME(sc), iface);
     859           0 :                         return (USBD_INVAL);
     860             :                 }
     861           0 :                 usbd_claim_iface(sc->sc_udev, iface);
     862             : 
     863           0 :                 numalts = usbd_get_no_alts(cdesc, id->bInterfaceNumber);
     864             : 
     865             :                 DPRINTF(1, "%s: VS interface %d, ", DEVNAME(sc), i);
     866             :                 DPRINTF(1, "bInterfaceNumber=0x%02x, numalts=%d\n",
     867             :                     id->bInterfaceNumber, numalts);
     868             : 
     869           0 :                 error = uvideo_vs_parse_desc_alt(sc, i, iface, numalts);
     870           0 :                 if (error != USBD_NORMAL_COMPLETION)
     871           0 :                         return (error);
     872             :         }
     873             : 
     874             :         /* XXX for now always use the first video stream */
     875           0 :         sc->sc_vs_cur = &sc->sc_vs_coll[0];
     876             : 
     877           0 :         return (USBD_NORMAL_COMPLETION);
     878           0 : }
     879             : 
     880             : usbd_status
     881           0 : uvideo_vs_parse_desc_input_header(struct uvideo_softc *sc,
     882             :     const usb_descriptor_t *desc)
     883             : {
     884             :         struct usb_video_input_header_desc *d;
     885             : 
     886           0 :         d = (struct usb_video_input_header_desc *)(uint8_t *)desc;
     887             : 
     888             :         /* on some devices bNumFormats is larger than the truth */
     889           0 :         if (d->bNumFormats == 0) {
     890           0 :                 printf("%s: no INPUT FORMAT descriptors found!\n", DEVNAME(sc));
     891           0 :                 return (USBD_INVAL);
     892             :         }
     893             : 
     894           0 :         sc->sc_desc_vs_input_header.fix = d;
     895           0 :         sc->sc_desc_vs_input_header.bmaControls = (uByte *)(d + 1);
     896             : 
     897           0 :         return (USBD_NORMAL_COMPLETION);
     898           0 : }
     899             : 
     900             : usbd_status
     901           0 : uvideo_vs_parse_desc_format(struct uvideo_softc *sc)
     902             : {
     903           0 :         struct usbd_desc_iter iter;
     904             :         const usb_descriptor_t *desc;
     905             : 
     906             :         DPRINTF(1, "%s: %s\n", DEVNAME(sc), __func__);
     907             : 
     908           0 :         usbd_desc_iter_init(sc->sc_udev, &iter);
     909           0 :         desc = usbd_desc_iter_next(&iter);
     910           0 :         while (desc) {
     911           0 :                 if (desc->bDescriptorType != UDESC_CS_INTERFACE) {
     912           0 :                         desc = usbd_desc_iter_next(&iter);
     913           0 :                         continue;
     914             :                 }
     915             : 
     916           0 :                 switch (desc->bDescriptorSubtype) {
     917             :                 case UDESCSUB_VS_FORMAT_MJPEG:
     918           0 :                         if (desc->bLength == 11) {
     919           0 :                                 (void)uvideo_vs_parse_desc_format_mjpeg(
     920             :                                     sc, desc);
     921           0 :                         }
     922             :                         break;
     923             :                 case UDESCSUB_VS_FORMAT_UNCOMPRESSED:
     924           0 :                         if (desc->bLength == 27) {
     925           0 :                                 (void)uvideo_vs_parse_desc_format_uncompressed(
     926             :                                     sc, desc);
     927           0 :                         }
     928             :                         break;
     929             :                 }
     930             : 
     931           0 :                 desc = usbd_desc_iter_next(&iter);
     932             :         }
     933             : 
     934           0 :         sc->sc_fmtgrp_idx = 0;
     935             : 
     936           0 :         if (sc->sc_fmtgrp_num == 0) {
     937           0 :                 printf("%s: no format descriptors found!\n", DEVNAME(sc));
     938           0 :                 return (USBD_INVAL);
     939             :         }
     940             :         DPRINTF(1, "%s: number of total format descriptors=%d\n",
     941             :             DEVNAME(sc), sc->sc_fmtgrp_num);
     942             : 
     943           0 :         return (USBD_NORMAL_COMPLETION);
     944           0 : }
     945             : 
     946             : usbd_status
     947           0 : uvideo_vs_parse_desc_format_mjpeg(struct uvideo_softc *sc,
     948             :     const usb_descriptor_t *desc)
     949             : {
     950             :         struct usb_video_format_mjpeg_desc *d;
     951             : 
     952           0 :         d = (struct usb_video_format_mjpeg_desc *)(uint8_t *)desc;
     953             : 
     954           0 :         if (d->bNumFrameDescriptors == 0) {
     955           0 :                 printf("%s: no MJPEG frame descriptors available!\n",
     956           0 :                     DEVNAME(sc));
     957           0 :                 return (USBD_INVAL);
     958             :         }
     959             : 
     960           0 :         if (sc->sc_fmtgrp_idx >= UVIDEO_MAX_FORMAT) {
     961           0 :                 printf("%s: too many format descriptors found!\n", DEVNAME(sc));
     962           0 :                 return (USBD_INVAL);
     963             :         }
     964             : 
     965           0 :         sc->sc_fmtgrp[sc->sc_fmtgrp_idx].format =
     966           0 :             (struct uvideo_format_desc *)d;
     967           0 :         if (d->bDefaultFrameIndex > d->bNumFrameDescriptors ||
     968           0 :             d->bDefaultFrameIndex < 1) {
     969             :                 /* sanitize wrong bDefaultFrameIndex value */
     970           0 :                 sc->sc_fmtgrp[sc->sc_fmtgrp_idx].format_dfidx = 1;
     971           0 :         } else {
     972           0 :                 sc->sc_fmtgrp[sc->sc_fmtgrp_idx].format_dfidx =
     973             :                     d->bDefaultFrameIndex;
     974             :         }
     975           0 :         sc->sc_fmtgrp[sc->sc_fmtgrp_idx].pixelformat = V4L2_PIX_FMT_MJPEG;
     976             : 
     977           0 :         if (sc->sc_fmtgrp_cur == NULL)
     978             :                 /* set MJPEG format */
     979           0 :                 sc->sc_fmtgrp_cur = &sc->sc_fmtgrp[sc->sc_fmtgrp_idx];
     980             : 
     981           0 :         sc->sc_fmtgrp_idx++;
     982           0 :         sc->sc_fmtgrp_num++;
     983             : 
     984           0 :         return (USBD_NORMAL_COMPLETION);
     985           0 : }
     986             : 
     987             : usbd_status
     988           0 : uvideo_vs_parse_desc_format_uncompressed(struct uvideo_softc *sc,
     989             :     const usb_descriptor_t *desc)
     990             : {
     991             :         struct usb_video_format_uncompressed_desc *d;
     992             :         int i;
     993             : 
     994           0 :         d = (struct usb_video_format_uncompressed_desc *)(uint8_t *)desc;
     995             : 
     996           0 :         if (d->bNumFrameDescriptors == 0) {
     997           0 :                 printf("%s: no UNCOMPRESSED frame descriptors available!\n",
     998           0 :                     DEVNAME(sc));
     999           0 :                 return (USBD_INVAL);
    1000             :         }
    1001             : 
    1002           0 :         if (sc->sc_fmtgrp_idx >= UVIDEO_MAX_FORMAT) {
    1003           0 :                 printf("%s: too many format descriptors found!\n", DEVNAME(sc));
    1004           0 :                 return (USBD_INVAL);
    1005             :         }
    1006             : 
    1007           0 :         sc->sc_fmtgrp[sc->sc_fmtgrp_idx].format =
    1008           0 :             (struct uvideo_format_desc *)d;
    1009           0 :         if (d->bDefaultFrameIndex > d->bNumFrameDescriptors ||
    1010           0 :             d->bDefaultFrameIndex < 1) {
    1011             :                 /* sanitize wrong bDefaultFrameIndex value */
    1012           0 :                 sc->sc_fmtgrp[sc->sc_fmtgrp_idx].format_dfidx = 1;
    1013           0 :         } else {
    1014           0 :                 sc->sc_fmtgrp[sc->sc_fmtgrp_idx].format_dfidx =
    1015             :                     d->bDefaultFrameIndex;
    1016             :         }
    1017           0 :         i = sc->sc_fmtgrp_idx;
    1018           0 :         if (!strcmp(sc->sc_fmtgrp[i].format->u.uc.guidFormat, "YUY2")) {
    1019           0 :                 sc->sc_fmtgrp[i].pixelformat = V4L2_PIX_FMT_YUYV;
    1020           0 :         } else if (!strcmp(sc->sc_fmtgrp[i].format->u.uc.guidFormat, "NV12")) {
    1021           0 :                 sc->sc_fmtgrp[i].pixelformat = V4L2_PIX_FMT_NV12;
    1022           0 :         } else if (!strcmp(sc->sc_fmtgrp[i].format->u.uc.guidFormat, "UYVY")) {
    1023           0 :                 sc->sc_fmtgrp[i].pixelformat = V4L2_PIX_FMT_UYVY;
    1024           0 :         } else {
    1025           0 :                 sc->sc_fmtgrp[i].pixelformat = 0;
    1026             :         }
    1027             : 
    1028           0 :         if (sc->sc_fmtgrp_cur == NULL)
    1029             :                 /* set UNCOMPRESSED format */
    1030           0 :                 sc->sc_fmtgrp_cur = &sc->sc_fmtgrp[sc->sc_fmtgrp_idx];
    1031             : 
    1032           0 :         sc->sc_fmtgrp_idx++;
    1033           0 :         sc->sc_fmtgrp_num++;
    1034             : 
    1035           0 :         return (USBD_NORMAL_COMPLETION);
    1036           0 : }
    1037             : 
    1038             : usbd_status
    1039           0 : uvideo_vs_parse_desc_frame(struct uvideo_softc *sc)
    1040             : {
    1041           0 :         struct usbd_desc_iter iter;
    1042             :         const usb_descriptor_t *desc;
    1043             :         usbd_status error;
    1044             : 
    1045             :         DPRINTF(1, "%s: %s\n", DEVNAME(sc), __func__);
    1046             : 
    1047           0 :         usbd_desc_iter_init(sc->sc_udev, &iter);
    1048           0 :         desc = usbd_desc_iter_next(&iter);
    1049           0 :         while (desc) {
    1050           0 :                 if (desc->bDescriptorType == UDESC_CS_INTERFACE &&
    1051           0 :                     desc->bLength > sizeof(struct usb_video_frame_desc) &&
    1052           0 :                     (desc->bDescriptorSubtype == UDESCSUB_VS_FRAME_MJPEG ||
    1053           0 :                     desc->bDescriptorSubtype == UDESCSUB_VS_FRAME_UNCOMPRESSED)) {
    1054           0 :                         error = uvideo_vs_parse_desc_frame_sub(sc, desc);
    1055           0 :                         if (error != USBD_NORMAL_COMPLETION)
    1056           0 :                                 return (error);
    1057             :                 }
    1058           0 :                 desc = usbd_desc_iter_next(&iter);
    1059             :         }
    1060             : 
    1061           0 :         return (USBD_NORMAL_COMPLETION);
    1062           0 : }
    1063             : 
    1064             : usbd_status
    1065           0 : uvideo_vs_parse_desc_frame_sub(struct uvideo_softc *sc,
    1066             :     const usb_descriptor_t *desc)
    1067             : {
    1068             :         struct usb_video_frame_desc *fd = 
    1069           0 :             (struct usb_video_frame_desc *)(uint8_t *)desc;
    1070             :         int fmtidx, frame_num;
    1071             :         uint32_t fbuf_size;
    1072             : 
    1073           0 :         fmtidx = sc->sc_fmtgrp_idx;
    1074           0 :         frame_num = sc->sc_fmtgrp[fmtidx].frame_num;
    1075           0 :         if (frame_num >= UVIDEO_MAX_FRAME) {
    1076           0 :                 printf("%s: too many %s frame descriptors found!\n",
    1077           0 :                     DEVNAME(sc),
    1078           0 :                     desc->bDescriptorSubtype == UDESCSUB_VS_FRAME_MJPEG ?
    1079             :                     "MJPEG" : "UNCOMPRESSED");
    1080           0 :                 return (USBD_INVAL);
    1081             :         }
    1082           0 :         sc->sc_fmtgrp[fmtidx].frame[frame_num] = fd;
    1083             : 
    1084           0 :         if (sc->sc_fmtgrp[fmtidx].frame_cur == NULL ||
    1085           0 :             sc->sc_fmtgrp[fmtidx].format_dfidx == fd->bFrameIndex)
    1086           0 :                 sc->sc_fmtgrp[fmtidx].frame_cur = fd;
    1087             : 
    1088             :         /*
    1089             :          * On some devices, dwMaxVideoFrameBufferSize is not correct.
    1090             :          * Version 1.1 of the UVC spec says this field is deprecated.
    1091             :          * For uncompressed pixel formats, the frame buffer size can
    1092             :          * be determined by multiplying width, height, and bytes per pixel.
    1093             :          * Uncompressed formats have a fixed number of bytes per pixel.
    1094             :          * Bytes per pixel can vary with compressed formats.
    1095             :          */
    1096           0 :         if (desc->bDescriptorSubtype == UDESCSUB_VS_FRAME_UNCOMPRESSED) {
    1097           0 :                 fbuf_size = UGETW(fd->wWidth) * UGETW(fd->wHeight) *
    1098           0 :                     sc->sc_fmtgrp[fmtidx].format->u.uc.bBitsPerPixel / NBBY;
    1099             :                 DPRINTF(10, "%s: %s: frame buffer size=%d "
    1100             :                     "width=%d height=%d bpp=%d\n", DEVNAME(sc), __func__,
    1101             :                     fbuf_size, UGETW(fd->wWidth), UGETW(fd->wHeight),
    1102             :                     sc->sc_fmtgrp[fmtidx].format->u.uc.bBitsPerPixel);
    1103           0 :         } else
    1104           0 :                 fbuf_size = UGETDW(fd->dwMaxVideoFrameBufferSize);
    1105             : 
    1106             :         /* store max value */
    1107           0 :         if (fbuf_size > sc->sc_max_fbuf_size)
    1108           0 :                 sc->sc_max_fbuf_size = fbuf_size;
    1109             : 
    1110             :         /*
    1111             :          * Increment frame count.  If this is the last frame in the
    1112             :          * format group, go on to next group.
    1113             :          */
    1114           0 :         if (++sc->sc_fmtgrp[fmtidx].frame_num ==
    1115           0 :             sc->sc_fmtgrp[fmtidx].format->bNumFrameDescriptors) {
    1116           0 :                 sc->sc_fmtgrp_idx++;
    1117           0 :         }
    1118             : 
    1119           0 :         return (USBD_NORMAL_COMPLETION);
    1120           0 : }
    1121             : 
    1122             : usbd_status
    1123           0 : uvideo_vs_parse_desc_alt(struct uvideo_softc *sc, int vs_nr, int iface, int numalts)
    1124             : {
    1125             :         struct uvideo_vs_iface *vs;
    1126           0 :         struct usbd_desc_iter iter;
    1127             :         const usb_descriptor_t *desc;
    1128             :         usb_interface_descriptor_t *id;
    1129             :         usb_endpoint_descriptor_t *ed;
    1130             :         uint8_t ep_dir, ep_type;
    1131             : 
    1132           0 :         vs = &sc->sc_vs_coll[vs_nr];
    1133             : 
    1134           0 :         usbd_desc_iter_init(sc->sc_udev, &iter);
    1135           0 :         desc = usbd_desc_iter_next(&iter);
    1136           0 :         while (desc) {
    1137             :                 /* find video stream interface */
    1138           0 :                 if (desc->bDescriptorType != UDESC_INTERFACE)
    1139             :                         goto next;
    1140           0 :                 id = (usb_interface_descriptor_t *)(uint8_t *)desc;
    1141           0 :                 if (id->bInterfaceNumber != iface)
    1142             :                         goto next;
    1143             :                 DPRINTF(1, "%s: bAlternateSetting=0x%02x, ",
    1144             :                     DEVNAME(sc), id->bAlternateSetting);
    1145           0 :                 if (id->bNumEndpoints == 0) {
    1146             :                         DPRINTF(1, "no endpoint descriptor\n");
    1147             :                         goto next;
    1148             :                 }
    1149             : 
    1150             :                 /* jump to corresponding endpoint descriptor */
    1151           0 :                 while ((desc = usbd_desc_iter_next(&iter))) {
    1152           0 :                         if (desc->bDescriptorType == UDESC_ENDPOINT)
    1153             :                                 break;
    1154             :                 }
    1155           0 :                 ed = (usb_endpoint_descriptor_t *)(uint8_t *)desc;
    1156             :                 DPRINTF(1, "bEndpointAddress=0x%02x, ", ed->bEndpointAddress);
    1157             :                 DPRINTF(1, "wMaxPacketSize=%d\n", UGETW(ed->wMaxPacketSize));
    1158             : 
    1159             :                 /* locate endpoint type */
    1160           0 :                 ep_dir = UE_GET_DIR(ed->bEndpointAddress);
    1161           0 :                 ep_type = UE_GET_XFERTYPE(ed->bmAttributes);
    1162           0 :                 if (ep_dir == UE_DIR_IN && ep_type == UE_ISOCHRONOUS)
    1163           0 :                         vs->bulk_endpoint = 0;
    1164           0 :                 else if (ep_dir == UE_DIR_IN && ep_type == UE_BULK)
    1165           0 :                         vs->bulk_endpoint = 1;
    1166             :                 else
    1167             :                         goto next;
    1168             : 
    1169             :                 /* save endpoint with largest bandwidth */
    1170           0 :                 if (UGETW(ed->wMaxPacketSize) > vs->psize) {
    1171           0 :                         vs->ifaceh = &sc->sc_udev->ifaces[iface];
    1172           0 :                         vs->endpoint = ed->bEndpointAddress;
    1173           0 :                         vs->numalts = numalts;
    1174           0 :                         vs->curalt = id->bAlternateSetting;
    1175           0 :                         vs->psize = UGETW(ed->wMaxPacketSize);
    1176           0 :                         vs->iface = iface;
    1177           0 :                 }
    1178             : next:
    1179           0 :                 desc = usbd_desc_iter_next(&iter);
    1180             :         }
    1181             : 
    1182             :         /* check if we have found a valid alternate interface */
    1183           0 :         if (vs->ifaceh == NULL) {
    1184           0 :                 printf("%s: no valid alternate interface found!\n",
    1185           0 :                     DEVNAME(sc));
    1186           0 :                 return (USBD_INVAL);
    1187             :         }
    1188             : 
    1189           0 :         return (USBD_NORMAL_COMPLETION);
    1190           0 : }
    1191             : 
    1192             : usbd_status
    1193           0 : uvideo_vs_set_alt(struct uvideo_softc *sc, struct usbd_interface *ifaceh,
    1194             :     int max_packet_size)
    1195             : {
    1196           0 :         struct usbd_desc_iter iter;
    1197             :         const usb_descriptor_t *desc;
    1198             :         usb_interface_descriptor_t *id;
    1199             :         usb_endpoint_descriptor_t *ed;
    1200             :         int diff, best_diff = INT_MAX;
    1201             :         usbd_status error;
    1202             :         uint32_t psize;
    1203             : 
    1204           0 :         usbd_desc_iter_init(sc->sc_udev, &iter);
    1205           0 :         desc = usbd_desc_iter_next(&iter);
    1206           0 :         while (desc) {
    1207             :                 /* find video stream interface */
    1208           0 :                 if (desc->bDescriptorType != UDESC_INTERFACE)
    1209             :                         goto next;
    1210           0 :                 id = (usb_interface_descriptor_t *)(uint8_t *)desc;
    1211           0 :                 if (id->bInterfaceNumber != sc->sc_vs_cur->iface)
    1212             :                         goto next;
    1213           0 :                 if (id->bNumEndpoints == 0)
    1214             :                         goto next;
    1215             : 
    1216             :                 /* jump to corresponding endpoint descriptor */
    1217           0 :                 desc = usbd_desc_iter_next(&iter);
    1218           0 :                 if (desc->bDescriptorType != UDESC_ENDPOINT)
    1219             :                         goto next;
    1220           0 :                 ed = (usb_endpoint_descriptor_t *)(uint8_t *)desc;
    1221             : 
    1222             :                 /* save endpoint with requested bandwidth */
    1223           0 :                 psize = UGETW(ed->wMaxPacketSize);
    1224           0 :                 psize = UE_GET_SIZE(psize) * (1 + UE_GET_TRANS(psize));
    1225           0 :                 if (psize >= max_packet_size)
    1226           0 :                         diff = psize - max_packet_size;
    1227             :                 else
    1228             :                         goto next;
    1229           0 :                 if (diff < best_diff) {
    1230             :                         best_diff = diff;
    1231           0 :                         sc->sc_vs_cur->endpoint = ed->bEndpointAddress;
    1232           0 :                         sc->sc_vs_cur->curalt = id->bAlternateSetting;
    1233           0 :                         sc->sc_vs_cur->psize = psize;
    1234           0 :                         if (diff == 0)
    1235             :                                 break;
    1236             :                 }
    1237             : next:
    1238           0 :                 desc = usbd_desc_iter_next(&iter);
    1239             :         }
    1240             : 
    1241             :         DPRINTF(1, "%s: set alternate iface to ", DEVNAME(sc));
    1242             :         DPRINTF(1, "bAlternateSetting=0x%02x psize=%d max_packet_size=%d\n",
    1243             :             sc->sc_vs_cur->curalt, sc->sc_vs_cur->psize, max_packet_size);
    1244             : 
    1245             :         /* set alternate video stream interface */
    1246           0 :         error = usbd_set_interface(ifaceh, sc->sc_vs_cur->curalt);
    1247           0 :         if (error) {
    1248           0 :                 printf("%s: could not set alternate interface %d!\n",
    1249           0 :                     DEVNAME(sc), sc->sc_vs_cur->curalt);
    1250           0 :                 return (USBD_INVAL);
    1251             :         }
    1252             : 
    1253           0 :         return (USBD_NORMAL_COMPLETION);
    1254           0 : }
    1255             : 
    1256             : /*
    1257             :  * Thanks to the retarded USB Video Class specs there are different
    1258             :  * descriptors types with the same bDescriptorSubtype which makes
    1259             :  * it necessary to differ between those types by doing descriptor
    1260             :  * size dances :-(
    1261             :  *
    1262             :  * size_fix:            total size of the fixed structure part
    1263             :  * off_num_elements:    offset which tells the number of following elements
    1264             :  * size_element:        size of a single element
    1265             :  * off_size_element:    if size_element is 0 the element size is taken from
    1266             :  *                      this offset in the descriptor 
    1267             :  */
    1268             : int
    1269           0 : uvideo_desc_len(const usb_descriptor_t *desc,
    1270             :     int size_fix, int off_num_elements, int size_element, int off_size_element)
    1271             : {
    1272             :         uint8_t *buf;
    1273             :         int size_elements, size_total;
    1274             : 
    1275           0 :         if (desc->bLength < size_fix)
    1276           0 :                 return (0);
    1277             : 
    1278           0 :         buf = (uint8_t *)desc;
    1279             : 
    1280           0 :         if (size_element == 0)
    1281           0 :                 size_element = buf[off_size_element];
    1282             : 
    1283           0 :         size_elements = buf[off_num_elements] * size_element;
    1284           0 :         size_total = size_fix + size_elements;
    1285             : 
    1286           0 :         if (desc->bLength == size_total && size_elements != 0)
    1287           0 :                 return (1);
    1288             : 
    1289           0 :         return (0);
    1290           0 : }
    1291             : 
    1292             : /*
    1293             :  * Find the next best matching resolution which we can offer and
    1294             :  * return it.
    1295             :  */
    1296             : void
    1297           0 : uvideo_find_res(struct uvideo_softc *sc, int idx, int width, int height,
    1298             :     struct uvideo_res *r)
    1299             : {
    1300             :         int i, w, h, diff, diff_best, size_want, size_is;
    1301             : 
    1302           0 :         size_want = width * height;
    1303             : 
    1304           0 :         for (i = 0; i < sc->sc_fmtgrp[idx].frame_num; i++) {
    1305           0 :                 w = UGETW(sc->sc_fmtgrp[idx].frame[i]->wWidth);
    1306           0 :                 h = UGETW(sc->sc_fmtgrp[idx].frame[i]->wHeight);
    1307           0 :                 size_is = w * h;
    1308           0 :                 if (size_is > size_want)
    1309           0 :                         diff = size_is - size_want;
    1310             :                 else
    1311           0 :                         diff = size_want - size_is;
    1312           0 :                 if (i == 0)
    1313           0 :                         diff_best = diff;
    1314           0 :                 if (diff <= diff_best) {
    1315             :                         diff_best = diff;
    1316           0 :                         r->width = w;
    1317           0 :                         r->height = h;
    1318           0 :                         r->fidx = i;
    1319           0 :                 }
    1320             :                 DPRINTF(1, "%s: %s: frame index %d: width=%d, height=%d\n",
    1321             :                     DEVNAME(sc), __func__, i, w, h);
    1322             :         }
    1323           0 : }
    1324             : 
    1325             : usbd_status
    1326           0 : uvideo_vs_negotiation(struct uvideo_softc *sc, int commit)
    1327             : {
    1328             :         struct usb_video_probe_commit *pc;
    1329             :         struct uvideo_format_group *fmtgrp;
    1330             :         struct usb_video_header_desc *hd;
    1331             :         struct usb_video_frame_desc *frame;
    1332             :         uint8_t *p, *cur;
    1333           0 :         uint8_t probe_data[34];
    1334             :         uint32_t frame_ival, nivals, min, max, step, diff;
    1335             :         usbd_status error;
    1336             :         int i, ival_bytes, changed = 0;
    1337             : 
    1338           0 :         pc = (struct usb_video_probe_commit *)probe_data;
    1339             : 
    1340           0 :         fmtgrp = sc->sc_fmtgrp_cur;
    1341             : 
    1342             :         /* check if the format descriptor contains frame descriptors */
    1343           0 :         if (fmtgrp->frame_num == 0) {
    1344           0 :                 printf("%s: %s: no frame descriptors found!\n",
    1345           0 :                     __func__, DEVNAME(sc));
    1346           0 :                 return (USBD_INVAL);
    1347             :         }
    1348             : 
    1349             :         /* set probe */
    1350           0 :         bzero(probe_data, sizeof(probe_data));
    1351             :         /* hint that dwFrameInterval should be favored over other parameters */
    1352           0 :         USETW(pc->bmHint, 0x1);
    1353           0 :         pc->bFormatIndex = fmtgrp->format->bFormatIndex;
    1354           0 :         pc->bFrameIndex = fmtgrp->frame_cur->bFrameIndex;
    1355             :         /* dwFrameInterval: 30fps=333333, 15fps=666666, 10fps=1000000 */
    1356           0 :         frame_ival = UGETDW(fmtgrp->frame_cur->dwDefaultFrameInterval);
    1357           0 :         if (sc->sc_frame_rate != 0) {
    1358           0 :                 frame_ival = 10000000 / sc->sc_frame_rate;
    1359             :                 /* find closest matching interval the device supports */
    1360           0 :                 p = (uint8_t *)fmtgrp->frame_cur;
    1361           0 :                 p += sizeof(struct usb_video_frame_desc);
    1362           0 :                 nivals = fmtgrp->frame_cur->bFrameIntervalType;
    1363           0 :                 ival_bytes = fmtgrp->frame_cur->bLength -
    1364             :                     sizeof(struct usb_video_frame_desc);
    1365           0 :                 if (!nivals && (ival_bytes >= sizeof(uDWord) * 3)) {
    1366             :                         /* continuous */
    1367           0 :                         min = UGETDW(p);
    1368           0 :                         p += sizeof(uDWord);
    1369           0 :                         max = UGETDW(p);
    1370           0 :                         p += sizeof(uDWord);
    1371           0 :                         step = UGETDW(p);
    1372             :                         p += sizeof(uDWord);
    1373           0 :                         if (frame_ival <= min)
    1374           0 :                                 frame_ival = min;
    1375           0 :                         else if (frame_ival >= max)
    1376           0 :                                 frame_ival = max;
    1377             :                         else {
    1378           0 :                                 for (i = min; i + step/2 < frame_ival; i+= step)
    1379             :                                         ;       /* nothing */
    1380             :                                 frame_ival = i;
    1381             :                         }
    1382           0 :                 } else if (nivals > 0 && ival_bytes >= sizeof(uDWord)) {
    1383             :                         /* discrete */
    1384             :                         cur = p;
    1385             :                         min = UINT_MAX;
    1386           0 :                         for (i = 0; i < nivals; i++) {
    1387           0 :                                 if (ival_bytes < sizeof(uDWord)) {
    1388             :                                         /* short descriptor ? */
    1389             :                                         break;
    1390             :                                 }
    1391           0 :                                 diff = abs(UGETDW(p) - frame_ival);
    1392           0 :                                 if (diff < min) {
    1393             :                                         min = diff;
    1394             :                                         cur = p;
    1395           0 :                                         if (diff == 0)
    1396             :                                                 break;
    1397             :                                 }
    1398           0 :                                 p += sizeof(uDWord);
    1399           0 :                                 ival_bytes -= sizeof(uDWord);
    1400             :                         }
    1401           0 :                         frame_ival = UGETDW(cur);
    1402           0 :                 } else {
    1403             :                         DPRINTF(1, "%s: %s: bad frame ival descriptor\n",
    1404             :                             DEVNAME(sc), __func__);
    1405             :                 }
    1406             :         }
    1407           0 :         USETDW(pc->dwFrameInterval, frame_ival);
    1408           0 :         error = uvideo_vs_set_probe(sc, probe_data);
    1409           0 :         if (error != USBD_NORMAL_COMPLETION)
    1410           0 :                 return (error);
    1411             : 
    1412             :         /* get probe */
    1413           0 :         bzero(probe_data, sizeof(probe_data));
    1414           0 :         error = uvideo_vs_get_probe(sc, probe_data, GET_CUR);
    1415           0 :         if (error != USBD_NORMAL_COMPLETION)
    1416           0 :                 return (error);
    1417             : 
    1418             :         /* check that the format and frame indexes are what we wanted */
    1419           0 :         if (pc->bFormatIndex != fmtgrp->format->bFormatIndex) {
    1420             :                 changed++;
    1421             :                 DPRINTF(1, "%s: %s: wanted format 0x%x, got format 0x%x\n",
    1422             :                     DEVNAME(sc), __func__, fmtgrp->format->bFormatIndex,
    1423             :                     pc->bFormatIndex);
    1424           0 :                 for (i = 0; i < sc->sc_fmtgrp_num; i++) {
    1425           0 :                         if (sc->sc_fmtgrp[i].format->bFormatIndex ==
    1426           0 :                             pc->bFormatIndex) {
    1427             :                                 fmtgrp = &sc->sc_fmtgrp[i];
    1428           0 :                                 break;
    1429             :                         }
    1430             :                 }
    1431           0 :                 if (i == sc->sc_fmtgrp_num) {
    1432             :                         DPRINTF(1, "%s: %s: invalid format index 0x%x\n",
    1433             :                             DEVNAME(sc), __func__, pc->bFormatIndex);
    1434           0 :                         return (USBD_INVAL);
    1435             :                 }
    1436             :         }
    1437           0 :         if (pc->bFrameIndex != fmtgrp->frame_cur->bFrameIndex) {
    1438           0 :                 changed++;
    1439             :                 DPRINTF(1, "%s: %s: wanted frame 0x%x, got frame 0x%x\n",
    1440             :                     DEVNAME(sc), __func__, fmtgrp->frame_cur->bFrameIndex,
    1441             :                     pc->bFrameIndex);
    1442           0 :                 for (i = 0; i < fmtgrp->frame_num; i++) {
    1443           0 :                         if (fmtgrp->frame[i]->bFrameIndex == pc->bFrameIndex) {
    1444             :                                 frame = fmtgrp->frame[i];
    1445           0 :                                 break;
    1446             :                         }
    1447             :                 }
    1448           0 :                 if (i == fmtgrp->frame_num) {
    1449             :                         DPRINTF(1, "%s: %s: invalid frame index 0x%x\n",
    1450             :                             DEVNAME(sc), __func__, pc->bFrameIndex);
    1451           0 :                         return (USBD_INVAL);
    1452             :                 }
    1453             :         } else
    1454             :                 frame = fmtgrp->frame_cur;
    1455             : 
    1456             :         /*
    1457             :          * Uncompressed formats have fixed bits per pixel, which means
    1458             :          * the frame buffer size is fixed and can be calculated.  Because
    1459             :          * some devices return incorrect values, always override the
    1460             :          * the frame size with a calculated value.
    1461             :          */
    1462           0 :         if (frame->bDescriptorSubtype == UDESCSUB_VS_FRAME_UNCOMPRESSED) {
    1463           0 :                 USETDW(pc->dwMaxVideoFrameSize,
    1464             :                     UGETW(frame->wWidth) * UGETW(frame->wHeight) *
    1465             :                     fmtgrp->format->u.uc.bBitsPerPixel / NBBY);
    1466             :                 DPRINTF(1, "fixed dwMaxVideoFrameSize=%d, "
    1467             :                     "width=%d height=%d bpp=%d\n",
    1468             :                     UGETDW(pc->dwMaxVideoFrameSize),
    1469             :                     UGETW(frame->wWidth), UGETW(frame->wHeight),
    1470             :                     fmtgrp->format->u.uc.bBitsPerPixel);
    1471           0 :         } else {
    1472             :                 /*
    1473             :                  * Some UVC 1.00 devices return dwMaxVideoFrameSize = 0.
    1474             :                  * If so, fix it by format/frame descriptors.
    1475             :                  */
    1476           0 :                 hd = sc->sc_desc_vc_header.fix;
    1477           0 :                 if (UGETDW(pc->dwMaxVideoFrameSize) == 0 &&
    1478           0 :                     UGETW(hd->bcdUVC) < 0x0110 ) {
    1479             :                         DPRINTF(1, "%s: dwMaxVideoFrameSize == 0, fixed\n",
    1480             :                             DEVNAME(sc));
    1481           0 :                         USETDW(pc->dwMaxVideoFrameSize, 
    1482             :                             UGETDW(frame->dwMaxVideoFrameBufferSize));
    1483           0 :                 }
    1484             :         }
    1485             : 
    1486             :         /* commit */
    1487           0 :         if (commit) {
    1488           0 :                 if (changed > 0) {
    1489             :                         /* didn't get the frame format or size we wanted */
    1490           0 :                         return (USBD_INVAL);
    1491             :                 }
    1492           0 :                 error = uvideo_vs_set_commit(sc, probe_data);
    1493           0 :                 if (error != USBD_NORMAL_COMPLETION)
    1494           0 :                         return (error);
    1495             :         }
    1496             : 
    1497             :         /* save a copy of probe commit */
    1498           0 :         bcopy(pc, &sc->sc_desc_probe, sizeof(sc->sc_desc_probe));
    1499             : 
    1500           0 :         return (USBD_NORMAL_COMPLETION);
    1501           0 : }
    1502             : 
    1503             : usbd_status
    1504           0 : uvideo_vs_set_probe(struct uvideo_softc *sc, uint8_t *probe_data)
    1505             : {
    1506           0 :         usb_device_request_t req;
    1507             :         usbd_status error;
    1508             :         uint16_t tmp;
    1509             :         struct usb_video_probe_commit *pc;
    1510             : 
    1511           0 :         req.bmRequestType = UVIDEO_SET_IF;
    1512           0 :         req.bRequest = SET_CUR;
    1513             :         tmp = VS_PROBE_CONTROL;
    1514             :         tmp = tmp << 8;
    1515           0 :         USETW(req.wValue, tmp);
    1516           0 :         USETW(req.wIndex, sc->sc_vs_cur->iface);
    1517           0 :         USETW(req.wLength, 26);
    1518             : 
    1519             :         pc = (struct usb_video_probe_commit *)probe_data;
    1520             : 
    1521           0 :         error = usbd_do_request(sc->sc_udev, &req, probe_data);
    1522           0 :         if (error) {
    1523           0 :                 printf("%s: could not SET probe request: %s\n",
    1524           0 :                     DEVNAME(sc), usbd_errstr(error));
    1525           0 :                 return (USBD_INVAL);
    1526             :         }
    1527             :         DPRINTF(1, "%s: SET probe request successfully\n", DEVNAME(sc));
    1528             : 
    1529             :         DPRINTF(1, "bmHint=0x%02x\n", UGETW(pc->bmHint));
    1530             :         DPRINTF(1, "bFormatIndex=0x%02x\n", pc->bFormatIndex);
    1531             :         DPRINTF(1, "bFrameIndex=0x%02x\n", pc->bFrameIndex);
    1532             :         DPRINTF(1, "dwFrameInterval=%d (100ns units)\n",
    1533             :             UGETDW(pc->dwFrameInterval));
    1534             :         DPRINTF(1, "wKeyFrameRate=%d\n", UGETW(pc->wKeyFrameRate));
    1535             :         DPRINTF(1, "wPFrameRate=%d\n", UGETW(pc->wPFrameRate));
    1536             :         DPRINTF(1, "wCompQuality=%d\n", UGETW(pc->wCompQuality));
    1537             :         DPRINTF(1, "wCompWindowSize=%d\n", UGETW(pc->wCompWindowSize));
    1538             :         DPRINTF(1, "wDelay=%d (ms)\n", UGETW(pc->wDelay));
    1539             :         DPRINTF(1, "dwMaxVideoFrameSize=%d (bytes)\n",
    1540             :             UGETDW(pc->dwMaxVideoFrameSize));
    1541             :         DPRINTF(1, "dwMaxPayloadTransferSize=%d (bytes)\n",
    1542             :             UGETDW(pc->dwMaxPayloadTransferSize));
    1543             : 
    1544           0 :         return (USBD_NORMAL_COMPLETION);
    1545           0 : }
    1546             : 
    1547             : usbd_status
    1548           0 : uvideo_vs_get_probe(struct uvideo_softc *sc, uint8_t *probe_data,
    1549             :     uint8_t request)
    1550             : {
    1551           0 :         usb_device_request_t req;
    1552             :         usbd_status error;
    1553             :         uint16_t tmp;
    1554             :         struct usb_video_probe_commit *pc;
    1555             : 
    1556           0 :         req.bmRequestType = UVIDEO_GET_IF;
    1557           0 :         req.bRequest = request;
    1558             :         tmp = VS_PROBE_CONTROL;
    1559             :         tmp = tmp << 8;
    1560           0 :         USETW(req.wValue, tmp);
    1561           0 :         USETW(req.wIndex, sc->sc_vs_cur->iface);
    1562           0 :         USETW(req.wLength, 26);
    1563             : 
    1564             :         pc = (struct usb_video_probe_commit *)probe_data;
    1565             : 
    1566           0 :         error = usbd_do_request(sc->sc_udev, &req, probe_data);
    1567           0 :         if (error) {
    1568           0 :                 printf("%s: could not GET probe request: %s\n",
    1569           0 :                     DEVNAME(sc), usbd_errstr(error));
    1570           0 :                 return (USBD_INVAL);
    1571             :         }
    1572             :         DPRINTF(1, "%s: GET probe request successfully\n", DEVNAME(sc));
    1573             : 
    1574             :         DPRINTF(1, "bmHint=0x%02x\n", UGETW(pc->bmHint));
    1575             :         DPRINTF(1, "bFormatIndex=0x%02x\n", pc->bFormatIndex);
    1576             :         DPRINTF(1, "bFrameIndex=0x%02x\n", pc->bFrameIndex);
    1577             :         DPRINTF(1, "dwFrameInterval=%d (100ns units)\n",
    1578             :             UGETDW(pc->dwFrameInterval));
    1579             :         DPRINTF(1, "wKeyFrameRate=%d\n", UGETW(pc->wKeyFrameRate));
    1580             :         DPRINTF(1, "wPFrameRate=%d\n", UGETW(pc->wPFrameRate));
    1581             :         DPRINTF(1, "wCompQuality=%d\n", UGETW(pc->wCompQuality));
    1582             :         DPRINTF(1, "wCompWindowSize=%d\n", UGETW(pc->wCompWindowSize));
    1583             :         DPRINTF(1, "wDelay=%d (ms)\n", UGETW(pc->wDelay));
    1584             :         DPRINTF(1, "dwMaxVideoFrameSize=%d (bytes)\n",
    1585             :             UGETDW(pc->dwMaxVideoFrameSize));
    1586             :         DPRINTF(1, "dwMaxPayloadTransferSize=%d (bytes)\n",
    1587             :             UGETDW(pc->dwMaxPayloadTransferSize));
    1588             : 
    1589           0 :         return (USBD_NORMAL_COMPLETION);
    1590           0 : }
    1591             : 
    1592             : usbd_status
    1593           0 : uvideo_vs_set_commit(struct uvideo_softc *sc, uint8_t *probe_data)
    1594             : {
    1595           0 :         usb_device_request_t req;
    1596             :         usbd_status error;
    1597             :         uint16_t tmp;
    1598             : 
    1599           0 :         req.bmRequestType = UVIDEO_SET_IF;
    1600           0 :         req.bRequest = SET_CUR;
    1601             :         tmp = VS_COMMIT_CONTROL;
    1602             :         tmp = tmp << 8;
    1603           0 :         USETW(req.wValue, tmp);
    1604           0 :         USETW(req.wIndex, sc->sc_vs_cur->iface);
    1605           0 :         USETW(req.wLength, 26);
    1606             : 
    1607           0 :         error = usbd_do_request(sc->sc_udev, &req, probe_data);
    1608           0 :         if (error) {
    1609           0 :                 printf("%s: could not SET commit request: %s\n",
    1610           0 :                     DEVNAME(sc), usbd_errstr(error));
    1611           0 :                 return (USBD_INVAL);
    1612             :         }
    1613             :         DPRINTF(1, "%s: SET commit request successfully\n", DEVNAME(sc));
    1614             : 
    1615           0 :         return (USBD_NORMAL_COMPLETION);
    1616           0 : }
    1617             : 
    1618             : usbd_status
    1619           0 : uvideo_vs_alloc_frame(struct uvideo_softc *sc)
    1620             : {
    1621           0 :         struct uvideo_frame_buffer *fb = &sc->sc_frame_buffer;
    1622             : 
    1623           0 :         fb->buf_size = UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
    1624             : 
    1625             :         /* don't overflow the upper layer frame buffer */
    1626           0 :         if (sc->sc_max_fbuf_size < fb->buf_size &&
    1627           0 :             sc->sc_mmap_flag == 0) {
    1628           0 :                 printf("%s: software video buffer is too small!\n",
    1629           0 :                     DEVNAME(sc));
    1630           0 :                 return (USBD_NOMEM);
    1631             :         }
    1632             : 
    1633           0 :         fb->buf = malloc(fb->buf_size, M_DEVBUF, M_NOWAIT);
    1634           0 :         if (fb->buf == NULL) {
    1635           0 :                 printf("%s: can't allocate frame buffer!\n", DEVNAME(sc));
    1636           0 :                 return (USBD_NOMEM);
    1637             :         }
    1638             : 
    1639             :         DPRINTF(1, "%s: %s: allocated %d bytes frame buffer\n",
    1640             :             DEVNAME(sc), __func__, fb->buf_size);
    1641             : 
    1642           0 :         fb->sample = 0;
    1643           0 :         fb->fid = 0;
    1644           0 :         fb->offset = 0;
    1645           0 :         fb->fmt_flags = sc->sc_fmtgrp_cur->frame_cur->bDescriptorSubtype ==
    1646             :             UDESCSUB_VS_FRAME_UNCOMPRESSED ? 0 : V4L2_FMT_FLAG_COMPRESSED;
    1647             : 
    1648           0 :         return (USBD_NORMAL_COMPLETION);
    1649           0 : }
    1650             : 
    1651             : void
    1652           0 : uvideo_vs_free_frame(struct uvideo_softc *sc)
    1653             : {
    1654           0 :         struct uvideo_frame_buffer *fb = &sc->sc_frame_buffer;
    1655             : 
    1656           0 :         if (fb->buf != NULL) {
    1657           0 :                 free(fb->buf, M_DEVBUF, fb->buf_size);
    1658           0 :                 fb->buf = NULL;
    1659           0 :         }
    1660             : 
    1661           0 :         if (sc->sc_mmap_buffer != NULL) {
    1662           0 :                 free(sc->sc_mmap_buffer, M_DEVBUF, sc->sc_mmap_buffer_size);
    1663           0 :                 sc->sc_mmap_buffer = NULL;
    1664           0 :                 sc->sc_mmap_buffer_size = 0;
    1665           0 :         }
    1666             : 
    1667           0 :         while (!SIMPLEQ_EMPTY(&sc->sc_mmap_q))
    1668           0 :                 SIMPLEQ_REMOVE_HEAD(&sc->sc_mmap_q, q_frames);
    1669             : 
    1670           0 :         sc->sc_mmap_count = 0;
    1671           0 : }
    1672             : 
    1673             : usbd_status
    1674           0 : uvideo_vs_alloc_isoc(struct uvideo_softc *sc)
    1675             : {
    1676             :         int size, i;
    1677             : 
    1678             :         DPRINTF(1, "%s: %s\n", DEVNAME(sc), __func__);
    1679             : 
    1680           0 :         for (i = 0; i < UVIDEO_IXFERS; i++) {
    1681           0 :                 sc->sc_vs_cur->ixfer[i].sc = sc;
    1682             : 
    1683           0 :                 sc->sc_vs_cur->ixfer[i].xfer = usbd_alloc_xfer(sc->sc_udev);   
    1684           0 :                 if (sc->sc_vs_cur->ixfer[i].xfer == NULL) {
    1685           0 :                         printf("%s: could not allocate isoc VS xfer!\n",
    1686           0 :                             DEVNAME(sc));
    1687           0 :                         return (USBD_NOMEM);    
    1688             :                 }
    1689             : 
    1690           0 :                 size = sc->sc_vs_cur->psize * sc->sc_nframes;
    1691             : 
    1692           0 :                 sc->sc_vs_cur->ixfer[i].buf =
    1693           0 :                     usbd_alloc_buffer(sc->sc_vs_cur->ixfer[i].xfer, size);
    1694           0 :                 if (sc->sc_vs_cur->ixfer[i].buf == NULL) {
    1695           0 :                         printf("%s: could not allocate isoc VS buffer!\n",
    1696           0 :                             DEVNAME(sc));
    1697           0 :                         return (USBD_NOMEM);
    1698             :                 }
    1699             :                 DPRINTF(1, "%s: allocated %d bytes isoc VS xfer buffer\n",
    1700             :                     DEVNAME(sc), size);
    1701             :         }
    1702             : 
    1703           0 :         return (USBD_NORMAL_COMPLETION);
    1704           0 : }
    1705             : 
    1706             : usbd_status
    1707           0 : uvideo_vs_alloc_bulk(struct uvideo_softc *sc)
    1708             : {
    1709             :         int size;
    1710             : 
    1711           0 :         sc->sc_vs_cur->bxfer.sc = sc;
    1712             : 
    1713           0 :         sc->sc_vs_cur->bxfer.xfer = usbd_alloc_xfer(sc->sc_udev);
    1714           0 :         if (sc->sc_vs_cur->bxfer.xfer == NULL) {
    1715           0 :                 printf("%s: could not allocate bulk VS xfer!\n",
    1716           0 :                     DEVNAME(sc));
    1717           0 :                 return (USBD_NOMEM);
    1718             :         }
    1719             : 
    1720           0 :         size = UGETDW(sc->sc_desc_probe.dwMaxPayloadTransferSize);
    1721             : 
    1722           0 :         sc->sc_vs_cur->bxfer.buf =
    1723           0 :             usbd_alloc_buffer(sc->sc_vs_cur->bxfer.xfer, size);
    1724           0 :         if (sc->sc_vs_cur->bxfer.buf == NULL) {
    1725           0 :                 printf("%s: could not allocate bulk VS buffer!\n",
    1726           0 :                     DEVNAME(sc));
    1727           0 :                 return (USBD_NOMEM);
    1728             :         }
    1729             :         DPRINTF(1, "%s: allocated %d bytes bulk VS xfer buffer\n",
    1730             :             DEVNAME(sc), size);
    1731             : 
    1732           0 :         return (USBD_NORMAL_COMPLETION);
    1733           0 : }
    1734             : 
    1735             : void
    1736           0 : uvideo_vs_free_isoc(struct uvideo_softc *sc)
    1737             : {
    1738             :         int i;
    1739             : 
    1740             :         DPRINTF(1, "%s: %s\n", DEVNAME(sc), __func__);
    1741             : 
    1742           0 :         for (i = 0; i < UVIDEO_IXFERS; i++) {
    1743           0 :                 if (sc->sc_vs_cur->ixfer[i].buf != NULL) {
    1744           0 :                         usbd_free_buffer(sc->sc_vs_cur->ixfer[i].xfer);
    1745           0 :                         sc->sc_vs_cur->ixfer[i].buf = NULL;
    1746           0 :                 }
    1747             : 
    1748           0 :                 if (sc->sc_vs_cur->ixfer[i].xfer != NULL) {
    1749           0 :                         usbd_free_xfer(sc->sc_vs_cur->ixfer[i].xfer);
    1750           0 :                         sc->sc_vs_cur->ixfer[i].xfer = NULL;
    1751           0 :                 }
    1752             :         }
    1753           0 : }
    1754             : 
    1755             : void
    1756           0 : uvideo_vs_free_bulk(struct uvideo_softc *sc)
    1757             : {
    1758           0 :         if (sc->sc_vs_cur->bxfer.buf != NULL) {
    1759           0 :                 usbd_free_buffer(sc->sc_vs_cur->bxfer.xfer);
    1760           0 :                 sc->sc_vs_cur->bxfer.buf = NULL;
    1761           0 :         }
    1762             : 
    1763           0 :         if (sc->sc_vs_cur->bxfer.xfer != NULL) {
    1764           0 :                 usbd_free_xfer(sc->sc_vs_cur->bxfer.xfer);
    1765           0 :                 sc->sc_vs_cur->bxfer.xfer = NULL;
    1766           0 :         }
    1767           0 : }
    1768             : 
    1769             : usbd_status
    1770           0 : uvideo_vs_open(struct uvideo_softc *sc)
    1771             : {
    1772             :         usb_endpoint_descriptor_t *ed;
    1773             :         usbd_status error;
    1774             :         uint32_t dwMaxVideoFrameSize;
    1775             : 
    1776             :         DPRINTF(1, "%s: %s\n", DEVNAME(sc), __func__);
    1777             : 
    1778           0 :         if (sc->sc_negotiated_flag == 0) {
    1779             :                 /* do device negotiation with commit */
    1780           0 :                 error = uvideo_vs_negotiation(sc, 1);
    1781           0 :                 if (error != USBD_NORMAL_COMPLETION)
    1782           0 :                         return (error);
    1783             :         }
    1784             : 
    1785           0 :         error = uvideo_vs_set_alt(sc, sc->sc_vs_cur->ifaceh,
    1786           0 :             UGETDW(sc->sc_desc_probe.dwMaxPayloadTransferSize));
    1787           0 :         if (error != USBD_NORMAL_COMPLETION) {
    1788           0 :                 printf("%s: could not set alternate interface!\n",
    1789           0 :                     DEVNAME(sc));
    1790           0 :                 return (error);
    1791             :         }
    1792             : 
    1793             :         /* double check if we can access the selected endpoint descriptor */
    1794           0 :         ed = usbd_get_endpoint_descriptor(sc->sc_vs_cur->ifaceh,
    1795           0 :             sc->sc_vs_cur->endpoint);
    1796           0 :         if (ed == NULL) {
    1797           0 :                 printf("%s: no endpoint descriptor for VS iface\n",
    1798           0 :                     DEVNAME(sc));
    1799           0 :                 return (USBD_INVAL);
    1800             :         }
    1801             : 
    1802             :         DPRINTF(1, "%s: open pipe for bEndpointAddress=0x%02x\n",
    1803             :             DEVNAME(sc), sc->sc_vs_cur->endpoint);
    1804           0 :         error = usbd_open_pipe(
    1805           0 :             sc->sc_vs_cur->ifaceh,
    1806           0 :             sc->sc_vs_cur->endpoint,
    1807             :             USBD_EXCLUSIVE_USE,
    1808           0 :             &sc->sc_vs_cur->pipeh);
    1809           0 :         if (error != USBD_NORMAL_COMPLETION) {
    1810           0 :                 printf("%s: could not open VS pipe: %s\n",
    1811           0 :                     DEVNAME(sc), usbd_errstr(error));
    1812           0 :                 return (error);
    1813             :         }
    1814             : 
    1815             :         /* calculate optimal isoc xfer size */
    1816           0 :         if (strcmp(sc->sc_udev->bus->bdev.dv_cfdata->cf_driver->cd_name,
    1817           0 :             "ohci") == 0) {
    1818             :                 /* ohci workaround */
    1819           0 :                 sc->sc_nframes = 8;
    1820           0 :         } else {
    1821             :                 dwMaxVideoFrameSize =
    1822           0 :                     UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
    1823           0 :                 sc->sc_nframes = (dwMaxVideoFrameSize + sc->sc_vs_cur->psize -
    1824           0 :                     1) / sc->sc_vs_cur->psize;
    1825             :         }
    1826           0 :         if (sc->sc_nframes > UVIDEO_NFRAMES_MAX)
    1827           0 :                 sc->sc_nframes = UVIDEO_NFRAMES_MAX;
    1828             :         DPRINTF(1, "%s: nframes=%d\n", DEVNAME(sc), sc->sc_nframes);
    1829             : 
    1830           0 :         return (USBD_NORMAL_COMPLETION);
    1831           0 : }
    1832             : 
    1833             : void
    1834           0 : uvideo_vs_close(struct uvideo_softc *sc)
    1835             : {
    1836           0 :         if (sc->sc_vs_cur->bulk_running == 1) {
    1837           0 :                 sc->sc_vs_cur->bulk_running = 0;
    1838           0 :                 usbd_ref_wait(sc->sc_udev);
    1839           0 :         }
    1840             : 
    1841           0 :         if (sc->sc_vs_cur->pipeh) {
    1842           0 :                 usbd_abort_pipe(sc->sc_vs_cur->pipeh);
    1843           0 :                 usbd_close_pipe(sc->sc_vs_cur->pipeh);
    1844           0 :                 sc->sc_vs_cur->pipeh = NULL;
    1845           0 :         }
    1846             : 
    1847             :         /*
    1848             :          * Some devices need time to shutdown before we switch back to
    1849             :          * the default interface (0).  Not doing so can leave the device
    1850             :          * back in a undefined condition.
    1851             :          */
    1852           0 :         usbd_delay_ms(sc->sc_udev, 100);
    1853             : 
    1854             :         /* switch back to default interface (turns off cam LED) */
    1855           0 :         (void)usbd_set_interface(sc->sc_vs_cur->ifaceh, 0);
    1856           0 : }
    1857             : 
    1858             : usbd_status
    1859           0 : uvideo_vs_init(struct uvideo_softc *sc)
    1860             : {
    1861             :         usbd_status error;
    1862             : 
    1863             :         /* open video stream pipe */
    1864           0 :         error = uvideo_vs_open(sc);
    1865           0 :         if (error != USBD_NORMAL_COMPLETION)
    1866           0 :                 return (USBD_INVAL);
    1867             : 
    1868             :         /* allocate video stream xfer buffer */
    1869           0 :         if (sc->sc_vs_cur->bulk_endpoint)
    1870           0 :                 error = uvideo_vs_alloc_bulk(sc);
    1871             :         else
    1872           0 :                 error = uvideo_vs_alloc_isoc(sc);
    1873           0 :         if (error != USBD_NORMAL_COMPLETION)
    1874           0 :                 return (USBD_INVAL);
    1875             : 
    1876             :         /* allocate video stream frame buffer */
    1877           0 :         error = uvideo_vs_alloc_frame(sc);
    1878           0 :         if (error != USBD_NORMAL_COMPLETION)
    1879           0 :                 return (USBD_INVAL);
    1880             : #ifdef UVIDEO_DUMP
    1881             :         if (uvideo_debug_file_open(sc) != 0)
    1882             :                 return (USBD_INVAL);
    1883             :         usb_init_task(&sc->sc_task_write, uvideo_debug_file_write_frame, sc,
    1884             :             USB_TASK_TYPE_GENERIC);
    1885             : #endif
    1886           0 :         return (USBD_NORMAL_COMPLETION);
    1887           0 : }
    1888             : 
    1889             : int
    1890           0 : uvideo_vs_start_bulk(struct uvideo_softc *sc)
    1891             : {
    1892             :         int error;
    1893             : 
    1894           0 :         sc->sc_vs_cur->bulk_running = 1;
    1895             : 
    1896           0 :         error = kthread_create(uvideo_vs_start_bulk_thread, sc, NULL,
    1897           0 :             DEVNAME(sc));
    1898           0 :         if (error) {
    1899           0 :                 printf("%s: can't create kernel thread!", DEVNAME(sc));
    1900           0 :                 return (error);
    1901             :         }
    1902             : 
    1903           0 :         return (0);
    1904           0 : }
    1905             : 
    1906             : void
    1907           0 : uvideo_vs_start_bulk_thread(void *arg)
    1908             : {
    1909           0 :         struct uvideo_softc *sc = arg;
    1910             :         usbd_status error;
    1911             :         int size;
    1912             : 
    1913           0 :         usbd_ref_incr(sc->sc_udev);
    1914           0 :         while (sc->sc_vs_cur->bulk_running) {
    1915           0 :                 size = UGETDW(sc->sc_desc_probe.dwMaxPayloadTransferSize);
    1916             : 
    1917           0 :                 usbd_setup_xfer(
    1918           0 :                     sc->sc_vs_cur->bxfer.xfer,
    1919           0 :                     sc->sc_vs_cur->pipeh,
    1920             :                     0,
    1921           0 :                     sc->sc_vs_cur->bxfer.buf,
    1922             :                     size,
    1923             :                     USBD_NO_COPY | USBD_SHORT_XFER_OK | USBD_SYNCHRONOUS,
    1924             :                     0,
    1925             :                     NULL);
    1926           0 :                 error = usbd_transfer(sc->sc_vs_cur->bxfer.xfer);
    1927           0 :                 if (error != USBD_NORMAL_COMPLETION) {
    1928             :                         DPRINTF(1, "%s: error in bulk xfer: %s!\n",
    1929             :                             DEVNAME(sc), usbd_errstr(error));
    1930             :                         break;
    1931             :                 }
    1932             : 
    1933             :                 DPRINTF(2, "%s: *** buffer len = %d\n", DEVNAME(sc), size);
    1934             : 
    1935           0 :                 (void)sc->sc_decode_stream_header(sc,
    1936           0 :                     sc->sc_vs_cur->bxfer.buf, size);
    1937             :         }
    1938           0 :         usbd_ref_decr(sc->sc_udev);
    1939             : 
    1940           0 :         kthread_exit(0);
    1941             : }
    1942             : 
    1943             : void
    1944           0 : uvideo_vs_start_isoc(struct uvideo_softc *sc)
    1945             : {
    1946             :         int i;
    1947             : 
    1948           0 :         for (i = 0; i < UVIDEO_IXFERS; i++)
    1949           0 :                 uvideo_vs_start_isoc_ixfer(sc, &sc->sc_vs_cur->ixfer[i]);
    1950           0 : }
    1951             : 
    1952             : void
    1953           0 : uvideo_vs_start_isoc_ixfer(struct uvideo_softc *sc,
    1954             :     struct uvideo_isoc_xfer *ixfer)
    1955             : {
    1956             :         int i;
    1957             :         usbd_status error;
    1958             : 
    1959             :         DPRINTF(2, "%s: %s\n", DEVNAME(sc), __func__);
    1960             : 
    1961           0 :         if (usbd_is_dying(sc->sc_udev))
    1962           0 :                 return;
    1963             : 
    1964           0 :         for (i = 0; i < sc->sc_nframes; i++)
    1965           0 :                 ixfer->size[i] = sc->sc_vs_cur->psize;
    1966             : 
    1967           0 :         usbd_setup_isoc_xfer(
    1968           0 :             ixfer->xfer,
    1969           0 :             sc->sc_vs_cur->pipeh,
    1970           0 :             ixfer,
    1971           0 :             ixfer->size,
    1972             :             sc->sc_nframes,
    1973             :             USBD_NO_COPY | USBD_SHORT_XFER_OK,
    1974             :             uvideo_vs_cb);
    1975             : 
    1976           0 :         error = usbd_transfer(ixfer->xfer);
    1977           0 :         if (error && error != USBD_IN_PROGRESS) {
    1978             :                 DPRINTF(1, "%s: usbd_transfer error=%s!\n",
    1979             :                     DEVNAME(sc), usbd_errstr(error));
    1980             :         }
    1981           0 : }
    1982             : 
    1983             : void
    1984           0 : uvideo_vs_cb(struct usbd_xfer *xfer, void *priv,
    1985             :     usbd_status status)
    1986             : {
    1987           0 :         struct uvideo_isoc_xfer *ixfer = priv;
    1988           0 :         struct uvideo_softc *sc = ixfer->sc;
    1989           0 :         int len, i, frame_size;
    1990             :         uint8_t *frame;
    1991             :         usbd_status error;
    1992             : 
    1993             :         DPRINTF(2, "%s: %s\n", DEVNAME(sc), __func__);
    1994             : 
    1995           0 :         if (status != USBD_NORMAL_COMPLETION) {
    1996             :                 DPRINTF(1, "%s: %s: %s\n", DEVNAME(sc), __func__,
    1997             :                     usbd_errstr(status));
    1998           0 :                 return;
    1999             :         }
    2000           0 :         usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
    2001             : 
    2002             :         DPRINTF(2, "%s: *** buffer len = %d\n", DEVNAME(sc), len);
    2003           0 :         if (len == 0)
    2004             :                 goto skip;
    2005             : 
    2006           0 :         for (i = 0; i < sc->sc_nframes; i++) {
    2007           0 :                 frame = ixfer->buf + (i * sc->sc_vs_cur->psize);
    2008           0 :                 frame_size = ixfer->size[i];
    2009             : 
    2010           0 :                 if (frame_size == 0)
    2011             :                         /* frame is empty */
    2012             :                         continue;
    2013             : 
    2014           0 :                 error = sc->sc_decode_stream_header(sc, frame, frame_size);
    2015           0 :                 if (error == USBD_CANCELLED)
    2016             :                         break;
    2017             :         }
    2018             : 
    2019             : skip:   /* setup new transfer */
    2020           0 :         uvideo_vs_start_isoc_ixfer(sc, ixfer);
    2021           0 : }
    2022             : 
    2023             : usbd_status
    2024           0 : uvideo_vs_decode_stream_header(struct uvideo_softc *sc, uint8_t *frame,
    2025             :     int frame_size)
    2026             : {
    2027           0 :         struct uvideo_frame_buffer *fb = &sc->sc_frame_buffer;
    2028             :         struct usb_video_stream_header *sh;
    2029             :         int sample_len;
    2030             : 
    2031           0 :         if (frame_size < UVIDEO_SH_MIN_LEN)
    2032             :                 /* frame too small to contain a valid stream header */
    2033           0 :                 return (USBD_INVAL);
    2034             : 
    2035           0 :         sh = (struct usb_video_stream_header *)frame;
    2036             : 
    2037             :         DPRINTF(2, "%s: stream header len = %d\n", DEVNAME(sc), sh->bLength);
    2038             : 
    2039           0 :         if (sh->bLength > UVIDEO_SH_MAX_LEN || sh->bLength < UVIDEO_SH_MIN_LEN)
    2040             :                 /* invalid header size */
    2041           0 :                 return (USBD_INVAL);
    2042           0 :         if (sh->bLength == frame_size && !(sh->bFlags & UVIDEO_SH_FLAG_EOF)) {
    2043             :                 /* stream header without payload and no EOF */
    2044           0 :                 return (USBD_INVAL);
    2045             :         }
    2046           0 :         if (sh->bFlags & UVIDEO_SH_FLAG_ERR) {
    2047             :                 /* stream error, skip xfer */
    2048             :                 DPRINTF(1, "%s: %s: stream error!\n", DEVNAME(sc), __func__);
    2049           0 :                 return (USBD_CANCELLED);
    2050             :         }
    2051             : 
    2052             :         DPRINTF(2, "%s: frame_size = %d\n", DEVNAME(sc), frame_size);
    2053             : 
    2054             :         if (sh->bFlags & UVIDEO_SH_FLAG_FID) {
    2055             :                 DPRINTF(2, "%s: %s: FID ON (0x%02x)\n",
    2056             :                     DEVNAME(sc), __func__,
    2057             :                     sh->bFlags & UVIDEO_SH_FLAG_FID);
    2058             :         } else {
    2059             :                 DPRINTF(2, "%s: %s: FID OFF (0x%02x)\n",
    2060             :                     DEVNAME(sc), __func__,
    2061             :                     sh->bFlags & UVIDEO_SH_FLAG_FID);
    2062             :         }
    2063             : 
    2064           0 :         if (fb->sample == 0) {
    2065             :                 /* first sample for a frame */
    2066           0 :                 fb->sample = 1;
    2067           0 :                 fb->fid = sh->bFlags & UVIDEO_SH_FLAG_FID;
    2068           0 :                 fb->offset = 0;
    2069           0 :         } else {
    2070             :                 /* continues sample for a frame, check consistency */
    2071           0 :                 if (fb->fid != (sh->bFlags & UVIDEO_SH_FLAG_FID)) {
    2072             :                         DPRINTF(1, "%s: %s: wrong FID, ignore last frame!\n",
    2073             :                             DEVNAME(sc), __func__);
    2074           0 :                         fb->sample = 1;
    2075           0 :                         fb->fid = sh->bFlags & UVIDEO_SH_FLAG_FID;
    2076           0 :                         fb->offset = 0;
    2077           0 :                 }
    2078             :         }
    2079             : 
    2080             :         /* save sample */
    2081           0 :         sample_len = frame_size - sh->bLength;
    2082           0 :         if ((fb->offset + sample_len) <= fb->buf_size) {
    2083           0 :                 bcopy(frame + sh->bLength, fb->buf + fb->offset, sample_len);
    2084           0 :                 fb->offset += sample_len;
    2085           0 :         }
    2086             : 
    2087           0 :         if (sh->bFlags & UVIDEO_SH_FLAG_EOF) {
    2088             :                 /* got a full frame */
    2089             :                 DPRINTF(2, "%s: %s: EOF (frame size = %d bytes)\n",
    2090             :                     DEVNAME(sc), __func__, fb->offset);
    2091             : 
    2092           0 :                 if (fb->offset > fb->buf_size) {
    2093             :                         DPRINTF(1, "%s: %s: frame too large, skipped!\n",
    2094             :                             DEVNAME(sc), __func__);
    2095           0 :                 } else if (fb->offset < fb->buf_size &&
    2096           0 :                     !(fb->fmt_flags & V4L2_FMT_FLAG_COMPRESSED)) {
    2097             :                         DPRINTF(1, "%s: %s: frame too small, skipped!\n",
    2098             :                             DEVNAME(sc), __func__);
    2099             :                 } else {
    2100             : #ifdef UVIDEO_DUMP
    2101             :                         /* do the file write in process context */
    2102             :                         usb_rem_task(sc->sc_udev, &sc->sc_task_write);
    2103             :                         usb_add_task(sc->sc_udev, &sc->sc_task_write);
    2104             : #endif
    2105           0 :                         if (sc->sc_mmap_flag) {
    2106             :                                 /* mmap */
    2107           0 :                                 if (uvideo_mmap_queue(sc, fb->buf, fb->offset))
    2108           0 :                                         return (USBD_NOMEM);
    2109             :                         } else {
    2110             :                                 /* read */
    2111           0 :                                 uvideo_read(sc, fb->buf, fb->offset);
    2112             :                         }
    2113             :                 }
    2114             : 
    2115           0 :                 fb->sample = 0;
    2116           0 :                 fb->fid = 0;
    2117           0 :         }
    2118             : 
    2119           0 :         return (USBD_NORMAL_COMPLETION);
    2120           0 : }
    2121             : 
    2122             : /*
    2123             :  * XXX Doesn't work yet.  Fix it!
    2124             :  *
    2125             :  * The iSight first generation device uses a own, non-standard streaming
    2126             :  * protocol.  The stream header is just sent once per image and looks
    2127             :  * like following:
    2128             :  *
    2129             :  *      uByte   header length
    2130             :  *      uByte   flags
    2131             :  *      uByte   magic1[4]       always "11223344"
    2132             :  *      uByte   magic2[8]       always "deadbeefdeadface"
    2133             :  *      uByte   unknown[16]
    2134             :  *
    2135             :  * Sometimes the stream header is prefixed by a unknown byte.  Therefore
    2136             :  * we check for the magic value on two offsets.
    2137             :  */
    2138             : usbd_status
    2139           0 : uvideo_vs_decode_stream_header_isight(struct uvideo_softc *sc, uint8_t *frame,
    2140             :     int frame_size)
    2141             : {
    2142           0 :         struct uvideo_frame_buffer *fb = &sc->sc_frame_buffer;
    2143             :         int sample_len, header = 0;
    2144           0 :         uint8_t magic[] = {
    2145             :             0x11, 0x22, 0x33, 0x44,
    2146             :             0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xfa, 0xce };
    2147             : 
    2148           0 :         if (frame_size > 13 && !memcmp(&frame[2], magic, 12))
    2149           0 :                 header = 1;
    2150           0 :         if (frame_size > 14 && !memcmp(&frame[3], magic, 12))
    2151           0 :                 header = 1;
    2152             : 
    2153           0 :         if (header && fb->fid == 0) {
    2154           0 :                 fb->fid = 1;
    2155           0 :                 return (USBD_NORMAL_COMPLETION);
    2156             :         }
    2157             : 
    2158           0 :         if (header) {
    2159           0 :                 if (sc->sc_mmap_flag) {
    2160             :                         /* mmap */
    2161           0 :                         if (uvideo_mmap_queue(sc, fb->buf, fb->offset))
    2162           0 :                                 return (USBD_NOMEM);
    2163             :                 } else {
    2164             :                         /* read */
    2165           0 :                         uvideo_read(sc, fb->buf, fb->offset);
    2166             :                 }
    2167           0 :                 fb->offset = 0;
    2168           0 :         } else {
    2169             :                 /* save sample */
    2170             :                 sample_len = frame_size;
    2171           0 :                 if ((fb->offset + sample_len) <= fb->buf_size) {
    2172           0 :                         bcopy(frame, fb->buf + fb->offset, sample_len);
    2173           0 :                         fb->offset += sample_len;
    2174           0 :                 }
    2175             :         }
    2176             : 
    2177           0 :         return (USBD_NORMAL_COMPLETION);
    2178           0 : }
    2179             : 
    2180             : int
    2181           0 : uvideo_mmap_queue(struct uvideo_softc *sc, uint8_t *buf, int len)
    2182             : {
    2183             :         int i;
    2184             : 
    2185           0 :         if (sc->sc_mmap_count == 0 || sc->sc_mmap_buffer == NULL)
    2186           0 :                 panic("%s: mmap buffers not allocated", __func__);
    2187             : 
    2188             :         /* find a buffer which is ready for queueing */
    2189           0 :         for (i = 0; i < sc->sc_mmap_count; i++) {
    2190           0 :                 if (sc->sc_mmap[i].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)
    2191             :                         break;
    2192             :         }
    2193           0 :         if (i == sc->sc_mmap_count) {
    2194             :                 DPRINTF(1, "%s: %s: mmap queue is full!",
    2195             :                     DEVNAME(sc), __func__);
    2196           0 :                 return ENOMEM;
    2197             :         }
    2198             : 
    2199             :         /* copy frame to mmap buffer and report length */
    2200           0 :         bcopy(buf, sc->sc_mmap[i].buf, len);
    2201           0 :         sc->sc_mmap[i].v4l2_buf.bytesused = len;
    2202             : 
    2203             :         /* timestamp it */
    2204           0 :         getmicrotime(&sc->sc_mmap[i].v4l2_buf.timestamp);
    2205             : 
    2206             :         /* queue it */
    2207           0 :         sc->sc_mmap[i].v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
    2208           0 :         sc->sc_mmap[i].v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
    2209           0 :         SIMPLEQ_INSERT_TAIL(&sc->sc_mmap_q, &sc->sc_mmap[i], q_frames);
    2210             :         DPRINTF(2, "%s: %s: frame queued on index %d\n",
    2211             :             DEVNAME(sc), __func__, i);
    2212             : 
    2213           0 :         wakeup(sc);
    2214             : 
    2215             :         /*
    2216             :          * In case userland uses poll(2), signal that we have a frame
    2217             :          * ready to dequeue.
    2218             :          */
    2219           0 :         sc->sc_uplayer_intr(sc->sc_uplayer_arg);
    2220             : 
    2221           0 :         return 0;
    2222           0 : }
    2223             : 
    2224             : void
    2225           0 : uvideo_read(struct uvideo_softc *sc, uint8_t *buf, int len)
    2226             : {
    2227             :         /*
    2228             :          * Copy video frame to upper layer buffer and call
    2229             :          * upper layer interrupt.
    2230             :          */
    2231           0 :         *sc->sc_uplayer_fsize = len;
    2232           0 :         bcopy(buf, sc->sc_uplayer_fbuffer, len);
    2233           0 :         sc->sc_uplayer_intr(sc->sc_uplayer_arg);
    2234           0 : }
    2235             : 
    2236             : #ifdef UVIDEO_DEBUG
    2237             : void
    2238             : uvideo_dump_desc_all(struct uvideo_softc *sc)
    2239             : {
    2240             :         struct usbd_desc_iter iter;
    2241             :         const usb_descriptor_t *desc;
    2242             : 
    2243             :         usbd_desc_iter_init(sc->sc_udev, &iter);
    2244             :         desc = usbd_desc_iter_next(&iter);
    2245             :         while (desc) {
    2246             :                 printf("bLength=%d\n", desc->bLength);
    2247             :                 printf("bDescriptorType=0x%02x", desc->bDescriptorType);
    2248             : 
    2249             :                 switch (desc->bDescriptorType) {
    2250             :                 case UDESC_CS_INTERFACE:
    2251             :                         printf(" (CS_INTERFACE)\n");
    2252             : 
    2253             :                         switch (desc->bDescriptorSubtype) {
    2254             :                         case UDESCSUB_VC_HEADER:
    2255             :                                 printf("bDescriptorSubtype=0x%02x",
    2256             :                                     desc->bDescriptorSubtype);
    2257             :                                 if (uvideo_desc_len(desc, 12, 11, 1, 0)) {
    2258             :                                         printf(" (UDESCSUB_VC_HEADER)\n");
    2259             :                                         printf("|\n");
    2260             :                                         uvideo_dump_desc_vc_header(sc, desc);
    2261             :                                         break;
    2262             :                                 }
    2263             :                                 if (uvideo_desc_len(desc, 13, 3, 0, 12)) {
    2264             :                                         printf(" (UDESCSUB_VS_INPUT_HEADER)\n");
    2265             :                                         printf("|\n");
    2266             :                                         uvideo_dump_desc_input_header(sc, desc);
    2267             :                                         break;
    2268             :                                 }
    2269             :                                 printf(" (unknown)\n");
    2270             :                                 break;
    2271             :                         case UDESCSUB_VC_INPUT_TERMINAL:
    2272             :                                 printf("bDescriptorSubtype=0x%02x",
    2273             :                                     desc->bDescriptorSubtype);
    2274             :                                 printf(" (UDESCSUB_VC_INPUT_TERMINAL)\n");
    2275             :                                 printf("|\n");
    2276             :                                 uvideo_dump_desc_input(sc, desc);
    2277             :                                 break;
    2278             :                         case UDESCSUB_VC_OUTPUT_TERMINAL:
    2279             :                                 printf("bDescriptorSubtype=0x%02x",
    2280             :                                     desc->bDescriptorSubtype);
    2281             :                                 printf(" (UDESCSUB_VC_OUTPUT)\n");
    2282             :                                 printf("|\n");
    2283             :                                 uvideo_dump_desc_output(sc, desc);
    2284             :                                 break;
    2285             :                         case UDESCSUB_VC_SELECTOR_UNIT:
    2286             :                                 printf("bDescriptorSubtype=0x%02x",
    2287             :                                     desc->bDescriptorSubtype);
    2288             :                                 if (desc->bLength == 27) {
    2289             :                                         printf(" (UDESCSUB_VS_FORMAT_"
    2290             :                                             "UNCOMPRESSED)\n");
    2291             :                                         uvideo_dump_desc_format_uncompressed(
    2292             :                                             sc, desc);
    2293             :                                 } else {
    2294             :                                         printf(" (UDESCSUB_VC_SELECTOR_"
    2295             :                                             "UNIT)\n");
    2296             :                                         /* TODO */
    2297             :                                 }
    2298             :                                 break;
    2299             :                         case UDESCSUB_VC_PROCESSING_UNIT:
    2300             :                                 printf("bDescriptorSubtype=0x%02x",
    2301             :                                     desc->bDescriptorSubtype);
    2302             :                                 if (desc->bLength >
    2303             :                                     sizeof(struct usb_video_frame_desc)) {
    2304             :                                         printf(" (UDESCSUB_VS_FRAME_"
    2305             :                                             "UNCOMPRESSED)\n");
    2306             :                                         uvideo_dump_desc_frame(sc, desc);
    2307             :                                 } else {
    2308             :                                         printf(" (UDESCSUB_VC_PROCESSING_"
    2309             :                                             "UNIT)\n");
    2310             :                                         printf("|\n");
    2311             :                                         uvideo_dump_desc_processing(sc, desc);
    2312             :                                 }
    2313             :                                 break;
    2314             :                         case UDESCSUB_VC_EXTENSION_UNIT:
    2315             :                                 printf("bDescriptorSubtype=0x%02x",
    2316             :                                     desc->bDescriptorSubtype);
    2317             :                                 if (desc->bLength == 11) {
    2318             :                                         printf(" (UDESCSUB_VS_FORMAT_MJPEG)\n");
    2319             :                                         printf("|\n");
    2320             :                                         uvideo_dump_desc_format_mjpeg(sc, desc);
    2321             :                                 } else {
    2322             :                                         printf(" (UDESCSUB_VC_EXTENSION_"
    2323             :                                             "UNIT)\n");
    2324             :                                         printf("|\n");
    2325             :                                         uvideo_dump_desc_extension(sc, desc);
    2326             :                                 }
    2327             :                                 break;
    2328             :                         case UDESCSUB_VS_FRAME_MJPEG:
    2329             :                                 printf("bDescriptorSubtype=0x%02x",
    2330             :                                     desc->bDescriptorSubtype);
    2331             :                                 printf(" (UDESCSUB_VS_FRAME_MJPEG)\n");
    2332             :                                 if (desc->bLength >
    2333             :                                     sizeof(struct usb_video_frame_desc)) {
    2334             :                                         printf("|\n");
    2335             :                                         uvideo_dump_desc_frame(sc, desc);
    2336             :                                 }
    2337             :                                 break;
    2338             :                         case UDESCSUB_VS_COLORFORMAT:
    2339             :                                 printf("bDescriptorSubtype=0x%02x",
    2340             :                                    desc->bDescriptorSubtype);
    2341             :                                 printf(" (UDESCSUB_VS_COLORFORMAT)\n");
    2342             :                                 printf("|\n");
    2343             :                                 uvideo_dump_desc_colorformat(sc, desc);
    2344             :                                 break;
    2345             :                         }
    2346             : 
    2347             :                         break;
    2348             :                 case UDESC_CS_ENDPOINT:
    2349             :                         printf(" (UDESC_CS_ENDPOINT)\n");
    2350             : 
    2351             :                         switch (desc->bDescriptorSubtype) {
    2352             :                         case EP_INTERRUPT:
    2353             :                                 printf("bDescriptorSubtype=0x%02x",
    2354             :                                     desc->bDescriptorSubtype);
    2355             :                                 printf(" (EP_INTERRUPT)\n");
    2356             :                                 printf("|\n");
    2357             :                                 uvideo_dump_desc_cs_endpoint(sc, desc);
    2358             :                                 break;
    2359             :                         case EP_GENERAL:
    2360             :                                 printf("bDescriptorSubtype=0x%02x",
    2361             :                                     desc->bDescriptorSubtype);
    2362             :                                 printf(" (EP_GENERAL)\n");
    2363             :                                 printf("|\n");
    2364             :                                 uvideo_dump_desc_cs_endpoint(sc, desc);
    2365             :                                 break;
    2366             :                         }
    2367             : 
    2368             :                         break;
    2369             :                 case UDESC_CONFIG:
    2370             :                         printf(" (UDESC_CONFIG)\n");
    2371             :                         printf("|\n");
    2372             :                         uvideo_dump_desc_config(sc, desc);
    2373             :                         break;
    2374             :                 case UDESC_ENDPOINT:
    2375             :                         printf(" (UDESC_ENDPOINT)\n");
    2376             :                         printf("|\n");
    2377             :                         uvideo_dump_desc_endpoint(sc, desc);
    2378             :                         break;
    2379             :                 case UDESC_INTERFACE:
    2380             :                         printf(" (UDESC_INTERFACE)\n");
    2381             :                         printf("|\n");
    2382             :                         uvideo_dump_desc_interface(sc, desc);
    2383             :                         break;
    2384             :                 default:
    2385             :                         printf(" (unknown)\n");
    2386             :                         break;
    2387             :                 }
    2388             : 
    2389             :                 printf("\n");
    2390             : 
    2391             :                 desc = usbd_desc_iter_next(&iter);
    2392             :         }       
    2393             : 
    2394             : }
    2395             : 
    2396             : void
    2397             : uvideo_dump_desc_vc_header(struct uvideo_softc *sc,
    2398             :     const usb_descriptor_t *desc)
    2399             : {
    2400             :         struct usb_video_header_desc *d;
    2401             : 
    2402             :         d = (struct usb_video_header_desc *)(uint8_t *)desc;
    2403             : 
    2404             :         printf("bLength=%d\n", d->bLength);
    2405             :         printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
    2406             :         printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
    2407             :         printf("bcdUVC=0x%04x\n", UGETW(d->bcdUVC));
    2408             :         printf("wTotalLength=%d\n", UGETW(d->wTotalLength));
    2409             :         printf("dwClockFrequency=%d\n", UGETDW(d->dwClockFrequency));
    2410             :         printf("bInCollection=0x%02x\n", d->bInCollection);
    2411             : }
    2412             : 
    2413             : void
    2414             : uvideo_dump_desc_input_header(struct uvideo_softc *sc,
    2415             :     const usb_descriptor_t *desc)
    2416             : {
    2417             :         struct usb_video_input_header_desc *d;
    2418             : 
    2419             :         d = (struct usb_video_input_header_desc *)(uint8_t *)desc;
    2420             : 
    2421             :         printf("bLength=%d\n", d->bLength);
    2422             :         printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
    2423             :         printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
    2424             :         printf("bNumFormats=%d\n", d->bNumFormats);
    2425             :         printf("wTotalLength=%d\n", UGETW(d->wTotalLength));
    2426             :         printf("bEndpointAddress=0x%02x\n", d->bEndpointAddress);
    2427             :         printf("bmInfo=0x%02x\n", d->bmInfo);
    2428             :         printf("bTerminalLink=0x%02x\n", d->bTerminalLink);
    2429             :         printf("bStillCaptureMethod=0x%02x\n", d->bStillCaptureMethod);
    2430             :         printf("bTriggerSupport=0x%02x\n", d->bTriggerSupport);
    2431             :         printf("bTriggerUsage=0x%02x\n", d->bTriggerUsage);
    2432             :         printf("bControlSize=%d\n", d->bControlSize);
    2433             : }
    2434             : 
    2435             : void
    2436             : uvideo_dump_desc_input(struct uvideo_softc *sc,
    2437             :     const usb_descriptor_t *desc)
    2438             : {
    2439             :         struct usb_video_input_terminal_desc *d;
    2440             : 
    2441             :         d = (struct usb_video_input_terminal_desc *)(uint8_t *)desc;
    2442             : 
    2443             :         printf("bLength=%d\n", d->bLength);
    2444             :         printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
    2445             :         printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
    2446             :         printf("bTerminalID=0x%02x\n", d->bTerminalID);
    2447             :         printf("wTerminalType=0x%04x\n", UGETW(d->wTerminalType));
    2448             :         printf("bAssocTerminal=0x%02x\n", d->bAssocTerminal);
    2449             :         printf("iTerminal=0x%02x\n", d->iTerminal);
    2450             : }
    2451             : 
    2452             : void
    2453             : uvideo_dump_desc_output(struct uvideo_softc *sc,
    2454             :     const usb_descriptor_t *desc)
    2455             : {
    2456             :         struct usb_video_output_terminal_desc *d;
    2457             : 
    2458             :         d = (struct usb_video_output_terminal_desc *)(uint8_t *)desc;
    2459             : 
    2460             :         printf("bLength=%d\n", d->bLength);
    2461             :         printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
    2462             :         printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
    2463             :         printf("bTerminalID=0x%02x\n", d->bTerminalID);
    2464             :         printf("bAssocTerminal=0x%02x\n", d->bAssocTerminal);
    2465             :         printf("bSourceID=0x%02x\n", d->bSourceID);
    2466             :         printf("iTerminal=0x%02x\n", d->iTerminal);
    2467             : 
    2468             : }
    2469             : 
    2470             : void
    2471             : uvideo_dump_desc_endpoint(struct uvideo_softc *sc,
    2472             :     const usb_descriptor_t *desc)
    2473             : {
    2474             :         usb_endpoint_descriptor_t *d;
    2475             : 
    2476             :         d = (usb_endpoint_descriptor_t *)(uint8_t *)desc;
    2477             : 
    2478             :         printf("bLength=%d\n", d->bLength);
    2479             :         printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
    2480             :         printf("bEndpointAddress=0x%02x", d->bEndpointAddress);
    2481             :         if (UE_GET_DIR(d->bEndpointAddress) == UE_DIR_IN)
    2482             :                 printf(" (IN)\n");
    2483             :         if (UE_GET_DIR(d->bEndpointAddress) == UE_DIR_OUT)
    2484             :                 printf(" (OUT)\n");
    2485             :         printf("bmAttributes=0x%02x", d->bmAttributes);
    2486             :         if (UE_GET_XFERTYPE(d->bmAttributes) == UE_ISOCHRONOUS) {
    2487             :                 printf(" (UE_ISOCHRONOUS,");
    2488             :                 if (UE_GET_ISO_TYPE(d->bmAttributes) == UE_ISO_ASYNC)
    2489             :                         printf(" UE_ISO_ASYNC)\n");
    2490             :                 if (UE_GET_ISO_TYPE(d->bmAttributes) == UE_ISO_ADAPT)
    2491             :                         printf(" UE_ISO_ADAPT)\n");
    2492             :                 if (UE_GET_ISO_TYPE(d->bmAttributes) == UE_ISO_SYNC)
    2493             :                         printf(" UE_ISO_SYNC)\n");
    2494             :         }
    2495             :         if (UE_GET_XFERTYPE(d->bmAttributes) == UE_CONTROL)
    2496             :                 printf(" (UE_CONTROL)\n");
    2497             :         if (UE_GET_XFERTYPE(d->bmAttributes) == UE_BULK)
    2498             :                 printf(" (UE_BULK)\n");
    2499             :         if (UE_GET_XFERTYPE(d->bmAttributes) == UE_INTERRUPT)
    2500             :                 printf(" (UE_INTERRUPT)\n");
    2501             :         printf("wMaxPacketSize=%d\n", UGETW(d->wMaxPacketSize));
    2502             :         printf("bInterval=0x%02x\n", d->bInterval);
    2503             : }
    2504             : 
    2505             : void
    2506             : uvideo_dump_desc_interface(struct uvideo_softc *sc,
    2507             :     const usb_descriptor_t *desc)
    2508             : {
    2509             :         usb_interface_descriptor_t *d;
    2510             : 
    2511             :         d = (usb_interface_descriptor_t *)(uint8_t *)desc;
    2512             : 
    2513             :         printf("bLength=%d\n", d->bLength);
    2514             :         printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
    2515             :         printf("bInterfaceNumber=0x%02x\n", d->bInterfaceNumber);
    2516             :         printf("bAlternateSetting=0x%02x\n", d->bAlternateSetting);
    2517             :         printf("bNumEndpoints=%d\n", d->bNumEndpoints);
    2518             :         printf("bInterfaceClass=0x%02x\n", d->bInterfaceClass);
    2519             :         printf("bInterfaceSubClass=0x%02x\n", d->bInterfaceSubClass);
    2520             :         printf("bInterfaceProtocol=0x%02x\n", d->bInterfaceProtocol);
    2521             :         printf("iInterface=0x%02x\n", d->iInterface);
    2522             : }
    2523             : 
    2524             : void
    2525             : uvideo_dump_desc_config(struct uvideo_softc *sc,
    2526             :     const usb_descriptor_t *desc)
    2527             : {
    2528             :         usb_config_descriptor_t *d;
    2529             : 
    2530             :         d = (usb_config_descriptor_t *)(uint8_t *)desc;
    2531             : 
    2532             :         printf("bLength=%d\n", d->bLength);
    2533             :         printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
    2534             :         printf("wTotalLength=%d\n", UGETW(d->wTotalLength));
    2535             :         printf("bNumInterface=0x%02x\n", d->bNumInterface);
    2536             :         printf("bConfigurationValue=0x%02x\n", d->bConfigurationValue);
    2537             :         printf("iConfiguration=0x%02x\n", d->iConfiguration);
    2538             :         printf("bmAttributes=0x%02x\n", d->bmAttributes);
    2539             :         printf("bMaxPower=0x%02x\n", d->bMaxPower);
    2540             : }
    2541             : 
    2542             : void
    2543             : uvideo_dump_desc_cs_endpoint(struct uvideo_softc *sc,
    2544             :     const usb_descriptor_t *desc)
    2545             : {
    2546             :         struct usb_video_vc_endpoint_desc *d;
    2547             : 
    2548             :         d = (struct usb_video_vc_endpoint_desc *)(uint8_t *)desc;
    2549             : 
    2550             :         printf("bLength=%d\n", d->bLength);
    2551             :         printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
    2552             :         printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
    2553             :         printf("wMaxTransferSize=%d\n", UGETW(d->wMaxTransferSize));
    2554             : }
    2555             : 
    2556             : void
    2557             : uvideo_dump_desc_colorformat(struct uvideo_softc *sc,
    2558             :     const usb_descriptor_t *desc)
    2559             : {
    2560             :         struct usb_video_color_matching_descr *d;
    2561             : 
    2562             :         d = (struct usb_video_color_matching_descr *)(uint8_t *)desc;
    2563             : 
    2564             :         printf("bLength=%d\n", d->bLength);
    2565             :         printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
    2566             :         printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
    2567             :         printf("bColorPrimaries=0x%02x\n", d->bColorPrimaries);
    2568             :         printf("bTransferCharacteristics=0x%02x\n",
    2569             :             d->bTransferCharacteristics);
    2570             :         printf("bMatrixCoefficients=0x%02x\n", d->bMatrixCoefficients);
    2571             : }
    2572             : void
    2573             : uvideo_dump_desc_format_mjpeg(struct uvideo_softc *sc,
    2574             :     const usb_descriptor_t *desc)
    2575             : {
    2576             :         struct usb_video_format_mjpeg_desc *d;
    2577             : 
    2578             :         d = (struct usb_video_format_mjpeg_desc *)(uint8_t *)desc;
    2579             : 
    2580             :         printf("bLength=%d\n", d->bLength);
    2581             :         printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
    2582             :         printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
    2583             :         printf("bFormatIndex=0x%02x\n", d->bFormatIndex);
    2584             :         printf("bNumFrameDescriptors=0x%02x\n", d->bNumFrameDescriptors);
    2585             :         printf("bmFlags=0x%02x\n", d->bmFlags);
    2586             :         printf("bDefaultFrameIndex=0x%02x\n", d->bDefaultFrameIndex);
    2587             :         printf("bAspectRatioX=0x%02x\n", d->bAspectRatioX);
    2588             :         printf("bAspectRatioY=0x%02x\n", d->bAspectRatioY);
    2589             :         printf("bmInterlaceFlags=0x%02x\n", d->bmInterlaceFlags);
    2590             :         printf("bCopyProtect=0x%02x\n", d->bCopyProtect);
    2591             : }
    2592             : 
    2593             : void
    2594             : uvideo_dump_desc_frame(struct uvideo_softc *sc, const usb_descriptor_t *desc)
    2595             : {
    2596             :         struct usb_video_frame_desc *d;
    2597             :         uint8_t *p;
    2598             :         int length, i;
    2599             : 
    2600             :         d = (struct usb_video_frame_desc *)(uint8_t *)desc;
    2601             : 
    2602             :         printf("bLength=%d\n", d->bLength);
    2603             :         printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
    2604             :         printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
    2605             :         printf("bFrameIndex=0x%02x\n", d->bFrameIndex);
    2606             :         printf("bmCapabilities=0x%02x\n", d->bmCapabilities);
    2607             :         printf("wWidth=%d\n", UGETW(d->wWidth));
    2608             :         printf("wHeight=%d\n", UGETW(d->wHeight));
    2609             :         printf("dwMinBitRate=%d\n", UGETDW(d->dwMinBitRate));
    2610             :         printf("dwMaxBitRate=%d\n", UGETDW(d->dwMaxBitRate));
    2611             :         printf("dwMaxVideoFrameBufferSize=%d\n",
    2612             :             UGETDW(d->dwMaxVideoFrameBufferSize));
    2613             :         printf("dwDefaultFrameInterval=%d\n",
    2614             :             UGETDW(d->dwDefaultFrameInterval));
    2615             :         printf("bFrameIntervalType=0x%02x\n", d->bFrameIntervalType);
    2616             : 
    2617             :         p = (uint8_t *)d;
    2618             :         p += sizeof(struct usb_video_frame_desc);
    2619             : 
    2620             :         if (!d->bFrameIntervalType) {
    2621             :                 /* continuous */
    2622             :                 if (d->bLength < (sizeof(struct usb_video_frame_desc) +
    2623             :                     sizeof(uDWord) * 3)) {
    2624             :                         printf("invalid frame descriptor length\n");
    2625             :                 } else {
    2626             :                         printf("dwMinFrameInterval = %d\n", UGETDW(p));
    2627             :                         p += sizeof(uDWord);
    2628             :                         printf("dwMaxFrameInterval = %d\n", UGETDW(p));
    2629             :                         p += sizeof(uDWord);
    2630             :                         printf("dwFrameIntervalStep = %d\n", UGETDW(p));
    2631             :                         p += sizeof(uDWord);
    2632             :                 }
    2633             :         } else {
    2634             :                 /* discrete */
    2635             :                 length = d->bLength - sizeof(struct usb_video_frame_desc);
    2636             :                 for (i = 0; i < d->bFrameIntervalType; i++) {
    2637             :                         if (length <= 0) {
    2638             :                                 printf("frame descriptor ended early\n");
    2639             :                                 break;
    2640             :                         }
    2641             :                         printf("dwFrameInterval = %d\n", UGETDW(p));
    2642             :                         p += sizeof(uDWord);
    2643             :                         length -= sizeof(uDWord);
    2644             :                 }
    2645             :         }
    2646             : }
    2647             : 
    2648             : void
    2649             : uvideo_dump_desc_format_uncompressed(struct uvideo_softc *sc,
    2650             :     const usb_descriptor_t *desc)
    2651             : {
    2652             :         struct usb_video_format_uncompressed_desc *d;
    2653             : 
    2654             :         d = (struct usb_video_format_uncompressed_desc *)(uint8_t *)desc;
    2655             : 
    2656             :         printf("bLength=%d\n", d->bLength);
    2657             :         printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
    2658             :         printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
    2659             :         printf("bFormatIndex=0x%02x\n", d->bFormatIndex);
    2660             :         printf("bNumFrameDescriptors=0x%02x\n", d->bNumFrameDescriptors);
    2661             :         printf("guidFormat=%s\n", d->guidFormat);
    2662             :         printf("bBitsPerPixel=0x%02x\n", d->bBitsPerPixel);
    2663             :         printf("bDefaultFrameIndex=0x%02x\n", d->bDefaultFrameIndex);
    2664             :         printf("bAspectRatioX=0x%02x\n", d->bAspectRatioX);
    2665             :         printf("bAspectRatioY=0x%02x\n", d->bAspectRatioY);
    2666             :         printf("bmInterlaceFlags=0x%02x\n", d->bmInterlaceFlags);
    2667             :         printf("bCopyProtect=0x%02x\n", d->bCopyProtect);
    2668             : }
    2669             : 
    2670             : void
    2671             : uvideo_dump_desc_processing(struct uvideo_softc *sc,
    2672             :     const usb_descriptor_t *desc)
    2673             : {
    2674             :         struct usb_video_vc_processing_desc *d;
    2675             : 
    2676             :         /* PU descriptor is variable sized */
    2677             :         d = (void *)desc;
    2678             : 
    2679             :         printf("bLength=%d\n", d->bLength);
    2680             :         printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
    2681             :         printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
    2682             :         printf("bUnitID=0x%02x\n", d->bUnitID);
    2683             :         printf("bSourceID=0x%02x\n", d->bSourceID);
    2684             :         printf("wMaxMultiplier=%d\n", UGETW(d->wMaxMultiplier));
    2685             :         printf("bControlSize=%d\n", d->bControlSize);
    2686             :         printf("bmControls=0x");
    2687             :         uvideo_hexdump(d->bmControls, d->bControlSize, 1);
    2688             :         printf("iProcessing=0x%02x\n", d->bmControls[d->bControlSize]);
    2689             :         printf("bmVideoStandards=0x%02x\n", d->bmControls[d->bControlSize + 1]);
    2690             : }
    2691             : 
    2692             : void
    2693             : uvideo_dump_desc_extension(struct uvideo_softc *sc,
    2694             :     const usb_descriptor_t *desc)
    2695             : {
    2696             :         struct usb_video_vc_extension_desc *d;
    2697             : 
    2698             :         d = (struct usb_video_vc_extension_desc *)(uint8_t *)desc;
    2699             : 
    2700             :         printf("bLength=%d\n", d->bLength);
    2701             :         printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
    2702             :         printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype);
    2703             :         printf("bUnitID=0x%02x\n", d->bUnitID);
    2704             :         printf("guidExtensionCode=0x");
    2705             :         uvideo_hexdump(d->guidExtensionCode, sizeof(d->guidExtensionCode), 1);
    2706             :         printf("bNumControls=0x%02x\n", d->bNumControls);
    2707             :         printf("bNrInPins=0x%02x\n", d->bNrInPins);
    2708             : }
    2709             : 
    2710             : void
    2711             : uvideo_hexdump(void *buf, int len, int quiet)
    2712             : {
    2713             :         int i;
    2714             : 
    2715             :         for (i = 0; i < len; i++) {
    2716             :                 if (quiet == 0) {
    2717             :                         if (i % 16 == 0)
    2718             :                                 printf("%s%5i:", i ? "\n" : "", i);
    2719             :                         if (i % 4 == 0)
    2720             :                                 printf(" ");
    2721             :                 }
    2722             :                 printf("%02x", (int)*((u_char *)buf + i));
    2723             :         }
    2724             :         printf("\n");
    2725             : }
    2726             : 
    2727             : int
    2728             : uvideo_debug_file_open(struct uvideo_softc *sc)
    2729             : {
    2730             :         struct proc *p = curproc;
    2731             :         struct nameidata nd;
    2732             :         char name[] = "/tmp/uvideo.mjpeg";
    2733             :         int error;
    2734             : 
    2735             :         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p);
    2736             :         error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR);
    2737             :         if (error) {
    2738             :                 DPRINTF(1, "%s: %s: can't create debug file %s!\n",
    2739             :                     DEVNAME(sc), __func__, name);
    2740             :                 return (error);
    2741             :         }
    2742             : 
    2743             :         sc->sc_vp = nd.ni_vp;
    2744             :         VOP_UNLOCK(sc->sc_vp);
    2745             :         if (nd.ni_vp->v_type != VREG) {
    2746             :                 vn_close(nd.ni_vp, FWRITE, p->p_ucred, p);
    2747             :                 return (EIO);
    2748             :         }
    2749             : 
    2750             :         DPRINTF(1, "%s: %s: created debug file %s\n",
    2751             :             DEVNAME(sc), __func__, name);
    2752             : 
    2753             :         return (0);
    2754             : }
    2755             : 
    2756             : void
    2757             : uvideo_debug_file_write_frame(void *arg)
    2758             : {
    2759             :         struct uvideo_softc *sc = arg;
    2760             :         struct uvideo_frame_buffer *sb = &sc->sc_frame_buffer;
    2761             :         struct proc *p = curproc;
    2762             :         int error;
    2763             : 
    2764             :         if (sc->sc_vp == NULL) {
    2765             :                 printf("%s: %s: no file open!\n", DEVNAME(sc), __func__);
    2766             :                 return;
    2767             :         }
    2768             : 
    2769             :         error = vn_rdwr(UIO_WRITE, sc->sc_vp, sb->buf, sb->offset, (off_t)0,
    2770             :             UIO_SYSSPACE, IO_APPEND|IO_UNIT, p->p_ucred, NULL, p);
    2771             : 
    2772             :         if (error)
    2773             :                 DPRINTF(1, "vn_rdwr error!\n");
    2774             : }
    2775             : #endif
    2776             : 
    2777             : /*
    2778             :  * IOCTL's
    2779             :  */
    2780             : int
    2781           0 : uvideo_querycap(void *v, struct v4l2_capability *caps)
    2782             : {
    2783           0 :         struct uvideo_softc *sc = v;
    2784             : 
    2785           0 :         bzero(caps, sizeof(*caps));
    2786           0 :         strlcpy(caps->driver, DEVNAME(sc), sizeof(caps->driver));
    2787           0 :         strlcpy(caps->card, sc->sc_udev->product, sizeof(caps->card));
    2788           0 :         strlcpy(caps->bus_info, "usb", sizeof(caps->bus_info));
    2789             : 
    2790           0 :         caps->version = 1;
    2791           0 :         caps->capabilities = V4L2_CAP_VIDEO_CAPTURE
    2792             :             | V4L2_CAP_STREAMING
    2793             :             | V4L2_CAP_READWRITE;
    2794             : 
    2795           0 :         return (0);
    2796             : }
    2797             : 
    2798             : int
    2799           0 : uvideo_enum_fmt(void *v, struct v4l2_fmtdesc *fmtdesc)
    2800             : {
    2801           0 :         struct uvideo_softc *sc = v;
    2802             :         int idx;
    2803             : 
    2804           0 :         if (fmtdesc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
    2805             :                 /* type not supported */
    2806           0 :                 return (EINVAL);
    2807             : 
    2808           0 :         if (fmtdesc->index >= sc->sc_fmtgrp_num)
    2809             :                 /* no more formats left */
    2810           0 :                 return (EINVAL);
    2811             :         idx = fmtdesc->index;
    2812             : 
    2813           0 :         switch (sc->sc_fmtgrp[idx].format->bDescriptorSubtype) {
    2814             :         case UDESCSUB_VS_FORMAT_MJPEG:
    2815           0 :                 fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
    2816           0 :                 (void)strlcpy(fmtdesc->description, "MJPEG",
    2817             :                     sizeof(fmtdesc->description));
    2818           0 :                 fmtdesc->pixelformat = V4L2_PIX_FMT_MJPEG;
    2819           0 :                 bzero(fmtdesc->reserved, sizeof(fmtdesc->reserved));
    2820           0 :                 break;
    2821             :         case UDESCSUB_VS_FORMAT_UNCOMPRESSED:
    2822           0 :                 fmtdesc->flags = 0;
    2823           0 :                 if (sc->sc_fmtgrp[idx].pixelformat ==
    2824             :                     V4L2_PIX_FMT_YUYV) {
    2825           0 :                         (void)strlcpy(fmtdesc->description, "YUYV",
    2826             :                             sizeof(fmtdesc->description));
    2827           0 :                         fmtdesc->pixelformat = V4L2_PIX_FMT_YUYV;
    2828           0 :                 } else if (sc->sc_fmtgrp[idx].pixelformat ==
    2829             :                     V4L2_PIX_FMT_NV12) {
    2830           0 :                         (void)strlcpy(fmtdesc->description, "NV12",
    2831             :                             sizeof(fmtdesc->description));
    2832           0 :                         fmtdesc->pixelformat = V4L2_PIX_FMT_NV12;
    2833           0 :                 } else if (sc->sc_fmtgrp[idx].pixelformat ==
    2834             :                     V4L2_PIX_FMT_UYVY) {
    2835           0 :                         (void)strlcpy(fmtdesc->description, "UYVY",
    2836             :                             sizeof(fmtdesc->description));
    2837           0 :                         fmtdesc->pixelformat = V4L2_PIX_FMT_UYVY;
    2838           0 :                 } else {
    2839           0 :                         (void)strlcpy(fmtdesc->description, "Unknown UC Format",
    2840             :                             sizeof(fmtdesc->description));
    2841           0 :                         fmtdesc->pixelformat = 0;
    2842             :                 }
    2843           0 :                 bzero(fmtdesc->reserved, sizeof(fmtdesc->reserved));
    2844           0 :                 break;
    2845             :         default:
    2846           0 :                 fmtdesc->flags = 0;
    2847           0 :                 (void)strlcpy(fmtdesc->description, "Unknown Format",
    2848             :                     sizeof(fmtdesc->description));
    2849           0 :                 fmtdesc->pixelformat = 0;
    2850           0 :                 bzero(fmtdesc->reserved, sizeof(fmtdesc->reserved));
    2851           0 :                 break;
    2852             :         }
    2853             : 
    2854           0 :         return (0);
    2855           0 : }
    2856             : 
    2857             : int
    2858           0 : uvideo_enum_fsizes(void *v, struct v4l2_frmsizeenum *fsizes)
    2859             : {
    2860           0 :         struct uvideo_softc *sc = v;
    2861             :         int idx, found = 0;
    2862             : 
    2863           0 :         for (idx = 0; idx < sc->sc_fmtgrp_num; idx++) {
    2864           0 :                 if (sc->sc_fmtgrp[idx].pixelformat == fsizes->pixel_format) {
    2865             :                         found = 1;
    2866           0 :                         break;
    2867             :                 }
    2868             :         }
    2869           0 :         if (found == 0)
    2870           0 :                 return (EINVAL);
    2871             : 
    2872           0 :         if (fsizes->index >= sc->sc_fmtgrp[idx].frame_num)
    2873           0 :                 return (EINVAL);
    2874             : 
    2875           0 :         fsizes->type = V4L2_FRMSIZE_TYPE_DISCRETE;
    2876           0 :         fsizes->discrete.width =
    2877           0 :             UGETW(sc->sc_fmtgrp[idx].frame[fsizes->index]->wWidth);
    2878           0 :         fsizes->discrete.height =
    2879           0 :             UGETW(sc->sc_fmtgrp[idx].frame[fsizes->index]->wHeight);
    2880             : 
    2881           0 :         return (0);
    2882           0 : }
    2883             : 
    2884             : int
    2885           0 : uvideo_enum_fivals(void *v, struct v4l2_frmivalenum *fivals)
    2886             : {
    2887           0 :         struct uvideo_softc *sc = v;
    2888             :         int idx;
    2889             :         struct uvideo_format_group *fmtgrp = NULL;
    2890             :         struct usb_video_frame_desc *frame = NULL;
    2891             :         uint8_t *p;
    2892             : 
    2893           0 :         for (idx = 0; idx < sc->sc_fmtgrp_num; idx++) {
    2894           0 :                 if (sc->sc_fmtgrp[idx].pixelformat == fivals->pixel_format) {
    2895             :                         fmtgrp = &sc->sc_fmtgrp[idx];
    2896           0 :                         break;
    2897             :                 }
    2898             :         }
    2899           0 :         if (fmtgrp == NULL)
    2900           0 :                 return (EINVAL);
    2901             : 
    2902           0 :         for (idx = 0; idx < fmtgrp->frame_num; idx++) {
    2903           0 :                 if (UGETW(fmtgrp->frame[idx]->wWidth) == fivals->width &&
    2904           0 :                     UGETW(fmtgrp->frame[idx]->wHeight) == fivals->height) {
    2905             :                         frame = fmtgrp->frame[idx];
    2906           0 :                         break;
    2907             :                 }
    2908             :         }
    2909           0 :         if (frame == NULL)
    2910           0 :                 return (EINVAL);
    2911             : 
    2912             :         /* byte-wise pointer to start of frame intervals */
    2913           0 :         p = (uint8_t *)frame;
    2914           0 :         p += sizeof(struct usb_video_frame_desc);
    2915             : 
    2916           0 :         if (frame->bFrameIntervalType == 0) {
    2917           0 :                 if (fivals->index != 0)
    2918           0 :                         return (EINVAL);
    2919           0 :                 fivals->type = V4L2_FRMIVAL_TYPE_STEPWISE;
    2920           0 :                 fivals->stepwise.min.numerator = UGETDW(p);
    2921           0 :                 fivals->stepwise.min.denominator = 10000000;
    2922           0 :                 p += sizeof(uDWord);
    2923           0 :                 fivals->stepwise.max.numerator = UGETDW(p);
    2924           0 :                 fivals->stepwise.max.denominator = 10000000;
    2925           0 :                 p += sizeof(uDWord);
    2926           0 :                 fivals->stepwise.step.numerator = UGETDW(p);
    2927           0 :                 fivals->stepwise.step.denominator = 10000000;
    2928             :                 p += sizeof(uDWord);
    2929           0 :         } else {
    2930           0 :                 if (fivals->index >= frame->bFrameIntervalType)
    2931           0 :                         return (EINVAL);
    2932           0 :                 p += sizeof(uDWord) * fivals->index;
    2933           0 :                 if (p > frame->bLength + (uint8_t *)frame) {
    2934           0 :                         printf("%s: frame desc too short?\n", __func__);
    2935           0 :                         return (EINVAL);
    2936             :                 }
    2937           0 :                 fivals->type = V4L2_FRMIVAL_TYPE_DISCRETE;
    2938           0 :                 fivals->discrete.numerator = UGETDW(p);
    2939           0 :                 fivals->discrete.denominator = 10000000;
    2940             :         }
    2941             : 
    2942           0 :         return (0);
    2943           0 : }
    2944             : 
    2945             : int
    2946           0 : uvideo_s_fmt(void *v, struct v4l2_format *fmt)
    2947             : {
    2948           0 :         struct uvideo_softc *sc = v;
    2949             :         struct uvideo_format_group *fmtgrp_save;
    2950             :         struct usb_video_frame_desc *frame_save;
    2951           0 :         struct uvideo_res r;
    2952             :         int found, i;
    2953             :         usbd_status error;
    2954             : 
    2955           0 :         if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
    2956           0 :                 return (EINVAL);
    2957             : 
    2958             :         DPRINTF(1, "%s: %s: requested width=%d, height=%d\n",
    2959             :             DEVNAME(sc), __func__, fmt->fmt.pix.width, fmt->fmt.pix.height);
    2960             : 
    2961             :         /* search requested pixel format */
    2962           0 :         for (found = 0, i = 0; i < sc->sc_fmtgrp_num; i++) {
    2963           0 :                 if (fmt->fmt.pix.pixelformat == sc->sc_fmtgrp[i].pixelformat) {
    2964             :                         found = 1;
    2965           0 :                         break;
    2966             :                 }
    2967             :         }
    2968           0 :         if (found == 0)
    2969           0 :                 return (EINVAL);
    2970             : 
    2971             :         /* check if the format descriptor contains frame descriptors */
    2972           0 :         if (sc->sc_fmtgrp[i].frame_num == 0) {
    2973           0 :                 printf("%s: %s: no frame descriptors found!\n",
    2974           0 :                     __func__, DEVNAME(sc));
    2975           0 :                 return (EINVAL);
    2976             :         }
    2977             : 
    2978             :         /* search requested frame resolution */
    2979           0 :         uvideo_find_res(sc, i, fmt->fmt.pix.width, fmt->fmt.pix.height, &r);
    2980             : 
    2981             :         /*
    2982             :          * Do negotiation.
    2983             :          */
    2984             :         /* save a copy of current fromat group in case of negotiation fails */
    2985           0 :         fmtgrp_save = sc->sc_fmtgrp_cur;
    2986           0 :         frame_save = sc->sc_fmtgrp_cur->frame_cur;
    2987             :         /* set new format group */
    2988           0 :         sc->sc_fmtgrp_cur = &sc->sc_fmtgrp[i];
    2989           0 :         sc->sc_fmtgrp[i].frame_cur = sc->sc_fmtgrp[i].frame[r.fidx];
    2990             : 
    2991             :         /* do device negotiation with commit */
    2992           0 :         error = uvideo_vs_negotiation(sc, 1);
    2993           0 :         if (error != USBD_NORMAL_COMPLETION) {
    2994           0 :                 sc->sc_fmtgrp_cur = fmtgrp_save;
    2995           0 :                 sc->sc_fmtgrp_cur->frame_cur = frame_save;
    2996           0 :                 return (EINVAL);
    2997             :         }
    2998           0 :         sc->sc_negotiated_flag = 1;
    2999             : 
    3000             :         /* offer closest resolution which we have found */
    3001           0 :         fmt->fmt.pix.width = r.width;
    3002           0 :         fmt->fmt.pix.height = r.height;
    3003             : 
    3004             :         DPRINTF(1, "%s: %s: offered width=%d, height=%d\n",
    3005             :             DEVNAME(sc), __func__, r.width, r.height);
    3006             : 
    3007             :         /* tell our frame buffer size */
    3008           0 :         fmt->fmt.pix.sizeimage = UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
    3009             : 
    3010           0 :         return (0);
    3011           0 : }
    3012             : 
    3013             : int
    3014           0 : uvideo_g_fmt(void *v, struct v4l2_format *fmt)
    3015             : {
    3016           0 :         struct uvideo_softc *sc = v;
    3017             : 
    3018           0 :         if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
    3019           0 :                 return (EINVAL);
    3020             : 
    3021           0 :         fmt->fmt.pix.pixelformat = sc->sc_fmtgrp_cur->pixelformat;
    3022           0 :         fmt->fmt.pix.width = UGETW(sc->sc_fmtgrp_cur->frame_cur->wWidth);
    3023           0 :         fmt->fmt.pix.height = UGETW(sc->sc_fmtgrp_cur->frame_cur->wHeight);
    3024           0 :         fmt->fmt.pix.sizeimage = UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
    3025             : 
    3026             :         DPRINTF(1, "%s: %s: current width=%d, height=%d\n",
    3027             :             DEVNAME(sc), __func__, fmt->fmt.pix.width, fmt->fmt.pix.height);
    3028             : 
    3029           0 :         return (0);
    3030           0 : }
    3031             : 
    3032             : int
    3033           0 : uvideo_s_parm(void *v, struct v4l2_streamparm *parm)
    3034             : {
    3035           0 :         struct uvideo_softc *sc = v;
    3036             :         usbd_status error;
    3037             : 
    3038           0 :         if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
    3039             :                 /*
    3040             :                  * XXX Only whole number frame rates for now.  Frame
    3041             :                  * rate is the inverse of time per frame.
    3042             :                  */
    3043           0 :                 if (parm->parm.capture.timeperframe.numerator == 0 ||
    3044           0 :                     parm->parm.capture.timeperframe.denominator == 0) {
    3045           0 :                         sc->sc_frame_rate = 0;
    3046           0 :                 } else {
    3047           0 :                         sc->sc_frame_rate =
    3048           0 :                             parm->parm.capture.timeperframe.denominator /
    3049             :                             parm->parm.capture.timeperframe.numerator;
    3050             :                 }
    3051             :         } else
    3052           0 :                 return (EINVAL);
    3053             : 
    3054             :         /* renegotiate if necessary */
    3055           0 :         if (sc->sc_negotiated_flag) {
    3056           0 :                 error = uvideo_vs_negotiation(sc, 1);
    3057           0 :                 if (error != USBD_NORMAL_COMPLETION)
    3058           0 :                         return (error);
    3059             :         }
    3060             : 
    3061           0 :         return (0);
    3062           0 : }
    3063             : 
    3064             : int
    3065           0 : uvideo_g_parm(void *v, struct v4l2_streamparm *parm)
    3066             : {
    3067           0 :         struct uvideo_softc *sc = v;
    3068             : 
    3069           0 :         if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
    3070           0 :                 parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
    3071           0 :                 parm->parm.capture.capturemode = 0;
    3072           0 :                 parm->parm.capture.timeperframe.numerator =
    3073           0 :                     UGETDW(sc->sc_desc_probe.dwFrameInterval);
    3074           0 :                 parm->parm.capture.timeperframe.denominator = 10000000;
    3075             :         } else
    3076           0 :                 return (EINVAL);
    3077             : 
    3078           0 :         return (0);
    3079           0 : }
    3080             : 
    3081             : int
    3082           0 : uvideo_enum_input(void *v, struct v4l2_input *input)
    3083             : {
    3084           0 :         if (input->index != 0)
    3085             :                 /* XXX we just support one input for now */
    3086           0 :                 return (EINVAL);
    3087             : 
    3088           0 :         strlcpy(input->name, "Camera Terminal", sizeof(input->name));
    3089           0 :         input->type = V4L2_INPUT_TYPE_CAMERA;
    3090             : 
    3091           0 :         return (0);
    3092           0 : }
    3093             : 
    3094             : int
    3095           0 : uvideo_s_input(void *v, int input)
    3096             : {
    3097           0 :         if (input != 0)
    3098             :                 /* XXX we just support one input for now */
    3099           0 :                 return (EINVAL);
    3100             : 
    3101           0 :         return (0);
    3102           0 : }
    3103             : 
    3104             : int
    3105           0 : uvideo_g_input(void *v, int *input)
    3106             : {
    3107             :         /* XXX we just support one input for now */
    3108           0 :         *input = 0;
    3109             : 
    3110           0 :         return (0);
    3111             : }
    3112             : 
    3113             : int
    3114           0 : uvideo_reqbufs(void *v, struct v4l2_requestbuffers *rb)
    3115             : {
    3116           0 :         struct uvideo_softc *sc = v;
    3117             :         int i, buf_size, buf_size_total;
    3118             : 
    3119             :         DPRINTF(1, "%s: %s: count=%d\n", DEVNAME(sc), __func__, rb->count);
    3120             : 
    3121             :         /* We do not support freeing buffers via reqbufs(0) */
    3122           0 :         if (rb->count == 0)
    3123           0 :                 return (EINVAL);
    3124             : 
    3125           0 :         if (sc->sc_mmap_count > 0 || sc->sc_mmap_buffer != NULL) {
    3126             :                 DPRINTF(1, "%s: %s: mmap buffers already allocated\n",
    3127             :                     DEVNAME(sc), __func__);
    3128           0 :                 return (EINVAL);
    3129             :         }
    3130             : 
    3131             :         /* limit the buffers */
    3132           0 :         if (rb->count > UVIDEO_MAX_BUFFERS)
    3133           0 :                 sc->sc_mmap_count = UVIDEO_MAX_BUFFERS;
    3134             :         else
    3135           0 :                 sc->sc_mmap_count = rb->count;
    3136             : 
    3137             :         /* allocate the total mmap buffer */    
    3138           0 :         buf_size = UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
    3139           0 :         if (buf_size >= SIZE_MAX / UVIDEO_MAX_BUFFERS) {
    3140           0 :                 printf("%s: video frame size too large!\n", DEVNAME(sc));
    3141           0 :                 sc->sc_mmap_count = 0;
    3142           0 :                 return (EINVAL);
    3143             :         }
    3144           0 :         buf_size_total = sc->sc_mmap_count * buf_size;
    3145           0 :         buf_size_total = round_page(buf_size_total); /* page align buffer */
    3146           0 :         sc->sc_mmap_buffer = malloc(buf_size_total, M_DEVBUF, M_NOWAIT);
    3147           0 :         if (sc->sc_mmap_buffer == NULL) {
    3148           0 :                 printf("%s: can't allocate mmap buffer!\n", DEVNAME(sc));
    3149           0 :                 sc->sc_mmap_count = 0;
    3150           0 :                 return (EINVAL);
    3151             :         }
    3152           0 :         sc->sc_mmap_buffer_size = buf_size_total;
    3153             :         DPRINTF(1, "%s: allocated %d bytes mmap buffer\n",
    3154             :             DEVNAME(sc), buf_size_total);
    3155             : 
    3156             :         /* fill the v4l2_buffer structure */
    3157           0 :         for (i = 0; i < sc->sc_mmap_count; i++) {
    3158           0 :                 sc->sc_mmap[i].buf = sc->sc_mmap_buffer + (i * buf_size);
    3159             : 
    3160           0 :                 sc->sc_mmap[i].v4l2_buf.index = i;
    3161           0 :                 sc->sc_mmap[i].v4l2_buf.m.offset = i * buf_size;
    3162           0 :                 sc->sc_mmap[i].v4l2_buf.length = buf_size;
    3163           0 :                 sc->sc_mmap[i].v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    3164           0 :                 sc->sc_mmap[i].v4l2_buf.sequence = 0;
    3165           0 :                 sc->sc_mmap[i].v4l2_buf.field = V4L2_FIELD_NONE;
    3166           0 :                 sc->sc_mmap[i].v4l2_buf.memory = V4L2_MEMORY_MMAP;
    3167           0 :                 sc->sc_mmap[i].v4l2_buf.flags = V4L2_BUF_FLAG_MAPPED;
    3168             : 
    3169             :                 DPRINTF(1, "%s: %s: index=%d, offset=%d, length=%d\n",
    3170             :                     DEVNAME(sc), __func__,
    3171             :                     sc->sc_mmap[i].v4l2_buf.index,
    3172             :                     sc->sc_mmap[i].v4l2_buf.m.offset,
    3173             :                     sc->sc_mmap[i].v4l2_buf.length);
    3174             :         }
    3175             : 
    3176             :         /* tell how many buffers we have really allocated */
    3177           0 :         rb->count = sc->sc_mmap_count;
    3178             : 
    3179           0 :         return (0);
    3180           0 : }
    3181             : 
    3182             : int
    3183           0 : uvideo_querybuf(void *v, struct v4l2_buffer *qb)
    3184             : {
    3185           0 :         struct uvideo_softc *sc = v;
    3186             : 
    3187           0 :         if (qb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
    3188           0 :             qb->memory != V4L2_MEMORY_MMAP ||
    3189           0 :             qb->index >= sc->sc_mmap_count)
    3190           0 :                 return (EINVAL);
    3191             : 
    3192           0 :         bcopy(&sc->sc_mmap[qb->index].v4l2_buf, qb,
    3193             :             sizeof(struct v4l2_buffer));
    3194             : 
    3195             :         DPRINTF(1, "%s: %s: index=%d, offset=%d, length=%d\n",
    3196             :             DEVNAME(sc), __func__,
    3197             :             qb->index,
    3198             :             qb->m.offset,
    3199             :             qb->length);
    3200             : 
    3201           0 :         return (0);
    3202           0 : }
    3203             : 
    3204             : int
    3205           0 : uvideo_qbuf(void *v, struct v4l2_buffer *qb)
    3206             : {
    3207           0 :         struct uvideo_softc *sc = v;
    3208             : 
    3209           0 :         if (qb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
    3210           0 :             qb->memory != V4L2_MEMORY_MMAP ||
    3211           0 :             qb->index >= sc->sc_mmap_count)
    3212           0 :                 return (EINVAL);
    3213             : 
    3214           0 :         sc->sc_mmap[qb->index].v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
    3215           0 :         sc->sc_mmap[qb->index].v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED;
    3216             : 
    3217             :         DPRINTF(2, "%s: %s: buffer on index %d ready for queueing\n",
    3218             :             DEVNAME(sc), __func__, qb->index);
    3219             : 
    3220           0 :         return (0);
    3221           0 : }
    3222             : 
    3223             : int
    3224           0 : uvideo_dqbuf(void *v, struct v4l2_buffer *dqb)
    3225             : {
    3226           0 :         struct uvideo_softc *sc = v;
    3227             :         struct uvideo_mmap *mmap;
    3228             :         int error;
    3229             : 
    3230           0 :         if (dqb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
    3231           0 :             dqb->memory != V4L2_MEMORY_MMAP)
    3232           0 :                 return (EINVAL);
    3233             : 
    3234           0 :         if (SIMPLEQ_EMPTY(&sc->sc_mmap_q)) {
    3235             :                 /* mmap queue is empty, block until first frame is queued */
    3236           0 :                 error = tsleep(sc, 0, "vid_mmap", 10 * hz);
    3237           0 :                 if (error)
    3238           0 :                         return (EINVAL);
    3239             :         }
    3240             : 
    3241           0 :         mmap = SIMPLEQ_FIRST(&sc->sc_mmap_q);
    3242           0 :         if (mmap == NULL)
    3243           0 :                 panic("uvideo_dqbuf: NULL pointer!");
    3244             : 
    3245           0 :         bcopy(&mmap->v4l2_buf, dqb, sizeof(struct v4l2_buffer));
    3246             : 
    3247           0 :         mmap->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
    3248           0 :         mmap->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
    3249             : 
    3250             :         DPRINTF(2, "%s: %s: frame dequeued from index %d\n",
    3251             :             DEVNAME(sc), __func__, mmap->v4l2_buf.index);
    3252           0 :         SIMPLEQ_REMOVE_HEAD(&sc->sc_mmap_q, q_frames);
    3253             : 
    3254           0 :         return (0);
    3255           0 : }
    3256             : 
    3257             : int
    3258           0 : uvideo_streamon(void *v, int type)
    3259             : {
    3260           0 :         struct uvideo_softc *sc = v;
    3261             :         usbd_status error;
    3262             : 
    3263           0 :         error = uvideo_vs_init(sc);
    3264           0 :         if (error != USBD_NORMAL_COMPLETION)
    3265           0 :                 return (EINVAL);
    3266             : 
    3267           0 :         if (sc->sc_vs_cur->bulk_endpoint)
    3268           0 :                 uvideo_vs_start_bulk(sc);
    3269             :         else
    3270           0 :                 uvideo_vs_start_isoc(sc);
    3271             : 
    3272           0 :         return (0);
    3273           0 : }
    3274             : 
    3275             : int
    3276           0 : uvideo_streamoff(void *v, int type)
    3277             : {
    3278           0 :         struct uvideo_softc *sc = v;
    3279             : 
    3280           0 :         uvideo_vs_close(sc);
    3281             : 
    3282           0 :         return (0);
    3283             : }
    3284             : 
    3285             : int
    3286           0 : uvideo_queryctrl(void *v, struct v4l2_queryctrl *qctrl)
    3287             : {
    3288           0 :         struct uvideo_softc *sc = v;
    3289             :         int i, ret = 0;
    3290             :         usbd_status error;
    3291             :         uint8_t *ctrl_data;
    3292             :         uint16_t ctrl_len;
    3293             : 
    3294           0 :         i = uvideo_find_ctrl(sc, qctrl->id);
    3295           0 :         if (i == EINVAL)
    3296           0 :                 return (i);
    3297             : 
    3298           0 :         ctrl_len = uvideo_ctrls[i].ctrl_len;
    3299           0 :         if (ctrl_len < 1 || ctrl_len > 2) {
    3300           0 :                 printf("%s: invalid control length: %d\n", __func__, ctrl_len);
    3301           0 :                 return (EINVAL);
    3302             :         }
    3303             : 
    3304           0 :         ctrl_data = malloc(ctrl_len, M_USBDEV, M_WAITOK | M_CANFAIL);
    3305           0 :         if (ctrl_data == NULL) {
    3306           0 :                 printf("%s: could not allocate control data\n", __func__);
    3307           0 :                 return (ENOMEM);
    3308             :         }
    3309             : 
    3310             :         /* set type */
    3311           0 :         qctrl->type = uvideo_ctrls[i].type;
    3312             : 
    3313             :         /* set description name */
    3314           0 :         strlcpy(qctrl->name, uvideo_ctrls[i].name, sizeof(qctrl->name));
    3315             : 
    3316             :         /* set minimum */
    3317           0 :         error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_MIN,
    3318           0 :             sc->sc_desc_vc_pu_cur->bUnitID,
    3319           0 :             uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
    3320           0 :         if (error != USBD_NORMAL_COMPLETION) {
    3321             :                 ret = EINVAL;
    3322           0 :                 goto out;
    3323             :         }
    3324           0 :         switch (ctrl_len) {
    3325             :         case 1:
    3326           0 :                 qctrl->minimum = uvideo_ctrls[i].sig ?
    3327           0 :                     *(int8_t *)ctrl_data :
    3328           0 :                     *ctrl_data;
    3329           0 :                 break;
    3330             :         case 2:
    3331           0 :                 qctrl->minimum = uvideo_ctrls[i].sig ?
    3332           0 :                     (int16_t)UGETW(ctrl_data) :
    3333           0 :                     UGETW(ctrl_data);
    3334           0 :                 break;
    3335             :         }
    3336             : 
    3337             :         /* set maximum */
    3338           0 :         error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_MAX,
    3339           0 :             sc->sc_desc_vc_pu_cur->bUnitID,
    3340           0 :             uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
    3341           0 :         if (error != USBD_NORMAL_COMPLETION) {
    3342             :                 ret = EINVAL;
    3343           0 :                 goto out;
    3344             :         }
    3345           0 :         switch(ctrl_len) {
    3346             :         case 1:
    3347           0 :                 qctrl->maximum = uvideo_ctrls[i].sig ?
    3348           0 :                     *(int8_t *)ctrl_data :
    3349           0 :                     *ctrl_data;
    3350           0 :                 break;
    3351             :         case 2:
    3352           0 :                 qctrl->maximum = uvideo_ctrls[i].sig ?
    3353           0 :                     (int16_t)UGETW(ctrl_data) :
    3354           0 :                     UGETW(ctrl_data);
    3355           0 :                 break;
    3356             :         }
    3357             : 
    3358             :         /* set resolution */
    3359           0 :         error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_RES,
    3360           0 :             sc->sc_desc_vc_pu_cur->bUnitID,
    3361           0 :             uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
    3362           0 :         if (error != USBD_NORMAL_COMPLETION) {
    3363             :                 ret = EINVAL;
    3364           0 :                 goto out;
    3365             :         }
    3366           0 :         switch(ctrl_len) {
    3367             :         case 1:
    3368           0 :                 qctrl->step = uvideo_ctrls[i].sig ?
    3369           0 :                     *(int8_t *)ctrl_data:
    3370           0 :                     *ctrl_data;
    3371           0 :                 break;
    3372             :         case 2:
    3373           0 :                 qctrl->step = uvideo_ctrls[i].sig ?
    3374           0 :                     (int16_t)UGETW(ctrl_data) :
    3375           0 :                     UGETW(ctrl_data);
    3376           0 :                 break;
    3377             :         }
    3378             : 
    3379             :         /* set default */
    3380           0 :         error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_DEF,
    3381           0 :             sc->sc_desc_vc_pu_cur->bUnitID,
    3382           0 :             uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
    3383           0 :         if (error != USBD_NORMAL_COMPLETION) {
    3384             :                 ret = EINVAL;
    3385           0 :                 goto out;
    3386             :         }
    3387           0 :         switch(ctrl_len) {
    3388             :         case 1:
    3389           0 :                 qctrl->default_value = uvideo_ctrls[i].sig ?
    3390           0 :                     *(int8_t *)ctrl_data :
    3391           0 :                     *ctrl_data;
    3392           0 :                 break;
    3393             :         case 2:
    3394           0 :                 qctrl->default_value = uvideo_ctrls[i].sig ?
    3395           0 :                     (int16_t)UGETW(ctrl_data) :
    3396           0 :                     UGETW(ctrl_data);
    3397           0 :                 break;
    3398             :         }
    3399             : 
    3400             :         /* set flags */
    3401           0 :         qctrl->flags = 0;
    3402             : 
    3403             : out:
    3404           0 :         free(ctrl_data, M_USBDEV, ctrl_len);
    3405             : 
    3406           0 :         return (ret);
    3407           0 : }
    3408             : 
    3409             : int
    3410           0 : uvideo_g_ctrl(void *v, struct v4l2_control *gctrl)
    3411             : {
    3412           0 :         struct uvideo_softc *sc = v;
    3413             :         int i, ret = 0;
    3414             :         usbd_status error;
    3415             :         uint8_t *ctrl_data;
    3416             :         uint16_t ctrl_len;
    3417             : 
    3418           0 :         i = uvideo_find_ctrl(sc, gctrl->id);
    3419           0 :         if (i == EINVAL)
    3420           0 :                 return (i);
    3421             : 
    3422           0 :         ctrl_len = uvideo_ctrls[i].ctrl_len;
    3423           0 :         if (ctrl_len < 1 || ctrl_len > 2) {
    3424           0 :                 printf("%s: invalid control length: %d\n", __func__, ctrl_len);
    3425           0 :                 return (EINVAL);
    3426             :         }
    3427             : 
    3428           0 :         ctrl_data = malloc(ctrl_len, M_USBDEV, M_WAITOK | M_CANFAIL);
    3429           0 :         if (ctrl_data == NULL) {
    3430           0 :                 printf("%s: could not allocate control data\n", __func__);
    3431           0 :                 return (ENOMEM);
    3432             :         }
    3433             : 
    3434           0 :         error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_CUR,
    3435           0 :             sc->sc_desc_vc_pu_cur->bUnitID,
    3436           0 :             uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
    3437           0 :         if (error != USBD_NORMAL_COMPLETION) {
    3438             :                 ret = EINVAL;
    3439           0 :                 goto out;
    3440             :         }
    3441           0 :         switch(ctrl_len) {
    3442             :         case 1:
    3443           0 :                 gctrl->value = uvideo_ctrls[i].sig ?
    3444           0 :                     *(int8_t *)ctrl_data :
    3445           0 :                     *ctrl_data;
    3446           0 :                 break;
    3447             :         case 2:
    3448           0 :                 gctrl->value = uvideo_ctrls[i].sig ?
    3449           0 :                     (int16_t)UGETW(ctrl_data) :
    3450           0 :                     UGETW(ctrl_data);
    3451           0 :                 break;
    3452             :         }
    3453             : 
    3454             : out:
    3455           0 :         free(ctrl_data, M_USBDEV, ctrl_len);
    3456             : 
    3457           0 :         return (0);
    3458           0 : }
    3459             : 
    3460             : int
    3461           0 : uvideo_s_ctrl(void *v, struct v4l2_control *sctrl)
    3462             : {
    3463           0 :         struct uvideo_softc *sc = v;
    3464             :         int i, ret = 0;
    3465             :         usbd_status error;
    3466             :         uint8_t *ctrl_data;
    3467             :         uint16_t ctrl_len;
    3468             : 
    3469           0 :         i = uvideo_find_ctrl(sc, sctrl->id);
    3470           0 :         if (i == EINVAL)
    3471           0 :                 return (i);
    3472             : 
    3473           0 :         ctrl_len = uvideo_ctrls[i].ctrl_len;
    3474           0 :         if (ctrl_len < 1 || ctrl_len > 2) {
    3475           0 :                 printf("%s: invalid control length: %d\n", __func__, ctrl_len);
    3476           0 :                 return (EINVAL);
    3477             :         }
    3478             : 
    3479           0 :         ctrl_data = malloc(ctrl_len, M_USBDEV, M_WAITOK | M_CANFAIL);
    3480           0 :         if (ctrl_data == NULL) {
    3481           0 :                 printf("%s: could not allocate control data\n", __func__);
    3482           0 :                 return (ENOMEM);
    3483             :         }
    3484             : 
    3485           0 :         switch(ctrl_len) {
    3486             :         case 1:
    3487             :                 if (uvideo_ctrls[i].sig)
    3488             :                         *(int8_t *)ctrl_data = sctrl->value;
    3489             :                 else
    3490             :                         *ctrl_data = sctrl->value;
    3491           0 :                 break;
    3492             :         case 2:
    3493           0 :                 USETW(ctrl_data, sctrl->value);
    3494           0 :                 break;
    3495             :         }
    3496           0 :         error = uvideo_vc_set_ctrl(sc, ctrl_data, SET_CUR,
    3497           0 :             sc->sc_desc_vc_pu_cur->bUnitID,
    3498           0 :             uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
    3499           0 :         if (error != USBD_NORMAL_COMPLETION)
    3500           0 :                 ret = EINVAL;
    3501             : 
    3502           0 :         free(ctrl_data, M_USBDEV, ctrl_len);
    3503             : 
    3504           0 :         return (ret);
    3505           0 : }
    3506             : 
    3507             : int
    3508           0 : uvideo_try_fmt(void *v, struct v4l2_format *fmt)
    3509             : {
    3510           0 :         struct uvideo_softc *sc = v;
    3511           0 :         struct uvideo_res r;
    3512             :         int found, i;
    3513             : 
    3514           0 :         if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
    3515           0 :                 return (EINVAL);
    3516             : 
    3517             :         DPRINTF(1, "%s: %s: requested width=%d, height=%d\n",
    3518             :             DEVNAME(sc), __func__, fmt->fmt.pix.width, fmt->fmt.pix.height);
    3519             : 
    3520             :         /* search requested pixel format */
    3521           0 :         for (found = 0, i = 0; i < sc->sc_fmtgrp_num; i++) {
    3522           0 :                 if (fmt->fmt.pix.pixelformat == sc->sc_fmtgrp[i].pixelformat) {
    3523             :                         found = 1;
    3524           0 :                         break;
    3525             :                 }
    3526             :         }
    3527           0 :         if (found == 0)
    3528           0 :                 return (EINVAL);
    3529             : 
    3530             :         /* search requested frame resolution */
    3531           0 :         uvideo_find_res(sc, i, fmt->fmt.pix.width, fmt->fmt.pix.height, &r);
    3532             : 
    3533             :         /* offer closest resolution which we have found */
    3534           0 :         fmt->fmt.pix.width = r.width;
    3535           0 :         fmt->fmt.pix.height = r.height;
    3536             : 
    3537             :         DPRINTF(1, "%s: %s: offered width=%d, height=%d\n",
    3538             :             DEVNAME(sc), __func__, r.width, r.height);
    3539             : 
    3540             :         /* tell our frame buffer size */
    3541           0 :         fmt->fmt.pix.sizeimage = sc->sc_frame_buffer.buf_size;
    3542             : 
    3543           0 :         return (0);
    3544           0 : }
    3545             : 
    3546             : caddr_t
    3547           0 : uvideo_mappage(void *v, off_t off, int prot)
    3548             : {
    3549           0 :         struct uvideo_softc *sc = v;
    3550             :         caddr_t p;
    3551             : 
    3552           0 :         if (off >= sc->sc_mmap_buffer_size)
    3553           0 :                 return NULL;
    3554             : 
    3555           0 :         if (!sc->sc_mmap_flag)
    3556           0 :                 sc->sc_mmap_flag = 1;
    3557             : 
    3558           0 :         p = sc->sc_mmap_buffer + off;
    3559             : 
    3560           0 :         return (p);
    3561           0 : }
    3562             : 
    3563             : int
    3564           0 : uvideo_get_bufsize(void *v)
    3565             : {
    3566           0 :         struct uvideo_softc *sc = v;
    3567             : 
    3568           0 :         return (sc->sc_max_fbuf_size);
    3569             : }
    3570             : 
    3571             : int
    3572           0 : uvideo_start_read(void *v)
    3573             : {
    3574           0 :         struct uvideo_softc *sc = v;
    3575             :         usbd_status error;
    3576             : 
    3577           0 :         if (sc->sc_mmap_flag)
    3578           0 :                 sc->sc_mmap_flag = 0;
    3579             : 
    3580           0 :         error = uvideo_vs_init(sc);
    3581           0 :         if (error != USBD_NORMAL_COMPLETION)
    3582           0 :                 return (EINVAL);
    3583             : 
    3584           0 :         if (sc->sc_vs_cur->bulk_endpoint)
    3585           0 :                 uvideo_vs_start_bulk(sc);
    3586             :         else
    3587           0 :                 uvideo_vs_start_isoc(sc);
    3588             : 
    3589           0 :         return (0);
    3590           0 : }
    3591             : 
    3592             : usbd_status
    3593           0 : uvideo_usb_control(struct uvideo_softc *sc, uint8_t rt, uint8_t r,
    3594             :     uint16_t value, uint8_t *data, size_t length)
    3595             : {
    3596           0 :         usb_device_request_t    req;
    3597             :         usbd_status             err;
    3598             : 
    3599           0 :         req.bmRequestType = rt;
    3600           0 :         req.bRequest = r;
    3601           0 :         USETW(req.wIndex, 0);
    3602           0 :         USETW(req.wValue, value);
    3603           0 :         USETW(req.wLength, length);
    3604             : 
    3605           0 :         err = usbd_do_request(sc->sc_udev, &req, data);
    3606           0 :         if (err != USBD_NORMAL_COMPLETION)
    3607           0 :                 return (err);
    3608             : 
    3609           0 :         return (USBD_NORMAL_COMPLETION);
    3610           0 : }
    3611             : 
    3612             : usbd_status
    3613           0 : uvideo_ucode_loader_ricoh(struct uvideo_softc *sc)
    3614             : {
    3615             :         usbd_status error;
    3616           0 :         uint8_t *ucode, len, cbuf;
    3617           0 :         size_t ucode_size;
    3618             :         uint16_t addr;
    3619             :         int offset = 0, remain;
    3620             : 
    3621             :         /* get device microcode status */
    3622           0 :         cbuf = 0;
    3623           0 :         error = uvideo_usb_control(sc, UT_READ_VENDOR_DEVICE,
    3624             :             0xa4, 0, &cbuf, sizeof cbuf);
    3625           0 :         if (error != USBD_NORMAL_COMPLETION) {
    3626           0 :                 printf("%s: ucode status error=%s!\n",
    3627           0 :                     DEVNAME(sc), usbd_errstr(error));
    3628           0 :                 return (USBD_INVAL);
    3629             :         }
    3630           0 :         if (cbuf) {
    3631             :                 DPRINTF(1, "%s: microcode already loaded\n", DEVNAME(sc));
    3632           0 :                 return (USBD_NORMAL_COMPLETION);
    3633             :         } else {
    3634             :                 DPRINTF(1, "%s: microcode not loaded\n", DEVNAME(sc));
    3635             :         }
    3636             : 
    3637             :         /* open microcode file */
    3638           0 :         error = loadfirmware(sc->sc_quirk->ucode_name, &ucode, &ucode_size);
    3639           0 :         if (error != 0) {
    3640           0 :                 printf("%s: loadfirmware error=%d!\n", DEVNAME(sc), error);
    3641           0 :                 return (USBD_INVAL);
    3642             :         }
    3643             : 
    3644             :         /* upload microcode */
    3645           0 :         remain = ucode_size;
    3646           0 :         while (remain > 0) {
    3647           0 :                 if (remain < 3) {
    3648           0 :                         printf("%s: ucode file incomplete!\n", DEVNAME(sc));
    3649           0 :                         free(ucode, M_DEVBUF, ucode_size);
    3650           0 :                         return (USBD_INVAL);
    3651             :                 }
    3652             : 
    3653           0 :                 len = ucode[offset];
    3654           0 :                 addr = ucode[offset + 1] | (ucode[offset + 2] << 8);
    3655           0 :                 offset += 3;
    3656           0 :                 remain -= 3;
    3657             : 
    3658           0 :                 error = uvideo_usb_control(sc, UT_WRITE_VENDOR_DEVICE,
    3659           0 :                     0xa0, addr, &ucode[offset], len);
    3660           0 :                 if (error != USBD_NORMAL_COMPLETION) {
    3661           0 :                         printf("%s: ucode upload error=%s!\n",
    3662           0 :                             DEVNAME(sc), usbd_errstr(error));
    3663           0 :                         free(ucode, M_DEVBUF, ucode_size);
    3664           0 :                         return (USBD_INVAL);
    3665             :                 }
    3666             :                 DPRINTF(1, "%s: uploaded %d bytes ucode to addr 0x%x\n",
    3667             :                     DEVNAME(sc), len, addr);
    3668             : 
    3669           0 :                 offset += len;
    3670           0 :                 remain -= len;
    3671             :         }
    3672           0 :         free(ucode, M_DEVBUF, ucode_size);
    3673             : 
    3674             :         /* activate microcode */
    3675           0 :         cbuf = 0;
    3676           0 :         error = uvideo_usb_control(sc, UT_WRITE_VENDOR_DEVICE,
    3677             :             0xa1, 0, &cbuf, sizeof cbuf);
    3678           0 :         if (error != USBD_NORMAL_COMPLETION) {
    3679           0 :                 printf("%s: ucode activate error=%s!\n",
    3680           0 :                     DEVNAME(sc), usbd_errstr(error));
    3681           0 :                 return (USBD_INVAL);
    3682             :         }
    3683             :         DPRINTF(1, "%s: ucode activated\n", DEVNAME(sc));
    3684             : 
    3685           0 :         return (USBD_NORMAL_COMPLETION);
    3686           0 : }
    3687             : 
    3688             : /*
    3689             :  * The iSight first generation device will first attach as
    3690             :  * 0x8300 non-UVC.  After the firmware gots uploaded, the device
    3691             :  * will reset and come back as 0x8501 UVC compatible.
    3692             :  */
    3693             : usbd_status
    3694           0 : uvideo_ucode_loader_apple_isight(struct uvideo_softc *sc)
    3695             : {
    3696             :         usbd_status error;
    3697           0 :         uint8_t *ucode, *code, cbuf;
    3698           0 :         size_t ucode_size;
    3699             :         uint16_t len, req, off, llen;
    3700             : 
    3701             :         /* open microcode file */
    3702           0 :         error = loadfirmware(sc->sc_quirk->ucode_name, &ucode, &ucode_size);
    3703           0 :         if (error != 0) {
    3704           0 :                 printf("%s: loadfirmware error=%d!\n", DEVNAME(sc), error);
    3705           0 :                 return (USBD_INVAL);
    3706             :         }
    3707             : 
    3708             :         /* send init request */
    3709           0 :         cbuf = 1;
    3710           0 :         error = uvideo_usb_control(sc, UT_WRITE_VENDOR_DEVICE, 0xa0, 0xe600,
    3711             :             &cbuf, sizeof(cbuf));
    3712           0 :         if (error) {
    3713           0 :                 printf("%s: failed to init firmware loading state: %s\n",
    3714           0 :                     DEVNAME(sc), usbd_errstr(error));
    3715           0 :                 return (error);
    3716             :         }
    3717             : 
    3718           0 :         code = ucode;
    3719           0 :         while (code < ucode + ucode_size) {
    3720             :                 /* get header information */
    3721           0 :                 len = (code[0] << 8) | code[1];
    3722           0 :                 req = (code[2] << 8) | code[3];
    3723             :                 DPRINTF(1, "%s: ucode data len=%d, request=0x%x\n",
    3724             :                     DEVNAME(sc), len, req);
    3725           0 :                 if (len < 1 || len > 1023) {
    3726           0 :                         printf("%s: ucode header contains wrong value!\n",
    3727           0 :                             DEVNAME(sc));
    3728           0 :                         free(ucode, M_DEVBUF, ucode_size);
    3729           0 :                         return (USBD_INVAL);
    3730             :                 }
    3731           0 :                 code += 4;
    3732             : 
    3733             :                 /* send data to device */
    3734           0 :                 for (off = 0; len > 0; req += 50, off += 50) {
    3735           0 :                         llen = len > 50 ? 50 : len;
    3736           0 :                         len -= llen;
    3737             : 
    3738             :                         DPRINTF(1, "%s: send %d bytes data to offset 0x%x\n",
    3739             :                             DEVNAME(sc), llen, req);
    3740           0 :                         error = uvideo_usb_control(sc, UT_WRITE_VENDOR_DEVICE,
    3741           0 :                             0xa0, req, code, llen);
    3742           0 :                         if (error) {
    3743           0 :                                 printf("%s: ucode load failed: %s\n",
    3744           0 :                                     DEVNAME(sc), usbd_errstr(error));
    3745           0 :                                 free(ucode, M_DEVBUF, ucode_size);
    3746           0 :                                 return (USBD_INVAL);
    3747             :                         }
    3748             : 
    3749           0 :                         code += llen;
    3750             :                 }
    3751             :         }
    3752           0 :         free(ucode, M_DEVBUF, ucode_size);
    3753             : 
    3754             :         /* send finished request */
    3755           0 :         cbuf = 0;
    3756           0 :         error = uvideo_usb_control(sc, UT_WRITE_VENDOR_DEVICE, 0xa0, 0xe600,
    3757             :             &cbuf, sizeof(cbuf));
    3758           0 :         if (error != USBD_NORMAL_COMPLETION) {
    3759           0 :                 printf("%s: ucode activate error=%s!\n",
    3760           0 :                     DEVNAME(sc), usbd_errstr(error));
    3761           0 :                 return (USBD_INVAL);
    3762             :         }
    3763             :         DPRINTF(1, "%s: ucode activated\n", DEVNAME(sc));
    3764             : 
    3765             :         /*
    3766             :          * We will always return from the attach routine since the device
    3767             :          * will reset and re-attach at this point.
    3768             :          */
    3769           0 :         return (USBD_INVAL);
    3770           0 : }

Generated by: LCOV version 1.13