linux/drivers/media/video/videodev.c
<<
>>
Prefs
   1/*
   2 * Video capture interface for Linux version 2
   3 *
   4 *      A generic video device interface for the LINUX operating system
   5 *      using a set of device structures/vectors for low level operations.
   6 *
   7 *      This program is free software; you can redistribute it and/or
   8 *      modify it under the terms of the GNU General Public License
   9 *      as published by the Free Software Foundation; either version
  10 *      2 of the License, or (at your option) any later version.
  11 *
  12 * Authors:     Alan Cox, <alan@redhat.com> (version 1)
  13 *              Mauro Carvalho Chehab <mchehab@infradead.org> (version 2)
  14 *
  15 * Fixes:       20000516  Claudio Matsuoka <claudio@conectiva.com>
  16 *              - Added procfs support
  17 */
  18
  19#define dbgarg(cmd, fmt, arg...) \
  20                if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {                \
  21                        printk (KERN_DEBUG "%s: ",  vfd->name);         \
  22                        v4l_printk_ioctl(cmd);                          \
  23                        printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg); \
  24                }
  25
  26#define dbgarg2(fmt, arg...) \
  27                if (vfd->debug & V4L2_DEBUG_IOCTL_ARG)                  \
  28                        printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
  29
  30#include <linux/module.h>
  31#include <linux/types.h>
  32#include <linux/kernel.h>
  33#include <linux/mm.h>
  34#include <linux/string.h>
  35#include <linux/errno.h>
  36#include <linux/init.h>
  37#include <linux/kmod.h>
  38#include <linux/slab.h>
  39#include <asm/uaccess.h>
  40#include <asm/system.h>
  41
  42#define __OLD_VIDIOC_ /* To allow fixing old calls*/
  43#include <linux/videodev2.h>
  44
  45#ifdef CONFIG_VIDEO_V4L1
  46#include <linux/videodev.h>
  47#endif
  48#include <media/v4l2-common.h>
  49
  50#define VIDEO_NUM_DEVICES       256
  51#define VIDEO_NAME              "video4linux"
  52
  53/*
  54 *      sysfs stuff
  55 */
  56
  57static ssize_t show_name(struct device *cd,
  58                         struct device_attribute *attr, char *buf)
  59{
  60        struct video_device *vfd = container_of(cd, struct video_device,
  61                                                class_dev);
  62        return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name);
  63}
  64
  65struct video_device *video_device_alloc(void)
  66{
  67        struct video_device *vfd;
  68
  69        vfd = kzalloc(sizeof(*vfd),GFP_KERNEL);
  70        return vfd;
  71}
  72
  73void video_device_release(struct video_device *vfd)
  74{
  75        kfree(vfd);
  76}
  77
  78static void video_release(struct device *cd)
  79{
  80        struct video_device *vfd = container_of(cd, struct video_device,
  81                                                                class_dev);
  82
  83#if 1
  84        /* needed until all drivers are fixed */
  85        if (!vfd->release)
  86                return;
  87#endif
  88        vfd->release(vfd);
  89}
  90
  91static struct device_attribute video_device_attrs[] = {
  92        __ATTR(name, S_IRUGO, show_name, NULL),
  93        __ATTR_NULL
  94};
  95
  96static struct class video_class = {
  97        .name    = VIDEO_NAME,
  98        .dev_attrs = video_device_attrs,
  99        .dev_release = video_release,
 100};
 101
 102/*
 103 *      Active devices
 104 */
 105
 106static struct video_device *video_device[VIDEO_NUM_DEVICES];
 107static DEFINE_MUTEX(videodev_lock);
 108
 109struct video_device* video_devdata(struct file *file)
 110{
 111        return video_device[iminor(file->f_path.dentry->d_inode)];
 112}
 113
 114/*
 115 *      Open a video device - FIXME: Obsoleted
 116 */
 117static int video_open(struct inode *inode, struct file *file)
 118{
 119        unsigned int minor = iminor(inode);
 120        int err = 0;
 121        struct video_device *vfl;
 122        const struct file_operations *old_fops;
 123
 124        if(minor>=VIDEO_NUM_DEVICES)
 125                return -ENODEV;
 126        mutex_lock(&videodev_lock);
 127        vfl=video_device[minor];
 128        if(vfl==NULL) {
 129                mutex_unlock(&videodev_lock);
 130                request_module("char-major-%d-%d", VIDEO_MAJOR, minor);
 131                mutex_lock(&videodev_lock);
 132                vfl=video_device[minor];
 133                if (vfl==NULL) {
 134                        mutex_unlock(&videodev_lock);
 135                        return -ENODEV;
 136                }
 137        }
 138        old_fops = file->f_op;
 139        file->f_op = fops_get(vfl->fops);
 140        if(file->f_op->open)
 141                err = file->f_op->open(inode,file);
 142        if (err) {
 143                fops_put(file->f_op);
 144                file->f_op = fops_get(old_fops);
 145        }
 146        fops_put(old_fops);
 147        mutex_unlock(&videodev_lock);
 148        return err;
 149}
 150
 151/*
 152 * helper function -- handles userspace copying for ioctl arguments
 153 */
 154
 155#ifdef __OLD_VIDIOC_
 156static unsigned int
 157video_fix_command(unsigned int cmd)
 158{
 159        switch (cmd) {
 160        case VIDIOC_OVERLAY_OLD:
 161                cmd = VIDIOC_OVERLAY;
 162                break;
 163        case VIDIOC_S_PARM_OLD:
 164                cmd = VIDIOC_S_PARM;
 165                break;
 166        case VIDIOC_S_CTRL_OLD:
 167                cmd = VIDIOC_S_CTRL;
 168                break;
 169        case VIDIOC_G_AUDIO_OLD:
 170                cmd = VIDIOC_G_AUDIO;
 171                break;
 172        case VIDIOC_G_AUDOUT_OLD:
 173                cmd = VIDIOC_G_AUDOUT;
 174                break;
 175        case VIDIOC_CROPCAP_OLD:
 176                cmd = VIDIOC_CROPCAP;
 177                break;
 178        }
 179        return cmd;
 180}
 181#endif
 182
 183/*
 184 * Obsolete usercopy function - Should be removed soon
 185 */
 186int
 187video_usercopy(struct inode *inode, struct file *file,
 188               unsigned int cmd, unsigned long arg,
 189               int (*func)(struct inode *inode, struct file *file,
 190                           unsigned int cmd, void *arg))
 191{
 192        char    sbuf[128];
 193        void    *mbuf = NULL;
 194        void    *parg = NULL;
 195        int     err  = -EINVAL;
 196        int     is_ext_ctrl;
 197        size_t  ctrls_size = 0;
 198        void __user *user_ptr = NULL;
 199
 200#ifdef __OLD_VIDIOC_
 201        cmd = video_fix_command(cmd);
 202#endif
 203        is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
 204                       cmd == VIDIOC_TRY_EXT_CTRLS);
 205
 206        /*  Copy arguments into temp kernel buffer  */
 207        switch (_IOC_DIR(cmd)) {
 208        case _IOC_NONE:
 209                parg = NULL;
 210                break;
 211        case _IOC_READ:
 212        case _IOC_WRITE:
 213        case (_IOC_WRITE | _IOC_READ):
 214                if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
 215                        parg = sbuf;
 216                } else {
 217                        /* too big to allocate from stack */
 218                        mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
 219                        if (NULL == mbuf)
 220                                return -ENOMEM;
 221                        parg = mbuf;
 222                }
 223
 224                err = -EFAULT;
 225                if (_IOC_DIR(cmd) & _IOC_WRITE)
 226                        if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
 227                                goto out;
 228                break;
 229        }
 230        if (is_ext_ctrl) {
 231                struct v4l2_ext_controls *p = parg;
 232
 233                /* In case of an error, tell the caller that it wasn't
 234                   a specific control that caused it. */
 235                p->error_idx = p->count;
 236                user_ptr = (void __user *)p->controls;
 237                if (p->count) {
 238                        ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
 239                        /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
 240                        mbuf = kmalloc(ctrls_size, GFP_KERNEL);
 241                        err = -ENOMEM;
 242                        if (NULL == mbuf)
 243                                goto out_ext_ctrl;
 244                        err = -EFAULT;
 245                        if (copy_from_user(mbuf, user_ptr, ctrls_size))
 246                                goto out_ext_ctrl;
 247                        p->controls = mbuf;
 248                }
 249        }
 250
 251        /* call driver */
 252        err = func(inode, file, cmd, parg);
 253        if (err == -ENOIOCTLCMD)
 254                err = -EINVAL;
 255        if (is_ext_ctrl) {
 256                struct v4l2_ext_controls *p = parg;
 257
 258                p->controls = (void *)user_ptr;
 259                if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
 260                        err = -EFAULT;
 261                goto out_ext_ctrl;
 262        }
 263        if (err < 0)
 264                goto out;
 265
 266out_ext_ctrl:
 267        /*  Copy results into user buffer  */
 268        switch (_IOC_DIR(cmd))
 269        {
 270        case _IOC_READ:
 271        case (_IOC_WRITE | _IOC_READ):
 272                if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
 273                        err = -EFAULT;
 274                break;
 275        }
 276
 277out:
 278        kfree(mbuf);
 279        return err;
 280}
 281
 282/*
 283 * open/release helper functions -- handle exclusive opens
 284 * Should be removed soon
 285 */
 286int video_exclusive_open(struct inode *inode, struct file *file)
 287{
 288        struct  video_device *vfl = video_devdata(file);
 289        int retval = 0;
 290
 291        mutex_lock(&vfl->lock);
 292        if (vfl->users) {
 293                retval = -EBUSY;
 294        } else {
 295                vfl->users++;
 296        }
 297        mutex_unlock(&vfl->lock);
 298        return retval;
 299}
 300
 301int video_exclusive_release(struct inode *inode, struct file *file)
 302{
 303        struct  video_device *vfl = video_devdata(file);
 304
 305        vfl->users--;
 306        return 0;
 307}
 308
 309static char *v4l2_memory_names[] = {
 310        [V4L2_MEMORY_MMAP]    = "mmap",
 311        [V4L2_MEMORY_USERPTR] = "userptr",
 312        [V4L2_MEMORY_OVERLAY] = "overlay",
 313};
 314
 315
 316/* FIXME: Those stuff are replicated also on v4l2-common.c */
 317static char *v4l2_type_names_FIXME[] = {
 318        [V4L2_BUF_TYPE_VIDEO_CAPTURE]      = "video-cap",
 319        [V4L2_BUF_TYPE_VIDEO_OVERLAY]      = "video-over",
 320        [V4L2_BUF_TYPE_VIDEO_OUTPUT]       = "video-out",
 321        [V4L2_BUF_TYPE_VBI_CAPTURE]        = "vbi-cap",
 322        [V4L2_BUF_TYPE_VBI_OUTPUT]         = "vbi-out",
 323        [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT]  = "sliced-vbi-out",
 324        [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-capture",
 325        [V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "video-out-over",
 326        [V4L2_BUF_TYPE_PRIVATE]            = "private",
 327};
 328
 329static char *v4l2_field_names_FIXME[] = {
 330        [V4L2_FIELD_ANY]        = "any",
 331        [V4L2_FIELD_NONE]       = "none",
 332        [V4L2_FIELD_TOP]        = "top",
 333        [V4L2_FIELD_BOTTOM]     = "bottom",
 334        [V4L2_FIELD_INTERLACED] = "interlaced",
 335        [V4L2_FIELD_SEQ_TB]     = "seq-tb",
 336        [V4L2_FIELD_SEQ_BT]     = "seq-bt",
 337        [V4L2_FIELD_ALTERNATE]  = "alternate",
 338        [V4L2_FIELD_INTERLACED_TB] = "interlaced-tb",
 339        [V4L2_FIELD_INTERLACED_BT] = "interlaced-bt",
 340};
 341
 342#define prt_names(a,arr) (((a)>=0)&&((a)<ARRAY_SIZE(arr)))?arr[a]:"unknown"
 343
 344static void dbgbuf(unsigned int cmd, struct video_device *vfd,
 345                                        struct v4l2_buffer *p)
 346{
 347        struct v4l2_timecode *tc=&p->timecode;
 348
 349        dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
 350                "bytesused=%d, flags=0x%08d, "
 351                "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n",
 352                        (p->timestamp.tv_sec/3600),
 353                        (int)(p->timestamp.tv_sec/60)%60,
 354                        (int)(p->timestamp.tv_sec%60),
 355                        p->timestamp.tv_usec,
 356                        p->index,
 357                        prt_names(p->type,v4l2_type_names_FIXME),
 358                        p->bytesused,p->flags,
 359                        p->field,p->sequence,
 360                        prt_names(p->memory,v4l2_memory_names),
 361                        p->m.userptr, p->length);
 362        dbgarg2 ("timecode= %02d:%02d:%02d type=%d, "
 363                "flags=0x%08d, frames=%d, userbits=0x%08x\n",
 364                        tc->hours,tc->minutes,tc->seconds,
 365                        tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits);
 366}
 367
 368static inline void dbgrect(struct video_device *vfd, char *s,
 369                                                        struct v4l2_rect *r)
 370{
 371        dbgarg2 ("%sRect start at %dx%d, size= %dx%d\n", s, r->left, r->top,
 372                                                r->width, r->height);
 373};
 374
 375static inline void v4l_print_pix_fmt (struct video_device *vfd,
 376                                                struct v4l2_pix_format *fmt)
 377{
 378        dbgarg2 ("width=%d, height=%d, format=%c%c%c%c, field=%s, "
 379                "bytesperline=%d sizeimage=%d, colorspace=%d\n",
 380                fmt->width,fmt->height,
 381                (fmt->pixelformat & 0xff),
 382                (fmt->pixelformat >>  8) & 0xff,
 383                (fmt->pixelformat >> 16) & 0xff,
 384                (fmt->pixelformat >> 24) & 0xff,
 385                prt_names(fmt->field,v4l2_field_names_FIXME),
 386                fmt->bytesperline,fmt->sizeimage,fmt->colorspace);
 387};
 388
 389
 390static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type)
 391{
 392        switch (type) {
 393        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 394                if (vfd->vidioc_try_fmt_cap)
 395                        return (0);
 396                break;
 397        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 398                if (vfd->vidioc_try_fmt_overlay)
 399                        return (0);
 400                break;
 401        case V4L2_BUF_TYPE_VBI_CAPTURE:
 402                if (vfd->vidioc_try_fmt_vbi)
 403                        return (0);
 404                break;
 405        case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
 406                if (vfd->vidioc_try_fmt_vbi_output)
 407                        return (0);
 408                break;
 409        case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 410                if (vfd->vidioc_try_fmt_vbi_capture)
 411                        return (0);
 412                break;
 413        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 414                if (vfd->vidioc_try_fmt_video_output)
 415                        return (0);
 416                break;
 417        case V4L2_BUF_TYPE_VBI_OUTPUT:
 418                if (vfd->vidioc_try_fmt_vbi_output)
 419                        return (0);
 420                break;
 421        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
 422                if (vfd->vidioc_try_fmt_output_overlay)
 423                        return (0);
 424                break;
 425        case V4L2_BUF_TYPE_PRIVATE:
 426                if (vfd->vidioc_try_fmt_type_private)
 427                        return (0);
 428                break;
 429        }
 430        return (-EINVAL);
 431}
 432
 433static int __video_do_ioctl(struct inode *inode, struct file *file,
 434                unsigned int cmd, void *arg)
 435{
 436        struct video_device *vfd = video_devdata(file);
 437        void                 *fh = file->private_data;
 438        int                  ret = -EINVAL;
 439
 440        if ( (vfd->debug & V4L2_DEBUG_IOCTL) &&
 441                                !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
 442                v4l_print_ioctl(vfd->name, cmd);
 443        }
 444
 445#ifdef CONFIG_VIDEO_V4L1_COMPAT
 446        /***********************************************************
 447         Handles calls to the obsoleted V4L1 API
 448         Due to the nature of VIDIOCGMBUF, each driver that supports
 449         V4L1 should implement its own handler for this ioctl.
 450         ***********************************************************/
 451
 452        /* --- streaming capture ------------------------------------- */
 453        if (cmd == VIDIOCGMBUF) {
 454                struct video_mbuf *p=arg;
 455
 456                memset(p, 0, sizeof(*p));
 457
 458                if (!vfd->vidiocgmbuf)
 459                        return ret;
 460                ret=vfd->vidiocgmbuf(file, fh, p);
 461                if (!ret)
 462                        dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n",
 463                                                p->size, p->frames,
 464                                                (unsigned long)p->offsets);
 465                return ret;
 466        }
 467
 468        /********************************************************
 469         All other V4L1 calls are handled by v4l1_compat module.
 470         Those calls will be translated into V4L2 calls, and
 471         __video_do_ioctl will be called again, with one or more
 472         V4L2 ioctls.
 473         ********************************************************/
 474        if (_IOC_TYPE(cmd)=='v')
 475                return v4l_compat_translate_ioctl(inode,file,cmd,arg,
 476                                                __video_do_ioctl);
 477#endif
 478
 479        switch(cmd) {
 480        /* --- capabilities ------------------------------------------ */
 481        case VIDIOC_QUERYCAP:
 482        {
 483                struct v4l2_capability *cap = (struct v4l2_capability*)arg;
 484                memset(cap, 0, sizeof(*cap));
 485
 486                if (!vfd->vidioc_querycap)
 487                        break;
 488
 489                ret=vfd->vidioc_querycap(file, fh, cap);
 490                if (!ret)
 491                        dbgarg (cmd, "driver=%s, card=%s, bus=%s, "
 492                                        "version=0x%08x, "
 493                                        "capabilities=0x%08x\n",
 494                                        cap->driver,cap->card,cap->bus_info,
 495                                        cap->version,
 496                                        cap->capabilities);
 497                break;
 498        }
 499
 500        /* --- priority ------------------------------------------ */
 501        case VIDIOC_G_PRIORITY:
 502        {
 503                enum v4l2_priority *p=arg;
 504
 505                if (!vfd->vidioc_g_priority)
 506                        break;
 507                ret=vfd->vidioc_g_priority(file, fh, p);
 508                if (!ret)
 509                        dbgarg(cmd, "priority is %d\n", *p);
 510                break;
 511        }
 512        case VIDIOC_S_PRIORITY:
 513        {
 514                enum v4l2_priority *p=arg;
 515
 516                if (!vfd->vidioc_s_priority)
 517                        break;
 518                dbgarg(cmd, "setting priority to %d\n", *p);
 519                ret=vfd->vidioc_s_priority(file, fh, *p);
 520                break;
 521        }
 522
 523        /* --- capture ioctls ---------------------------------------- */
 524        case VIDIOC_ENUM_FMT:
 525        {
 526                struct v4l2_fmtdesc *f = arg;
 527                enum v4l2_buf_type type;
 528                unsigned int index;
 529
 530                index = f->index;
 531                type  = f->type;
 532                memset(f,0,sizeof(*f));
 533                f->index = index;
 534                f->type  = type;
 535
 536                switch (type) {
 537                case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 538                        if (vfd->vidioc_enum_fmt_cap)
 539                                ret=vfd->vidioc_enum_fmt_cap(file, fh, f);
 540                        break;
 541                case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 542                        if (vfd->vidioc_enum_fmt_overlay)
 543                                ret=vfd->vidioc_enum_fmt_overlay(file, fh, f);
 544                        break;
 545                case V4L2_BUF_TYPE_VBI_CAPTURE:
 546                        if (vfd->vidioc_enum_fmt_vbi)
 547                                ret=vfd->vidioc_enum_fmt_vbi(file, fh, f);
 548                        break;
 549                case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
 550                        if (vfd->vidioc_enum_fmt_vbi_output)
 551                                ret=vfd->vidioc_enum_fmt_vbi_output(file,
 552                                                                fh, f);
 553                        break;
 554                case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 555                        if (vfd->vidioc_enum_fmt_vbi_capture)
 556                                ret=vfd->vidioc_enum_fmt_vbi_capture(file,
 557                                                                fh, f);
 558                        break;
 559                case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 560                        if (vfd->vidioc_enum_fmt_video_output)
 561                                ret=vfd->vidioc_enum_fmt_video_output(file,
 562                                                                fh, f);
 563                        break;
 564                case V4L2_BUF_TYPE_VBI_OUTPUT:
 565                        if (vfd->vidioc_enum_fmt_vbi_output)
 566                                ret=vfd->vidioc_enum_fmt_vbi_output(file,
 567                                                                fh, f);
 568                        break;
 569                case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
 570                        if (vfd->vidioc_enum_fmt_output_overlay)
 571                                ret=vfd->vidioc_enum_fmt_output_overlay(file, fh, f);
 572                        break;
 573                case V4L2_BUF_TYPE_PRIVATE:
 574                        if (vfd->vidioc_enum_fmt_type_private)
 575                                ret=vfd->vidioc_enum_fmt_type_private(file,
 576                                                                fh, f);
 577                        break;
 578                }
 579                if (!ret)
 580                        dbgarg (cmd, "index=%d, type=%d, flags=%d, "
 581                                        "pixelformat=%c%c%c%c, description='%s'\n",
 582                                        f->index, f->type, f->flags,
 583                                        (f->pixelformat & 0xff),
 584                                        (f->pixelformat >>  8) & 0xff,
 585                                        (f->pixelformat >> 16) & 0xff,
 586                                        (f->pixelformat >> 24) & 0xff,
 587                                        f->description);
 588                break;
 589        }
 590        case VIDIOC_G_FMT:
 591        {
 592                struct v4l2_format *f = (struct v4l2_format *)arg;
 593                enum v4l2_buf_type type=f->type;
 594
 595                memset(&f->fmt.pix,0,sizeof(f->fmt.pix));
 596                f->type=type;
 597
 598                /* FIXME: Should be one dump per type */
 599                dbgarg (cmd, "type=%s\n", prt_names(type,
 600                                        v4l2_type_names_FIXME));
 601
 602                switch (type) {
 603                case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 604                        if (vfd->vidioc_g_fmt_cap)
 605                                ret=vfd->vidioc_g_fmt_cap(file, fh, f);
 606                        if (!ret)
 607                                v4l_print_pix_fmt(vfd,&f->fmt.pix);
 608                        break;
 609                case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 610                        if (vfd->vidioc_g_fmt_overlay)
 611                                ret=vfd->vidioc_g_fmt_overlay(file, fh, f);
 612                        break;
 613                case V4L2_BUF_TYPE_VBI_CAPTURE:
 614                        if (vfd->vidioc_g_fmt_vbi)
 615                                ret=vfd->vidioc_g_fmt_vbi(file, fh, f);
 616                        break;
 617                case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
 618                        if (vfd->vidioc_g_fmt_vbi_output)
 619                                ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f);
 620                        break;
 621                case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 622                        if (vfd->vidioc_g_fmt_vbi_capture)
 623                                ret=vfd->vidioc_g_fmt_vbi_capture(file, fh, f);
 624                        break;
 625                case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 626                        if (vfd->vidioc_g_fmt_video_output)
 627                                ret=vfd->vidioc_g_fmt_video_output(file,
 628                                                                fh, f);
 629                        break;
 630                case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
 631                        if (vfd->vidioc_g_fmt_output_overlay)
 632                                ret=vfd->vidioc_g_fmt_output_overlay(file, fh, f);
 633                        break;
 634                case V4L2_BUF_TYPE_VBI_OUTPUT:
 635                        if (vfd->vidioc_g_fmt_vbi_output)
 636                                ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f);
 637                        break;
 638                case V4L2_BUF_TYPE_PRIVATE:
 639                        if (vfd->vidioc_g_fmt_type_private)
 640                                ret=vfd->vidioc_g_fmt_type_private(file,
 641                                                                fh, f);
 642                        break;
 643                }
 644
 645                break;
 646        }
 647        case VIDIOC_S_FMT:
 648        {
 649                struct v4l2_format *f = (struct v4l2_format *)arg;
 650
 651                /* FIXME: Should be one dump per type */
 652                dbgarg (cmd, "type=%s\n", prt_names(f->type,
 653                                        v4l2_type_names_FIXME));
 654
 655                switch (f->type) {
 656                case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 657                        v4l_print_pix_fmt(vfd,&f->fmt.pix);
 658                        if (vfd->vidioc_s_fmt_cap)
 659                                ret=vfd->vidioc_s_fmt_cap(file, fh, f);
 660                        break;
 661                case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 662                        if (vfd->vidioc_s_fmt_overlay)
 663                                ret=vfd->vidioc_s_fmt_overlay(file, fh, f);
 664                        break;
 665                case V4L2_BUF_TYPE_VBI_CAPTURE:
 666                        if (vfd->vidioc_s_fmt_vbi)
 667                                ret=vfd->vidioc_s_fmt_vbi(file, fh, f);
 668                        break;
 669                case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
 670                        if (vfd->vidioc_s_fmt_vbi_output)
 671                                ret=vfd->vidioc_s_fmt_vbi_output(file, fh, f);
 672                        break;
 673                case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 674                        if (vfd->vidioc_s_fmt_vbi_capture)
 675                                ret=vfd->vidioc_s_fmt_vbi_capture(file, fh, f);
 676                        break;
 677                case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 678                        if (vfd->vidioc_s_fmt_video_output)
 679                                ret=vfd->vidioc_s_fmt_video_output(file,
 680                                                                fh, f);
 681                        break;
 682                case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
 683                        if (vfd->vidioc_s_fmt_output_overlay)
 684                                ret=vfd->vidioc_s_fmt_output_overlay(file, fh, f);
 685                        break;
 686                case V4L2_BUF_TYPE_VBI_OUTPUT:
 687                        if (vfd->vidioc_s_fmt_vbi_output)
 688                                ret=vfd->vidioc_s_fmt_vbi_output(file,
 689                                                                fh, f);
 690                        break;
 691                case V4L2_BUF_TYPE_PRIVATE:
 692                        if (vfd->vidioc_s_fmt_type_private)
 693                                ret=vfd->vidioc_s_fmt_type_private(file,
 694                                                                fh, f);
 695                        break;
 696                }
 697                break;
 698        }
 699        case VIDIOC_TRY_FMT:
 700        {
 701                struct v4l2_format *f = (struct v4l2_format *)arg;
 702
 703                /* FIXME: Should be one dump per type */
 704                dbgarg (cmd, "type=%s\n", prt_names(f->type,
 705                                                v4l2_type_names_FIXME));
 706                switch (f->type) {
 707                case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 708                        if (vfd->vidioc_try_fmt_cap)
 709                                ret=vfd->vidioc_try_fmt_cap(file, fh, f);
 710                        if (!ret)
 711                                v4l_print_pix_fmt(vfd,&f->fmt.pix);
 712                        break;
 713                case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 714                        if (vfd->vidioc_try_fmt_overlay)
 715                                ret=vfd->vidioc_try_fmt_overlay(file, fh, f);
 716                        break;
 717                case V4L2_BUF_TYPE_VBI_CAPTURE:
 718                        if (vfd->vidioc_try_fmt_vbi)
 719                                ret=vfd->vidioc_try_fmt_vbi(file, fh, f);
 720                        break;
 721                case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
 722                        if (vfd->vidioc_try_fmt_vbi_output)
 723                                ret=vfd->vidioc_try_fmt_vbi_output(file,
 724                                                                fh, f);
 725                        break;
 726                case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 727                        if (vfd->vidioc_try_fmt_vbi_capture)
 728                                ret=vfd->vidioc_try_fmt_vbi_capture(file,
 729                                                                fh, f);
 730                        break;
 731                case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 732                        if (vfd->vidioc_try_fmt_video_output)
 733                                ret=vfd->vidioc_try_fmt_video_output(file,
 734                                                                fh, f);
 735                        break;
 736                case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
 737                        if (vfd->vidioc_try_fmt_output_overlay)
 738                                ret=vfd->vidioc_try_fmt_output_overlay(file, fh, f);
 739                        break;
 740                case V4L2_BUF_TYPE_VBI_OUTPUT:
 741                        if (vfd->vidioc_try_fmt_vbi_output)
 742                                ret=vfd->vidioc_try_fmt_vbi_output(file,
 743                                                                fh, f);
 744                        break;
 745                case V4L2_BUF_TYPE_PRIVATE:
 746                        if (vfd->vidioc_try_fmt_type_private)
 747                                ret=vfd->vidioc_try_fmt_type_private(file,
 748                                                                fh, f);
 749                        break;
 750                }
 751
 752                break;
 753        }
 754        /* FIXME: Those buf reqs could be handled here,
 755           with some changes on videobuf to allow its header to be included at
 756           videodev2.h or being merged at videodev2.
 757         */
 758        case VIDIOC_REQBUFS:
 759        {
 760                struct v4l2_requestbuffers *p=arg;
 761
 762                if (!vfd->vidioc_reqbufs)
 763                        break;
 764                ret = check_fmt (vfd, p->type);
 765                if (ret)
 766                        break;
 767
 768                ret=vfd->vidioc_reqbufs(file, fh, p);
 769                dbgarg (cmd, "count=%d, type=%s, memory=%s\n",
 770                                p->count,
 771                                prt_names(p->type,v4l2_type_names_FIXME),
 772                                prt_names(p->memory,v4l2_memory_names));
 773                break;
 774        }
 775        case VIDIOC_QUERYBUF:
 776        {
 777                struct v4l2_buffer *p=arg;
 778
 779                if (!vfd->vidioc_querybuf)
 780                        break;
 781                ret = check_fmt (vfd, p->type);
 782                if (ret)
 783                        break;
 784
 785                ret=vfd->vidioc_querybuf(file, fh, p);
 786                if (!ret)
 787                        dbgbuf(cmd,vfd,p);
 788                break;
 789        }
 790        case VIDIOC_QBUF:
 791        {
 792                struct v4l2_buffer *p=arg;
 793
 794                if (!vfd->vidioc_qbuf)
 795                        break;
 796                ret = check_fmt (vfd, p->type);
 797                if (ret)
 798                        break;
 799
 800                ret=vfd->vidioc_qbuf(file, fh, p);
 801                if (!ret)
 802                        dbgbuf(cmd,vfd,p);
 803                break;
 804        }
 805        case VIDIOC_DQBUF:
 806        {
 807                struct v4l2_buffer *p=arg;
 808                if (!vfd->vidioc_dqbuf)
 809                        break;
 810                ret = check_fmt (vfd, p->type);
 811                if (ret)
 812                        break;
 813
 814                ret=vfd->vidioc_dqbuf(file, fh, p);
 815                if (!ret)
 816                        dbgbuf(cmd,vfd,p);
 817                break;
 818        }
 819        case VIDIOC_OVERLAY:
 820        {
 821                int *i = arg;
 822
 823                if (!vfd->vidioc_overlay)
 824                        break;
 825                dbgarg (cmd, "value=%d\n",*i);
 826                ret=vfd->vidioc_overlay(file, fh, *i);
 827                break;
 828        }
 829        case VIDIOC_G_FBUF:
 830        {
 831                struct v4l2_framebuffer *p=arg;
 832                if (!vfd->vidioc_g_fbuf)
 833                        break;
 834                ret=vfd->vidioc_g_fbuf(file, fh, arg);
 835                if (!ret) {
 836                        dbgarg (cmd, "capability=%d, flags=%d, base=0x%08lx\n",
 837                                        p->capability,p->flags,
 838                                        (unsigned long)p->base);
 839                        v4l_print_pix_fmt (vfd, &p->fmt);
 840                }
 841                break;
 842        }
 843        case VIDIOC_S_FBUF:
 844        {
 845                struct v4l2_framebuffer *p=arg;
 846                if (!vfd->vidioc_s_fbuf)
 847                        break;
 848
 849                dbgarg (cmd, "capability=%d, flags=%d, base=0x%08lx\n",
 850                                p->capability,p->flags,(unsigned long)p->base);
 851                v4l_print_pix_fmt (vfd, &p->fmt);
 852                ret=vfd->vidioc_s_fbuf(file, fh, arg);
 853
 854                break;
 855        }
 856        case VIDIOC_STREAMON:
 857        {
 858                enum v4l2_buf_type i = *(int *)arg;
 859                if (!vfd->vidioc_streamon)
 860                        break;
 861                dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME));
 862                ret=vfd->vidioc_streamon(file, fh,i);
 863                break;
 864        }
 865        case VIDIOC_STREAMOFF:
 866        {
 867                enum v4l2_buf_type i = *(int *)arg;
 868
 869                if (!vfd->vidioc_streamoff)
 870                        break;
 871                dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME));
 872                ret=vfd->vidioc_streamoff(file, fh, i);
 873                break;
 874        }
 875        /* ---------- tv norms ---------- */
 876        case VIDIOC_ENUMSTD:
 877        {
 878                struct v4l2_standard *p = arg;
 879                v4l2_std_id id = vfd->tvnorms,curr_id=0;
 880                unsigned int index = p->index,i;
 881
 882                if (index<0) {
 883                        ret=-EINVAL;
 884                        break;
 885                }
 886
 887                /* Return norm array on a canonical way */
 888                for (i=0;i<= index && id; i++) {
 889                        if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) {
 890                                curr_id = V4L2_STD_PAL;
 891                        } else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) {
 892                                curr_id = V4L2_STD_PAL_BG;
 893                        } else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) {
 894                                curr_id = V4L2_STD_PAL_DK;
 895                        } else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) {
 896                                curr_id = V4L2_STD_PAL_B;
 897                        } else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) {
 898                                curr_id = V4L2_STD_PAL_B1;
 899                        } else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) {
 900                                curr_id = V4L2_STD_PAL_G;
 901                        } else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) {
 902                                curr_id = V4L2_STD_PAL_H;
 903                        } else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) {
 904                                curr_id = V4L2_STD_PAL_I;
 905                        } else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) {
 906                                curr_id = V4L2_STD_PAL_D;
 907                        } else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) {
 908                                curr_id = V4L2_STD_PAL_D1;
 909                        } else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) {
 910                                curr_id = V4L2_STD_PAL_K;
 911                        } else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) {
 912                                curr_id = V4L2_STD_PAL_M;
 913                        } else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) {
 914                                curr_id = V4L2_STD_PAL_N;
 915                        } else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) {
 916                                curr_id = V4L2_STD_PAL_Nc;
 917                        } else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) {
 918                                curr_id = V4L2_STD_PAL_60;
 919                        } else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
 920                                curr_id = V4L2_STD_NTSC;
 921                        } else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) {
 922                                curr_id = V4L2_STD_NTSC_M;
 923                        } else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) {
 924                                curr_id = V4L2_STD_NTSC_M_JP;
 925                        } else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) {
 926                                curr_id = V4L2_STD_NTSC_443;
 927                        } else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) {
 928                                curr_id = V4L2_STD_NTSC_M_KR;
 929                        } else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
 930                                curr_id = V4L2_STD_SECAM;
 931                        } else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) {
 932                                curr_id = V4L2_STD_SECAM_DK;
 933                        } else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) {
 934                                curr_id = V4L2_STD_SECAM_B;
 935                        } else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) {
 936                                curr_id = V4L2_STD_SECAM_D;
 937                        } else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) {
 938                                curr_id = V4L2_STD_SECAM_G;
 939                        } else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) {
 940                                curr_id = V4L2_STD_SECAM_H;
 941                        } else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) {
 942                                curr_id = V4L2_STD_SECAM_K;
 943                        } else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) {
 944                                curr_id = V4L2_STD_SECAM_K1;
 945                        } else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) {
 946                                curr_id = V4L2_STD_SECAM_L;
 947                        } else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) {
 948                                curr_id = V4L2_STD_SECAM_LC;
 949                        } else {
 950                                break;
 951                        }
 952                        id &= ~curr_id;
 953                }
 954                if (i<=index)
 955                        return -EINVAL;
 956
 957                v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id));
 958                p->index = index;
 959
 960                dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, "
 961                                "framelines=%d\n", p->index,
 962                                (unsigned long long)p->id, p->name,
 963                                p->frameperiod.numerator,
 964                                p->frameperiod.denominator,
 965                                p->framelines);
 966
 967                ret=0;
 968                break;
 969        }
 970        case VIDIOC_G_STD:
 971        {
 972                v4l2_std_id *id = arg;
 973
 974                *id = vfd->current_norm;
 975
 976                dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id);
 977
 978                ret=0;
 979                break;
 980        }
 981        case VIDIOC_S_STD:
 982        {
 983                v4l2_std_id *id = arg,norm;
 984
 985                dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id);
 986
 987                norm = (*id) & vfd->tvnorms;
 988                if ( vfd->tvnorms && !norm)     /* Check if std is supported */
 989                        break;
 990
 991                /* Calls the specific handler */
 992                if (vfd->vidioc_s_std)
 993                        ret=vfd->vidioc_s_std(file, fh, &norm);
 994                else
 995                        ret=-EINVAL;
 996
 997                /* Updates standard information */
 998                if (ret>=0)
 999                        vfd->current_norm=norm;
1000
1001                break;
1002        }
1003        case VIDIOC_QUERYSTD:
1004        {
1005                v4l2_std_id *p=arg;
1006
1007                if (!vfd->vidioc_querystd)
1008                        break;
1009                ret=vfd->vidioc_querystd(file, fh, arg);
1010                if (!ret)
1011                        dbgarg (cmd, "detected std=%Lu\n",
1012                                                (unsigned long long)*p);
1013                break;
1014        }
1015        /* ------ input switching ---------- */
1016        /* FIXME: Inputs can be handled inside videodev2 */
1017        case VIDIOC_ENUMINPUT:
1018        {
1019                struct v4l2_input *p=arg;
1020                int i=p->index;
1021
1022                if (!vfd->vidioc_enum_input)
1023                        break;
1024                memset(p, 0, sizeof(*p));
1025                p->index=i;
1026
1027                ret=vfd->vidioc_enum_input(file, fh, p);
1028                if (!ret)
1029                        dbgarg (cmd, "index=%d, name=%s, type=%d, "
1030                                        "audioset=%d, "
1031                                        "tuner=%d, std=%Ld, status=%d\n",
1032                                        p->index,p->name,p->type,p->audioset,
1033                                        p->tuner,
1034                                        (unsigned long long)p->std,
1035                                        p->status);
1036                break;
1037        }
1038        case VIDIOC_G_INPUT:
1039        {
1040                unsigned int *i = arg;
1041
1042                if (!vfd->vidioc_g_input)
1043                        break;
1044                ret=vfd->vidioc_g_input(file, fh, i);
1045                if (!ret)
1046                        dbgarg (cmd, "value=%d\n",*i);
1047                break;
1048        }
1049        case VIDIOC_S_INPUT:
1050        {
1051                unsigned int *i = arg;
1052
1053                if (!vfd->vidioc_s_input)
1054                        break;
1055                dbgarg (cmd, "value=%d\n",*i);
1056                ret=vfd->vidioc_s_input(file, fh, *i);
1057                break;
1058        }
1059
1060        /* ------ output switching ---------- */
1061        case VIDIOC_G_OUTPUT:
1062        {
1063                unsigned int *i = arg;
1064
1065                if (!vfd->vidioc_g_output)
1066                        break;
1067                ret=vfd->vidioc_g_output(file, fh, i);
1068                if (!ret)
1069                        dbgarg (cmd, "value=%d\n",*i);
1070                break;
1071        }
1072        case VIDIOC_S_OUTPUT:
1073        {
1074                unsigned int *i = arg;
1075
1076                if (!vfd->vidioc_s_output)
1077                        break;
1078                dbgarg (cmd, "value=%d\n",*i);
1079                ret=vfd->vidioc_s_output(file, fh, *i);
1080                break;
1081        }
1082
1083        /* --- controls ---------------------------------------------- */
1084        case VIDIOC_QUERYCTRL:
1085        {
1086                struct v4l2_queryctrl *p=arg;
1087
1088                if (!vfd->vidioc_queryctrl)
1089                        break;
1090                ret=vfd->vidioc_queryctrl(file, fh, p);
1091
1092                if (!ret)
1093                        dbgarg (cmd, "id=%d, type=%d, name=%s, "
1094                                        "min/max=%d/%d,"
1095                                        " step=%d, default=%d, flags=0x%08x\n",
1096                                        p->id,p->type,p->name,p->minimum,
1097                                        p->maximum,p->step,p->default_value,
1098                                        p->flags);
1099                break;
1100        }
1101        case VIDIOC_G_CTRL:
1102        {
1103                struct v4l2_control *p = arg;
1104
1105                if (!vfd->vidioc_g_ctrl)
1106                        break;
1107                dbgarg(cmd, "Enum for index=%d\n", p->id);
1108
1109                ret=vfd->vidioc_g_ctrl(file, fh, p);
1110                if (!ret)
1111                        dbgarg2 ( "id=%d, value=%d\n", p->id, p->value);
1112                break;
1113        }
1114        case VIDIOC_S_CTRL:
1115        {
1116                struct v4l2_control *p = arg;
1117
1118                if (!vfd->vidioc_s_ctrl)
1119                        break;
1120                dbgarg (cmd, "id=%d, value=%d\n", p->id, p->value);
1121
1122                ret=vfd->vidioc_s_ctrl(file, fh, p);
1123                break;
1124        }
1125        case VIDIOC_G_EXT_CTRLS:
1126        {
1127                struct v4l2_ext_controls *p = arg;
1128
1129                if (vfd->vidioc_g_ext_ctrls) {
1130                        dbgarg(cmd, "count=%d\n", p->count);
1131
1132                        ret=vfd->vidioc_g_ext_ctrls(file, fh, p);
1133                }
1134                break;
1135        }
1136        case VIDIOC_S_EXT_CTRLS:
1137        {
1138                struct v4l2_ext_controls *p = arg;
1139
1140                if (vfd->vidioc_s_ext_ctrls) {
1141                        dbgarg(cmd, "count=%d\n", p->count);
1142
1143                        ret=vfd->vidioc_s_ext_ctrls(file, fh, p);
1144                }
1145                break;
1146        }
1147        case VIDIOC_TRY_EXT_CTRLS:
1148        {
1149                struct v4l2_ext_controls *p = arg;
1150
1151                if (vfd->vidioc_try_ext_ctrls) {
1152                        dbgarg(cmd, "count=%d\n", p->count);
1153
1154                        ret=vfd->vidioc_try_ext_ctrls(file, fh, p);
1155                }
1156                break;
1157        }
1158        case VIDIOC_QUERYMENU:
1159        {
1160                struct v4l2_querymenu *p=arg;
1161                if (!vfd->vidioc_querymenu)
1162                        break;
1163                ret=vfd->vidioc_querymenu(file, fh, p);
1164                if (!ret)
1165                        dbgarg (cmd, "id=%d, index=%d, name=%s\n",
1166                                                p->id,p->index,p->name);
1167                break;
1168        }
1169        /* --- audio ---------------------------------------------- */
1170        case VIDIOC_ENUMAUDIO:
1171        {
1172                struct v4l2_audio *p=arg;
1173
1174                if (!vfd->vidioc_enumaudio)
1175                        break;
1176                dbgarg(cmd, "Enum for index=%d\n", p->index);
1177                ret=vfd->vidioc_enumaudio(file, fh, p);
1178                if (!ret)
1179                        dbgarg2("index=%d, name=%s, capability=%d, "
1180                                        "mode=%d\n",p->index,p->name,
1181                                        p->capability, p->mode);
1182                break;
1183        }
1184        case VIDIOC_G_AUDIO:
1185        {
1186                struct v4l2_audio *p=arg;
1187                __u32 index=p->index;
1188
1189                if (!vfd->vidioc_g_audio)
1190                        break;
1191
1192                memset(p,0,sizeof(*p));
1193                p->index=index;
1194                dbgarg(cmd, "Get for index=%d\n", p->index);
1195                ret=vfd->vidioc_g_audio(file, fh, p);
1196                if (!ret)
1197                        dbgarg2("index=%d, name=%s, capability=%d, "
1198                                        "mode=%d\n",p->index,
1199                                        p->name,p->capability, p->mode);
1200                break;
1201        }
1202        case VIDIOC_S_AUDIO:
1203        {
1204                struct v4l2_audio *p=arg;
1205
1206                if (!vfd->vidioc_s_audio)
1207                        break;
1208                dbgarg(cmd, "index=%d, name=%s, capability=%d, "
1209                                        "mode=%d\n", p->index, p->name,
1210                                        p->capability, p->mode);
1211                ret=vfd->vidioc_s_audio(file, fh, p);
1212                break;
1213        }
1214        case VIDIOC_ENUMAUDOUT:
1215        {
1216                struct v4l2_audioout *p=arg;
1217
1218                if (!vfd->vidioc_enumaudout)
1219                        break;
1220                dbgarg(cmd, "Enum for index=%d\n", p->index);
1221                ret=vfd->vidioc_enumaudout(file, fh, p);
1222                if (!ret)
1223                        dbgarg2("index=%d, name=%s, capability=%d, "
1224                                        "mode=%d\n", p->index, p->name,
1225                                        p->capability,p->mode);
1226                break;
1227        }
1228        case VIDIOC_G_AUDOUT:
1229        {
1230                struct v4l2_audioout *p=arg;
1231
1232                if (!vfd->vidioc_g_audout)
1233                        break;
1234                dbgarg(cmd, "Enum for index=%d\n", p->index);
1235                ret=vfd->vidioc_g_audout(file, fh, p);
1236                if (!ret)
1237                        dbgarg2("index=%d, name=%s, capability=%d, "
1238                                        "mode=%d\n", p->index, p->name,
1239                                        p->capability,p->mode);
1240                break;
1241        }
1242        case VIDIOC_S_AUDOUT:
1243        {
1244                struct v4l2_audioout *p=arg;
1245
1246                if (!vfd->vidioc_s_audout)
1247                        break;
1248                dbgarg(cmd, "index=%d, name=%s, capability=%d, "
1249                                        "mode=%d\n", p->index, p->name,
1250                                        p->capability,p->mode);
1251
1252                ret=vfd->vidioc_s_audout(file, fh, p);
1253                break;
1254        }
1255        case VIDIOC_G_MODULATOR:
1256        {
1257                struct v4l2_modulator *p=arg;
1258                if (!vfd->vidioc_g_modulator)
1259                        break;
1260                ret=vfd->vidioc_g_modulator(file, fh, p);
1261                if (!ret)
1262                        dbgarg(cmd, "index=%d, name=%s, "
1263                                        "capability=%d, rangelow=%d,"
1264                                        " rangehigh=%d, txsubchans=%d\n",
1265                                        p->index, p->name,p->capability,
1266                                        p->rangelow, p->rangehigh,
1267                                        p->txsubchans);
1268                break;
1269        }
1270        case VIDIOC_S_MODULATOR:
1271        {
1272                struct v4l2_modulator *p=arg;
1273                if (!vfd->vidioc_s_modulator)
1274                        break;
1275                dbgarg(cmd, "index=%d, name=%s, capability=%d, "
1276                                "rangelow=%d, rangehigh=%d, txsubchans=%d\n",
1277                                p->index, p->name,p->capability,p->rangelow,
1278                                p->rangehigh,p->txsubchans);
1279                        ret=vfd->vidioc_s_modulator(file, fh, p);
1280                break;
1281        }
1282        case VIDIOC_G_CROP:
1283        {
1284                struct v4l2_crop *p=arg;
1285                if (!vfd->vidioc_g_crop)
1286                        break;
1287                ret=vfd->vidioc_g_crop(file, fh, p);
1288                if (!ret) {
1289                        dbgarg(cmd, "type=%d\n", p->type);
1290                        dbgrect(vfd, "", &p->c);
1291                }
1292                break;
1293        }
1294        case VIDIOC_S_CROP:
1295        {
1296                struct v4l2_crop *p=arg;
1297                if (!vfd->vidioc_s_crop)
1298                        break;
1299                dbgarg(cmd, "type=%d\n", p->type);
1300                dbgrect(vfd, "", &p->c);
1301                ret=vfd->vidioc_s_crop(file, fh, p);
1302                break;
1303        }
1304        case VIDIOC_CROPCAP:
1305        {
1306                struct v4l2_cropcap *p=arg;
1307                /*FIXME: Should also show v4l2_fract pixelaspect */
1308                if (!vfd->vidioc_cropcap)
1309                        break;
1310                dbgarg(cmd, "type=%d\n", p->type);
1311                dbgrect(vfd, "bounds ", &p->bounds);
1312                dbgrect(vfd, "defrect ", &p->defrect);
1313                ret=vfd->vidioc_cropcap(file, fh, p);
1314                break;
1315        }
1316        case VIDIOC_G_JPEGCOMP:
1317        {
1318                struct v4l2_jpegcompression *p=arg;
1319                if (!vfd->vidioc_g_jpegcomp)
1320                        break;
1321                ret=vfd->vidioc_g_jpegcomp(file, fh, p);
1322                if (!ret)
1323                        dbgarg (cmd, "quality=%d, APPn=%d, "
1324                                                "APP_len=%d, COM_len=%d, "
1325                                                "jpeg_markers=%d\n",
1326                                                p->quality,p->APPn,p->APP_len,
1327                                                p->COM_len,p->jpeg_markers);
1328                break;
1329        }
1330        case VIDIOC_S_JPEGCOMP:
1331        {
1332                struct v4l2_jpegcompression *p=arg;
1333                if (!vfd->vidioc_g_jpegcomp)
1334                        break;
1335                dbgarg (cmd, "quality=%d, APPn=%d, APP_len=%d, "
1336                                        "COM_len=%d, jpeg_markers=%d\n",
1337                                        p->quality,p->APPn,p->APP_len,
1338                                        p->COM_len,p->jpeg_markers);
1339                        ret=vfd->vidioc_s_jpegcomp(file, fh, p);
1340                break;
1341        }
1342        case VIDIOC_G_ENC_INDEX:
1343        {
1344                struct v4l2_enc_idx *p=arg;
1345
1346                if (!vfd->vidioc_g_enc_index)
1347                        break;
1348                ret=vfd->vidioc_g_enc_index(file, fh, p);
1349                if (!ret)
1350                        dbgarg (cmd, "entries=%d, entries_cap=%d\n",
1351                                        p->entries,p->entries_cap);
1352                break;
1353        }
1354        case VIDIOC_ENCODER_CMD:
1355        {
1356                struct v4l2_encoder_cmd *p=arg;
1357
1358                if (!vfd->vidioc_encoder_cmd)
1359                        break;
1360                ret=vfd->vidioc_encoder_cmd(file, fh, p);
1361                if (!ret)
1362                        dbgarg (cmd, "cmd=%d, flags=%d\n",
1363                                        p->cmd,p->flags);
1364                break;
1365        }
1366        case VIDIOC_TRY_ENCODER_CMD:
1367        {
1368                struct v4l2_encoder_cmd *p=arg;
1369
1370                if (!vfd->vidioc_try_encoder_cmd)
1371                        break;
1372                ret=vfd->vidioc_try_encoder_cmd(file, fh, p);
1373                if (!ret)
1374                        dbgarg (cmd, "cmd=%d, flags=%d\n",
1375                                        p->cmd,p->flags);
1376                break;
1377        }
1378        case VIDIOC_G_PARM:
1379        {
1380                struct v4l2_streamparm *p=arg;
1381                __u32 type=p->type;
1382
1383                memset(p,0,sizeof(*p));
1384                p->type=type;
1385
1386                if (vfd->vidioc_g_parm) {
1387                        ret=vfd->vidioc_g_parm(file, fh, p);
1388                } else {
1389                        struct v4l2_standard s;
1390
1391                        if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1392                                return -EINVAL;
1393
1394                        v4l2_video_std_construct(&s, vfd->current_norm,
1395                                                 v4l2_norm_to_name(vfd->current_norm));
1396
1397                        p->parm.capture.timeperframe = s.frameperiod;
1398                        ret=0;
1399                }
1400
1401                dbgarg (cmd, "type=%d\n", p->type);
1402                break;
1403        }
1404        case VIDIOC_S_PARM:
1405        {
1406                struct v4l2_streamparm *p=arg;
1407                if (!vfd->vidioc_s_parm)
1408                        break;
1409                dbgarg (cmd, "type=%d\n", p->type);
1410                ret=vfd->vidioc_s_parm(file, fh, p);
1411                break;
1412        }
1413        case VIDIOC_G_TUNER:
1414        {
1415                struct v4l2_tuner *p=arg;
1416                __u32 index=p->index;
1417
1418                if (!vfd->vidioc_g_tuner)
1419                        break;
1420
1421                memset(p,0,sizeof(*p));
1422                p->index=index;
1423
1424                ret=vfd->vidioc_g_tuner(file, fh, p);
1425                if (!ret)
1426                        dbgarg (cmd, "index=%d, name=%s, type=%d, "
1427                                        "capability=%d, rangelow=%d, "
1428                                        "rangehigh=%d, signal=%d, afc=%d, "
1429                                        "rxsubchans=%d, audmode=%d\n",
1430                                        p->index, p->name, p->type,
1431                                        p->capability, p->rangelow,
1432                                        p->rangehigh, p->rxsubchans,
1433                                        p->audmode, p->signal, p->afc);
1434                break;
1435        }
1436        case VIDIOC_S_TUNER:
1437        {
1438                struct v4l2_tuner *p=arg;
1439                if (!vfd->vidioc_s_tuner)
1440                        break;
1441                dbgarg (cmd, "index=%d, name=%s, type=%d, "
1442                                "capability=%d, rangelow=%d, rangehigh=%d, "
1443                                "signal=%d, afc=%d, rxsubchans=%d, "
1444                                "audmode=%d\n",p->index, p->name, p->type,
1445                                p->capability, p->rangelow,p->rangehigh,
1446                                p->rxsubchans, p->audmode, p->signal,
1447                                p->afc);
1448                ret=vfd->vidioc_s_tuner(file, fh, p);
1449                break;
1450        }
1451        case VIDIOC_G_FREQUENCY:
1452        {
1453                struct v4l2_frequency *p=arg;
1454                if (!vfd->vidioc_g_frequency)
1455                        break;
1456
1457                memset(p,0,sizeof(*p));
1458
1459                ret=vfd->vidioc_g_frequency(file, fh, p);
1460                if (!ret)
1461                        dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n",
1462                                                p->tuner,p->type,p->frequency);
1463                break;
1464        }
1465        case VIDIOC_S_FREQUENCY:
1466        {
1467                struct v4l2_frequency *p=arg;
1468                if (!vfd->vidioc_s_frequency)
1469                        break;
1470                dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n",
1471                                p->tuner,p->type,p->frequency);
1472                ret=vfd->vidioc_s_frequency(file, fh, p);
1473                break;
1474        }
1475        case VIDIOC_G_SLICED_VBI_CAP:
1476        {
1477                struct v4l2_sliced_vbi_cap *p=arg;
1478                if (!vfd->vidioc_g_sliced_vbi_cap)
1479                        break;
1480                ret=vfd->vidioc_g_sliced_vbi_cap(file, fh, p);
1481                if (!ret)
1482                        dbgarg (cmd, "service_set=%d\n", p->service_set);
1483                break;
1484        }
1485        case VIDIOC_LOG_STATUS:
1486        {
1487                if (!vfd->vidioc_log_status)
1488                        break;
1489                ret=vfd->vidioc_log_status(file, fh);
1490                break;
1491        }
1492#ifdef CONFIG_VIDEO_ADV_DEBUG
1493        case VIDIOC_DBG_G_REGISTER:
1494        {
1495                struct v4l2_register *p=arg;
1496                if (!capable(CAP_SYS_ADMIN))
1497                        ret=-EPERM;
1498                else if (vfd->vidioc_g_register)
1499                        ret=vfd->vidioc_g_register(file, fh, p);
1500                break;
1501        }
1502        case VIDIOC_DBG_S_REGISTER:
1503        {
1504                struct v4l2_register *p=arg;
1505                if (!capable(CAP_SYS_ADMIN))
1506                        ret=-EPERM;
1507                else if (vfd->vidioc_s_register)
1508                        ret=vfd->vidioc_s_register(file, fh, p);
1509                break;
1510        }
1511#endif
1512        case VIDIOC_G_CHIP_IDENT:
1513        {
1514                struct v4l2_chip_ident *p=arg;
1515                if (!vfd->vidioc_g_chip_ident)
1516                        break;
1517                ret=vfd->vidioc_g_chip_ident(file, fh, p);
1518                if (!ret)
1519                        dbgarg (cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
1520                break;
1521        }
1522        } /* switch */
1523
1524        if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
1525                if (ret<0) {
1526                        printk ("%s: err:\n", vfd->name);
1527                        v4l_print_ioctl(vfd->name, cmd);
1528                }
1529        }
1530
1531        return ret;
1532}
1533
1534int video_ioctl2 (struct inode *inode, struct file *file,
1535               unsigned int cmd, unsigned long arg)
1536{
1537        char    sbuf[128];
1538        void    *mbuf = NULL;
1539        void    *parg = NULL;
1540        int     err  = -EINVAL;
1541        int     is_ext_ctrl;
1542        size_t  ctrls_size = 0;
1543        void __user *user_ptr = NULL;
1544
1545#ifdef __OLD_VIDIOC_
1546        cmd = video_fix_command(cmd);
1547#endif
1548        is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
1549                       cmd == VIDIOC_TRY_EXT_CTRLS);
1550
1551        /*  Copy arguments into temp kernel buffer  */
1552        switch (_IOC_DIR(cmd)) {
1553        case _IOC_NONE:
1554                parg = NULL;
1555                break;
1556        case _IOC_READ:
1557        case _IOC_WRITE:
1558        case (_IOC_WRITE | _IOC_READ):
1559                if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
1560                        parg = sbuf;
1561                } else {
1562                        /* too big to allocate from stack */
1563                        mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
1564                        if (NULL == mbuf)
1565                                return -ENOMEM;
1566                        parg = mbuf;
1567                }
1568
1569                err = -EFAULT;
1570                if (_IOC_DIR(cmd) & _IOC_WRITE)
1571                        if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
1572                                goto out;
1573                break;
1574        }
1575
1576        if (is_ext_ctrl) {
1577                struct v4l2_ext_controls *p = parg;
1578
1579                /* In case of an error, tell the caller that it wasn't
1580                   a specific control that caused it. */
1581                p->error_idx = p->count;
1582                user_ptr = (void __user *)p->controls;
1583                if (p->count) {
1584                        ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
1585                        /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
1586                        mbuf = kmalloc(ctrls_size, GFP_KERNEL);
1587                        err = -ENOMEM;
1588                        if (NULL == mbuf)
1589                                goto out_ext_ctrl;
1590                        err = -EFAULT;
1591                        if (copy_from_user(mbuf, user_ptr, ctrls_size))
1592                                goto out_ext_ctrl;
1593                        p->controls = mbuf;
1594                }
1595        }
1596
1597        /* Handles IOCTL */
1598        err = __video_do_ioctl(inode, file, cmd, parg);
1599        if (err == -ENOIOCTLCMD)
1600                err = -EINVAL;
1601        if (is_ext_ctrl) {
1602                struct v4l2_ext_controls *p = parg;
1603
1604                p->controls = (void *)user_ptr;
1605                if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
1606                        err = -EFAULT;
1607                goto out_ext_ctrl;
1608        }
1609        if (err < 0)
1610                goto out;
1611
1612out_ext_ctrl:
1613        /*  Copy results into user buffer  */
1614        switch (_IOC_DIR(cmd))
1615        {
1616        case _IOC_READ:
1617        case (_IOC_WRITE | _IOC_READ):
1618                if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
1619                        err = -EFAULT;
1620                break;
1621        }
1622
1623out:
1624        kfree(mbuf);
1625        return err;
1626}
1627
1628
1629static const struct file_operations video_fops;
1630
1631/**
1632 *      video_register_device - register video4linux devices
1633 *      @vfd:  video device structure we want to register
1634 *      @type: type of device to register
1635 *      @nr:   which device number (0 == /dev/video0, 1 == /dev/video1, ...
1636 *             -1 == first free)
1637 *
1638 *      The registration code assigns minor numbers based on the type
1639 *      requested. -ENFILE is returned in all the device slots for this
1640 *      category are full. If not then the minor field is set and the
1641 *      driver initialize function is called (if non %NULL).
1642 *
1643 *      Zero is returned on success.
1644 *
1645 *      Valid types are
1646 *
1647 *      %VFL_TYPE_GRABBER - A frame grabber
1648 *
1649 *      %VFL_TYPE_VTX - A teletext device
1650 *
1651 *      %VFL_TYPE_VBI - Vertical blank data (undecoded)
1652 *
1653 *      %VFL_TYPE_RADIO - A radio card
1654 */
1655
1656int video_register_device(struct video_device *vfd, int type, int nr)
1657{
1658        int i=0;
1659        int base;
1660        int end;
1661        int ret;
1662        char *name_base;
1663
1664        switch(type)
1665        {
1666                case VFL_TYPE_GRABBER:
1667                        base=MINOR_VFL_TYPE_GRABBER_MIN;
1668                        end=MINOR_VFL_TYPE_GRABBER_MAX+1;
1669                        name_base = "video";
1670                        break;
1671                case VFL_TYPE_VTX:
1672                        base=MINOR_VFL_TYPE_VTX_MIN;
1673                        end=MINOR_VFL_TYPE_VTX_MAX+1;
1674                        name_base = "vtx";
1675                        break;
1676                case VFL_TYPE_VBI:
1677                        base=MINOR_VFL_TYPE_VBI_MIN;
1678                        end=MINOR_VFL_TYPE_VBI_MAX+1;
1679                        name_base = "vbi";
1680                        break;
1681                case VFL_TYPE_RADIO:
1682                        base=MINOR_VFL_TYPE_RADIO_MIN;
1683                        end=MINOR_VFL_TYPE_RADIO_MAX+1;
1684                        name_base = "radio";
1685                        break;
1686                default:
1687                        printk(KERN_ERR "%s called with unknown type: %d\n",
1688                               __FUNCTION__, type);
1689                        return -1;
1690        }
1691
1692        /* pick a minor number */
1693        mutex_lock(&videodev_lock);
1694        if (nr >= 0  &&  nr < end-base) {
1695                /* use the one the driver asked for */
1696                i = base+nr;
1697                if (NULL != video_device[i]) {
1698                        mutex_unlock(&videodev_lock);
1699                        return -ENFILE;
1700                }
1701        } else {
1702                /* use first free */
1703                for(i=base;i<end;i++)
1704                        if (NULL == video_device[i])
1705                                break;
1706                if (i == end) {
1707                        mutex_unlock(&videodev_lock);
1708                        return -ENFILE;
1709                }
1710        }
1711        video_device[i]=vfd;
1712        vfd->minor=i;
1713        mutex_unlock(&videodev_lock);
1714        mutex_init(&vfd->lock);
1715
1716        /* sysfs class */
1717        memset(&vfd->class_dev, 0x00, sizeof(vfd->class_dev));
1718        if (vfd->dev)
1719                vfd->class_dev.parent = vfd->dev;
1720        vfd->class_dev.class       = &video_class;
1721        vfd->class_dev.devt        = MKDEV(VIDEO_MAJOR, vfd->minor);
1722        sprintf(vfd->class_dev.bus_id, "%s%d", name_base, i - base);
1723        ret = device_register(&vfd->class_dev);
1724        if (ret < 0) {
1725                printk(KERN_ERR "%s: device_register failed\n",
1726                       __FUNCTION__);
1727                goto fail_minor;
1728        }
1729
1730#if 1
1731        /* needed until all drivers are fixed */
1732        if (!vfd->release)
1733                printk(KERN_WARNING "videodev: \"%s\" has no release callback. "
1734                       "Please fix your driver for proper sysfs support, see "
1735                       "http://lwn.net/Articles/36850/\n", vfd->name);
1736#endif
1737        return 0;
1738
1739fail_minor:
1740        mutex_lock(&videodev_lock);
1741        video_device[vfd->minor] = NULL;
1742        vfd->minor = -1;
1743        mutex_unlock(&videodev_lock);
1744        return ret;
1745}
1746
1747/**
1748 *      video_unregister_device - unregister a video4linux device
1749 *      @vfd: the device to unregister
1750 *
1751 *      This unregisters the passed device and deassigns the minor
1752 *      number. Future open calls will be met with errors.
1753 */
1754
1755void video_unregister_device(struct video_device *vfd)
1756{
1757        mutex_lock(&videodev_lock);
1758        if(video_device[vfd->minor]!=vfd)
1759                panic("videodev: bad unregister");
1760
1761        video_device[vfd->minor]=NULL;
1762        device_unregister(&vfd->class_dev);
1763        mutex_unlock(&videodev_lock);
1764}
1765
1766/*
1767 * Video fs operations
1768 */
1769static const struct file_operations video_fops=
1770{
1771        .owner          = THIS_MODULE,
1772        .llseek         = no_llseek,
1773        .open           = video_open,
1774};
1775
1776/*
1777 *      Initialise video for linux
1778 */
1779
1780static int __init videodev_init(void)
1781{
1782        int ret;
1783
1784        printk(KERN_INFO "Linux video capture interface: v2.00\n");
1785        if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) {
1786                printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR);
1787                return -EIO;
1788        }
1789
1790        ret = class_register(&video_class);
1791        if (ret < 0) {
1792                unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME);
1793                printk(KERN_WARNING "video_dev: class_register failed\n");
1794                return -EIO;
1795        }
1796
1797        return 0;
1798}
1799
1800static void __exit videodev_exit(void)
1801{
1802        class_unregister(&video_class);
1803        unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME);
1804}
1805
1806module_init(videodev_init)
1807module_exit(videodev_exit)
1808
1809EXPORT_SYMBOL(video_register_device);
1810EXPORT_SYMBOL(video_unregister_device);
1811EXPORT_SYMBOL(video_devdata);
1812EXPORT_SYMBOL(video_usercopy);
1813EXPORT_SYMBOL(video_exclusive_open);
1814EXPORT_SYMBOL(video_exclusive_release);
1815EXPORT_SYMBOL(video_ioctl2);
1816EXPORT_SYMBOL(video_device_alloc);
1817EXPORT_SYMBOL(video_device_release);
1818
1819MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org>");
1820MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2");
1821MODULE_LICENSE("GPL");
1822
1823
1824/*
1825 * Local variables:
1826 * c-basic-offset: 8
1827 * End:
1828 */
1829