The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/video.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $NetBSD: video.c,v 1.45 2022/03/03 06:23:25 riastradh Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2008 Patrick Mahoney <pat@polycrystal.org>
    5  * All rights reserved.
    6  *
    7  * This code was written by Patrick Mahoney (pat@polycrystal.org) as
    8  * part of Google Summer of Code 2008.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * This ia a Video4Linux 2 compatible /dev/video driver for NetBSD
   34  *
   35  * See http://v4l2spec.bytesex.org/ for Video4Linux 2 specifications
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __KERNEL_RCSID(0, "$NetBSD: video.c,v 1.45 2022/03/03 06:23:25 riastradh Exp $");
   40 
   41 #include "video.h"
   42 #if NVIDEO > 0
   43 
   44 #include <sys/param.h>
   45 #include <sys/ioctl.h>
   46 #include <sys/fcntl.h>
   47 #include <sys/vnode.h>
   48 #include <sys/poll.h>
   49 #include <sys/select.h>
   50 #include <sys/kmem.h>
   51 #include <sys/pool.h>
   52 #include <sys/conf.h>
   53 #include <sys/types.h>
   54 #include <sys/device.h>
   55 #include <sys/condvar.h>
   56 #include <sys/queue.h>
   57 #include <sys/videoio.h>
   58 
   59 #include <dev/video_if.h>
   60 
   61 #include "ioconf.h"
   62 
   63 /* #define VIDEO_DEBUG 1 */
   64 
   65 #ifdef VIDEO_DEBUG
   66 #define DPRINTF(x)      do { if (videodebug) printf x; } while (0)
   67 #define DPRINTFN(n,x)   do { if (videodebug>(n)) printf x; } while (0)
   68 int     videodebug = VIDEO_DEBUG;
   69 #else
   70 #define DPRINTF(x)
   71 #define DPRINTFN(n,x)
   72 #endif
   73 
   74 #define PAGE_ALIGN(a)           (((a) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
   75 
   76 #define VIDEO_DRIVER_VERSION                            \
   77         (((__NetBSD_Version__ / 100000000) << 16) |     \
   78          ((__NetBSD_Version__ / 1000000 % 100) << 8) |  \
   79          (__NetBSD_Version__ / 100 % 100))
   80 
   81 /* TODO: move to sys/intr.h */
   82 #define IPL_VIDEO       IPL_VM
   83 #define splvideo()      splvm()
   84 
   85 #define VIDEO_MIN_BUFS 2
   86 #define VIDEO_MAX_BUFS 32
   87 #define VIDEO_NUM_BUFS 4
   88 
   89 /* Scatter Buffer - an array of fixed size (PAGE_SIZE) chunks
   90  * allocated non-contiguously and functions to get data into and out
   91  * of the scatter buffer. */
   92 struct scatter_buf {
   93         pool_cache_t    sb_pool;
   94         size_t          sb_size;    /* size in bytes */
   95         size_t          sb_npages;  /* number of pages */
   96         uint8_t         **sb_page_ary; /* array of page pointers */
   97 };
   98 
   99 struct scatter_io {
  100         struct scatter_buf *sio_buf;
  101         off_t           sio_offset;
  102         size_t          sio_resid;
  103 };
  104 
  105 static void     scatter_buf_init(struct scatter_buf *);
  106 static void     scatter_buf_destroy(struct scatter_buf *);
  107 static int      scatter_buf_set_size(struct scatter_buf *, size_t);
  108 static paddr_t  scatter_buf_map(struct scatter_buf *, off_t);
  109 
  110 static bool     scatter_io_init(struct scatter_buf *, off_t, size_t, struct scatter_io *);
  111 static bool     scatter_io_next(struct scatter_io *, void **, size_t *);
  112 static void     scatter_io_undo(struct scatter_io *, size_t);
  113 static void     scatter_io_copyin(struct scatter_io *, const void *);
  114 /* static void  scatter_io_copyout(struct scatter_io *, void *); */
  115 static int      scatter_io_uiomove(struct scatter_io *, struct uio *);
  116 
  117 
  118 enum video_stream_method {
  119         VIDEO_STREAM_METHOD_NONE,
  120         VIDEO_STREAM_METHOD_READ,
  121         VIDEO_STREAM_METHOD_MMAP,
  122         VIDEO_STREAM_METHOD_USERPTR
  123 };
  124 
  125 struct video_buffer {
  126         struct v4l2_buffer              *vb_buf;
  127         SIMPLEQ_ENTRY(video_buffer)     entries;
  128 };
  129 
  130 SIMPLEQ_HEAD(sample_queue, video_buffer);
  131 
  132 struct video_stream {
  133         int                     vs_flags; /* flags given to open() */
  134 
  135         struct video_format     vs_format;
  136 
  137         int                     vs_frameno; /* toggles between 0 and 1,
  138                                              * or -1 if new */
  139         uint32_t                vs_sequence; /* absolute frame/sample number in
  140                                               * sequence, wraps around */
  141         bool                    vs_drop; /* drop payloads from current
  142                                           * frameno? */
  143 
  144         enum v4l2_buf_type      vs_type;
  145         uint8_t                 vs_nbufs;
  146         struct video_buffer     **vs_buf;
  147 
  148         struct scatter_buf      vs_data; /* stores video data for MMAP
  149                                           * and READ */
  150 
  151         /* Video samples may exist in different locations.  Initially,
  152          * samples are queued into the ingress queue.  The driver
  153          * grabs these in turn and fills them with video data.  Once
  154          * filled, they are moved to the egress queue.  Samples are
  155          * dequeued either by user with MMAP method or, with READ
  156          * method, videoread() works from the first sample in the
  157          * ingress queue without dequeing.  In the first case, the
  158          * user re-queues the buffer when finished, and videoread()
  159          * does the same when all data has been read.  The sample now
  160          * returns to the ingress queue. */
  161         struct sample_queue     vs_ingress; /* samples under driver control */
  162         struct sample_queue     vs_egress; /* samples headed for userspace */
  163 
  164         bool                    vs_streaming;
  165         enum video_stream_method vs_method; /* method by which
  166                                              * userspace will read
  167                                              * samples */
  168 
  169         kmutex_t                vs_lock; /* Lock to manipulate queues.
  170                                           * Should also be held when
  171                                           * changing number of
  172                                           * buffers. */
  173         kcondvar_t              vs_sample_cv; /* signaled on new
  174                                                * ingress sample */
  175         struct selinfo          vs_sel;
  176 
  177         uint32_t                vs_bytesread; /* bytes read() from current
  178                                                * sample thus far */
  179 };
  180 
  181 struct video_softc {
  182         device_t        sc_dev;
  183         device_t        hw_dev;          /* Hardware (parent) device */
  184         void *          hw_softc;        /* Hardware device private softc */
  185         const struct video_hw_if *hw_if; /* Hardware interface */
  186 
  187         u_int           sc_open;
  188         int             sc_refcnt;
  189         int             sc_opencnt;
  190         bool            sc_dying;
  191 
  192         struct video_stream sc_stream_in;
  193 };
  194 static int      video_print(void *, const char *);
  195 
  196 static int      video_match(device_t, cfdata_t, void *);
  197 static void     video_attach(device_t, device_t, void *);
  198 static int      video_detach(device_t, int);
  199 static int      video_activate(device_t, enum devact);
  200 
  201 dev_type_open(videoopen);
  202 dev_type_close(videoclose);
  203 dev_type_read(videoread);
  204 dev_type_write(videowrite);
  205 dev_type_ioctl(videoioctl);
  206 dev_type_poll(videopoll);
  207 dev_type_mmap(videommap);
  208 
  209 const struct cdevsw video_cdevsw = {
  210         .d_open = videoopen,
  211         .d_close = videoclose,
  212         .d_read = videoread,
  213         .d_write = videowrite,
  214         .d_ioctl = videoioctl,
  215         .d_stop = nostop,
  216         .d_tty = notty,
  217         .d_poll = videopoll,
  218         .d_mmap = videommap,
  219         .d_kqfilter = nokqfilter,
  220         .d_discard = nodiscard,
  221         .d_flag = D_OTHER
  222 };
  223 
  224 #define VIDEOUNIT(n)    (minor(n))
  225 
  226 CFATTACH_DECL_NEW(video, sizeof(struct video_softc),
  227                   video_match, video_attach, video_detach, video_activate);
  228 
  229 static const char *     video_pixel_format_str(enum video_pixel_format);
  230 
  231 /* convert various values from V4L2 to native values of this driver */
  232 static uint16_t v4l2id_to_control_id(uint32_t);
  233 static uint32_t control_flags_to_v4l2flags(uint32_t);
  234 static enum v4l2_ctrl_type control_type_to_v4l2type(enum video_control_type);
  235 
  236 static void     v4l2_format_to_video_format(const struct v4l2_format *,
  237                                             struct video_format *);
  238 static void     video_format_to_v4l2_format(const struct video_format *,
  239                                             struct v4l2_format *);
  240 static void     v4l2_standard_to_video_standard(v4l2_std_id,
  241                                                 enum video_standard *);
  242 static void     video_standard_to_v4l2_standard(enum video_standard,
  243                                                 struct v4l2_standard *);
  244 static void     v4l2_input_to_video_input(const struct v4l2_input *,
  245                                           struct video_input *);
  246 static void     video_input_to_v4l2_input(const struct video_input *,
  247                                           struct v4l2_input *);
  248 static void     v4l2_audio_to_video_audio(const struct v4l2_audio *,
  249                                           struct video_audio *);
  250 static void     video_audio_to_v4l2_audio(const struct video_audio *,
  251                                           struct v4l2_audio *);
  252 static void     v4l2_tuner_to_video_tuner(const struct v4l2_tuner *,
  253                                           struct video_tuner *);
  254 static void     video_tuner_to_v4l2_tuner(const struct video_tuner *,
  255                                           struct v4l2_tuner *);
  256 
  257 /* V4L2 api functions, typically called from videoioctl() */
  258 static int      video_enum_format(struct video_softc *, struct v4l2_fmtdesc *);
  259 static int      video_get_format(struct video_softc *,
  260                                  struct v4l2_format *);
  261 static int      video_set_format(struct video_softc *,
  262                                  struct v4l2_format *);
  263 static int      video_try_format(struct video_softc *,
  264                                  struct v4l2_format *);
  265 static int      video_get_parm(struct video_softc *,
  266                                struct v4l2_streamparm *);
  267 static int      video_set_parm(struct video_softc *,
  268                                struct v4l2_streamparm *);
  269 static int      video_enum_standard(struct video_softc *,
  270                                     struct v4l2_standard *);
  271 static int      video_get_standard(struct video_softc *, v4l2_std_id *);
  272 static int      video_set_standard(struct video_softc *, v4l2_std_id);
  273 static int      video_enum_input(struct video_softc *, struct v4l2_input *);
  274 static int      video_get_input(struct video_softc *, int *);
  275 static int      video_set_input(struct video_softc *, int);
  276 static int      video_enum_audio(struct video_softc *, struct v4l2_audio *);
  277 static int      video_get_audio(struct video_softc *, struct v4l2_audio *);
  278 static int      video_set_audio(struct video_softc *, struct v4l2_audio *);
  279 static int      video_get_tuner(struct video_softc *, struct v4l2_tuner *);
  280 static int      video_set_tuner(struct video_softc *, struct v4l2_tuner *);
  281 static int      video_get_frequency(struct video_softc *,
  282                                     struct v4l2_frequency *);
  283 static int      video_set_frequency(struct video_softc *,
  284                                     struct v4l2_frequency *);
  285 static int      video_query_control(struct video_softc *,
  286                                     struct v4l2_queryctrl *);
  287 static int      video_get_control(struct video_softc *,
  288                                   struct v4l2_control *);
  289 static int      video_set_control(struct video_softc *,
  290                                   const struct v4l2_control *);
  291 static int      video_request_bufs(struct video_softc *,
  292                                    struct v4l2_requestbuffers *);
  293 static int      video_query_buf(struct video_softc *, struct v4l2_buffer *);
  294 static int      video_queue_buf(struct video_softc *, struct v4l2_buffer *);
  295 static int      video_dequeue_buf(struct video_softc *, struct v4l2_buffer *);
  296 static int      video_stream_on(struct video_softc *, enum v4l2_buf_type);
  297 static int      video_stream_off(struct video_softc *, enum v4l2_buf_type);
  298 
  299 static struct video_buffer *    video_buffer_alloc(void);
  300 static void                     video_buffer_free(struct video_buffer *);
  301 
  302 
  303 /* functions for video_stream */
  304 static void     video_stream_init(struct video_stream *);
  305 static void     video_stream_fini(struct video_stream *);
  306 
  307 static int      video_stream_setup_bufs(struct video_stream *,
  308                                         enum video_stream_method,
  309                                         uint8_t);
  310 static void     video_stream_teardown_bufs(struct video_stream *);
  311 
  312 static int      video_stream_realloc_bufs(struct video_stream *, uint8_t);
  313 #define         video_stream_free_bufs(vs) \
  314         video_stream_realloc_bufs((vs), 0)
  315 
  316 static void     video_stream_enqueue(struct video_stream *,
  317                                      struct video_buffer *);
  318 static struct video_buffer * video_stream_dequeue(struct video_stream *);
  319 static void     video_stream_write(struct video_stream *,
  320                                    const struct video_payload *);
  321 static void     video_stream_sample_done(struct video_stream *);
  322 
  323 #ifdef VIDEO_DEBUG
  324 /* debugging */
  325 static const char *     video_ioctl_str(u_long);
  326 #endif
  327 
  328 
  329 static int
  330 video_match(device_t parent, cfdata_t match, void *aux)
  331 {
  332 #ifdef VIDEO_DEBUG
  333         struct video_attach_args *args;
  334 
  335         args = aux;
  336         DPRINTF(("video_match: hw=%p\n", args->hw_if));
  337 #endif
  338         return 1;
  339 }
  340 
  341 
  342 static void
  343 video_attach(device_t parent, device_t self, void *aux)
  344 {
  345         struct video_softc *sc;
  346         struct video_attach_args *args;
  347 
  348         sc = device_private(self);
  349         args = aux;
  350 
  351         sc->sc_dev = self;
  352         sc->hw_dev = parent;
  353         sc->hw_if = args->hw_if;
  354         sc->hw_softc = args->hw_softc;
  355 
  356         sc->sc_open = 0;
  357         sc->sc_refcnt = 0;
  358         sc->sc_opencnt = 0;
  359         sc->sc_dying = false;
  360 
  361         video_stream_init(&sc->sc_stream_in);
  362 
  363         aprint_naive("\n");
  364         aprint_normal(": %s\n", sc->hw_if->get_devname(sc->hw_softc));
  365 
  366         DPRINTF(("video_attach: sc=%p hwif=%p\n", sc, sc->hw_if));
  367 
  368         if (!pmf_device_register(self, NULL, NULL))
  369                 aprint_error_dev(self, "couldn't establish power handler\n");
  370 }
  371 
  372 
  373 static int
  374 video_activate(device_t self, enum devact act)
  375 {
  376         struct video_softc *sc = device_private(self);
  377 
  378         DPRINTF(("video_activate: sc=%p\n", sc));
  379         switch (act) {
  380         case DVACT_DEACTIVATE:
  381                 sc->sc_dying = true;
  382                 return 0;
  383         default:
  384                 return EOPNOTSUPP;
  385         }
  386 }
  387 
  388 
  389 static int
  390 video_detach(device_t self, int flags)
  391 {
  392         struct video_softc *sc;
  393         int maj, mn;
  394 
  395         sc = device_private(self);
  396         DPRINTF(("video_detach: sc=%p flags=%d\n", sc, flags));
  397 
  398         sc->sc_dying = true;
  399 
  400         pmf_device_deregister(self);
  401 
  402         maj = cdevsw_lookup_major(&video_cdevsw);
  403         mn = device_unit(self);
  404         /* close open instances */
  405         vdevgone(maj, mn, mn, VCHR);
  406 
  407         video_stream_fini(&sc->sc_stream_in);
  408 
  409         return 0;
  410 }
  411 
  412 
  413 static int
  414 video_print(void *aux, const char *pnp)
  415 {
  416         if (pnp != NULL) {
  417                 DPRINTF(("video_print: have pnp\n"));
  418                 aprint_normal("%s at %s\n", "video", pnp);
  419         } else {
  420                 DPRINTF(("video_print: pnp is NULL\n"));
  421         }
  422         return UNCONF;
  423 }
  424 
  425 
  426 /*
  427  * Called from hardware driver.  This is where the MI audio driver
  428  * gets probed/attached to the hardware driver.
  429  */
  430 device_t
  431 video_attach_mi(const struct video_hw_if *hw_if, device_t parent, void *sc)
  432 {
  433         struct video_attach_args args;
  434 
  435         args.hw_if = hw_if;
  436         args.hw_softc = sc;
  437         return config_found(parent, &args, video_print,
  438             CFARGS(.iattr = "videobus"));
  439 }
  440 
  441 /* video_submit_payload - called by hardware driver to submit payload data */
  442 void
  443 video_submit_payload(device_t self, const struct video_payload *payload)
  444 {
  445         struct video_softc *sc;
  446 
  447         sc = device_private(self);
  448 
  449         if (sc == NULL)
  450                 return;
  451 
  452         video_stream_write(&sc->sc_stream_in, payload);
  453 }
  454 
  455 static const char *
  456 video_pixel_format_str(enum video_pixel_format px)
  457 {
  458         switch (px) {
  459         case VIDEO_FORMAT_UYVY:         return "UYVY";
  460         case VIDEO_FORMAT_YUV420:       return "YUV420";
  461         case VIDEO_FORMAT_YUY2:         return "YUYV";
  462         case VIDEO_FORMAT_NV12:         return "NV12";
  463         case VIDEO_FORMAT_RGB24:        return "RGB24";
  464         case VIDEO_FORMAT_RGB555:       return "RGB555";
  465         case VIDEO_FORMAT_RGB565:       return "RGB565";
  466         case VIDEO_FORMAT_SBGGR8:       return "SBGGR8";
  467         case VIDEO_FORMAT_MJPEG:        return "MJPEG";
  468         case VIDEO_FORMAT_DV:           return "DV";
  469         case VIDEO_FORMAT_MPEG:         return "MPEG";
  470         default:                        return "Unknown";
  471         }
  472 }
  473 
  474 /* Takes a V4L2 id and returns a "native" video driver control id.
  475  * TODO: is there a better way to do this?  some kind of array? */
  476 static uint16_t
  477 v4l2id_to_control_id(uint32_t v4l2id)
  478 {
  479         /* mask includes class bits and control id bits */
  480         switch (v4l2id & 0xffffff) {
  481         case V4L2_CID_BRIGHTNESS:       return VIDEO_CONTROL_BRIGHTNESS;
  482         case V4L2_CID_CONTRAST:         return VIDEO_CONTROL_CONTRAST;
  483         case V4L2_CID_SATURATION:       return VIDEO_CONTROL_SATURATION;
  484         case V4L2_CID_HUE:              return VIDEO_CONTROL_HUE;
  485         case V4L2_CID_HUE_AUTO:         return VIDEO_CONTROL_HUE_AUTO;
  486         case V4L2_CID_SHARPNESS:        return VIDEO_CONTROL_SHARPNESS;
  487         case V4L2_CID_GAMMA:            return VIDEO_CONTROL_GAMMA;
  488 
  489         /* "black level" means the same as "brightness", but V4L2
  490          * defines two separate controls that are not identical.
  491          * V4L2_CID_BLACK_LEVEL is deprecated however in V4L2. */
  492         case V4L2_CID_BLACK_LEVEL:      return VIDEO_CONTROL_BRIGHTNESS;
  493 
  494         case V4L2_CID_AUDIO_VOLUME:     return VIDEO_CONTROL_UNDEFINED;
  495         case V4L2_CID_AUDIO_BALANCE:    return VIDEO_CONTROL_UNDEFINED;
  496         case V4L2_CID_AUDIO_BASS:       return VIDEO_CONTROL_UNDEFINED;
  497         case V4L2_CID_AUDIO_TREBLE:     return VIDEO_CONTROL_UNDEFINED;
  498         case V4L2_CID_AUDIO_MUTE:       return VIDEO_CONTROL_UNDEFINED;
  499         case V4L2_CID_AUDIO_LOUDNESS:   return VIDEO_CONTROL_UNDEFINED;
  500 
  501         case V4L2_CID_AUTO_WHITE_BALANCE:
  502                 return VIDEO_CONTROL_WHITE_BALANCE_AUTO;
  503         case V4L2_CID_DO_WHITE_BALANCE:
  504                 return VIDEO_CONTROL_WHITE_BALANCE_ACTION;
  505         case V4L2_CID_RED_BALANCE:
  506         case V4L2_CID_BLUE_BALANCE:
  507                 /* This might not fit in with the control_id/value_id scheme */
  508                 return VIDEO_CONTROL_WHITE_BALANCE_COMPONENT;
  509         case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
  510                 return VIDEO_CONTROL_WHITE_BALANCE_TEMPERATURE;
  511         case V4L2_CID_EXPOSURE:
  512                 return VIDEO_CONTROL_EXPOSURE_TIME_ABSOLUTE;
  513         case V4L2_CID_GAIN:             return VIDEO_CONTROL_GAIN;
  514         case V4L2_CID_AUTOGAIN:         return VIDEO_CONTROL_GAIN_AUTO;
  515         case V4L2_CID_HFLIP:            return VIDEO_CONTROL_HFLIP;
  516         case V4L2_CID_VFLIP:            return VIDEO_CONTROL_VFLIP;
  517         case V4L2_CID_HCENTER_DEPRECATED:
  518         case V4L2_CID_VCENTER_DEPRECATED:
  519                 return VIDEO_CONTROL_UNDEFINED;
  520         case V4L2_CID_POWER_LINE_FREQUENCY:
  521                 return VIDEO_CONTROL_POWER_LINE_FREQUENCY;
  522         case V4L2_CID_BACKLIGHT_COMPENSATION:
  523                 return VIDEO_CONTROL_BACKLIGHT_COMPENSATION;
  524         default:                        return V4L2_CTRL_ID2CID(v4l2id);
  525         }
  526 }
  527 
  528 
  529 static uint32_t
  530 control_flags_to_v4l2flags(uint32_t flags)
  531 {
  532         uint32_t v4l2flags = 0;
  533 
  534         if (flags & VIDEO_CONTROL_FLAG_DISABLED)
  535                 v4l2flags |= V4L2_CTRL_FLAG_INACTIVE;
  536 
  537         if (!(flags & VIDEO_CONTROL_FLAG_WRITE))
  538                 v4l2flags |= V4L2_CTRL_FLAG_READ_ONLY;
  539 
  540         if (flags & VIDEO_CONTROL_FLAG_AUTOUPDATE)
  541                 v4l2flags |= V4L2_CTRL_FLAG_GRABBED;
  542 
  543         return v4l2flags;
  544 }
  545 
  546 
  547 static enum v4l2_ctrl_type
  548 control_type_to_v4l2type(enum video_control_type type) {
  549         switch (type) {
  550         case VIDEO_CONTROL_TYPE_INT:    return V4L2_CTRL_TYPE_INTEGER;
  551         case VIDEO_CONTROL_TYPE_BOOL:   return V4L2_CTRL_TYPE_BOOLEAN;
  552         case VIDEO_CONTROL_TYPE_LIST:   return V4L2_CTRL_TYPE_MENU;
  553         case VIDEO_CONTROL_TYPE_ACTION: return V4L2_CTRL_TYPE_BUTTON;
  554         default:                        return V4L2_CTRL_TYPE_INTEGER; /* err? */
  555         }
  556 }
  557 
  558 
  559 static int
  560 video_query_control(struct video_softc *sc,
  561                     struct v4l2_queryctrl *query)
  562 {
  563         const struct video_hw_if *hw;
  564         struct video_control_desc_group desc_group;
  565         struct video_control_desc desc;
  566         int err;
  567 
  568         hw = sc->hw_if;
  569         if (hw->get_control_desc_group) {
  570                 desc.group_id = desc.control_id =
  571                     v4l2id_to_control_id(query->id);
  572 
  573                 desc_group.group_id = desc.group_id;
  574                 desc_group.length = 1;
  575                 desc_group.desc = &desc;
  576 
  577                 err = hw->get_control_desc_group(sc->hw_softc, &desc_group);
  578                 if (err != 0)
  579                         return err;
  580 
  581                 query->type = control_type_to_v4l2type(desc.type);
  582                 memcpy(query->name, desc.name, 32);
  583                 query->minimum = desc.min;
  584                 query->maximum = desc.max;
  585                 query->step = desc.step;
  586                 query->default_value = desc.def;
  587                 query->flags = control_flags_to_v4l2flags(desc.flags);
  588 
  589                 return 0;
  590         } else {
  591                 return EINVAL;
  592         }
  593 }
  594 
  595 
  596 /* Takes a single Video4Linux2 control and queries the driver for the
  597  * current value. */
  598 static int
  599 video_get_control(struct video_softc *sc,
  600                   struct v4l2_control *vcontrol)
  601 {
  602         const struct video_hw_if *hw;
  603         struct video_control_group group;
  604         struct video_control control;
  605         int err;
  606 
  607         hw = sc->hw_if;
  608         if (hw->get_control_group) {
  609                 control.group_id = control.control_id =
  610                     v4l2id_to_control_id(vcontrol->id);
  611                 /* ?? if "control_id" is arbitrarily defined by the
  612                  * driver, then we need some way to store it...  Maybe
  613                  * it doesn't matter for single value controls. */
  614                 control.value = 0;
  615 
  616                 group.group_id = control.group_id;
  617                 group.length = 1;
  618                 group.control = &control;
  619 
  620                 err = hw->get_control_group(sc->hw_softc, &group);
  621                 if (err != 0)
  622                         return err;
  623 
  624                 vcontrol->value = control.value;
  625                 return 0;
  626         } else {
  627                 return EINVAL;
  628         }
  629 }
  630 
  631 static void
  632 video_format_to_v4l2_format(const struct video_format *src,
  633                             struct v4l2_format *dest)
  634 {
  635         /* TODO: what about win and vbi formats? */
  636         dest->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  637         dest->fmt.pix.width = src->width;
  638         dest->fmt.pix.height = src->height;
  639         if (VIDEO_INTERLACED(src->interlace_flags))
  640                 dest->fmt.pix.field = V4L2_FIELD_INTERLACED;
  641         else
  642                 dest->fmt.pix.field = V4L2_FIELD_NONE;
  643         dest->fmt.pix.bytesperline = src->stride;
  644         dest->fmt.pix.sizeimage = src->sample_size;
  645         dest->fmt.pix.priv = src->priv;
  646 
  647         switch (src->color.primaries) {
  648         case VIDEO_COLOR_PRIMARIES_SMPTE_170M:
  649                 dest->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
  650                 break;
  651         /* XXX */
  652         case VIDEO_COLOR_PRIMARIES_UNSPECIFIED:
  653         default:
  654                 dest->fmt.pix.colorspace = 0;
  655                 break;
  656         }
  657 
  658         switch (src->pixel_format) {
  659         case VIDEO_FORMAT_UYVY:
  660                 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
  661                 break;
  662         case VIDEO_FORMAT_YUV420:
  663                 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
  664                 break;
  665         case VIDEO_FORMAT_YUY2:
  666                 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
  667                 break;
  668         case VIDEO_FORMAT_NV12:
  669                 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12;
  670                 break;
  671         case VIDEO_FORMAT_RGB24:
  672                 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
  673                 break;
  674         case VIDEO_FORMAT_RGB555:
  675                 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB555;
  676                 break;
  677         case VIDEO_FORMAT_RGB565:
  678                 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;
  679                 break;
  680         case VIDEO_FORMAT_SBGGR8:
  681                 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
  682                 break;
  683         case VIDEO_FORMAT_MJPEG:
  684                 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
  685                 break;
  686         case VIDEO_FORMAT_DV:
  687                 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_DV;
  688                 break;
  689         case VIDEO_FORMAT_MPEG:
  690                 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
  691                 break;
  692         case VIDEO_FORMAT_UNDEFINED:
  693         default:
  694                 DPRINTF(("video_get_format: unknown pixel format %d\n",
  695                          src->pixel_format));
  696                 dest->fmt.pix.pixelformat = 0; /* V4L2 doesn't define
  697                                                * and "undefined"
  698                                                * format? */
  699                 break;
  700         }
  701 
  702 }
  703 
  704 static void
  705 v4l2_format_to_video_format(const struct v4l2_format *src,
  706                             struct video_format *dest)
  707 {
  708         switch (src->type) {
  709         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
  710                 dest->width = src->fmt.pix.width;
  711                 dest->height = src->fmt.pix.height;
  712 
  713                 dest->stride = src->fmt.pix.bytesperline;
  714                 dest->sample_size = src->fmt.pix.sizeimage;
  715 
  716                 if (src->fmt.pix.field == V4L2_FIELD_INTERLACED)
  717                         dest->interlace_flags = VIDEO_INTERLACE_ON;
  718                 else
  719                         dest->interlace_flags = VIDEO_INTERLACE_OFF;
  720 
  721                 switch (src->fmt.pix.colorspace) {
  722                 case V4L2_COLORSPACE_SMPTE170M:
  723                         dest->color.primaries =
  724                             VIDEO_COLOR_PRIMARIES_SMPTE_170M;
  725                         break;
  726                 /* XXX */
  727                 default:
  728                         dest->color.primaries =
  729                             VIDEO_COLOR_PRIMARIES_UNSPECIFIED;
  730                         break;
  731                 }
  732 
  733                 switch (src->fmt.pix.pixelformat) {
  734                 case V4L2_PIX_FMT_UYVY:
  735                         dest->pixel_format = VIDEO_FORMAT_UYVY;
  736                         break;
  737                 case V4L2_PIX_FMT_YUV420:
  738                         dest->pixel_format = VIDEO_FORMAT_YUV420;
  739                         break;
  740                 case V4L2_PIX_FMT_YUYV:
  741                         dest->pixel_format = VIDEO_FORMAT_YUY2;
  742                         break;
  743                 case V4L2_PIX_FMT_NV12:
  744                         dest->pixel_format = VIDEO_FORMAT_NV12;
  745                         break;
  746                 case V4L2_PIX_FMT_RGB24:
  747                         dest->pixel_format = VIDEO_FORMAT_RGB24;
  748                         break;
  749                 case V4L2_PIX_FMT_RGB555:
  750                         dest->pixel_format = VIDEO_FORMAT_RGB555;
  751                         break;
  752                 case V4L2_PIX_FMT_RGB565:
  753                         dest->pixel_format = VIDEO_FORMAT_RGB565;
  754                         break;
  755                 case V4L2_PIX_FMT_SBGGR8:
  756                         dest->pixel_format = VIDEO_FORMAT_SBGGR8;
  757                         break;
  758                 case V4L2_PIX_FMT_MJPEG:
  759                         dest->pixel_format = VIDEO_FORMAT_MJPEG;
  760                         break;
  761                 case V4L2_PIX_FMT_DV:
  762                         dest->pixel_format = VIDEO_FORMAT_DV;
  763                         break;
  764                 case V4L2_PIX_FMT_MPEG:
  765                         dest->pixel_format = VIDEO_FORMAT_MPEG;
  766                         break;
  767                 default:
  768                         DPRINTF(("video: unknown v4l2 pixel format %d\n",
  769                                  src->fmt.pix.pixelformat));
  770                         dest->pixel_format = VIDEO_FORMAT_UNDEFINED;
  771                         break;
  772                 }
  773                 break;
  774         default:
  775                 /* TODO: other v4l2 format types */
  776                 DPRINTF(("video: unsupported v4l2 format type %d\n",
  777                          src->type));
  778                 break;
  779         }
  780 }
  781 
  782 static int
  783 video_enum_format(struct video_softc *sc, struct v4l2_fmtdesc *fmtdesc)
  784 {
  785         const struct video_hw_if *hw;
  786         struct video_format vfmt;
  787         struct v4l2_format fmt;
  788         int err;
  789 
  790         hw = sc->hw_if;
  791         if (hw->enum_format == NULL)
  792                 return ENOTTY;
  793 
  794         err = hw->enum_format(sc->hw_softc, fmtdesc->index, &vfmt);
  795         if (err != 0)
  796                 return err;
  797 
  798         video_format_to_v4l2_format(&vfmt, &fmt);
  799 
  800         fmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* TODO: only one type for now */
  801         fmtdesc->flags = 0;
  802         if (vfmt.pixel_format >= VIDEO_FORMAT_MJPEG)
  803                 fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
  804         strlcpy(fmtdesc->description,
  805                 video_pixel_format_str(vfmt.pixel_format),
  806                 sizeof(fmtdesc->description));
  807         fmtdesc->pixelformat = fmt.fmt.pix.pixelformat;
  808 
  809         return 0;
  810 }
  811 
  812 static int
  813 video_enum_framesizes(struct video_softc *sc, struct v4l2_frmsizeenum *frmdesc)
  814 {
  815         const struct video_hw_if *hw;
  816         struct video_format vfmt;
  817         struct v4l2_format fmt;
  818         int err;
  819 
  820         hw = sc->hw_if;
  821         if (hw->enum_format == NULL)
  822                 return ENOTTY;
  823 
  824         err = hw->enum_format(sc->hw_softc, frmdesc->index, &vfmt);
  825         if (err != 0)
  826                 return err;
  827 
  828         video_format_to_v4l2_format(&vfmt, &fmt);
  829         if (fmt.fmt.pix.pixelformat != frmdesc->pixel_format) {
  830                 printf("video_enum_framesizes: type mismatch %x %x\n",
  831                     fmt.fmt.pix.pixelformat, frmdesc->pixel_format);
  832         }
  833 
  834         frmdesc->type = V4L2_FRMSIZE_TYPE_DISCRETE; /* TODO: only one type for now */
  835         frmdesc->discrete.width = vfmt.width;
  836         frmdesc->discrete.height = vfmt.height;
  837         return 0;
  838 }
  839 
  840 static int
  841 video_enum_frameival(struct video_softc *sc, struct v4l2_frmivalenum *frmdesc)
  842 {
  843         const struct video_hw_if *hw;
  844 
  845         hw = sc->hw_if;
  846         if (hw->enum_format == NULL)
  847                 return ENOTTY;
  848 
  849         frmdesc->type = V4L2_FRMSIZE_TYPE_DISCRETE;
  850         frmdesc->discrete.numerator = 1;
  851         frmdesc->discrete.denominator = 15;
  852         return 0;
  853 }
  854 
  855 static int
  856 video_get_format(struct video_softc *sc,
  857                       struct v4l2_format *format)
  858 {
  859         const struct video_hw_if *hw;
  860         struct video_format vfmt;
  861         int err;
  862 
  863         hw = sc->hw_if;
  864         if (hw->get_format == NULL)
  865                 return ENOTTY;
  866 
  867         err = hw->get_format(sc->hw_softc, &vfmt);
  868         if (err != 0)
  869                 return err;
  870 
  871         video_format_to_v4l2_format(&vfmt, format);
  872 
  873         return 0;
  874 }
  875 
  876 static int
  877 video_set_format(struct video_softc *sc, struct v4l2_format *fmt)
  878 {
  879         const struct video_hw_if *hw;
  880         struct video_format vfmt;
  881         int err;
  882 
  883         hw = sc->hw_if;
  884         if (hw->set_format == NULL)
  885                 return ENOTTY;
  886 
  887         v4l2_format_to_video_format(fmt, &vfmt);
  888 
  889         err = hw->set_format(sc->hw_softc, &vfmt);
  890         if (err != 0)
  891                 return err;
  892 
  893         video_format_to_v4l2_format(&vfmt, fmt);
  894         sc->sc_stream_in.vs_format = vfmt;
  895 
  896         return 0;
  897 }
  898 
  899 
  900 static int
  901 video_try_format(struct video_softc *sc,
  902                       struct v4l2_format *format)
  903 {
  904         const struct video_hw_if *hw;
  905         struct video_format vfmt;
  906         int err;
  907 
  908         hw = sc->hw_if;
  909         if (hw->try_format == NULL)
  910                 return ENOTTY;
  911 
  912         v4l2_format_to_video_format(format, &vfmt);
  913 
  914         err = hw->try_format(sc->hw_softc, &vfmt);
  915         if (err != 0)
  916                 return err;
  917 
  918         video_format_to_v4l2_format(&vfmt, format);
  919 
  920         return 0;
  921 }
  922 
  923 static int
  924 video_get_parm(struct video_softc *sc, struct v4l2_streamparm *parm)
  925 {
  926         struct video_fract fract;
  927         const struct video_hw_if *hw;
  928         int error;
  929 
  930         if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
  931                 return EINVAL;
  932 
  933         hw = sc->hw_if;
  934         if (hw == NULL)
  935                 return ENXIO;
  936 
  937         memset(&parm->parm, 0, sizeof(parm->parm));
  938         if (hw->get_framerate != NULL) {
  939                 error = hw->get_framerate(sc->hw_softc, &fract);
  940                 if (error != 0)
  941                         return error;
  942                 parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
  943                 parm->parm.capture.timeperframe.numerator = fract.numerator;
  944                 parm->parm.capture.timeperframe.denominator = fract.denominator;
  945         }
  946 
  947         return 0;
  948 }
  949 
  950 static int
  951 video_set_parm(struct video_softc *sc, struct v4l2_streamparm *parm)
  952 {
  953         struct video_fract fract;
  954         const struct video_hw_if *hw;
  955         int error;
  956 
  957         if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
  958                 return EINVAL;
  959 
  960         hw = sc->hw_if;
  961         if (hw == NULL || hw->set_framerate == NULL)
  962                 return ENXIO;
  963 
  964         error = hw->set_framerate(sc->hw_softc, &fract);
  965         if (error != 0)
  966                 return error;
  967 
  968         parm->parm.capture.timeperframe.numerator = fract.numerator;
  969         parm->parm.capture.timeperframe.denominator = fract.denominator;
  970 
  971         return 0;
  972 }
  973 
  974 static void
  975 v4l2_standard_to_video_standard(v4l2_std_id stdid,
  976     enum video_standard *vstd)
  977 {
  978 #define VSTD(id, vid)   case (id):      *vstd = (vid); break;
  979         switch (stdid) {
  980         VSTD(V4L2_STD_NTSC_M, VIDEO_STANDARD_NTSC_M)
  981         default:
  982                 *vstd = VIDEO_STANDARD_UNKNOWN;
  983                 break;
  984         }
  985 #undef VSTD
  986 }
  987 
  988 static void
  989 video_standard_to_v4l2_standard(enum video_standard vstd,
  990     struct v4l2_standard *std)
  991 {
  992         switch (vstd) {
  993         case VIDEO_STANDARD_NTSC_M:
  994                 std->id = V4L2_STD_NTSC_M;
  995                 strlcpy(std->name, "NTSC-M", sizeof(std->name));
  996                 std->frameperiod.numerator = 1001;
  997                 std->frameperiod.denominator = 30000;
  998                 std->framelines = 525;
  999                 break;
 1000         default:
 1001                 std->id = V4L2_STD_UNKNOWN;
 1002                 strlcpy(std->name, "Unknown", sizeof(std->name));
 1003                 break;
 1004         }
 1005 }
 1006 
 1007 static int
 1008 video_enum_standard(struct video_softc *sc, struct v4l2_standard *std)
 1009 {
 1010         const struct video_hw_if *hw = sc->hw_if;
 1011         enum video_standard vstd;
 1012         int err;
 1013 
 1014         /* simple webcam drivers don't need to implement this callback */
 1015         if (hw->enum_standard == NULL) {
 1016                 if (std->index != 0)
 1017                         return EINVAL;
 1018                 std->id = V4L2_STD_UNKNOWN;
 1019                 strlcpy(std->name, "webcam", sizeof(std->name));
 1020                 return 0;
 1021         }
 1022 
 1023         v4l2_standard_to_video_standard(std->id, &vstd);
 1024 
 1025         err = hw->enum_standard(sc->hw_softc, std->index, &vstd);
 1026         if (err != 0)
 1027                 return err;
 1028 
 1029         video_standard_to_v4l2_standard(vstd, std);
 1030 
 1031         return 0;
 1032 }
 1033 
 1034 static int
 1035 video_get_standard(struct video_softc *sc, v4l2_std_id *stdid)
 1036 {
 1037         const struct video_hw_if *hw = sc->hw_if;
 1038         struct v4l2_standard std;
 1039         enum video_standard vstd;
 1040         int err;
 1041 
 1042         /* simple webcam drivers don't need to implement this callback */
 1043         if (hw->get_standard == NULL) {
 1044                 *stdid = V4L2_STD_UNKNOWN;
 1045                 return 0;
 1046         }
 1047 
 1048         err = hw->get_standard(sc->hw_softc, &vstd);
 1049         if (err != 0)
 1050                 return err;
 1051 
 1052         video_standard_to_v4l2_standard(vstd, &std);
 1053         *stdid = std.id;
 1054 
 1055         return 0;
 1056 }
 1057 
 1058 static int
 1059 video_set_standard(struct video_softc *sc, v4l2_std_id stdid)
 1060 {
 1061         const struct video_hw_if *hw = sc->hw_if;
 1062         enum video_standard vstd;
 1063 
 1064         /* simple webcam drivers don't need to implement this callback */
 1065         if (hw->set_standard == NULL) {
 1066                 if (stdid != V4L2_STD_UNKNOWN)
 1067                         return EINVAL;
 1068                 return 0;
 1069         }
 1070 
 1071         v4l2_standard_to_video_standard(stdid, &vstd);
 1072 
 1073         return hw->set_standard(sc->hw_softc, vstd);
 1074 }
 1075 
 1076 static void
 1077 v4l2_input_to_video_input(const struct v4l2_input *input,
 1078     struct video_input *vi)
 1079 {
 1080         vi->index = input->index;
 1081         strlcpy(vi->name, input->name, sizeof(vi->name));
 1082         switch (input->type) {
 1083         case V4L2_INPUT_TYPE_TUNER:
 1084                 vi->type = VIDEO_INPUT_TYPE_TUNER;
 1085                 break;
 1086         case V4L2_INPUT_TYPE_CAMERA:
 1087                 vi->type = VIDEO_INPUT_TYPE_CAMERA;
 1088                 break;
 1089         }
 1090         vi->audiomask = input->audioset;
 1091         vi->tuner_index = input->tuner;
 1092         vi->standards = input->std;     /* ... values are the same */
 1093         vi->status = 0;
 1094         if (input->status & V4L2_IN_ST_NO_POWER)
 1095                 vi->status |= VIDEO_STATUS_NO_POWER;
 1096         if (input->status & V4L2_IN_ST_NO_SIGNAL)
 1097                 vi->status |= VIDEO_STATUS_NO_SIGNAL;
 1098         if (input->status & V4L2_IN_ST_NO_COLOR)
 1099                 vi->status |= VIDEO_STATUS_NO_COLOR;
 1100         if (input->status & V4L2_IN_ST_NO_H_LOCK)
 1101                 vi->status |= VIDEO_STATUS_NO_HLOCK;
 1102         if (input->status & V4L2_IN_ST_MACROVISION)
 1103                 vi->status |= VIDEO_STATUS_MACROVISION;
 1104 }
 1105 
 1106 static void
 1107 video_input_to_v4l2_input(const struct video_input *vi,
 1108     struct v4l2_input *input)
 1109 {
 1110         input->index = vi->index;
 1111         strlcpy(input->name, vi->name, sizeof(input->name));
 1112         switch (vi->type) {
 1113         case VIDEO_INPUT_TYPE_TUNER:
 1114                 input->type = V4L2_INPUT_TYPE_TUNER;
 1115                 break;
 1116         case VIDEO_INPUT_TYPE_CAMERA:
 1117                 input->type = V4L2_INPUT_TYPE_CAMERA;
 1118                 break;
 1119         }
 1120         input->audioset = vi->audiomask;
 1121         input->tuner = vi->tuner_index;
 1122         input->std = vi->standards;     /* ... values are the same */
 1123         input->status = 0;
 1124         if (vi->status & VIDEO_STATUS_NO_POWER)
 1125                 input->status |= V4L2_IN_ST_NO_POWER;
 1126         if (vi->status & VIDEO_STATUS_NO_SIGNAL)
 1127                 input->status |= V4L2_IN_ST_NO_SIGNAL;
 1128         if (vi->status & VIDEO_STATUS_NO_COLOR)
 1129                 input->status |= V4L2_IN_ST_NO_COLOR;
 1130         if (vi->status & VIDEO_STATUS_NO_HLOCK)
 1131                 input->status |= V4L2_IN_ST_NO_H_LOCK;
 1132         if (vi->status & VIDEO_STATUS_MACROVISION)
 1133                 input->status |= V4L2_IN_ST_MACROVISION;
 1134 }
 1135 
 1136 static int
 1137 video_enum_input(struct video_softc *sc, struct v4l2_input *input)
 1138 {
 1139         const struct video_hw_if *hw = sc->hw_if;
 1140         struct video_input vi;
 1141         int err;
 1142 
 1143         /* simple webcam drivers don't need to implement this callback */
 1144         if (hw->enum_input == NULL) {
 1145                 if (input->index != 0)
 1146                         return EINVAL;
 1147                 memset(input, 0, sizeof(*input));
 1148                 input->index = 0;
 1149                 strlcpy(input->name, "Camera", sizeof(input->name));
 1150                 input->type = V4L2_INPUT_TYPE_CAMERA;
 1151                 return 0;
 1152         }
 1153 
 1154         v4l2_input_to_video_input(input, &vi);
 1155 
 1156         err = hw->enum_input(sc->hw_softc, input->index, &vi);
 1157         if (err != 0)
 1158                 return err;
 1159 
 1160         video_input_to_v4l2_input(&vi, input);
 1161 
 1162         return 0;
 1163 }
 1164 
 1165 static int
 1166 video_get_input(struct video_softc *sc, int *index)
 1167 {
 1168         const struct video_hw_if *hw = sc->hw_if;
 1169         struct video_input vi;
 1170         struct v4l2_input input;
 1171         int err;
 1172 
 1173         /* simple webcam drivers don't need to implement this callback */
 1174         if (hw->get_input == NULL) {
 1175                 *index = 0;
 1176                 return 0;
 1177         }
 1178 
 1179         input.index = *index;
 1180         v4l2_input_to_video_input(&input, &vi);
 1181 
 1182         err = hw->get_input(sc->hw_softc, &vi);
 1183         if (err != 0)
 1184                 return err;
 1185 
 1186         video_input_to_v4l2_input(&vi, &input);
 1187         *index = input.index;
 1188 
 1189         return 0;
 1190 }
 1191 
 1192 static int
 1193 video_set_input(struct video_softc *sc, int index)
 1194 {
 1195         const struct video_hw_if *hw = sc->hw_if;
 1196         struct video_input vi;
 1197         struct v4l2_input input;
 1198 
 1199         /* simple webcam drivers don't need to implement this callback */
 1200         if (hw->set_input == NULL) {
 1201                 if (index != 0)
 1202                         return EINVAL;
 1203                 return 0;
 1204         }
 1205 
 1206         input.index = index;
 1207         v4l2_input_to_video_input(&input, &vi);
 1208 
 1209         return hw->set_input(sc->hw_softc, &vi);
 1210 }
 1211 
 1212 static void
 1213 v4l2_audio_to_video_audio(const struct v4l2_audio *audio,
 1214     struct video_audio *va)
 1215 {
 1216         va->index = audio->index;
 1217         strlcpy(va->name, audio->name, sizeof(va->name));
 1218         va->caps = va->mode = 0;
 1219         if (audio->capability & V4L2_AUDCAP_STEREO)
 1220                 va->caps |= VIDEO_AUDIO_F_STEREO;
 1221         if (audio->capability & V4L2_AUDCAP_AVL)
 1222                 va->caps |= VIDEO_AUDIO_F_AVL;
 1223         if (audio->mode & V4L2_AUDMODE_AVL)
 1224                 va->mode |= VIDEO_AUDIO_F_AVL;
 1225 }
 1226 
 1227 static void
 1228 video_audio_to_v4l2_audio(const struct video_audio *va,
 1229     struct v4l2_audio *audio)
 1230 {
 1231         audio->index = va->index;
 1232         strlcpy(audio->name, va->name, sizeof(audio->name));
 1233         audio->capability = audio->mode = 0;
 1234         if (va->caps & VIDEO_AUDIO_F_STEREO)
 1235                 audio->capability |= V4L2_AUDCAP_STEREO;
 1236         if (va->caps & VIDEO_AUDIO_F_AVL)
 1237                 audio->capability |= V4L2_AUDCAP_AVL;
 1238         if (va->mode & VIDEO_AUDIO_F_AVL)
 1239                 audio->mode |= V4L2_AUDMODE_AVL;
 1240 }
 1241 
 1242 static int
 1243 video_enum_audio(struct video_softc *sc, struct v4l2_audio *audio)
 1244 {
 1245         const struct video_hw_if *hw = sc->hw_if;
 1246         struct video_audio va;
 1247         int err;
 1248 
 1249         if (hw->enum_audio == NULL)
 1250                 return ENOTTY;
 1251 
 1252         v4l2_audio_to_video_audio(audio, &va);
 1253 
 1254         err = hw->enum_audio(sc->hw_softc, audio->index, &va);
 1255         if (err != 0)
 1256                 return err;
 1257 
 1258         video_audio_to_v4l2_audio(&va, audio);
 1259 
 1260         return 0;
 1261 }
 1262 
 1263 static int
 1264 video_get_audio(struct video_softc *sc, struct v4l2_audio *audio)
 1265 {
 1266         const struct video_hw_if *hw = sc->hw_if;
 1267         struct video_audio va;
 1268         int err;
 1269 
 1270         if (hw->get_audio == NULL)
 1271                 return ENOTTY;
 1272 
 1273         v4l2_audio_to_video_audio(audio, &va);
 1274 
 1275         err = hw->get_audio(sc->hw_softc, &va);
 1276         if (err != 0)
 1277                 return err;
 1278 
 1279         video_audio_to_v4l2_audio(&va, audio);
 1280 
 1281         return 0;
 1282 }
 1283 
 1284 static int
 1285 video_set_audio(struct video_softc *sc, struct v4l2_audio *audio)
 1286 {
 1287         const struct video_hw_if *hw = sc->hw_if;
 1288         struct video_audio va;
 1289 
 1290         if (hw->set_audio == NULL)
 1291                 return ENOTTY;
 1292 
 1293         v4l2_audio_to_video_audio(audio, &va);
 1294 
 1295         return hw->set_audio(sc->hw_softc, &va);
 1296 }
 1297 
 1298 static void
 1299 v4l2_tuner_to_video_tuner(const struct v4l2_tuner *tuner,
 1300     struct video_tuner *vt)
 1301 {
 1302         vt->index = tuner->index;
 1303         strlcpy(vt->name, tuner->name, sizeof(vt->name));
 1304         vt->freq_lo = tuner->rangelow;
 1305         vt->freq_hi = tuner->rangehigh;
 1306         vt->signal = tuner->signal;
 1307         vt->afc = tuner->afc;
 1308         vt->caps = 0;
 1309         if (tuner->capability & V4L2_TUNER_CAP_STEREO)
 1310                 vt->caps |= VIDEO_TUNER_F_STEREO;
 1311         if (tuner->capability & V4L2_TUNER_CAP_LANG1)
 1312                 vt->caps |= VIDEO_TUNER_F_LANG1;
 1313         if (tuner->capability & V4L2_TUNER_CAP_LANG2)
 1314                 vt->caps |= VIDEO_TUNER_F_LANG2;
 1315         switch (tuner->audmode) {
 1316         case V4L2_TUNER_MODE_MONO:
 1317                 vt->mode = VIDEO_TUNER_F_MONO;
 1318                 break;
 1319         case V4L2_TUNER_MODE_STEREO:
 1320                 vt->mode = VIDEO_TUNER_F_STEREO;
 1321                 break;
 1322         case V4L2_TUNER_MODE_LANG1:
 1323                 vt->mode = VIDEO_TUNER_F_LANG1;
 1324                 break;
 1325         case V4L2_TUNER_MODE_LANG2:
 1326                 vt->mode = VIDEO_TUNER_F_LANG2;
 1327                 break;
 1328         case V4L2_TUNER_MODE_LANG1_LANG2:
 1329                 vt->mode = VIDEO_TUNER_F_LANG1 | VIDEO_TUNER_F_LANG2;
 1330                 break;
 1331         }
 1332 }
 1333 
 1334 static void
 1335 video_tuner_to_v4l2_tuner(const struct video_tuner *vt,
 1336     struct v4l2_tuner *tuner)
 1337 {
 1338         tuner->index = vt->index;
 1339         strlcpy(tuner->name, vt->name, sizeof(tuner->name));
 1340         tuner->rangelow = vt->freq_lo;
 1341         tuner->rangehigh = vt->freq_hi;
 1342         tuner->signal = vt->signal;
 1343         tuner->afc = vt->afc;
 1344         tuner->capability = 0;
 1345         if (vt->caps & VIDEO_TUNER_F_STEREO)
 1346                 tuner->capability |= V4L2_TUNER_CAP_STEREO;
 1347         if (vt->caps & VIDEO_TUNER_F_LANG1)
 1348                 tuner->capability |= V4L2_TUNER_CAP_LANG1;
 1349         if (vt->caps & VIDEO_TUNER_F_LANG2)
 1350                 tuner->capability |= V4L2_TUNER_CAP_LANG2;
 1351         switch (vt->mode) {
 1352         case VIDEO_TUNER_F_MONO:
 1353                 tuner->audmode = V4L2_TUNER_MODE_MONO;
 1354                 break;
 1355         case VIDEO_TUNER_F_STEREO:
 1356                 tuner->audmode = V4L2_TUNER_MODE_STEREO;
 1357                 break;
 1358         case VIDEO_TUNER_F_LANG1:
 1359                 tuner->audmode = V4L2_TUNER_MODE_LANG1;
 1360                 break;
 1361         case VIDEO_TUNER_F_LANG2:
 1362                 tuner->audmode = V4L2_TUNER_MODE_LANG2;
 1363                 break;
 1364         case VIDEO_TUNER_F_LANG1|VIDEO_TUNER_F_LANG2:
 1365                 tuner->audmode = V4L2_TUNER_MODE_LANG1_LANG2;
 1366                 break;
 1367         }
 1368 }
 1369 
 1370 static int
 1371 video_get_tuner(struct video_softc *sc, struct v4l2_tuner *tuner)
 1372 {
 1373         const struct video_hw_if *hw = sc->hw_if;
 1374         struct video_tuner vt;
 1375         int err;
 1376 
 1377         if (hw->get_tuner == NULL)
 1378                 return ENOTTY;
 1379 
 1380         v4l2_tuner_to_video_tuner(tuner, &vt);
 1381 
 1382         err = hw->get_tuner(sc->hw_softc, &vt);
 1383         if (err != 0)
 1384                 return err;
 1385 
 1386         video_tuner_to_v4l2_tuner(&vt, tuner);
 1387 
 1388         return 0;
 1389 }
 1390 
 1391 static int
 1392 video_set_tuner(struct video_softc *sc, struct v4l2_tuner *tuner)
 1393 {
 1394         const struct video_hw_if *hw = sc->hw_if;
 1395         struct video_tuner vt;
 1396 
 1397         if (hw->set_tuner == NULL)
 1398                 return ENOTTY;
 1399 
 1400         v4l2_tuner_to_video_tuner(tuner, &vt);
 1401 
 1402         return hw->set_tuner(sc->hw_softc, &vt);
 1403 }
 1404 
 1405 static int
 1406 video_get_frequency(struct video_softc *sc, struct v4l2_frequency *freq)
 1407 {
 1408         const struct video_hw_if *hw = sc->hw_if;
 1409         struct video_frequency vfreq;
 1410         int err;
 1411 
 1412         if (hw->get_frequency == NULL)
 1413                 return ENOTTY;
 1414 
 1415         err = hw->get_frequency(sc->hw_softc, &vfreq);
 1416         if (err)
 1417                 return err;
 1418 
 1419         freq->tuner = vfreq.tuner_index;
 1420         freq->type = V4L2_TUNER_ANALOG_TV;
 1421         freq->frequency = vfreq.frequency;
 1422 
 1423         return 0;
 1424 }
 1425 
 1426 static int
 1427 video_set_frequency(struct video_softc *sc, struct v4l2_frequency *freq)
 1428 {
 1429         const struct video_hw_if *hw = sc->hw_if;
 1430         struct video_frequency vfreq;
 1431         struct video_tuner vt;
 1432         int error;
 1433 
 1434         if (hw->set_frequency == NULL || hw->get_tuner == NULL)
 1435                 return ENOTTY;
 1436         if (freq->type != V4L2_TUNER_ANALOG_TV)
 1437                 return EINVAL;
 1438 
 1439         vt.index = freq->tuner;
 1440         error = hw->get_tuner(sc->hw_softc, &vt);
 1441         if (error)
 1442                 return error;
 1443 
 1444         if (freq->frequency < vt.freq_lo)
 1445                 freq->frequency = vt.freq_lo;
 1446         else if (freq->frequency > vt.freq_hi)
 1447                 freq->frequency = vt.freq_hi;
 1448 
 1449         vfreq.tuner_index = freq->tuner;
 1450         vfreq.frequency = freq->frequency;
 1451 
 1452         return hw->set_frequency(sc->hw_softc, &vfreq);
 1453 }
 1454 
 1455 /* Takes a single Video4Linux2 control, converts it to a struct
 1456  * video_control, and calls the hardware driver. */
 1457 static int
 1458 video_set_control(struct video_softc *sc,
 1459                        const struct v4l2_control *vcontrol)
 1460 {
 1461         const struct video_hw_if *hw;
 1462         struct video_control_group group;
 1463         struct video_control control;
 1464 
 1465         hw = sc->hw_if;
 1466         if (hw->set_control_group) {
 1467                 control.group_id = control.control_id =
 1468                     v4l2id_to_control_id(vcontrol->id);
 1469                 /* ?? if "control_id" is arbitrarily defined by the
 1470                  * driver, then we need some way to store it...  Maybe
 1471                  * it doesn't matter for single value controls. */
 1472                 control.value = vcontrol->value;
 1473 
 1474                 group.group_id = control.group_id;
 1475                 group.length = 1;
 1476                 group.control = &control;
 1477 
 1478                 return (hw->set_control_group(sc->hw_softc, &group));
 1479         } else {
 1480                 return EINVAL;
 1481         }
 1482 }
 1483 
 1484 static int
 1485 video_request_bufs(struct video_softc *sc,
 1486                    struct v4l2_requestbuffers *req)
 1487 {
 1488         struct video_stream *vs = &sc->sc_stream_in;
 1489         struct v4l2_buffer *buf;
 1490         int i, err;
 1491 
 1492         if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 1493                 return EINVAL;
 1494 
 1495         vs->vs_type = req->type;
 1496 
 1497         switch (req->memory) {
 1498         case V4L2_MEMORY_MMAP:
 1499                 if (req->count < VIDEO_MIN_BUFS)
 1500                         req->count = VIDEO_MIN_BUFS;
 1501                 else if (req->count > VIDEO_MAX_BUFS)
 1502                         req->count = VIDEO_MAX_BUFS;
 1503 
 1504                 err = video_stream_setup_bufs(vs,
 1505                                               VIDEO_STREAM_METHOD_MMAP,
 1506                                               req->count);
 1507                 if (err != 0)
 1508                         return err;
 1509 
 1510                 for (i = 0; i < req->count; ++i) {
 1511                         buf = vs->vs_buf[i]->vb_buf;
 1512                         buf->memory = V4L2_MEMORY_MMAP;
 1513                         buf->flags |= V4L2_BUF_FLAG_MAPPED;
 1514                 }
 1515                 break;
 1516         case V4L2_MEMORY_USERPTR:
 1517         default:
 1518                 return EINVAL;
 1519         }
 1520 
 1521         return 0;
 1522 }
 1523 
 1524 static int
 1525 video_query_buf(struct video_softc *sc,
 1526                 struct v4l2_buffer *buf)
 1527 {
 1528         struct video_stream *vs = &sc->sc_stream_in;
 1529 
 1530         if (buf->type != vs->vs_type)
 1531                 return EINVAL;
 1532         if (buf->index >= vs->vs_nbufs)
 1533                 return EINVAL;
 1534 
 1535         memcpy(buf, vs->vs_buf[buf->index]->vb_buf, sizeof(*buf));
 1536 
 1537         return 0;
 1538 }
 1539 
 1540 /* Accept a buffer descriptor from userspace and return the indicated
 1541  * buffer to the driver's queue. */
 1542 static int
 1543 video_queue_buf(struct video_softc *sc, struct v4l2_buffer *userbuf)
 1544 {
 1545         struct video_stream *vs = &sc->sc_stream_in;
 1546         struct video_buffer *vb;
 1547         struct v4l2_buffer *driverbuf;
 1548 
 1549         if (userbuf->type != vs->vs_type) {
 1550                 DPRINTF(("video_queue_buf: expected type=%d got type=%d\n",
 1551                          userbuf->type, vs->vs_type));
 1552                 return EINVAL;
 1553         }
 1554         if (userbuf->index >= vs->vs_nbufs) {
 1555                 DPRINTF(("video_queue_buf: invalid index %d >= %d\n",
 1556                          userbuf->index, vs->vs_nbufs));
 1557                 return EINVAL;
 1558         }
 1559 
 1560         switch (vs->vs_method) {
 1561         case VIDEO_STREAM_METHOD_MMAP:
 1562                 if (userbuf->memory != V4L2_MEMORY_MMAP) {
 1563                         DPRINTF(("video_queue_buf: invalid memory=%d\n",
 1564                                  userbuf->memory));
 1565                         return EINVAL;
 1566                 }
 1567 
 1568                 mutex_enter(&vs->vs_lock);
 1569 
 1570                 vb = vs->vs_buf[userbuf->index];
 1571                 driverbuf = vb->vb_buf;
 1572                 if (driverbuf->flags & V4L2_BUF_FLAG_QUEUED) {
 1573                         DPRINTF(("video_queue_buf: buf already queued; "
 1574                                  "flags=0x%x\n", driverbuf->flags));
 1575                         mutex_exit(&vs->vs_lock);
 1576                         return EINVAL;
 1577                 }
 1578                 video_stream_enqueue(vs, vb);
 1579                 memcpy(userbuf, driverbuf, sizeof(*driverbuf));
 1580 
 1581                 mutex_exit(&vs->vs_lock);
 1582                 break;
 1583         default:
 1584                 return EINVAL;
 1585         }
 1586 
 1587         return 0;
 1588 }
 1589 
 1590 /* Dequeue the described buffer from the driver queue, making it
 1591  * available for reading via mmap. */
 1592 static int
 1593 video_dequeue_buf(struct video_softc *sc, struct v4l2_buffer *buf)
 1594 {
 1595         struct video_stream *vs = &sc->sc_stream_in;
 1596         struct video_buffer *vb;
 1597         int err;
 1598 
 1599         if (buf->type != vs->vs_type) {
 1600                 aprint_debug_dev(sc->sc_dev,
 1601                     "requested type %d (expected %d)\n",
 1602                     buf->type, vs->vs_type);
 1603                 return EINVAL;
 1604         }
 1605 
 1606         switch (vs->vs_method) {
 1607         case VIDEO_STREAM_METHOD_MMAP:
 1608                 if (buf->memory != V4L2_MEMORY_MMAP) {
 1609                         aprint_debug_dev(sc->sc_dev,
 1610                             "requested memory %d (expected %d)\n",
 1611                             buf->memory, V4L2_MEMORY_MMAP);
 1612                         return EINVAL;
 1613                 }
 1614 
 1615                 mutex_enter(&vs->vs_lock);
 1616 
 1617                 if (vs->vs_flags & O_NONBLOCK) {
 1618                         vb = video_stream_dequeue(vs);
 1619                         if (vb == NULL) {
 1620                                 mutex_exit(&vs->vs_lock);
 1621                                 return EAGAIN;
 1622                         }
 1623                 } else {
 1624                         /* Block until we have sample */
 1625                         while ((vb = video_stream_dequeue(vs)) == NULL) {
 1626                                 if (!vs->vs_streaming) {
 1627                                         mutex_exit(&vs->vs_lock);
 1628                                         return EINVAL;
 1629                                 }
 1630                                 err = cv_wait_sig(&vs->vs_sample_cv,
 1631                                                   &vs->vs_lock);
 1632                                 if (err != 0) {
 1633                                         mutex_exit(&vs->vs_lock);
 1634                                         return EINTR;
 1635                                 }
 1636                         }
 1637                 }
 1638 
 1639                 memcpy(buf, vb->vb_buf, sizeof(*buf));
 1640 
 1641                 mutex_exit(&vs->vs_lock);
 1642                 break;
 1643         default:
 1644                 aprint_debug_dev(sc->sc_dev, "unknown vs_method %d\n",
 1645                     vs->vs_method);
 1646                 return EINVAL;
 1647         }
 1648 
 1649         return 0;
 1650 }
 1651 
 1652 static int
 1653 video_stream_on(struct video_softc *sc, enum v4l2_buf_type type)
 1654 {
 1655         int err;
 1656         struct video_stream *vs = &sc->sc_stream_in;
 1657         const struct video_hw_if *hw;
 1658 
 1659         if (vs->vs_streaming)
 1660                 return 0;
 1661         if (type != vs->vs_type)
 1662                 return EINVAL;
 1663 
 1664         hw = sc->hw_if;
 1665         if (hw == NULL)
 1666                 return ENXIO;
 1667 
 1668 
 1669         err = hw->start_transfer(sc->hw_softc);
 1670         if (err != 0)
 1671                 return err;
 1672 
 1673         vs->vs_streaming = true;
 1674         return 0;
 1675 }
 1676 
 1677 static int
 1678 video_stream_off(struct video_softc *sc, enum v4l2_buf_type type)
 1679 {
 1680         int err;
 1681         struct video_stream *vs = &sc->sc_stream_in;
 1682         const struct video_hw_if *hw;
 1683 
 1684         if (!vs->vs_streaming)
 1685                 return 0;
 1686         if (type != vs->vs_type)
 1687                 return EINVAL;
 1688 
 1689         hw = sc->hw_if;
 1690         if (hw == NULL)
 1691                 return ENXIO;
 1692 
 1693         err = hw->stop_transfer(sc->hw_softc);
 1694         if (err != 0)
 1695                 return err;
 1696 
 1697         vs->vs_frameno = -1;
 1698         vs->vs_sequence = 0;
 1699         vs->vs_streaming = false;
 1700 
 1701         return 0;
 1702 }
 1703 
 1704 int
 1705 videoopen(dev_t dev, int flags, int ifmt, struct lwp *l)
 1706 {
 1707         struct video_softc *sc;
 1708         const struct video_hw_if *hw;
 1709         struct video_stream *vs;
 1710         int err;
 1711 
 1712         DPRINTF(("videoopen\n"));
 1713 
 1714         sc = device_private(device_lookup(&video_cd, VIDEOUNIT(dev)));
 1715         if (sc == NULL) {
 1716                 DPRINTF(("videoopen: failed to get softc for unit %d\n",
 1717                         VIDEOUNIT(dev)));
 1718                 return ENXIO;
 1719         }
 1720 
 1721         if (sc->sc_dying) {
 1722                 DPRINTF(("videoopen: dying\n"));
 1723                 return EIO;
 1724         }
 1725 
 1726         sc->sc_stream_in.vs_flags = flags;
 1727 
 1728         DPRINTF(("videoopen: flags=0x%x sc=%p parent=%p\n",
 1729                  flags, sc, sc->hw_dev));
 1730 
 1731         hw = sc->hw_if;
 1732         if (hw == NULL)
 1733                 return ENXIO;
 1734 
 1735         device_active(sc->sc_dev, DVA_SYSTEM);
 1736 
 1737         sc->sc_opencnt++;
 1738 
 1739         if (hw->open != NULL) {
 1740                 err = hw->open(sc->hw_softc, flags);
 1741                 if (err)
 1742                         return err;
 1743         }
 1744 
 1745         /* set up input stream.  TODO: check flags to determine if
 1746          * "read" is desired? */
 1747         vs = &sc->sc_stream_in;
 1748 
 1749         if (hw->get_format != NULL) {
 1750                 err = hw->get_format(sc->hw_softc, &vs->vs_format);
 1751                 if (err != 0)
 1752                         return err;
 1753         }
 1754         return 0;
 1755 }
 1756 
 1757 
 1758 int
 1759 videoclose(dev_t dev, int flags, int ifmt, struct lwp *l)
 1760 {
 1761         struct video_softc *sc;
 1762         const struct video_hw_if *hw;
 1763 
 1764         sc = device_private(device_lookup(&video_cd, VIDEOUNIT(dev)));
 1765         if (sc == NULL)
 1766                 return ENXIO;
 1767 
 1768         DPRINTF(("videoclose: sc=%p\n", sc));
 1769 
 1770         hw = sc->hw_if;
 1771         if (hw == NULL)
 1772                 return ENXIO;
 1773 
 1774         device_active(sc->sc_dev, DVA_SYSTEM);
 1775 
 1776         video_stream_off(sc, sc->sc_stream_in.vs_type);
 1777 
 1778         /* ignore error */
 1779         if (hw->close != NULL)
 1780                 hw->close(sc->hw_softc);
 1781 
 1782         video_stream_teardown_bufs(&sc->sc_stream_in);
 1783 
 1784         sc->sc_open = 0;
 1785         sc->sc_opencnt--;
 1786 
 1787         return 0;
 1788 }
 1789 
 1790 
 1791 int
 1792 videoread(dev_t dev, struct uio *uio, int ioflag)
 1793 {
 1794         struct video_softc *sc;
 1795         struct video_stream *vs;
 1796         struct video_buffer *vb;
 1797         struct scatter_io sio;
 1798         int err;
 1799         size_t len;
 1800         off_t offset;
 1801 
 1802         sc = device_private(device_lookup(&video_cd, VIDEOUNIT(dev)));
 1803         if (sc == NULL)
 1804                 return ENXIO;
 1805 
 1806         if (sc->sc_dying)
 1807                 return EIO;
 1808 
 1809         vs = &sc->sc_stream_in;
 1810 
 1811         /* userspace has chosen read() method */
 1812         if (vs->vs_method == VIDEO_STREAM_METHOD_NONE) {
 1813                 err = video_stream_setup_bufs(vs,
 1814                                               VIDEO_STREAM_METHOD_READ,
 1815                                               VIDEO_NUM_BUFS);
 1816                 if (err != 0)
 1817                         return err;
 1818 
 1819                 err = video_stream_on(sc, vs->vs_type);
 1820                 if (err != 0)
 1821                         return err;
 1822         } else if (vs->vs_method != VIDEO_STREAM_METHOD_READ) {
 1823                 return EBUSY;
 1824         }
 1825 
 1826         mutex_enter(&vs->vs_lock);
 1827 
 1828 retry:
 1829         if (SIMPLEQ_EMPTY(&vs->vs_egress)) {
 1830                 if (vs->vs_flags & O_NONBLOCK) {
 1831                         mutex_exit(&vs->vs_lock);
 1832                         return EAGAIN;
 1833                 }
 1834 
 1835                 /* Block until we have a sample */
 1836                 while (SIMPLEQ_EMPTY(&vs->vs_egress)) {
 1837                         err = cv_wait_sig(&vs->vs_sample_cv,
 1838                                           &vs->vs_lock);
 1839                         if (err != 0) {
 1840                                 mutex_exit(&vs->vs_lock);
 1841                                 return EINTR;
 1842                         }
 1843                 }
 1844 
 1845                 vb = SIMPLEQ_FIRST(&vs->vs_egress);
 1846         } else {
 1847                 vb = SIMPLEQ_FIRST(&vs->vs_egress);
 1848         }
 1849 
 1850         /* Oops, empty sample buffer. */
 1851         if (vb->vb_buf->bytesused == 0) {
 1852                 vb = video_stream_dequeue(vs);
 1853                 video_stream_enqueue(vs, vb);
 1854                 vs->vs_bytesread = 0;
 1855                 goto retry;
 1856         }
 1857 
 1858         mutex_exit(&vs->vs_lock);
 1859 
 1860         len = uimin(uio->uio_resid, vb->vb_buf->bytesused - vs->vs_bytesread);
 1861         offset = vb->vb_buf->m.offset + vs->vs_bytesread;
 1862 
 1863         if (scatter_io_init(&vs->vs_data, offset, len, &sio)) {
 1864                 err = scatter_io_uiomove(&sio, uio);
 1865                 if (err == EFAULT)
 1866                         return EFAULT;
 1867                 vs->vs_bytesread += (len - sio.sio_resid);
 1868         } else {
 1869                 DPRINTF(("video: invalid read\n"));
 1870         }
 1871 
 1872         /* Move the sample to the ingress queue if everything has
 1873          * been read */
 1874         if (vs->vs_bytesread >= vb->vb_buf->bytesused) {
 1875                 mutex_enter(&vs->vs_lock);
 1876                 vb = video_stream_dequeue(vs);
 1877                 video_stream_enqueue(vs, vb);
 1878                 mutex_exit(&vs->vs_lock);
 1879 
 1880                 vs->vs_bytesread = 0;
 1881         }
 1882 
 1883         return 0;
 1884 }
 1885 
 1886 
 1887 int
 1888 videowrite(dev_t dev, struct uio *uio, int ioflag)
 1889 {
 1890         return ENXIO;
 1891 }
 1892 
 1893 
 1894 /*
 1895  * Before 64-bit time_t, timeval's tv_sec was 'long'.  Thus on LP64 ports
 1896  * v4l2_buffer is the same size and layout as before.  However it did change
 1897  * on LP32 ports, and we thus handle this difference here for "COMPAT_50".
 1898  */
 1899 
 1900 #ifndef _LP64
 1901 static void
 1902 buf50tobuf(const void *data, struct v4l2_buffer *buf)
 1903 {
 1904         const struct v4l2_buffer50 *b50 = data;
 1905 
 1906         buf->index = b50->index;
 1907         buf->type = b50->type;
 1908         buf->bytesused = b50->bytesused;
 1909         buf->flags = b50->flags;
 1910         buf->field = b50->field;
 1911         timeval50_to_timeval(&b50->timestamp, &buf->timestamp);
 1912         buf->timecode = b50->timecode;
 1913         buf->sequence = b50->sequence;
 1914         buf->memory = b50->memory;
 1915         buf->m.offset = b50->m.offset;
 1916         /* XXX: Handle userptr */
 1917         buf->length = b50->length;
 1918         buf->reserved2 = b50->reserved2;
 1919         buf->reserved = b50->reserved;
 1920 }
 1921 
 1922 static void
 1923 buftobuf50(void *data, const struct v4l2_buffer *buf)
 1924 {
 1925         struct v4l2_buffer50 *b50 = data;
 1926 
 1927         b50->index = buf->index;
 1928         b50->type = buf->type;
 1929         b50->bytesused = buf->bytesused;
 1930         b50->flags = buf->flags;
 1931         b50->field = buf->field;
 1932         timeval_to_timeval50(&buf->timestamp, &b50->timestamp);
 1933         b50->timecode = buf->timecode;
 1934         b50->sequence = buf->sequence;
 1935         b50->memory = buf->memory;
 1936         b50->m.offset = buf->m.offset;
 1937         /* XXX: Handle userptr */
 1938         b50->length = buf->length;
 1939         b50->reserved2 = buf->reserved2;
 1940         b50->reserved = buf->reserved;
 1941 }
 1942 #endif
 1943 
 1944 int
 1945 videoioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
 1946 {
 1947         struct video_softc *sc;
 1948         const struct video_hw_if *hw;
 1949         struct v4l2_capability *cap;
 1950         struct v4l2_fmtdesc *fmtdesc;
 1951         struct v4l2_format *fmt;
 1952         struct v4l2_standard *std;
 1953         struct v4l2_input *input;
 1954         struct v4l2_audio *audio;
 1955         struct v4l2_tuner *tuner;
 1956         struct v4l2_frequency *freq;
 1957         struct v4l2_control *control;
 1958         struct v4l2_queryctrl *query;
 1959         struct v4l2_requestbuffers *reqbufs;
 1960         struct v4l2_buffer *buf;
 1961         struct v4l2_streamparm *parm;
 1962         struct v4l2_frmsizeenum *size;
 1963         struct v4l2_frmivalenum *ival;
 1964         v4l2_std_id *stdid;
 1965         enum v4l2_buf_type *typep;
 1966         int *ip;
 1967 #ifndef _LP64
 1968         struct v4l2_buffer bufspace;
 1969         int error;
 1970 #endif
 1971 
 1972         sc = device_private(device_lookup(&video_cd, VIDEOUNIT(dev)));
 1973 
 1974         if (sc->sc_dying)
 1975                 return EIO;
 1976 
 1977         hw = sc->hw_if;
 1978         if (hw == NULL)
 1979                 return ENXIO;
 1980 
 1981         switch (cmd) {
 1982         case VIDIOC_QUERYCAP:
 1983                 cap = data;
 1984                 memset(cap, 0, sizeof(*cap));
 1985                 strlcpy(cap->driver,
 1986                         device_cfdriver(sc->hw_dev)->cd_name,
 1987                         sizeof(cap->driver));
 1988                 strlcpy(cap->card, hw->get_devname(sc->hw_softc),
 1989                         sizeof(cap->card));
 1990                 strlcpy(cap->bus_info, hw->get_businfo(sc->hw_softc),
 1991                         sizeof(cap->bus_info));
 1992                 cap->version = VIDEO_DRIVER_VERSION;
 1993                 cap->capabilities = 0;
 1994                 if (hw->start_transfer != NULL && hw->stop_transfer != NULL)
 1995                         cap->capabilities |= V4L2_CAP_VIDEO_CAPTURE |
 1996                             V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
 1997                 if (hw->set_tuner != NULL && hw->get_tuner != NULL)
 1998                         cap->capabilities |= V4L2_CAP_TUNER;
 1999                 if (hw->set_audio != NULL && hw->get_audio != NULL &&
 2000                     hw->enum_audio != NULL)
 2001                         cap->capabilities |= V4L2_CAP_AUDIO;
 2002                 return 0;
 2003         case VIDIOC_ENUM_FMT:
 2004                 /* TODO: for now, just enumerate one default format */
 2005                 fmtdesc = data;
 2006                 if (fmtdesc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 2007                         return EINVAL;
 2008                 return video_enum_format(sc, fmtdesc);
 2009         case VIDIOC_G_FMT:
 2010                 fmt = data;
 2011                 return video_get_format(sc, fmt);
 2012         case VIDIOC_S_FMT:
 2013                 fmt = data;
 2014                 if ((flag & FWRITE) == 0)
 2015                         return EPERM;
 2016                 return video_set_format(sc, fmt);
 2017         case VIDIOC_TRY_FMT:
 2018                 fmt = data;
 2019                 return video_try_format(sc, fmt);
 2020         case VIDIOC_G_PARM:
 2021                 parm = data;
 2022                 return video_get_parm(sc, parm);
 2023         case VIDIOC_S_PARM:
 2024                 parm = data;
 2025                 if ((flag & FWRITE) == 0)
 2026                         return EPERM;
 2027                 return video_set_parm(sc, parm);
 2028         case VIDIOC_ENUMSTD:
 2029                 std = data;
 2030                 return video_enum_standard(sc, std);
 2031         case VIDIOC_G_STD:
 2032                 stdid = data;
 2033                 return video_get_standard(sc, stdid);
 2034         case VIDIOC_S_STD:
 2035                 stdid = data;
 2036                 if ((flag & FWRITE) == 0)
 2037                         return EPERM;
 2038                 return video_set_standard(sc, *stdid);
 2039         case VIDIOC_ENUMINPUT:
 2040                 input = data;
 2041                 return video_enum_input(sc, input);
 2042         case VIDIOC_G_INPUT:
 2043                 ip = data;
 2044                 return video_get_input(sc, ip);
 2045         case VIDIOC_S_INPUT:
 2046                 ip = data;
 2047                 if ((flag & FWRITE) == 0)
 2048                         return EPERM;
 2049                 return video_set_input(sc, *ip);
 2050         case VIDIOC_ENUMAUDIO:
 2051                 audio = data;
 2052                 return video_enum_audio(sc, audio);
 2053         case VIDIOC_G_AUDIO:
 2054                 audio = data;
 2055                 return video_get_audio(sc, audio);
 2056         case VIDIOC_S_AUDIO:
 2057                 audio = data;
 2058                 if ((flag & FWRITE) == 0)
 2059                         return EPERM;
 2060                 return video_set_audio(sc, audio);
 2061         case VIDIOC_G_TUNER:
 2062                 tuner = data;
 2063                 return video_get_tuner(sc, tuner);
 2064         case VIDIOC_S_TUNER:
 2065                 tuner = data;
 2066                 if ((flag & FWRITE) == 0)
 2067                         return EPERM;
 2068                 return video_set_tuner(sc, tuner);
 2069         case VIDIOC_G_FREQUENCY:
 2070                 freq = data;
 2071                 return video_get_frequency(sc, freq);
 2072         case VIDIOC_S_FREQUENCY:
 2073                 freq = data;
 2074                 if ((flag & FWRITE) == 0)
 2075                         return EPERM;
 2076                 return video_set_frequency(sc, freq);
 2077         case VIDIOC_QUERYCTRL:
 2078                 query = data;
 2079                 return (video_query_control(sc, query));
 2080         case VIDIOC_G_CTRL:
 2081                 control = data;
 2082                 return (video_get_control(sc, control));
 2083         case VIDIOC_S_CTRL:
 2084                 control = data;
 2085                 if ((flag & FWRITE) == 0)
 2086                         return EPERM;
 2087                 return (video_set_control(sc, control));
 2088         case VIDIOC_REQBUFS:
 2089                 reqbufs = data;
 2090                 return (video_request_bufs(sc, reqbufs));
 2091         case VIDIOC_QUERYBUF:
 2092                 buf = data;
 2093                 return video_query_buf(sc, buf);
 2094 #ifndef _LP64
 2095         case VIDIOC_QUERYBUF50:
 2096                 buf50tobuf(data, buf = &bufspace);
 2097                 if ((error = video_query_buf(sc, buf)) != 0)
 2098                         return error;
 2099                 buftobuf50(data, buf);
 2100                 return 0;
 2101 #endif
 2102         case VIDIOC_QBUF:
 2103                 buf = data;
 2104                 return video_queue_buf(sc, buf);
 2105 #ifndef _LP64
 2106         case VIDIOC_QBUF50:
 2107                 buf50tobuf(data, buf = &bufspace);
 2108                 return video_queue_buf(sc, buf);
 2109 #endif
 2110         case VIDIOC_DQBUF:
 2111                 buf = data;
 2112                 return video_dequeue_buf(sc, buf);
 2113 #ifndef _LP64
 2114         case VIDIOC_DQBUF50:
 2115                 buf50tobuf(data, buf = &bufspace);
 2116                 if ((error = video_dequeue_buf(sc, buf)) != 0)
 2117                         return error;
 2118                 buftobuf50(data, buf);
 2119                 return 0;
 2120 #endif
 2121         case VIDIOC_STREAMON:
 2122                 typep = data;
 2123                 return video_stream_on(sc, *typep);
 2124         case VIDIOC_STREAMOFF:
 2125                 typep = data;
 2126                 return video_stream_off(sc, *typep);
 2127         case VIDIOC_ENUM_FRAMESIZES:
 2128                 size = data;
 2129                 return video_enum_framesizes(sc, size);
 2130         case VIDIOC_ENUM_FRAMEINTERVALS:
 2131                 ival = data;
 2132                 return video_enum_frameival(sc, ival);
 2133         default:
 2134                 DPRINTF(("videoioctl: invalid cmd %s (%lx)\n",
 2135                          video_ioctl_str(cmd), cmd));
 2136                 return EINVAL;
 2137         }
 2138 }
 2139 
 2140 #ifdef VIDEO_DEBUG
 2141 static const char *
 2142 video_ioctl_str(u_long cmd)
 2143 {
 2144         const char *str;
 2145 
 2146         switch (cmd) {
 2147         case VIDIOC_QUERYCAP:
 2148                 str = "VIDIOC_QUERYCAP";
 2149                 break;
 2150         case VIDIOC_RESERVED:
 2151                 str = "VIDIOC_RESERVED";
 2152                 break;
 2153         case VIDIOC_ENUM_FMT:
 2154                 str = "VIDIOC_ENUM_FMT";
 2155                 break;
 2156         case VIDIOC_G_FMT:
 2157                 str = "VIDIOC_G_FMT";
 2158                 break;
 2159         case VIDIOC_S_FMT:
 2160                 str = "VIDIOC_S_FMT";
 2161                 break;
 2162 /* 6 and 7 are VIDIOC_[SG]_COMP, which are unsupported */
 2163         case VIDIOC_REQBUFS:
 2164                 str = "VIDIOC_REQBUFS";
 2165                 break;
 2166         case VIDIOC_QUERYBUF:
 2167                 str = "VIDIOC_QUERYBUF";
 2168                 break;
 2169 #ifndef _LP64
 2170         case VIDIOC_QUERYBUF50:
 2171                 str = "VIDIOC_QUERYBUF50";
 2172                 break;
 2173 #endif
 2174         case VIDIOC_G_FBUF:
 2175                 str = "VIDIOC_G_FBUF";
 2176                 break;
 2177         case VIDIOC_S_FBUF:
 2178                 str = "VIDIOC_S_FBUF";
 2179                 break;
 2180         case VIDIOC_OVERLAY:
 2181                 str = "VIDIOC_OVERLAY";
 2182                 break;
 2183         case VIDIOC_QBUF:
 2184                 str = "VIDIOC_QBUF";
 2185                 break;
 2186 #ifndef _LP64
 2187         case VIDIOC_QBUF50:
 2188                 str = "VIDIOC_QBUF50";
 2189                 break;
 2190 #endif
 2191         case VIDIOC_DQBUF:
 2192                 str = "VIDIOC_DQBUF";
 2193                 break;
 2194 #ifndef _LP64
 2195         case VIDIOC_DQBUF50:
 2196                 str = "VIDIOC_DQBUF50";
 2197                 break;
 2198 #endif
 2199         case VIDIOC_STREAMON:
 2200                 str = "VIDIOC_STREAMON";
 2201                 break;
 2202         case VIDIOC_STREAMOFF:
 2203                 str = "VIDIOC_STREAMOFF";
 2204                 break;
 2205         case VIDIOC_G_PARM:
 2206                 str = "VIDIOC_G_PARM";
 2207                 break;
 2208         case VIDIOC_S_PARM:
 2209                 str = "VIDIOC_S_PARM";
 2210                 break;
 2211         case VIDIOC_G_STD:
 2212                 str = "VIDIOC_G_STD";
 2213                 break;
 2214         case VIDIOC_S_STD:
 2215                 str = "VIDIOC_S_STD";
 2216                 break;
 2217         case VIDIOC_ENUMSTD:
 2218                 str = "VIDIOC_ENUMSTD";
 2219                 break;
 2220         case VIDIOC_ENUMINPUT:
 2221                 str = "VIDIOC_ENUMINPUT";
 2222                 break;
 2223         case VIDIOC_G_CTRL:
 2224                 str = "VIDIOC_G_CTRL";
 2225                 break;
 2226         case VIDIOC_S_CTRL:
 2227                 str = "VIDIOC_S_CTRL";
 2228                 break;
 2229         case VIDIOC_G_TUNER:
 2230                 str = "VIDIOC_G_TUNER";
 2231                 break;
 2232         case VIDIOC_S_TUNER:
 2233                 str = "VIDIOC_S_TUNER";
 2234                 break;
 2235         case VIDIOC_G_AUDIO:
 2236                 str = "VIDIOC_G_AUDIO";
 2237                 break;
 2238         case VIDIOC_S_AUDIO:
 2239                 str = "VIDIOC_S_AUDIO";
 2240                 break;
 2241         case VIDIOC_QUERYCTRL:
 2242                 str = "VIDIOC_QUERYCTRL";
 2243                 break;
 2244         case VIDIOC_QUERYMENU:
 2245                 str = "VIDIOC_QUERYMENU";
 2246                 break;
 2247         case VIDIOC_G_INPUT:
 2248                 str = "VIDIOC_G_INPUT";
 2249                 break;
 2250         case VIDIOC_S_INPUT:
 2251                 str = "VIDIOC_S_INPUT";
 2252                 break;
 2253         case VIDIOC_G_OUTPUT:
 2254                 str = "VIDIOC_G_OUTPUT";
 2255                 break;
 2256         case VIDIOC_S_OUTPUT:
 2257                 str = "VIDIOC_S_OUTPUT";
 2258                 break;
 2259         case VIDIOC_ENUMOUTPUT:
 2260                 str = "VIDIOC_ENUMOUTPUT";
 2261                 break;
 2262         case VIDIOC_G_AUDOUT:
 2263                 str = "VIDIOC_G_AUDOUT";
 2264                 break;
 2265         case VIDIOC_S_AUDOUT:
 2266                 str = "VIDIOC_S_AUDOUT";
 2267                 break;
 2268         case VIDIOC_G_MODULATOR:
 2269                 str = "VIDIOC_G_MODULATOR";
 2270                 break;
 2271         case VIDIOC_S_MODULATOR:
 2272                 str = "VIDIOC_S_MODULATOR";
 2273                 break;
 2274         case VIDIOC_G_FREQUENCY:
 2275                 str = "VIDIOC_G_FREQUENCY";
 2276                 break;
 2277         case VIDIOC_S_FREQUENCY:
 2278                 str = "VIDIOC_S_FREQUENCY";
 2279                 break;
 2280         case VIDIOC_CROPCAP:
 2281                 str = "VIDIOC_CROPCAP";
 2282                 break;
 2283         case VIDIOC_G_CROP:
 2284                 str = "VIDIOC_G_CROP";
 2285                 break;
 2286         case VIDIOC_S_CROP:
 2287                 str = "VIDIOC_S_CROP";
 2288                 break;
 2289         case VIDIOC_G_JPEGCOMP:
 2290                 str = "VIDIOC_G_JPEGCOMP";
 2291                 break;
 2292         case VIDIOC_S_JPEGCOMP:
 2293                 str = "VIDIOC_S_JPEGCOMP";
 2294                 break;
 2295         case VIDIOC_QUERYSTD:
 2296                 str = "VIDIOC_QUERYSTD";
 2297                 break;
 2298         case VIDIOC_TRY_FMT:
 2299                 str = "VIDIOC_TRY_FMT";
 2300                 break;
 2301         case VIDIOC_ENUMAUDIO:
 2302                 str = "VIDIOC_ENUMAUDIO";
 2303                 break;
 2304         case VIDIOC_ENUMAUDOUT:
 2305                 str = "VIDIOC_ENUMAUDOUT";
 2306                 break;
 2307         case VIDIOC_G_PRIORITY:
 2308                 str = "VIDIOC_G_PRIORITY";
 2309                 break;
 2310         case VIDIOC_S_PRIORITY:
 2311                 str = "VIDIOC_S_PRIORITY";
 2312                 break;
 2313         case VIDIOC_ENUM_FRAMESIZES:
 2314                 str = "VIDIOC_ENUM_FRAMESIZES";
 2315                 break;
 2316         case VIDIOC_ENUM_FRAMEINTERVALS:
 2317                 str = "VIDIOC_FRAMEINTERVALS";
 2318                 break;
 2319         default:
 2320                 str = "unknown";
 2321                 break;
 2322         }
 2323         return str;
 2324 }
 2325 #endif
 2326 
 2327 
 2328 int
 2329 videopoll(dev_t dev, int events, struct lwp *l)
 2330 {
 2331         struct video_softc *sc;
 2332         struct video_stream *vs;
 2333         int err, revents = 0;
 2334 
 2335         sc = device_private(device_lookup(&video_cd, VIDEOUNIT(dev)));
 2336         vs = &sc->sc_stream_in;
 2337 
 2338         if (sc->sc_dying)
 2339                 return (POLLHUP);
 2340 
 2341         /* userspace has chosen read() method */
 2342         if (vs->vs_method == VIDEO_STREAM_METHOD_NONE) {
 2343                 err = video_stream_setup_bufs(vs,
 2344                                               VIDEO_STREAM_METHOD_READ,
 2345                                               VIDEO_NUM_BUFS);
 2346                 if (err != 0)
 2347                         return POLLERR;
 2348 
 2349                 err = video_stream_on(sc, vs->vs_type);
 2350                 if (err != 0)
 2351                         return POLLERR;
 2352         }
 2353 
 2354         mutex_enter(&vs->vs_lock);
 2355         if (!SIMPLEQ_EMPTY(&sc->sc_stream_in.vs_egress))
 2356                 revents |= events & (POLLIN | POLLRDNORM);
 2357         else
 2358                 selrecord(l, &vs->vs_sel);
 2359         mutex_exit(&vs->vs_lock);
 2360 
 2361         return (revents);
 2362 }
 2363 
 2364 
 2365 paddr_t
 2366 videommap(dev_t dev, off_t off, int prot)
 2367 {
 2368         struct video_softc *sc;
 2369         struct video_stream *vs;
 2370         /* paddr_t pa; */
 2371 
 2372         sc = device_lookup_private(&video_cd, VIDEOUNIT(dev));
 2373         if (sc->sc_dying)
 2374                 return -1;
 2375 
 2376         vs = &sc->sc_stream_in;
 2377 
 2378         return scatter_buf_map(&vs->vs_data, off);
 2379 }
 2380 
 2381 
 2382 /* Allocates buffers and initializes some fields.  The format field
 2383  * must already have been initialized. */
 2384 void
 2385 video_stream_init(struct video_stream *vs)
 2386 {
 2387         vs->vs_method = VIDEO_STREAM_METHOD_NONE;
 2388         vs->vs_flags = 0;
 2389         vs->vs_frameno = -1;
 2390         vs->vs_sequence = 0;
 2391         vs->vs_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 2392         vs->vs_nbufs = 0;
 2393         vs->vs_buf = NULL;
 2394         vs->vs_streaming = false;
 2395 
 2396         memset(&vs->vs_format, 0, sizeof(vs->vs_format));
 2397 
 2398         SIMPLEQ_INIT(&vs->vs_ingress);
 2399         SIMPLEQ_INIT(&vs->vs_egress);
 2400 
 2401         mutex_init(&vs->vs_lock, MUTEX_DEFAULT, IPL_NONE);
 2402         cv_init(&vs->vs_sample_cv, "video");
 2403         selinit(&vs->vs_sel);
 2404 
 2405         scatter_buf_init(&vs->vs_data);
 2406 }
 2407 
 2408 void
 2409 video_stream_fini(struct video_stream *vs)
 2410 {
 2411         /* Sample data in queues has already been freed */
 2412         /* while (SIMPLEQ_FIRST(&vs->vs_ingress) != NULL)
 2413                 SIMPLEQ_REMOVE_HEAD(&vs->vs_ingress, entries);
 2414         while (SIMPLEQ_FIRST(&vs->vs_egress) != NULL)
 2415         SIMPLEQ_REMOVE_HEAD(&vs->vs_egress, entries); */
 2416 
 2417         mutex_destroy(&vs->vs_lock);
 2418         cv_destroy(&vs->vs_sample_cv);
 2419         seldestroy(&vs->vs_sel);
 2420 
 2421         scatter_buf_destroy(&vs->vs_data);
 2422 }
 2423 
 2424 static int
 2425 video_stream_setup_bufs(struct video_stream *vs,
 2426                         enum video_stream_method method,
 2427                         uint8_t nbufs)
 2428 {
 2429         int i, err;
 2430 
 2431         mutex_enter(&vs->vs_lock);
 2432 
 2433         /* Ensure that all allocated buffers are queued and not under
 2434          * userspace control. */
 2435         for (i = 0; i < vs->vs_nbufs; ++i) {
 2436                 if (!(vs->vs_buf[i]->vb_buf->flags & V4L2_BUF_FLAG_QUEUED)) {
 2437                         mutex_exit(&vs->vs_lock);
 2438                         return EBUSY;
 2439                 }
 2440         }
 2441 
 2442         /* Allocate the buffers */
 2443         err = video_stream_realloc_bufs(vs, nbufs);
 2444         if (err != 0) {
 2445                 mutex_exit(&vs->vs_lock);
 2446                 return err;
 2447         }
 2448 
 2449         /* Queue up buffers for read method.  Other methods are queued
 2450          * by VIDIOC_QBUF ioctl. */
 2451         if (method == VIDEO_STREAM_METHOD_READ) {
 2452                 for (i = 0; i < nbufs; ++i)
 2453                         if (!(vs->vs_buf[i]->vb_buf->flags & V4L2_BUF_FLAG_QUEUED))
 2454                                 video_stream_enqueue(vs, vs->vs_buf[i]);
 2455         }
 2456 
 2457         vs->vs_method = method;
 2458         mutex_exit(&vs->vs_lock);
 2459 
 2460         return 0;
 2461 }
 2462 
 2463 /* Free all buffer memory in preparation for close().  This should
 2464  * free buffers regardless of errors.  Use video_stream_setup_bufs if
 2465  * you need to check for errors. Streaming should be off before
 2466  * calling this function. */
 2467 static void
 2468 video_stream_teardown_bufs(struct video_stream *vs)
 2469 {
 2470         int err;
 2471 
 2472         mutex_enter(&vs->vs_lock);
 2473 
 2474         if (vs->vs_streaming) {
 2475                 DPRINTF(("video_stream_teardown_bufs: "
 2476                          "tearing down bufs while streaming\n"));
 2477         }
 2478 
 2479         /* dequeue all buffers */
 2480         while (SIMPLEQ_FIRST(&vs->vs_ingress) != NULL)
 2481                 SIMPLEQ_REMOVE_HEAD(&vs->vs_ingress, entries);
 2482         while (SIMPLEQ_FIRST(&vs->vs_egress) != NULL)
 2483                 SIMPLEQ_REMOVE_HEAD(&vs->vs_egress, entries);
 2484 
 2485         err = video_stream_free_bufs(vs);
 2486         if (err != 0) {
 2487                 DPRINTF(("video_stream_teardown_bufs: "
 2488                          "error releasing buffers: %d\n",
 2489                          err));
 2490         }
 2491         vs->vs_method = VIDEO_STREAM_METHOD_NONE;
 2492 
 2493         mutex_exit(&vs->vs_lock);
 2494 }
 2495 
 2496 static struct video_buffer *
 2497 video_buffer_alloc(void)
 2498 {
 2499         struct video_buffer *vb;
 2500 
 2501         vb = kmem_alloc(sizeof(*vb), KM_SLEEP);
 2502         vb->vb_buf = kmem_alloc(sizeof(*vb->vb_buf), KM_SLEEP);
 2503         return vb;
 2504 }
 2505 
 2506 static void
 2507 video_buffer_free(struct video_buffer *vb)
 2508 {
 2509         kmem_free(vb->vb_buf, sizeof(*vb->vb_buf));
 2510         vb->vb_buf = NULL;
 2511         kmem_free(vb, sizeof(*vb));
 2512 }
 2513 
 2514 /* TODO: for userptr method
 2515 struct video_buffer *
 2516 video_buf_alloc_with_ubuf(struct v4l2_buffer *buf)
 2517 {
 2518 }
 2519 
 2520 void
 2521 video_buffer_free_with_ubuf(struct video_buffer *vb)
 2522 {
 2523 }
 2524 */
 2525 
 2526 static int
 2527 video_stream_realloc_bufs(struct video_stream *vs, uint8_t nbufs)
 2528 {
 2529         int i, err;
 2530         uint8_t minnbufs, oldnbufs;
 2531         size_t size;
 2532         off_t offset;
 2533         struct video_buffer **oldbuf;
 2534         struct v4l2_buffer *buf;
 2535 
 2536         size = PAGE_ALIGN(vs->vs_format.sample_size) * nbufs;
 2537         err = scatter_buf_set_size(&vs->vs_data, size);
 2538         if (err != 0)
 2539                 return err;
 2540 
 2541         oldnbufs = vs->vs_nbufs;
 2542         oldbuf = vs->vs_buf;
 2543 
 2544         vs->vs_nbufs = nbufs;
 2545         if (nbufs > 0) {
 2546                 vs->vs_buf =
 2547                     kmem_alloc(sizeof(struct video_buffer *) * nbufs, KM_SLEEP);
 2548         } else {
 2549                 vs->vs_buf = NULL;
 2550         }
 2551 
 2552         minnbufs = uimin(vs->vs_nbufs, oldnbufs);
 2553         /* copy any bufs that will be reused */
 2554         for (i = 0; i < minnbufs; ++i)
 2555                 vs->vs_buf[i] = oldbuf[i];
 2556         /* allocate any necessary new bufs */
 2557         for (; i < vs->vs_nbufs; ++i)
 2558                 vs->vs_buf[i] = video_buffer_alloc();
 2559         /* free any bufs no longer used */
 2560         for (; i < oldnbufs; ++i) {
 2561                 video_buffer_free(oldbuf[i]);
 2562                 oldbuf[i] = NULL;
 2563         }
 2564 
 2565         /* Free old buffer metadata */
 2566         if (oldbuf != NULL)
 2567                 kmem_free(oldbuf, sizeof(struct video_buffer *) * oldnbufs);
 2568 
 2569         /* initialize bufs */
 2570         offset = 0;
 2571         for (i = 0; i < vs->vs_nbufs; ++i) {
 2572                 buf = vs->vs_buf[i]->vb_buf;
 2573                 buf->index = i;
 2574                 buf->type = vs->vs_type;
 2575                 buf->bytesused = 0;
 2576                 buf->flags = 0;
 2577                 buf->field = 0;
 2578                 buf->sequence = 0;
 2579                 buf->memory = V4L2_MEMORY_MMAP;
 2580                 buf->m.offset = offset;
 2581                 buf->length = PAGE_ALIGN(vs->vs_format.sample_size);
 2582                 buf->reserved2 = 0;
 2583                 buf->reserved = 0;
 2584 
 2585                 offset += buf->length;
 2586         }
 2587 
 2588         return 0;
 2589 }
 2590 
 2591 /* Accepts a video_sample into the ingress queue.  Caller must hold
 2592  * the stream lock. */
 2593 void
 2594 video_stream_enqueue(struct video_stream *vs, struct video_buffer *vb)
 2595 {
 2596         if (vb->vb_buf->flags & V4L2_BUF_FLAG_QUEUED) {
 2597                 DPRINTF(("video_stream_enqueue: sample already queued\n"));
 2598                 return;
 2599         }
 2600 
 2601         vb->vb_buf->flags |= V4L2_BUF_FLAG_QUEUED;
 2602         vb->vb_buf->flags &= ~V4L2_BUF_FLAG_DONE;
 2603 
 2604         vb->vb_buf->bytesused = 0;
 2605 
 2606         SIMPLEQ_INSERT_TAIL(&vs->vs_ingress, vb, entries);
 2607 }
 2608 
 2609 
 2610 /* Removes the head of the egress queue for use by userspace.  Caller
 2611  * must hold the stream lock. */
 2612 struct video_buffer *
 2613 video_stream_dequeue(struct video_stream *vs)
 2614 {
 2615         struct video_buffer *vb;
 2616 
 2617         if (!SIMPLEQ_EMPTY(&vs->vs_egress)) {
 2618                 vb = SIMPLEQ_FIRST(&vs->vs_egress);
 2619                 SIMPLEQ_REMOVE_HEAD(&vs->vs_egress, entries);
 2620                 vb->vb_buf->flags &= ~V4L2_BUF_FLAG_QUEUED;
 2621                 vb->vb_buf->flags |= V4L2_BUF_FLAG_DONE;
 2622                 return vb;
 2623         } else {
 2624                 return NULL;
 2625         }
 2626 }
 2627 
 2628 static void
 2629 v4l2buf_set_timestamp(struct v4l2_buffer *buf)
 2630 {
 2631 
 2632         getmicrotime(&buf->timestamp);
 2633 }
 2634 
 2635 /*
 2636  * write payload data to the appropriate video sample, possibly moving
 2637  * the sample from ingress to egress queues
 2638  */
 2639 void
 2640 video_stream_write(struct video_stream *vs,
 2641                    const struct video_payload *payload)
 2642 {
 2643         struct video_buffer *vb;
 2644         struct v4l2_buffer *buf;
 2645         struct scatter_io sio;
 2646 
 2647         mutex_enter(&vs->vs_lock);
 2648 
 2649         /* change of frameno implies end of current frame */
 2650         if (vs->vs_frameno >= 0 && vs->vs_frameno != payload->frameno)
 2651                 video_stream_sample_done(vs);
 2652 
 2653         vs->vs_frameno = payload->frameno;
 2654 
 2655         if (vs->vs_drop || SIMPLEQ_EMPTY(&vs->vs_ingress)) {
 2656                 /* DPRINTF(("video_stream_write: dropping sample %d\n",
 2657                    vs->vs_sequence)); */
 2658                 vs->vs_drop = true;
 2659         } else if (payload->size > 0) {
 2660                 vb = SIMPLEQ_FIRST(&vs->vs_ingress);
 2661                 buf = vb->vb_buf;
 2662                 if (!buf->bytesused)
 2663                         v4l2buf_set_timestamp(buf);
 2664                 if (payload->size > buf->length - buf->bytesused) {
 2665                         DPRINTF(("video_stream_write: "
 2666                                  "payload would overflow\n"));
 2667                 } else if (scatter_io_init(&vs->vs_data,
 2668                                            buf->m.offset + buf->bytesused,
 2669                                            payload->size,
 2670                                            &sio))
 2671                 {
 2672                         scatter_io_copyin(&sio, payload->data);
 2673                         buf->bytesused += (payload->size - sio.sio_resid);
 2674                 } else {
 2675                         DPRINTF(("video_stream_write: failed to init scatter io "
 2676                                  "vb=%p buf=%p "
 2677                                  "buf->m.offset=%d buf->bytesused=%u "
 2678                                  "payload->size=%zu\n",
 2679                                  vb, buf,
 2680                                  buf->m.offset, buf->bytesused, payload->size));
 2681                 }
 2682         }
 2683 
 2684         /* if the payload marks it, we can do sample_done() early */
 2685         if (payload->end_of_frame)
 2686                 video_stream_sample_done(vs);
 2687 
 2688         mutex_exit(&vs->vs_lock);
 2689 }
 2690 
 2691 
 2692 /* Moves the head of the ingress queue to the tail of the egress
 2693  * queue, or resets drop status if we were dropping this sample.
 2694  * Caller should hold the stream queue lock. */
 2695 void
 2696 video_stream_sample_done(struct video_stream *vs)
 2697 {
 2698         struct video_buffer *vb;
 2699 
 2700         if (vs->vs_drop) {
 2701                 vs->vs_drop = false;
 2702         } else if (!SIMPLEQ_EMPTY(&vs->vs_ingress)) {
 2703                 vb = SIMPLEQ_FIRST(&vs->vs_ingress);
 2704                 vb->vb_buf->sequence = vs->vs_sequence;
 2705                 SIMPLEQ_REMOVE_HEAD(&vs->vs_ingress, entries);
 2706 
 2707                 SIMPLEQ_INSERT_TAIL(&vs->vs_egress, vb, entries);
 2708                 cv_signal(&vs->vs_sample_cv);
 2709                 selnotify(&vs->vs_sel, 0, 0);
 2710         } else {
 2711                 DPRINTF(("video_stream_sample_done: no sample\n"));
 2712         }
 2713 
 2714         vs->vs_frameno ^= 1;
 2715         vs->vs_sequence++;
 2716 }
 2717 
 2718 /* Check if all buffers are queued, i.e. none are under control of
 2719  * userspace. */
 2720 /*
 2721 static bool
 2722 video_stream_all_queued(struct video_stream *vs)
 2723 {
 2724 }
 2725 */
 2726 
 2727 
 2728 static void
 2729 scatter_buf_init(struct scatter_buf *sb)
 2730 {
 2731         sb->sb_pool = pool_cache_init(PAGE_SIZE, 0, 0, 0,
 2732                                       "video", NULL, IPL_VIDEO,
 2733                                       NULL, NULL, NULL);
 2734         sb->sb_size = 0;
 2735         sb->sb_npages = 0;
 2736         sb->sb_page_ary = NULL;
 2737 }
 2738 
 2739 static void
 2740 scatter_buf_destroy(struct scatter_buf *sb)
 2741 {
 2742         /* Do we need to return everything to the pool first? */
 2743         scatter_buf_set_size(sb, 0);
 2744         pool_cache_destroy(sb->sb_pool);
 2745         sb->sb_pool = 0;
 2746         sb->sb_npages = 0;
 2747         sb->sb_page_ary = NULL;
 2748 }
 2749 
 2750 /* Increase or decrease the size of the buffer */
 2751 static int
 2752 scatter_buf_set_size(struct scatter_buf *sb, size_t sz)
 2753 {
 2754         int i;
 2755         size_t npages, minpages, oldnpages;
 2756         uint8_t **old_ary;
 2757 
 2758         npages = (sz >> PAGE_SHIFT) + ((sz & PAGE_MASK) > 0);
 2759 
 2760         if (sb->sb_npages == npages) {
 2761                 return 0;
 2762         }
 2763 
 2764         oldnpages = sb->sb_npages;
 2765         old_ary = sb->sb_page_ary;
 2766 
 2767         sb->sb_npages = npages;
 2768         if (npages > 0) {
 2769                 sb->sb_page_ary =
 2770                     kmem_alloc(sizeof(uint8_t *) * npages, KM_SLEEP);
 2771         } else {
 2772                 sb->sb_page_ary = NULL;
 2773         }
 2774 
 2775         minpages = uimin(npages, oldnpages);
 2776         /* copy any pages that will be reused */
 2777         for (i = 0; i < minpages; ++i)
 2778                 sb->sb_page_ary[i] = old_ary[i];
 2779         /* allocate any new pages */
 2780         for (; i < npages; ++i)
 2781                 sb->sb_page_ary[i] = pool_cache_get(sb->sb_pool, PR_WAITOK);
 2782         /* return any pages no longer needed */
 2783         for (; i < oldnpages; ++i)
 2784                 pool_cache_put(sb->sb_pool, old_ary[i]);
 2785 
 2786         if (old_ary != NULL)
 2787                 kmem_free(old_ary, sizeof(uint8_t *) * oldnpages);
 2788 
 2789         sb->sb_size = sb->sb_npages << PAGE_SHIFT;
 2790 
 2791         return 0;
 2792 }
 2793 
 2794 
 2795 static paddr_t
 2796 scatter_buf_map(struct scatter_buf *sb, off_t off)
 2797 {
 2798         size_t pg;
 2799         paddr_t pa;
 2800 
 2801         pg = off >> PAGE_SHIFT;
 2802 
 2803         if (pg >= sb->sb_npages)
 2804                 return -1;
 2805         else if (!pmap_extract(pmap_kernel(), (vaddr_t)sb->sb_page_ary[pg], &pa))
 2806                 return -1;
 2807 
 2808         return atop(pa);
 2809 }
 2810 
 2811 /* Initialize data for an io operation on a scatter buffer. Returns
 2812  * true if the transfer is valid, or false if out of range. */
 2813 static bool
 2814 scatter_io_init(struct scatter_buf *sb,
 2815                     off_t off, size_t len,
 2816                     struct scatter_io *sio)
 2817 {
 2818         if ((off + len) > sb->sb_size) {
 2819                 DPRINTF(("video: scatter_io_init failed: off=%" PRId64
 2820                          " len=%zu sb->sb_size=%zu\n",
 2821                          off, len, sb->sb_size));
 2822                 return false;
 2823         }
 2824 
 2825         sio->sio_buf = sb;
 2826         sio->sio_offset = off;
 2827         sio->sio_resid = len;
 2828 
 2829         return true;
 2830 }
 2831 
 2832 /* Store the pointer and size of the next contiguous segment.  Returns
 2833  * true if the segment is valid, or false if all has been transferred.
 2834  * Does not check for overflow. */
 2835 static bool
 2836 scatter_io_next(struct scatter_io *sio, void **p, size_t *sz)
 2837 {
 2838         size_t pg, pgo;
 2839 
 2840         if (sio->sio_resid == 0)
 2841                 return false;
 2842 
 2843         pg = sio->sio_offset >> PAGE_SHIFT;
 2844         pgo = sio->sio_offset & PAGE_MASK;
 2845 
 2846         *sz = uimin(PAGE_SIZE - pgo, sio->sio_resid);
 2847         *p = sio->sio_buf->sb_page_ary[pg] + pgo;
 2848 
 2849         sio->sio_offset += *sz;
 2850         sio->sio_resid -= *sz;
 2851 
 2852         return true;
 2853 }
 2854 
 2855 /* Semi-undo of a failed segment copy.  Updates the scatter_io
 2856  * struct to the previous values prior to a failed segment copy. */
 2857 static void
 2858 scatter_io_undo(struct scatter_io *sio, size_t sz)
 2859 {
 2860         sio->sio_offset -= sz;
 2861         sio->sio_resid += sz;
 2862 }
 2863 
 2864 /* Copy data from src into the scatter_buf as described by io. */
 2865 static void
 2866 scatter_io_copyin(struct scatter_io *sio, const void *p)
 2867 {
 2868         void *dst;
 2869         const uint8_t *src = p;
 2870         size_t sz;
 2871 
 2872         while(scatter_io_next(sio, &dst, &sz)) {
 2873                 memcpy(dst, src, sz);
 2874                 src += sz;
 2875         }
 2876 }
 2877 
 2878 /* --not used; commented to avoid compiler warnings--
 2879 static void
 2880 scatter_io_copyout(struct scatter_io *sio, void *p)
 2881 {
 2882         void *src;
 2883         uint8_t *dst = p;
 2884         size_t sz;
 2885 
 2886         while(scatter_io_next(sio, &src, &sz)) {
 2887                 memcpy(dst, src, sz);
 2888                 dst += sz;
 2889         }
 2890 }
 2891 */
 2892 
 2893 /* Performat a series of uiomove calls on a scatter buf.  Returns
 2894  * EFAULT if uiomove EFAULTs on the first segment.  Otherwise, returns
 2895  * an incomplete transfer but with no error. */
 2896 static int
 2897 scatter_io_uiomove(struct scatter_io *sio, struct uio *uio)
 2898 {
 2899         void *p;
 2900         size_t sz;
 2901         bool first = true;
 2902         int err;
 2903 
 2904         while(scatter_io_next(sio, &p, &sz)) {
 2905                 err = uiomove(p, sz, uio);
 2906                 if (err == EFAULT) {
 2907                         scatter_io_undo(sio, sz);
 2908                         if (first)
 2909                                 return EFAULT;
 2910                         else
 2911                                 return 0;
 2912                 }
 2913                 first = false;
 2914         }
 2915 
 2916         return 0;
 2917 }
 2918 
 2919 #endif /* NVIDEO > 0 */

Cache object: 91741cca9d8fd9f378729bd4935e5e0b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.