一、V4L2框架主要结构体分析

V4L2(video for linux version 2),是内核中视频设备的驱动框架,为上层访问视频设备提供统一接口。

V4L2整体框架如下图:

图中主要包括两层和三个结构体:

两层是:

1. v4l2驱动核心层:包含video_device和v4l2_device的分配、设置和注册

2. v4l2下层接口层:具体的底层传感器驱动,现在的摄像头可能支持硬件解码,这就需要在摄像头驱动下面提供解码器IC驱动

三个结构体是:

1. v4l2_device:

structv4l2_device {/*dev->driver_data points to this struct.Note: dev might be NULL if there is no parent deviceas is the case with e.g. ISA devices.*/struct device *dev;/*used to keep track of the registered subdevs*/structlist_head subdevs;/*lock this struct; can be used by the driver as well if thisstruct is embedded into a larger struct.*/spinlock_tlock;/*unique device name, by default the driver name + bus ID*/charname[V4L2_DEVICE_NAME_SIZE];/*notify callback called by some sub-devices.*/void (*notify)(struct v4l2_subdev *sd,unsignedint notification, void *arg);/*The control handler. May be NULL.*/struct v4l2_ctrl_handler *ctrl_handler;/*Device's priority state*/structv4l2_prio_state prio;/*BKL replacement mutex. Temporary solution only.*/structmutex ioctl_lock;/*Keep track of the references to this struct.*/struct kref ref;/*Release function that is called when the ref count goes to 0.*/void (*release)(struct v4l2_device *v4l2_dev);
};

View Code

2. video_device:

structvideo_device
{const struct v4l2_file_operations *fops;    /*文件操作函数*/struct device dev;        /*v4l device*/struct cdev *cdev;        /*character device*/struct device *parent;        /*device parent*/struct v4l2_device *v4l2_dev;    /*v4l2_device parent*//*Control handler associated with this device node. May be NULL.*/struct v4l2_ctrl_handler *ctrl_handler;/*Priority state. If NULL, then v4l2_dev->prio will be used.*/struct v4l2_prio_state *prio;/*device info*/char name[32];intvfl_type;/*'minor' is set to -1 if the registration failed*/intminor;u16 num;
.../*ioctl callbacks*/const struct v4l2_ioctl_ops *ioctl_ops;        /*控制函数*//*serialization lock*/struct mutex *lock;
};

3. v4l2-subdev:

structv4l2_subdev {#if defined(CONFIG_MEDIA_CONTROLLER)structmedia_entity entity;#endifstructlist_head list;struct module *owner;u32 flags;struct v4l2_device *v4l2_dev;const struct v4l2_subdev_ops *ops;/*Never call these internal ops from within a driver!*/const struct v4l2_subdev_internal_ops *internal_ops;/*The control handler of this subdev. May be NULL.*/struct v4l2_ctrl_handler *ctrl_handler;/*name must be unique*/charname[V4L2_SUBDEV_NAME_SIZE];/*can be used to group similar subdevs, value is driver-specific*/u32 grp_id;/*pointer to private data*/void *dev_priv;void *host_priv;/*subdev device node*/struct video_device *devnode;
};

View Code

v4l2_device在v4l2框架中是v4l2_subdev的父设备

video_device是v4l2_device的上层结构体,存储v4l2_device数据和cdev,它会在/dev目录下生成设备节点文件

video_device的struct v4l2_ioctl_ops会在后面分析

在此我给出它的作用方便读者理解函数分析过程:

struct v4l2_ioctl_ops:它会在应用层使用ioctl()时根据传入的宏调用对应操作函数

二、核心层提供的注册函数

1. 注册和注销v4l2_device:

/*注册*/
int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)/*注销*/
void v4l2_device_unregister(struct v4l2_device *v4l2_dev)

注册函数调用关系如下:

/*将设备与v4l2_device捆绑,并把v4l2设备放到driver data中* 我们可以使用dev_get_drvdata(dev)获取到v4l2设备*/v4l2_device_register(&intf->dev, &dev->vdev)->dev_set_drvdata(dev, v4l2_dev);-> dev->p->driver_data = data;    /*device->device_private为v4l2_device*/

2. 注册和注销v4l2_subdev:

/*注册*/
int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, struct v4l2_subdev *sd)/*注销*/
void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)

注册函数调用关系如下:

v4l2_device_register_subdev()/*struct v4l2_ctrl_handler用于控制设备的亮度、饱和度等*/-> v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler);-> handler_new_ref(hdl, ctrl);         /*设置控制属性*/-> v4l2_ctrl_new_std(hdl, NULL, class_ctrl, 0, 0, 0, 0)-> v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);-> v4l2_ctrl_new(hdl, ops, ...); /*ops为v4l2_ctrl_ops,定义控制函数*/-> list_add_tail(&ctrl->node, &hdl->ctrls);-> list_add_tail(&sd->list, &v4l2_dev->subdevs);

v4l2_subdev注册函数主要设置了设备的控制属性和控制函数,并把设备放入列表中

控制函数结构体定义如下,读者有印象即可

structv4l2_ctrl_ops {int (*g_volatile_ctrl)(struct v4l2_ctrl *ctrl); /*获取控制器值*/int (*try_ctrl)(struct v4l2_ctrl *ctrl);        /*测试控制器值是否有效*/int (*s_ctrl)(struct v4l2_ctrl *ctrl);          /*设置控制器值*/};

3. 注册和注销video_device:

/*注册*/
static inline int __must_check video_register_device(struct video_device *vdev, int type, intnr)/*注销*/
void video_unregister_device(struct video_device *vdev)

注册函数调用关系如下:

video_register_device(vdev, VFL_TYPE_GRABBER, -1);-> __video_register_device(vdev, type, nr, 1, vdev->fops->owner);-> case VFL_TYPE_GRABBER:            /*摄像头设备*/-> name_base = "video";-> caseVFL_TYPE_GRABBER:-> minor_offset = 0;-> minor_cnt = 64;-> vdev->minor = i +minor_offset;-> vdev->cdev =cdev_alloc();-> vdev->cdev->ops = &v4l2_fops;-> cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);  /*依据次设备号分配cdev*/-> dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);    /*设备名为video%d*/-> device_register(&vdev->dev);-> device_add(dev);

video_register_device()函数主要分配、设置并注册了cdev和device。

三、v4l2_device和video_device的file_operations分析

分析到这里,产生了两个问题:

1. register_chrdev_region()和创建class在哪里被调用的?

2. v4l2_fops函数都做了什么?

我们先来决解第一个问题,两函数应该在初始化框架时被调用,初始化函数定义在v4l2-dev.c文件中:

1 static int __init videodev_init(void)2 {3     dev_t dev = MKDEV(VIDEO_MAJOR, 0);        /*VIDEO_MAJOR = 81*/
4     intret;5
6     ret =register_chrdev_region(dev, VIDEO_NUM_DEVICES, VIDEO_NAME);7 ...8     ret = class_register(&video_class);9 ...10     return 0;11 }

现在我们来看v4l2_fops的定义:

static const struct file_operations v4l2_fops ={.owner=THIS_MODULE,.read=v4l2_read,.write=v4l2_write,.open=v4l2_open,.get_unmapped_area=v4l2_get_unmapped_area,.mmap=v4l2_mmap,.unlocked_ioctl=v4l2_ioctl,.release=v4l2_release,.poll=v4l2_poll,.llseek=no_llseek,
};

首先从open()函数分析:

1 static int v4l2_open(struct inode *inode, struct file *filp)2 {3     struct video_device *vdev;4     int ret = 0;5 ...6     vdev =video_devdata(filp);7 ...8     if (vdev->fops->open) {9 ...10         if(video_is_registered(vdev))11             ret = vdev->fops->open(filp);    /*最终会调用video_device->fops的open()函数*/
12 ...13 }14 ...15 }

read()和其他函数亦是如此:

1 static ssize_t v4l2_read(struct file *filp, char __user *buf, size_t sz, loff_t *off)2 {3     struct video_device *vdev =video_devdata(filp);4 ...5     if(video_is_registered(vdev))6         ret = vdev->fops->read(filp, buf, sz, off);7 ...8 }9
10 static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned longarg)11 {12     struct video_device *vdev =video_devdata(filp);13     int ret = -ENODEV;14
15     if (vdev->fops->unlocked_ioctl) {16 ...17         if(video_is_registered(vdev))18             ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);19 ...20 }21 ...22 }

可以看到v4l2_fops定义的函数在底层都会调用video_device的fops函数,因此我们可以在SI4内核项目中搜索“struct v4l2_file_operations ”:

在此我以drivers/staging/media/solo6x10/v4l2.c文件为例分析

若读者使用它其他文件分析,可能在后面会遇到struct vb2_buffer、struct vb2_queue、struct vb2_ops和struct vb2_mem_ops,其实vb2就是videobuf2,是videobuf的新版本,在此不做介绍

文件链接:

https://files.cnblogs.com/files/Lioker/24_v4l2_xawtv.zip

static const struct v4l2_file_operations solo_v4l2_fops ={.owner=THIS_MODULE,.open=solo_v4l2_open,.release=solo_v4l2_release,.read=solo_v4l2_read,.poll=solo_v4l2_poll,.mmap=solo_v4l2_mmap,.ioctl=video_ioctl2,
};

首先从open()函数分析:

solo_v4l2_open-> INIT_LIST_HEAD(&fh->vidq_active);    /*初始化用于存放queue的list_head*/-> solo_start_thread(fh);               /*启动线程查询是否有数据*/-> solo_thread                        /*等待数据*/->DECLARE_WAITQUEUE(wait, current);-> add_wait_queue(&solo_dev->disp_thread_wait, &wait);->schedule_timeout_interruptible(HZ);-> solo_thread_try(fh);             /*如果有数据*//*取出等待队列头的第一个队列*/-> struct videobuf_buffer * vb = list_first_entry(&fh->vidq_active, structvideobuf_buffer, queue);-> list_del(&vb->queue);->solo_fillbuf(fh, vb);-> wake_up(&vb->done);          /*唤醒上层读写操作*/-> remove_wait_queue(&solo_dev->disp_thread_wait, &wait);-> videobuf_queue_sg_init(&fh->vidq,&solo_video_qops,   /*solo_video_qops为struct videobuf_queue_ops*/...,&fh->slock,    /*fh->slock为spinlock_t用于保护队列*/V4L2_BUF_TYPE_VIDEO_CAPTURE,/*是摄像头*/SOLO_DISP_PIX_FIELD,sizeof(struct videobuf_buffer), fh,...);

函数所使用的struct videobuf_queue、struct videobuf_queue_ops和struct videobuf_buffer会在后面分析

在此我给出它们的作用方便读者理解函数分析过程:

struct videobuf_queue:在数据传输过程中,首先把buffer放入queue,然后把queue放入list_head中,读写函数会通过操作list_head来操作queue中的buffer

struct videobuf_queue_ops:提供设置videobuf_buffer函数,添加queue到list_head函数,释放内存函数等

struct videobuf_buffer:用于数据传输,是数据传输的基本单位

函数所使用的videobuf_queue_sg_init()函数用于初始化queue,除此函数外,还有两函数可以用来初始化queue:

void videobuf_queue_vmalloc_init(struct videobuf_queue *q,struct videobuf_queue_ops *ops,struct device *dev,spinlock_t*irqlock,enumv4l2_buf_type type,enumv4l2_field field,unsignedintmsize,void *priv);void videobuf_queue_dma_contig_init(struct videobuf_queue *q,struct videobuf_queue_ops *ops,struct device *dev,spinlock_t*irqlock,enumv4l2_buf_type type,enumv4l2_field field,unsignedintmsize,void *priv);

videobuf_queue_sg_init():物理上和虚拟地址都是离散的buffer

videobuf_queue_vmalloc_init():物理上离散的,但虚拟地址是连续的buffer

videobuf_queue_dma_contig_init():物理上和虚拟地址都是连续的buffer

read()函数的调用关系如下:

solo_v4l2_read/*从videobuf_queue fh->vidq取出数据*/-> videobuf_read_stream(&fh->vidq, data, count, ppos, 0, file->f_flags &O_NONBLOCK);-> q->read_buf = list_entry(q->stream.next, structvideobuf_buffer, stream);-> list_del(&q->read_buf->stream);

ioctl()函数的调用关系如下:

video_ioctl2/*根据cmd,调用__video_do_ioctl()将数据拷贝到内核空间*/->__video_do_ioctl-> struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;-> case VIDIOC_QUERYCAP:    /*设备支持的能力*/-> ops->vidioc_querycap(file, fh, cap);-> case VIDIOC_G_FMT:        /*获取格式、分辨率等*/-> ps->vidioc_g_fmt_vid_cap(file, fh, f);-> case VIDIOC_QBUF:        /*把缓存区放入传输队列*/-> ops->vidioc_qbuf(file, fh, p);-> case VIDIOC_DQBUF:        /*把缓存从队列中取出*/-> ops->vidioc_dqbuf(file, fh, p);-> case VIDIOC_STREAMON:    /*启动视频传输*/-> ops->vidioc_streamon(file, fh, i);-> case VIDIOC_STREAMOFF:    /*关闭视频传输*/-> ops->vidioc_streamoff(file, fh, i);

分析完了这两个问题,下面我们来分析v4l2.c的init()函数

四、v4l2.c的init()函数分析

init()函数的调用关系:

solo_v4l2_init/*初始化open()等函数使用的wait_queue_head_t*/-> init_waitqueue_head(&solo_dev->disp_thread_wait);/*分配、设置和注册video_device*/-> solo_dev->vfd =video_device_alloc();-> *solo_dev->vfd = solo_v4l2_template;    /*struct video_device*/-> video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, video_nr);

根据上述过程,我们可以得到下图:

五、数据传输和控制结构体分析

我在前几节有几个结构体没有介绍,在此我还是以v4l2.c文件的实例进行介绍

数据控制相关:

1. struct v4l2_ioctl_ops

static const struct v4l2_ioctl_ops solo_v4l2_ioctl_ops ={/*表示它是一个摄像头设备*/.vidioc_querycap=solo_querycap,/*列举、获取、设置标准* 列举、获取标准使用的是* video_device的tvnorms和current_norm*/.vidioc_s_std=solo_s_std,/*列举、获取、设置输入源*/.vidioc_enum_input=solo_enum_input,.vidioc_s_input=solo_set_input,.vidioc_g_input=solo_get_input,/*列举、获得、测试、设置摄像头的数据格式*/.vidioc_enum_fmt_vid_cap=solo_enum_fmt_cap,.vidioc_try_fmt_vid_cap=solo_try_fmt_cap,.vidioc_s_fmt_vid_cap=solo_set_fmt_cap,.vidioc_g_fmt_vid_cap=solo_get_fmt_cap,/*缓冲区操作:申请、查询、放入队列、取出队列*/.vidioc_reqbufs=solo_reqbufs,.vidioc_querybuf=solo_querybuf,.vidioc_qbuf=solo_qbuf,.vidioc_dqbuf=solo_dqbuf,/*启动、停止视频流*/.vidioc_streamon=solo_streamon,.vidioc_streamoff=solo_streamoff,/*Controls*/.vidioc_queryctrl=solo_disp_queryctrl,.vidioc_g_ctrl=solo_disp_g_ctrl,.vidioc_s_ctrl=solo_disp_s_ctrl,
};

数据传输相关:

1. struct videobuf_buffer

structvideobuf_buffer {unsignedinti;u32                     magic;/*info about the buffer*/unsignedint            width;          /*摄像头图像像素长度*/unsignedint            height;          /*宽度*/unsignedint            bytesperline; /*一行的字节数*/unsignedlong           size;          /*size = height * bytesperline*/unsignedintinput;enumv4l2_field         field;enum videobuf_state     state;          /*用于存储状态*/struct list_head        stream;        /*QBUF/DQBUF list*//*touched by irq handler*/structlist_head        queue;wait_queue_head_t       done;unsignedintfield_count;structtimeval          ts;/*Memory type*/enumv4l2_memory        memory;/*buffer size*/size_t                  bsize;/*buffer offset (mmap + overlay)*/size_t                  boff;/*buffer addr (userland ptr!)*/unsignedlongbaddr;/*for mmap'ed buffers*/struct videobuf_mapping *map;/*Private pointer to allow specific methods to store their data*/intprivsize;void                    *priv;
};

View Code

2. struct videobuf_queue

structvideobuf_queue {structmutex           vb_lock;struct mutex           *ext_lock;spinlock_t*irqlock;struct device           *dev;wait_queue_head_t       wait;/*wait if queue is empty*/enumv4l2_buf_type         type;unsignedint               inputs; /*for V4L2_BUF_FLAG_INPUT*/unsignedintmsize;enumv4l2_field            field;enum v4l2_field            last;   /*for field=V4L2_FIELD_ALTERNATE*/struct videobuf_buffer     *bufs[VIDEO_MAX_FRAME];const struct videobuf_queue_ops  *ops;struct videobuf_qtype_ops  *int_ops;unsignedint               streaming:1;unsignedint               reading:1;/*capture via mmap() + ioctl(QBUF/DQBUF)*/structlist_head           stream;/*capture via read()*/unsignedintread_off;struct videobuf_buffer     *read_buf;/*driver private data*/void                       *priv_data;
};

View Code

3. struct videobuf_queue_ops

static struct videobuf_queue_ops solo_video_qops ={/*被v4l2_ioctl_ops->vidioc_reqbufs调用,用于重新调整count和size*/.buf_setup=solo_buf_setup,/*被v4l2_ioctl_ops->vidioc_qbuf调用,用于设置videobuf_buffer成员*/.buf_prepare=solo_buf_prepare,/*被v4l2_ioctl_ops->vidioc_qbuf调用,用于把queue放到list_head*/.buf_queue=solo_buf_queue,/*被v4l2_ioctl_ops->vidioc_streamoff调用,用于释放内存*/.buf_release=solo_buf_release,
};

当开始流I/O时,摄像头的图像会在应用和驱动间传输,它可能会有三个状态:

1. 在驱动的传入队列中,用户空间通过ioctl(..., VIDIOC_QBUF, ...)填充缓冲区,把缓冲区放入队列。

2. 在驱动的传出队列中,缓冲区已经填充了视频数据,等待用户空间读取

3. 在用户空间的队列中,用户空间已经通过ioctl(..., VIDIOC_DQBUF, ...)读取缓冲区了,此时驱动无法访问缓冲区

这三种状态的切换如下图:

六、虚拟摄像头驱动vivi.c虚拟机测试

本节我通过应用程序xawtv对vivi.c的系统调用的关系进行分析,我们需要做的有以下几步:

1. 执行$ sudo apt-get install xawtv在虚拟机中安装xawtv

2. 在网站https://www.kraxel.org/releases/xawtv/下载源码xawtv-3.95.tar.gz,并创建SI4工程

3. 虚拟机连接摄像头,执行$ ls /dev/video*可以看到生成了/dev/video0,执行xawtv即可看到图像

4. 执行$ uname -a,根据虚拟机内核版本去http://ftp.sjtu.edu.cn/sites/ftp.kernel.org/pub/linux/kernel/下载同版本的内核

5. 解压后把drivers/media/video目录单独取出,修改它的Makefile为:

KERN_DIR = /work/vmware/tools/linux-4.8all:make-C $(KERN_DIR) M=`pwd` modulesclean:make-C $(KERN_DIR) M=`pwd` modules cleanrm-rf modules.orderobj-m +=vivi.o
obj-m += videobuf-core.o
obj-m += videobuf-vmalloc.o
obj-m += v4l2-common.o

6. 编译后,由于vivi.ko模块涉及较多文件,为防止有模块未被载入,我们可以使用$ sudo modprobe vivi加载内核自带vivi驱动及其所需框架和文件,然后依次执行$ sudo rmmod vivi$ sudo insmod ./vivi.ko安装我们编译的vivi模块

7. 执行$ ls /dev/video*查看虚拟摄像头,然后执行$ xawtv -c /dev/videox打开虚拟摄像头

七、ioctl()执行过程和v4l2_ioctl_ops必需函数指针的确定

在可以看到图像后,我们就可以通过应用程序xawtv对应用程序ioctl()执行过程进行分析。

查看程序系统调用过程可以使用strace命令实现:

$ strace -o xawtv.log xawtv    /* 执行xawtv命令,调用过程会存储在xawtv.log文件中 */

xawtv.log文件会放在上面的百度网盘分享链接中

首先,我们搜索“open("/dev/video”,我们只需要关注第二次open(),因为第一次open()后面有close(),可以看到文件描述符为4

接下来,我们搜索“(4, ”,查看有哪些对应文件描述符的操作:

1 fstat64(4, {st_mode=S_IFREG|0600, st_size=57, ...}) = 0
2 read(4, "\1\0\0\fbook-desktop\0\0010\0\22MIT-MAGIC-C"..., 4096) = 57
3 read(4, "", 4096)                       = 0
4 fstat64(4, {st_mode=S_IFREG|0644, st_size=82376, ...}) = 0
5 read(4, "#\t$XdotOrg: lib/X11/nls/locale.a"..., 4096) = 4096
6 read(4, "\t\t\t\t\tbg_BG.UTF-8\nbn_IN.utf8\t\t\t\t\t"..., 4096) = 4096
7 read(4, "8859-15\t\t\t\tde_CH.ISO8859-15\nde_C"..., 4096) = 4096
8 read(4, "_ZA.ISO8859-1\nen_ZA.ISO-8859-1\t\t"..., 4096) = 4096
9 read(4, "85915\t\t\t\teu_ES.ISO8859-15\neu_ES."..., 4096) = 4096
10 read(4, "14\ngv_GB.ISO-8859-14\t\t\t\tgv_GB.IS"..., 4096) = 4096
11 read(4, "w_GB.ISO8859-1\nkw_GB.ISO-8859-1\t"..., 4096) = 4096
12 read(4, ".ISO8859-1\noc\t\t\t\t\t\toc_FR.ISO8859"..., 4096) = 4096
13 read(4, "r_RS.UTF-8\nsr_YU.UTF-8@cyrillic\t"..., 4096) = 4096
14 read(4, "yi_US.CP1255\nzh_CN\t\t\t\t\t\tzh_CN.gb"..., 4096) = 4096
15 read(4, ":00 dawes Exp $\n#\n\nPOSIX:\t\t\t\t\t\tC"..., 4096) = 4096
16 read(4, "4:\t\t\t\tbr_FR.ISO8859-14\nbr_FR.ISO"..., 4096) = 4096
17 read(4, "de_DE.88591.en:\t\t\t\t\tde_DE.ISO885"..., 4096) = 4096
18 read(4, "59-1:\t\t\t\ten_ZA.ISO8859-1\nen_ZA.I"..., 4096) = 4096
19 read(4, "_ES.ISO8859-1\neu_ES.iso88591:\t\t\t"..., 4096) = 4096
20 read(4, "F-8\ngu_IN.utf8:\t\t\t\t\tgu_IN.UTF-8\n"..., 4096) = 4096
21 read(4, "o_KR.utf8:\t\t\t\t\tko_KR.UTF-8\nKO_KR"..., 4096) = 4096
22 read(4, "o_NO.utf8:\t\t\t\t\tno_NO.UTF-8\nnr:\t\t"..., 4096) = 4096
23 read(4, "O8859-2\nsl_SI.iso88592:\t\t\t\t\tsl_S"..., 4096) = 4096
24 read(4, "N\nvi_VN.tcvn5712:\t\t\t\t\tvi_VN.TCVN"..., 4096) = 4096
25 read(4, "9-9\nturkish.iso88599:\t\t\t\ttr_TR.I"..., 4096) = 456
26 read(4, "", 4096)                       = 0
27 fstat64(4, {st_mode=S_IFREG|0644, st_size=40344, ...}) = 0
28 read(4, "#\t$XdotOrg: lib/X11/nls/locale.d"..., 4096) = 4096
29 read(4, "59-1/XLC_LOCALE\t\t\tes_AR.ISO8859-"..., 4096) = 4096
30 read(4, "_FR.ISO8859-1\niso8859-15/XLC_LOC"..., 4096) = 4096
31 read(4, "8/XLC_LOCALE\t\t\tbe_BY.UTF-8\nen_US"..., 4096) = 4096
32 read(4, "en_US.UTF-8/XLC_LOCALE\t\t\tlo_LA.U"..., 4096) = 4096
33 fstat64(4, {st_mode=S_IFREG|0644, st_size=772, ...}) = 0
34 read(4, "#  $Xorg: C,v 1.3 2000/08/17 19:"..., 4096) = 772
35 read(4, "", 4096)                       = 0
36 fstat64(4, {st_mode=S_IFREG|0644, st_size=82376, ...}) = 0
37 read(4, "#\t$XdotOrg: lib/X11/nls/locale.a"..., 4096) = 4096
38 read(4, "\t\t\t\t\tbg_BG.UTF-8\nbn_IN.utf8\t\t\t\t\t"..., 4096) = 4096
39 read(4, "8859-15\t\t\t\tde_CH.ISO8859-15\nde_C"..., 4096) = 4096
40 read(4, "_ZA.ISO8859-1\nen_ZA.ISO-8859-1\t\t"..., 4096) = 4096
41 read(4, "85915\t\t\t\teu_ES.ISO8859-15\neu_ES."..., 4096) = 4096
42 read(4, "14\ngv_GB.ISO-8859-14\t\t\t\tgv_GB.IS"..., 4096) = 4096
43 read(4, "w_GB.ISO8859-1\nkw_GB.ISO-8859-1\t"..., 4096) = 4096
44 read(4, ".ISO8859-1\noc\t\t\t\t\t\toc_FR.ISO8859"..., 4096) = 4096
45 read(4, "r_RS.UTF-8\nsr_YU.UTF-8@cyrillic\t"..., 4096) = 4096
46 read(4, "yi_US.CP1255\nzh_CN\t\t\t\t\t\tzh_CN.gb"..., 4096) = 4096
47 read(4, ":00 dawes Exp $\n#\n\nPOSIX:\t\t\t\t\t\tC"..., 4096) = 4096
48 read(4, "4:\t\t\t\tbr_FR.ISO8859-14\nbr_FR.ISO"..., 4096) = 4096
49 read(4, "de_DE.88591.en:\t\t\t\t\tde_DE.ISO885"..., 4096) = 4096
50 read(4, "59-1:\t\t\t\ten_ZA.ISO8859-1\nen_ZA.I"..., 4096) = 4096
51 read(4, "_ES.ISO8859-1\neu_ES.iso88591:\t\t\t"..., 4096) = 4096
52 read(4, "F-8\ngu_IN.utf8:\t\t\t\t\tgu_IN.UTF-8\n"..., 4096) = 4096
53 read(4, "o_KR.utf8:\t\t\t\t\tko_KR.UTF-8\nKO_KR"..., 4096) = 4096
54 read(4, "o_NO.utf8:\t\t\t\t\tno_NO.UTF-8\nnr:\t\t"..., 4096) = 4096
55 read(4, "O8859-2\nsl_SI.iso88592:\t\t\t\t\tsl_S"..., 4096) = 4096
56 read(4, "N\nvi_VN.tcvn5712:\t\t\t\t\tvi_VN.TCVN"..., 4096) = 4096
57 read(4, "9-9\nturkish.iso88599:\t\t\t\ttr_TR.I"..., 4096) = 456
58 read(4, "", 4096)                       = 0
59 fstat64(4, {st_mode=S_IFREG|0644, st_size=40344, ...}) = 0
60 read(4, "#\t$XdotOrg: lib/X11/nls/locale.d"..., 4096) = 4096
61 read(4, "59-1/XLC_LOCALE\t\t\tes_AR.ISO8859-"..., 4096) = 4096
62 read(4, "_FR.ISO8859-1\niso8859-15/XLC_LOC"..., 4096) = 4096
63 read(4, "8/XLC_LOCALE\t\t\tbe_BY.UTF-8\nen_US"..., 4096) = 4096
64 read(4, "en_US.UTF-8/XLC_LOCALE\t\t\tlo_LA.U"..., 4096) = 4096
65 fstat64(4, {st_mode=S_IFREG|0644, st_size=772, ...}) = 0
66 read(4, "#  $Xorg: C,v 1.3 2000/08/17 19:"..., 4096) = 772
67 read(4, "", 4096)                       = 0
68 fstat64(4, {st_mode=S_IFREG|0644, st_size=2570, ...}) = 0
69 read(4, "# Locale name alias data base.\n#"..., 4096) = 2570
70 read(4, "", 4096)                       = 0
71 fstat64(4, {st_mode=S_IFREG|0644, st_size=373, ...}) = 0
72 fstat64(4, {st_mode=S_IFREG|0644, st_size=26048, ...}) = 0
73 fstat64(4, {st_mode=S_IFREG|0644, st_size=23, ...}) = 0
74 fstat64(4, {st_mode=S_IFREG|0644, st_size=59, ...}) = 0
75 fstat64(4, {st_mode=S_IFREG|0644, st_size=155, ...}) = 0
76 fstat64(4, {st_mode=S_IFREG|0644, st_size=77, ...}) = 0
77 fstat64(4, {st_mode=S_IFREG|0644, st_size=34, ...}) = 0
78 fstat64(4, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
79 fstat64(4, {st_mode=S_IFREG|0644, st_size=52, ...}) = 0
80 fstat64(4, {st_mode=S_IFREG|0644, st_size=286, ...}) = 0
81 fstat64(4, {st_mode=S_IFREG|0644, st_size=966938, ...}) = 0
82 fstat64(4, {st_mode=S_IFREG|0644, st_size=2454, ...}) = 0
83 fstat64(4, {st_mode=S_IFREG|0644, st_size=54, ...}) = 0
84 fstat64(4, {st_mode=S_IFREG|0644, st_size=256316, ...}) = 0
85 fstat64(4, {st_mode=S_IFREG|0644, st_size=82376, ...}) = 0
86 read(4, "#\t$XdotOrg: lib/X11/nls/locale.a"..., 4096) = 4096
87 read(4, "\t\t\t\t\tbg_BG.UTF-8\nbn_IN.utf8\t\t\t\t\t"..., 4096) = 4096
88 read(4, "8859-15\t\t\t\tde_CH.ISO8859-15\nde_C"..., 4096) = 4096
89 read(4, "_ZA.ISO8859-1\nen_ZA.ISO-8859-1\t\t"..., 4096) = 4096
90 read(4, "85915\t\t\t\teu_ES.ISO8859-15\neu_ES."..., 4096) = 4096
91 read(4, "14\ngv_GB.ISO-8859-14\t\t\t\tgv_GB.IS"..., 4096) = 4096
92 read(4, "w_GB.ISO8859-1\nkw_GB.ISO-8859-1\t"..., 4096) = 4096
93 read(4, ".ISO8859-1\noc\t\t\t\t\t\toc_FR.ISO8859"..., 4096) = 4096
94 read(4, "r_RS.UTF-8\nsr_YU.UTF-8@cyrillic\t"..., 4096) = 4096
95 read(4, "yi_US.CP1255\nzh_CN\t\t\t\t\t\tzh_CN.gb"..., 4096) = 4096
96 read(4, ":00 dawes Exp $\n#\n\nPOSIX:\t\t\t\t\t\tC"..., 4096) = 4096
97 read(4, "4:\t\t\t\tbr_FR.ISO8859-14\nbr_FR.ISO"..., 4096) = 4096
98 read(4, "de_DE.88591.en:\t\t\t\t\tde_DE.ISO885"..., 4096) = 4096
99 read(4, "59-1:\t\t\t\ten_ZA.ISO8859-1\nen_ZA.I"..., 4096) = 4096
100 read(4, "_ES.ISO8859-1\neu_ES.iso88591:\t\t\t"..., 4096) = 4096
101 read(4, "F-8\ngu_IN.utf8:\t\t\t\t\tgu_IN.UTF-8\n"..., 4096) = 4096
102 read(4, "o_KR.utf8:\t\t\t\t\tko_KR.UTF-8\nKO_KR"..., 4096) = 4096
103 read(4, "o_NO.utf8:\t\t\t\t\tno_NO.UTF-8\nnr:\t\t"..., 4096) = 4096
104 read(4, "O8859-2\nsl_SI.iso88592:\t\t\t\t\tsl_S"..., 4096) = 4096
105 read(4, "N\nvi_VN.tcvn5712:\t\t\t\t\tvi_VN.TCVN"..., 4096) = 4096
106 read(4, "9-9\nturkish.iso88599:\t\t\t\ttr_TR.I"..., 4096) = 456
107 read(4, "", 4096)                       = 0
108 fstat64(4, {st_mode=S_IFREG|0644, st_size=82376, ...}) = 0
109 read(4, "#\t$XdotOrg: lib/X11/nls/locale.a"..., 4096) = 4096
110 read(4, "\t\t\t\t\tbg_BG.UTF-8\nbn_IN.utf8\t\t\t\t\t"..., 4096) = 4096
111 read(4, "8859-15\t\t\t\tde_CH.ISO8859-15\nde_C"..., 4096) = 4096
112 read(4, "_ZA.ISO8859-1\nen_ZA.ISO-8859-1\t\t"..., 4096) = 4096
113 read(4, "85915\t\t\t\teu_ES.ISO8859-15\neu_ES."..., 4096) = 4096
114 read(4, "14\ngv_GB.ISO-8859-14\t\t\t\tgv_GB.IS"..., 4096) = 4096
115 read(4, "w_GB.ISO8859-1\nkw_GB.ISO-8859-1\t"..., 4096) = 4096
116 read(4, ".ISO8859-1\noc\t\t\t\t\t\toc_FR.ISO8859"..., 4096) = 4096
117 read(4, "r_RS.UTF-8\nsr_YU.UTF-8@cyrillic\t"..., 4096) = 4096
118 read(4, "yi_US.CP1255\nzh_CN\t\t\t\t\t\tzh_CN.gb"..., 4096) = 4096
119 read(4, ":00 dawes Exp $\n#\n\nPOSIX:\t\t\t\t\t\tC"..., 4096) = 4096
120 read(4, "4:\t\t\t\tbr_FR.ISO8859-14\nbr_FR.ISO"..., 4096) = 4096
121 read(4, "de_DE.88591.en:\t\t\t\t\tde_DE.ISO885"..., 4096) = 4096
122 fstat64(4, {st_mode=S_IFREG|0644, st_size=40344, ...}) = 0
123 read(4, "#\t$XdotOrg: lib/X11/nls/locale.d"..., 4096) = 4096
124 read(4, "59-1/XLC_LOCALE\t\t\tes_AR.ISO8859-"..., 4096) = 4096
125 read(4, "_FR.ISO8859-1\niso8859-15/XLC_LOC"..., 4096) = 4096
126 read(4, "8/XLC_LOCALE\t\t\tbe_BY.UTF-8\nen_US"..., 4096) = 4096
127 read(4, "en_US.UTF-8/XLC_LOCALE\t\t\tlo_LA.U"..., 4096) = 4096
128 read(4, "LE:\t\t\taf_ZA.ISO8859-1\niso8859-15"..., 4096) = 4096
129 read(4, "LE:\t\t\tes_MX.ISO8859-1\niso8859-1/"..., 4096) = 4096
130 read(4, "9-2/XLC_LOCALE:\t\t\tpl_PL.ISO8859-"..., 4096) = 4096
131 read(4, "byn_ER.UTF-8\nen_US.UT"..., 4096) = 4096
132 fstat64(4, {st_mode=S_IFREG|0644, st_size=4287, ...}) = 0
133 read(4, "#  $XFree86: xc/nls/XLC_LOCALE/e"..., 4096) = 4096
134 read(4, "GB2312.1980-0:GL; GB2312.1980-0:"..., 4096) = 191
135 read(4, "", 4096)                       = 0
136 fstat64(4, {st_mode=S_IFREG|0644, st_size=18236, ...}) = 0
137 read(4, "\n! -----------------------------"..., 18236) = 18236
138 fcntl64(4, F_GETFD)                     = 0x1(flags FD_CLOEXEC)139 getdents64(4, /*19 entries*/, 32768)  = 640
140 getdents64(4, /*0 entries*/, 32768)   = 0
141 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\240\3\0\0004\0\0\0"..., 512) = 512
142 fstat64(4, {st_mode=S_IFREG|0644, st_size=5396, ...}) = 0
143 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320\v\0\0004\0\0\0"..., 512) = 512
144 fstat64(4, {st_mode=S_IFREG|0644, st_size=13944, ...}) = 0
145 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220\3\0\0004\0\0\0"..., 512) = 512
146 fstat64(4, {st_mode=S_IFREG|0644, st_size=5396, ...}) = 0
147 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\240\17\0\0004\0\0\0"..., 512) = 512
148 fstat64(4, {st_mode=S_IFREG|0644, st_size=22128, ...}) = 0
149 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0000'\0\0004\0\0\0"..., 512) = 512
150 fstat64(4, {st_mode=S_IFREG|0644, st_size=75356, ...}) = 0
151 fstat64(4, {st_mode=S_IFREG|0644, st_size=71399, ...}) = 0
152 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\0\17\0\0004\0\0\0"..., 512) = 512
153 fstat64(4, {st_mode=S_IFREG|0644, st_size=38144, ...}) = 0
154 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0@\22\0\0004\0\0\0"..., 512) = 512
155 fstat64(4, {st_mode=S_IFREG|0644, st_size=103964, ...}) = 0
156 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\360\30\0\0004\0\0\0"..., 512) = 512
157 fstat64(4, {st_mode=S_IFREG|0644, st_size=44184, ...}) = 0
158 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\0\6\0\0004\0\0\0"..., 512) = 512
159 fstat64(4, {st_mode=S_IFREG|0644, st_size=5640, ...}) = 0
160 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\240\4\0\0004\0\0\0"..., 512) = 512
161 fstat64(4, {st_mode=S_IFREG|0644, st_size=5496, ...}) = 0
162 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0P\4\0\0004\0\0\0"..., 512) = 512
163 fstat64(4, {st_mode=S_IFREG|0644, st_size=5400, ...}) = 0
164 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0`\4\0\0004\0\0\0"..., 512) = 512
165 fstat64(4, {st_mode=S_IFREG|0644, st_size=9640, ...}) = 0
166 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\240\3\0\0004\0\0\0"..., 512) = 512
167 fstat64(4, {st_mode=S_IFREG|0644, st_size=5400, ...}) = 0
168 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\240\3\0\0004\0\0\0"..., 512) = 512
169 fstat64(4, {st_mode=S_IFREG|0644, st_size=5400, ...}) = 0
170 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\200\10\0\0004\0\0\0"..., 512) = 512
171 fstat64(4, {st_mode=S_IFREG|0644, st_size=9640, ...}) = 0
172 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\260\n\0\0004\0\0\0"..., 512) = 512
173 fstat64(4, {st_mode=S_IFREG|0644, st_size=9704, ...}) = 0
174 fstat64(4, {st_mode=S_IFREG|0644, st_size=71399, ...}) = 0
175 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\3405\0\0004\0\0\0"..., 512) = 512
176 fstat64(4, {st_mode=S_IFREG|0644, st_size=121640, ...}) = 0
177 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220\r\0\0004\0\0\0"..., 512) = 512
178 fstat64(4, {st_mode=S_IFREG|0644, st_size=13992, ...}) = 0
179 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220\10\0\0004\0\0\0"..., 512) = 512
180 fstat64(4, {st_mode=S_IFREG|0644, st_size=13776, ...}) = 0
181 read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\240\7\0\0004\0\0\0"..., 512) = 512
182 fstat64(4, {st_mode=S_IFREG|0644, st_size=9588, ...}) = 0
183 fstat64(4, {st_mode=S_IFREG|0644, st_size=8982, ...}) = 0
184 read(4, "! $Xorg: XKeysymDB,v 1.3 2000/08"..., 8982) = 8982
185 ioctl(4, VIDIOC_QUERYCAP or VT_OPENQRY, 0x9b40998) = -1EINVAL (Invalid argument)186 ioctl(4, VIDIOC_QUERYCAP or VT_OPENQRY, 0xbfaccd44) = 0
187 ioctl(4, VIDIOC_G_FMT or VT_SENDSIG, 0xbfaccc78) = 0
188 ioctl(4, VIDIOC_ENUM_FMT or VT_SETMODE, 0xbfaccbec) = 0
189 ioctl(4, 0xc02c564a, 0xbfaccb58)        = -1EINVAL (Invalid argument)190 ioctl(4, VIDIOC_ENUM_FMT or VT_SETMODE, 0xbfaccbec) = 0
191 ioctl(4, 0xc02c564a, 0xbfaccb58)        = -1EINVAL (Invalid argument)192 ioctl(4, VIDIOC_ENUM_FMT or VT_SETMODE, 0xbfaccbec) = 0
193 ioctl(4, 0xc02c564a, 0xbfaccb58)        = -1EINVAL (Invalid argument)194 ioctl(4, VIDIOC_ENUM_FMT or VT_SETMODE, 0xbfaccbec) = 0
195 ioctl(4, VIDIOC_ENUM_FMT or VT_SETMODE, 0xbfaccbec) = 0
196 ioctl(4, VIDIOC_ENUM_FMT or VT_SETMODE, 0xbfaccbec) = 0
197 ioctl(4, VIDIOC_ENUM_FMT or VT_SETMODE, 0xbfaccbec) = -1EINVAL (Invalid argument)198 ioctl(4, VIDIOC_QUERYCAP or VT_OPENQRY, 0xbfaccb84) = 0
199 ioctl(4, VIDIOC_G_INPUT, 0xbfacca2c)    = 0
200 ioctl(4, VIDIOC_ENUMINPUT, 0xbfacca2c)  = 0
201 fstat64(4, {st_mode=S_IFCHR|0660, st_rdev=makedev(81, 0), ...}) = 0
202 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0xbfacca78) = -1EINVAL (Invalid argument)203 ioctl(4, VIDIOC_QUERYCAP or VT_OPENQRY, 0x9b40998) = 0
204 fcntl64(4, F_SETFD, FD_CLOEXEC)         = 0
205 ioctl(4, VIDIOC_ENUMINPUT, 0x9b40acc)   = 0
206 ioctl(4, VIDIOC_ENUMINPUT, 0x9b40b18)   = 0
207 ioctl(4, VIDIOC_ENUMINPUT, 0x9b40b64)   = 0
208 ioctl(4, VIDIOC_ENUMINPUT, 0x9b40bb0)   = 0
209 ioctl(4, VIDIOC_ENUMINPUT, 0x9b40bfc)   = -1EINVAL (Invalid argument)210 ioctl(4, VIDIOC_ENUMSTD, 0x9b40f8c)     = 0
211 ioctl(4, VIDIOC_ENUMSTD, 0x9b40fcc)     = 0
212 ioctl(4, VIDIOC_ENUMSTD, 0x9b4100c)     = 0
213 ioctl(4, VIDIOC_ENUMSTD, 0x9b4104c)     = 0
214 ioctl(4, VIDIOC_ENUMSTD, 0x9b4108c)     = 0
215 ioctl(4, VIDIOC_ENUMSTD, 0x9b410cc)     = 0
216 ioctl(4, VIDIOC_ENUMSTD, 0x9b4110c)     = 0
217 ioctl(4, VIDIOC_ENUMSTD, 0x9b4114c)     = -1EINVAL (Invalid argument)218 ioctl(4, VIDIOC_ENUM_FMT or VT_SETMODE, 0x9b4138c) = 0
219 ioctl(4, VIDIOC_ENUM_FMT or VT_SETMODE, 0x9b413cc) = 0
220 ioctl(4, VIDIOC_ENUM_FMT or VT_SETMODE, 0x9b4140c) = 0
221 ioctl(4, VIDIOC_ENUM_FMT or VT_SETMODE, 0x9b4144c) = 0
222 ioctl(4, VIDIOC_ENUM_FMT or VT_SETMODE, 0x9b4148c) = 0
223 ioctl(4, VIDIOC_ENUM_FMT or VT_SETMODE, 0x9b414cc) = 0
224 ioctl(4, VIDIOC_G_PARM, 0x9b40a00)      = 0
225 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41b8c) = 0
226 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41bd0) = 0
227 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41c14) = 0
228 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41c58) = 0
229 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41c9c) = -1EINVAL (Invalid argument)230 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41ce0) = 0
231 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41d24) = -1EINVAL (Invalid argument)232 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41d68) = -1EINVAL (Invalid argument)233 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41dac) = -1EINVAL (Invalid argument)234 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41df0) = -1EINVAL (Invalid argument)235 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41e34) = -1EINVAL (Invalid argument)236 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41e78) = -1EINVAL (Invalid argument)237 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41ebc) = -1EINVAL (Invalid argument)238 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41f00) = -1EINVAL (Invalid argument)239 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41f44) = -1EINVAL (Invalid argument)240 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41f88) = -1EINVAL (Invalid argument)241 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41fcc) = -1EINVAL (Invalid argument)242 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42010) = -1EINVAL (Invalid argument)243 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42054) = -1EINVAL (Invalid argument)244 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42098) = -1EINVAL (Invalid argument)245 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b420dc) = -1EINVAL (Invalid argument)246 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42120) = -1EINVAL (Invalid argument)247 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42164) = -1EINVAL (Invalid argument)248 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b421a8) = -1EINVAL (Invalid argument)249 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b421ec) = -1EINVAL (Invalid argument)250 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42230) = -1EINVAL (Invalid argument)251 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42274) = -1EINVAL (Invalid argument)252 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b422b8) = -1EINVAL (Invalid argument)253 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b422fc) = -1EINVAL (Invalid argument)254 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42340) = -1EINVAL (Invalid argument)255 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42384) = -1EINVAL (Invalid argument)256 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b423c8) = -1EINVAL (Invalid argument)257 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b4240c) = -1EINVAL (Invalid argument)258 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42450) = -1EINVAL (Invalid argument)259 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42494) = -1EINVAL (Invalid argument)260 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b424d8) = -1EINVAL (Invalid argument)261 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b4251c) = -1EINVAL (Invalid argument)262 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42560) = -1EINVAL (Invalid argument)263 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b425a4) = -1EINVAL (Invalid argument)264 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b425e8) = -1EINVAL (Invalid argument)265 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b4262c) = -1EINVAL (Invalid argument)266 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42670) = -1EINVAL (Invalid argument)267 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b426b4) = -1EINVAL (Invalid argument)268 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b426f8) = -1EINVAL (Invalid argument)269 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b4273c) = -1EINVAL (Invalid argument)270 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42780) = -1EINVAL (Invalid argument)271 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b427c4) = -1EINVAL (Invalid argument)272 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42808) = -1EINVAL (Invalid argument)273 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b4284c) = -1EINVAL (Invalid argument)274 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42890) = -1EINVAL (Invalid argument)275 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b428d4) = -1EINVAL (Invalid argument)276 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42918) = -1EINVAL (Invalid argument)277 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b4295c) = -1EINVAL (Invalid argument)278 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b429a0) = -1EINVAL (Invalid argument)279 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b429e4) = -1EINVAL (Invalid argument)280 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42a28) = -1EINVAL (Invalid argument)281 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42a6c) = -1EINVAL (Invalid argument)282 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42ab0) = -1EINVAL (Invalid argument)283 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42af4) = -1EINVAL (Invalid argument)284 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42b38) = -1EINVAL (Invalid argument)285 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42b7c) = -1EINVAL (Invalid argument)286 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42bc0) = -1EINVAL (Invalid argument)287 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42c04) = -1EINVAL (Invalid argument)288 ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b42c48) = -1EINVAL (Invalid argument)289 ioctl(4, VIDIOC_G_STD, 0xbfacce08)      = 0
290 ioctl(4, VIDIOC_G_INPUT, 0xbfacce1c)    = 0
291 ioctl(4, MATROXFB_G_TVOCTRL or VIDIOC_G_CTRL, 0xbfacce14) = 0
292 ioctl(4, MATROXFB_G_TVOCTRL or VIDIOC_G_CTRL, 0xbfacce14) = 0
293 ioctl(4, MATROXFB_G_TVOCTRL or VIDIOC_G_CTRL, 0xbfacce14) = 0
294 ioctl(4, MATROXFB_G_TVOCTRL or VIDIOC_G_CTRL, 0xbfacce14) = 0
295 ioctl(4, MATROXFB_G_TVOCTRL or VIDIOC_G_CTRL, 0xbfacce24) = 0
296 ioctl(4, VIDIOC_TRY_FMT, 0x9b42ca4)     = 0
297 ioctl(4, VIDIOC_S_FMT or VT_RELDISP, 0xbfacc754) = 0
298 ioctl(4, VIDIOC_TRY_FMT, 0x9b42ca4)     = 0
299 ioctl(4, VIDIOC_REQBUFS or VT_DISALLOCATE, 0x9b42d80) = 0
300 ioctl(4, VIDIOC_QUERYBUF or VT_RESIZE, 0x9b42d94) = 0
301 ioctl(4, VIDIOC_QUERYBUF or VT_RESIZE, 0x9b42dd8) = 0
302 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
303 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
304 ioctl(4, VIDIOC_STREAMON, 0xbfacca2c)   = 0
305 ioctl(4, MATROXFB_S_TVOCTRL or VIDIOC_S_CTRL, 0xbfacce10) = 0
306 ioctl(4, MATROXFB_S_TVOCTRL or VIDIOC_S_CTRL, 0xbfacce10) = 0
307 ioctl(4, MATROXFB_S_TVOCTRL or VIDIOC_S_CTRL, 0xbfacce10) = 0
308 ioctl(4, MATROXFB_S_TVOCTRL or VIDIOC_S_CTRL, 0xbfacce10) = 0
309 ioctl(4, VIDIOC_S_INPUT, 0xbfacce84)    = 0
310 ioctl(4, VIDIOC_S_STD, 0x9b40f90)       = 0
311 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
312 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
313 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
314 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
315 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
316 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
317 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
318 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
319 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
320 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
321 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
322 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
323 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
324 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
325 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
326 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
327 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
328 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
329 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
330 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
331 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
332 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
333 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
334 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
335 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
336 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
337 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
338 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
339 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
340 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
341 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
342 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
343 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
344 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
345 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
346 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
347 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
348 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
349 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
350 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
351 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
352 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
353 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
354 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
355 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
356 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
357 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
358 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
359 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
360 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
361 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
362 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
363 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
364 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
365 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
366 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
367 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
368 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
369 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
370 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
371 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
372 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
373 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
374 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
375 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
376 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
377 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
378 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
379 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
380 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
381 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
382 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
383 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
384 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
385 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
386 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
387 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
388 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
389 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
390 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
391 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
392 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
393 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
394 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
395 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
396 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
397 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
398 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
399 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
400 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
401 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
402 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
403 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
404 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
405 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
406 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
407 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
408 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
409 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
410 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
411 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
412 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
413 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
414 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
415 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
416 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
417 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
418 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
419 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
420 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
421 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
422 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
423 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
424 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
425 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
426 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
427 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
428 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
429 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
430 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
431 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
432 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
433 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
434 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
435 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
436 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
437 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
438 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
439 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
440 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
441 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
442 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
443 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
444 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
445 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
446 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
447 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
448 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
449 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
450 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
451 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
452 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
453 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
454 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
455 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
456 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
457 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
458 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
459 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
460 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
461 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
462 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
463 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
464 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
465 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
466 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
467 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
468 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
469 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
470 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
471 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
472 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
473 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
474 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
475 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
476 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
477 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
478 ioctl(4, VIDIOC_QBUF, 0x9b42dd8)        = 0
479 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
480 ioctl(4, VIDIOC_QBUF, 0x9b42d94)        = 0
481 ioctl(4, VIDIOC_DQBUF, 0xbfaccd00)      = 0
482 ioctl(4, VIDIOC_STREAMOFF, 0xbfacc53c)  = 0
483 ioctl(4, VIDIOC_QUERYBUF or VT_RESIZE, 0xbfacc48c) = 0
484 ioctl(4, VIDIOC_QUERYBUF or VT_RESIZE, 0xbfacc48c) = 0
485 ioctl(4, VIDIOC_REQBUFS or VT_DISALLOCATE, 0x9b42d80) = -1EINVAL (Invalid argument)486 ioctl(4, VIDIOC_TRY_FMT, 0x9b42ca4)     = -1EINVAL (Invalid argument)487 ioctl(4, VIDIOC_TRY_FMT, 0xbfacc000)    = 0
488 ioctl(4, VIDIOC_TRY_FMT, 0xbfacc000)    = 0
489 ioctl(4, VIDIOC_TRY_FMT, 0xbfacc000)    = 0
490 ioctl(4, VIDIOC_TRY_FMT, 0xbfacc000)    = 0
491 ioctl(4, VIDIOC_TRY_FMT, 0xbfacc000)    = 0
492 ioctl(4, VIDIOC_TRY_FMT, 0xbfacc000)    = 0
493 ioctl(4, VIDIOC_REQBUFS or VT_DISALLOCATE, 0xbfacc70c) = 0
494 ioctl(4, VIDIOC_QUERYBUF or VT_RESIZE, 0xbfacc61c) = 0
495 ioctl(4, VIDIOC_QUERYBUF or VT_RESIZE, 0xbfacc61c) = 0
496 ioctl(4, VIDIOC_QBUF, 0xbfacc61c)       = 0
497 ioctl(4, VIDIOC_QBUF, 0xbfacc61c)       = 0
498 ioctl(4, VIDIOC_STREAMON, 0xbfacc65c)   = 0
499 ioctl(4, VIDIOC_DQBUF, 0xbfacc6c8)      = 0
500 ioctl(4, VIDIOC_QBUF, 0xbfacc61c)       = 0

View Code

xawtv.log文件中open()函数之后调用了ioctl(4, VIDIOC_QUERYCAP, ...),因此文件描述符操作ioctl(4, VIDIOC_QUERYCAP, ...)上面的所有行不会涉及驱动底层

最后,我们可以根据文件描述符操作文件、xawtv.log和SI4工程确定ioctl()执行过程:

open("/dev/video0", O_RDWR|O_LARGEFILE)    /*1. 打开video0*/ioctl(4, VIDIOC_QUERYCAP         /*2. 列举性能*/ioctl(4, VIDIOC_G_FMT            /*3. 获得格式*/
for()-> ioctl(4, VIDIOC_ENUM_FMT    /*4. 列举格式*/ioctl(4, VIDIOC_QUERYCAP         /*5.*/ioctl(4, VIDIOC_G_INPUT          /*6. 获取当前输入源*/ioctl(4, VIDIOC_ENUMINPUT        /*7. 列举输入源*/ioctl(4, VIDIOC_QUERYCTRL        /*8. 查询属性,如亮度范围、对比度范围*/ioctl(4, VIDIOC_QUERYCAP         /*9.*/ioctl(4, VIDIOC_ENUMINPUT        /*10.*/
for()-> ioctl(4, VIDIOC_ENUMINPUT   /*11.*/
for()-> ioctl(4, VIDIOC_ENUMSTD     /*12.列举标准*/
for()-> ioctl(4, VIDIOC_ENUM_FMT    /*13.*/ioctl(4, VIDIOC_G_PARM           /*14.*/
for()-> ioctl(4, VIDIOC_QUERYCTRL   /*15.*/ioctl(4, VIDIOC_G_STD            /*16.获取当前使用的标准*/ioctl(4, VIDIOC_G_INPUT          /*17.*/ioctl(4, VIDIOC_G_CTRL           /*18.获取当前所使用的属性*/ioctl(4, VIDIOC_TRY_FMT          /*19.测试摄像头支持的格式*/ioctl(4, VIDIOC_S_FMT            /*20.设置摄像头格式*/ioctl(4, VIDIOC_REQBUFS          /*21.请求系统分配缓冲区*/ioctl(4, VIDIOC_QUERYBUF         /*22.查询所分配的缓冲区*/
for()-> ioctl(4, VIDIOC_QBUF        /*23.把缓冲区放入队列*/ioctl(4, VIDIOC_STREAMON         /*24.启动摄像头*/
for()-> ioctl(4, VIDIOC_S_CTRL      /*25.设置属性*/ioctl(4, VIDIOC_S_INPUT          /*26.设置输入源*/ioctl(4, VIDIOC_S_STD            /*27.设置标准*/
for()-> select(5, [4]               /*28.查询文件描述符4是否有数据*/-> ioctl(4, VIDIOC_DQBUF       /*29.把缓冲区从队列中取出*/-> /*处理数据*/-> ioctl(4, VIDIOC_QBUF        /*30.把缓冲区放入队列*/ioctl(4, VIDIOC_STREAMOFF        /*31.关闭摄像头*/

View Code

在分析完ioctl()的执行过程后,我们需要在SI4工程文件drv0-v4l2.c文件中搜索ioctl()各个宏,确定v4l2_ioctl_ops必需的函数指针:

/** 1~2被v4l2_open(char *device)调用*/open("/dev/video0", O_RDWR|O_LARGEFILE)    /*1. 打开video0*/ioctl(4, VIDIOC_QUERYCAP         /*2. 列举性能*//** 3~10没有看到调用过程,可能源码和应用程序不一致,略*//** 11~15被get_device_capabilities(h)调用*/
for()-> ioctl(4, VIDIOC_ENUMINPUT   /*11.*/
for()-> ioctl(4, VIDIOC_ENUMSTD     /*12.列举标准*/
for()-> ioctl(4, VIDIOC_ENUM_FMT    /*13.*/ioctl(4, VIDIOC_G_PARM           /*14.*/
for()-> ioctl(4, VIDIOC_QUERYCTRL   /*15.*//** 16~18被v4l2_read_attr()调用*/ioctl(4, VIDIOC_G_STD            /*16.获取当前使用的标准*/ioctl(4, VIDIOC_G_INPUT          /*17.*/ioctl(4, VIDIOC_G_CTRL           /*18.获取当前所使用的属性*//** 19~20被v4l2_overlay()调用*/ioctl(4, VIDIOC_TRY_FMT          /*19.测试摄像头支持的格式*/ioctl(4, VIDIOC_S_FMT            /*20.设置摄像头格式*//** 21~24被v4l2_start_streaming()调用*/ioctl(4, VIDIOC_REQBUFS          /*21.请求系统分配缓冲区*/ioctl(4, VIDIOC_QUERYBUF         /*22.查询所分配的缓冲区*/
for()-> ioctl(4, VIDIOC_QBUF        /*23.把缓冲区放入队列*/-> h->buf_me[i].data =mmap(...);
ioctl(4, VIDIOC_STREAMON         /*24.启动摄像头*//** 25~27被v4l2_write_attr()调用*/
ioctl(4, VIDIOC_S_CTRL           /*25.设置属性*/ioctl(4, VIDIOC_S_INPUT          /*26.设置输入源*/ioctl(4, VIDIOC_S_STD            /*27.设置标准*//** 28~29被v4l2_waiton()调用*  30被v4l2_queue_buffer()调用*  v4l2_waiton()和v4l2_queue_buffer()被v4l2_nextframe()调用*/
for()-> select(5, [4]               /*28.查询文件描述符4是否有数据*/-> ioctl(4, VIDIOC_DQBUF       /*29.把缓冲区从队列中取出*/-> /*处理数据,之前使用mmap()获得了缓冲区的地址*/-> ioctl(4, VIDIOC_QBUF        /*30.把缓冲区放入队列*/
/** 31被v4l2_stop_streaming()调用*/ioctl(4, VIDIOC_STREAMOFF        /*31.关闭摄像头*/

剩下这么多宏,有哪个是可以省略的呢?

我们现在要回到虚拟机内核的vivi.c中vivi_ioctl_ops逐个测试,测试方法为:注释某个函数指针,重新编译挂载,测试是否可以正常使用。

我在此不再一一测试,最终结果如下:

static const struct v4l2_ioctl_ops vivi_ioctl_ops ={/*表示它是一个摄像头设备。不可省略*/.vidioc_querycap=vidioc_querycap,#if 0/*列举、获取、设置输入源。可以省略,使用默认输入源*/.vidioc_enum_input=vidioc_enum_input,.vidioc_g_input=vidioc_g_input,.vidioc_s_input=vidioc_s_input,#endif/*列举、获得、测试、设置摄像头的数据格式。不可省略*/.vidioc_enum_fmt_vid_cap=vidioc_enum_fmt_vid_cap,.vidioc_g_fmt_vid_cap=vidioc_g_fmt_vid_cap,.vidioc_try_fmt_vid_cap=vidioc_try_fmt_vid_cap,.vidioc_s_fmt_vid_cap=vidioc_s_fmt_vid_cap,/*缓冲区操作:申请、查询、放入队列、取出队列。不可省略*/.vidioc_reqbufs=vidioc_reqbufs,.vidioc_querybuf=vidioc_querybuf,.vidioc_qbuf=vidioc_qbuf,.vidioc_dqbuf=vidioc_dqbuf,#if 0/*列举、获取、设置标准。可以省略* 列举、获取标准使用的是* video_device的tvnorms和current_norm*/.vidioc_s_std=vidioc_s_std,#endif/*启动、停止视频流。不可省略*/.vidioc_streamon=vidioc_streamon,.vidioc_streamoff=vidioc_streamoff,#if 0/*在内核日志中记录状态。可以省略*/.vidioc_log_status=v4l2_ctrl_log_status,/*子系统事件。可以省略*/.vidioc_subscribe_event=v4l2_ctrl_subscribe_event,.vidioc_unsubscribe_event=v4l2_event_unsubscribe,#endif};

八、数据的获取过程

本节使用v4l2.c进行分析,读者若对vb2感兴趣也可以分析vivi.c

1. 请求分配缓冲区,但此阶段其实只分配了videobuf_buffer

ioctl(4, VIDIOC_REQBUFS->solo_reqbufs-> videobuf_reqbufs(&fh->vidq, req);-> *size = solo_image_size(solo_dev);        /*设置图片size*/-> __videobuf_mmap_setup(q, count, size, req->memory);-> q->bufs[i] = videobuf_alloc_vb(q);    /*分配设置videobuf_buffer*/

2. 查询映射缓冲区,通过videobuf_buffer设置供上层使用的v4l2_buffer

ioctl(4, VIDIOC_QUERYBUF->videobuf_querybuf-> videobuf_status(q, b, q->bufs[b->index], q->type);-> b->flags |=V4L2_BUF_FLAG_MAPPED;-> b->field     = vb->field;-> b->timestamp = vb->ts;            /*v4l2_buffer*/

3. 真正分配缓冲区

mmap(NULL, h->buf_v4l2[i].length, ...)->solo_v4l2_mmap-> videobuf_mmap_mapper(&fh->vidq, vma);-> CALL(q, mmap_mapper, q, buf, vma)

4. 把缓冲区放入队列

ioctl(4, VIDIOC_QBUF-> videobuf_qbuf(&fh->vidq, buf);-> buf = q->bufs[b->index];-> solo_buf_prepare            /*设置video_device成员*/-> vb->width  = solo_dev->video_hsize;-> vb->height =solo_vlines(solo_dev);-> list_add_tail(&buf->stream, &q->stream)-> solo_buf_queue            /*把queue放到list_head*/-> list_add_tail(&vb->queue, &fh->vidq_active);

5. 启动摄像头

ioctl(4, VIDIOC_STREAMON->solo_streamon-> videobuf_streamon(&fh->vidq);-> solo_buf_queue            /*把queue放到list_head*/-> list_add_tail(&vb->queue, &fh->vidq_active);-> wake_up_interruptible_sync(&q->wait);

6. 查询是否有数据

select(h->fd + 1, &rdset, NULL, NULL, &tv)->solo_v4l2_poll-> videobuf_poll_stream(file, &fh->vidq, wait);-> poll_wait(file, &buf->done, wait);

唤醒此进程的是open()函数注册的solo_thread()函数

7. 从缓冲区中取数据

ioctl(4, VIDIOC_DQBUF->solo_dqbuf-> videobuf_dqbuf(&fh->vidq, buf, file->f_flags &O_NONBLOCK);-> stream_next_buffer(q, &buf, nonblocking);    /*在queue中获取有数据的缓冲区*/-> videobuf_status(q, b, buf, q->type);        /*把缓冲区的状态返回给应用层*/-> list_del(&buf->stream);

九、虚拟摄像头驱动程序编写过程

1. 使用video_device_alloc()分配video_device

2. 设置结构体成员

.fops

.ioctl_ops(里面需要设置11项)

如果要用内核提供的缓冲区操作函数,还需要构造一个videobuf_queue_ops

3. 使用video_register_device()注册video_device

我们可以仿照v4l2.c写一个虚拟摄像头驱动程序

源代码:

1 #include <linux/module.h>
2 #include <linux/delay.h>
3 #include <linux/errno.h>
4 #include <linux/fs.h>
5 #include <linux/kernel.h>
6 #include <linux/slab.h>
7 #include <linux/mm.h>
8 #include <linux/ioport.h>
9 #include <linux/init.h>
10 #include <linux/sched.h>
11 #include <linux/pci.h>
12 #include <linux/random.h>
13 #include <linux/version.h>
14 #include <linux/mutex.h>
15 #include <linux/videodev2.h>
16 #include <linux/dma-mapping.h>
17 #include <linux/interrupt.h>
18 #include <linux/kthread.h>
19 #include <linux/highmem.h>
20 #include <linux/freezer.h>
21 #include <media/videobuf-vmalloc.h>
22 #include <media/v4l2-device.h>
23 #include <media/v4l2-ioctl.h>
24
25 #define USE_DMA        0
26
27 static struct video_device *myvivi;28 static structv4l2_format myvivi_format;29 static structvideobuf_queue myvivi_vb_vidq;30 staticspinlock_t myvivi_slock;31 static structtimer_list myvivi_timer;32 static structlist_head myvivi_list_head;33
34 /**35 *   videobuf_queue_ops36 **/
37 /*ioctl VIDIOC_REQBUFS导致此函数被调用38 * 用于重新调整count和size39  */
40 static int myvivi_buf_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)41 {42     *size =myvivi_format.fmt.pix.sizeimage;43
44     if (*count < 4)45         *count = 4;46
47     return 0;48 }49
50 /*ioctl VIDIOC_QBUF导致此函数被调用51 * 它会填充video_buffer结构体并调用videobuf_iolock来分配内存52  */
53 static int myvivi_buf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enumv4l2_field field)54 {55     vb->size    =myvivi_format.fmt.pix.sizeimage;56
57     /*XXX: These properties only change when queue is idle*/
58     vb->width    =myvivi_format.fmt.pix.width;59     vb->height    =myvivi_format.fmt.pix.height;60     vb->bytesperline =myvivi_format.fmt.pix.bytesperline;61     vb->field  =field;62 #if USE_DMA
63     if (vb->state ==VIDEOBUF_NEEDS_INIT) {64         int rc =videobuf_iolock(vq, vb, NULL);65         if (rc < 0) {66             struct videobuf_dmabuf *dma =videobuf_to_dma(vb);67             videobuf_dma_unmap(vq->dev, dma);68 videobuf_dma_free(dma);69             vb->state =VIDEOBUF_NEEDS_INIT;70             returnrc;71 }72 }73 #endif
74     vb->state =VIDEOBUF_PREPARED;75
76     return 0;77 }78
79 /*ioctl VIDIOC_QBUF时:80 * 1. 调用buf_prepare()做准备工作81 * 2. 把buf放入stream队列82 * 3. 调用buf_queue(起通知、记录作用)83  */
84 static void myvivi_buf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)85 {86     vb->state =VIDEOBUF_QUEUED;87     list_add_tail(&vb->queue, &myvivi_list_head);88     /*使用的定时器,不需要唤醒*/
89 //wake_up_interruptible(&solo_dev->disp_thread_wait);
90 }91
92 /*APP不再使用队列时,用它来释放内存*/
93 static void myvivi_buf_release(struct videobuf_queue *vq, struct videobuf_buffer *vb)94 {95 #if USE_DMA
96     struct videobuf_dmabuf *dma =videobuf_to_dma(vb);97
98     videobuf_dma_unmap(vq->dev, dma);99 videobuf_dma_free(dma);100 #endif
101     vb->state =VIDEOBUF_NEEDS_INIT;102 }103
104
105 static struct videobuf_queue_ops solo_video_qops ={106     .buf_setup        =myvivi_buf_setup,107     .buf_prepare    =myvivi_buf_prepare,108     .buf_queue        =myvivi_buf_queue,109     .buf_release    =myvivi_buf_release,110 };111
112 /**113 *   v4l2_file_operations114 **/
115 static int myvivi_open(struct file *file)116 {117     videobuf_queue_vmalloc_init(&myvivi_vb_vidq, &solo_video_qops,118                    NULL, &myvivi_slock,119 V4L2_BUF_TYPE_VIDEO_CAPTURE,120 V4L2_FIELD_INTERLACED,121                    sizeof(structvideobuf_buffer), NULL, NULL);122     /*其他程序在此处执行thread,本程序在此处执行定时器*/
123     myvivi_timer.expires = jiffies + 1;124     add_timer(&myvivi_timer);125
126     return 0;127 }128
129 static int myvivi_close(struct file *file)130 {131     del_timer(&myvivi_timer);132     videobuf_stop(&myvivi_vb_vidq);133     videobuf_mmap_free(&myvivi_vb_vidq);134
135     return 0;136 }137
138 static ssize_t myvivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)139 {140     return videobuf_read_stream(&myvivi_vb_vidq, data, count, ppos, 0, file->f_flags &O_NONBLOCK);141 }142
143 static unsigned int myvivi_poll(struct file *file, struct poll_table_struct *wait)144 {145     return videobuf_poll_stream(file, &myvivi_vb_vidq, wait);146 }147
148 extern int videobuf_mmap_mapper(struct videobuf_queue *, struct vm_area_struct *);149 static int myvivi_mmap(struct file *file, struct vm_area_struct *vma)150 {151     return videobuf_mmap_mapper(&myvivi_vb_vidq, vma);152 }153
154 static const struct v4l2_file_operations myvivi_fops ={155     .owner            =THIS_MODULE,156     .open           =myvivi_open,157     .release        =myvivi_close,158     .read           =myvivi_read,159     .poll            =myvivi_poll,160     .unlocked_ioctl =video_ioctl2,161     .mmap           =myvivi_mmap,162 };163
164 /**165 *   v4l2_ioctl_ops166 **/
167 static int myvivi_querycap(struct file *file, void  *priv, struct v4l2_capability *cap)168 {169     strcpy(cap->driver, "myvivi");170     strcpy(cap->card, "myvivi");171     cap->version = 0x01;172     cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |V4L2_CAP_STREAMING;173     return 0;174 }175
176 static int myvivi_enum_fmt_vid_cap(struct file *file, void  *priv, struct v4l2_fmtdesc *f)177 {178     if (f->index)179         return -EINVAL;180
181     f->pixelformat =V4L2_PIX_FMT_YUYV;182     strlcpy(f->description, "4:2:2, packed, YUYV", sizeof(f->description));183
184     return 0;185 }186
187 static int myvivi_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)188 {189     memcpy(f, &myvivi_format, sizeof(myvivi_format));190     return 0;191 }192
193 static int myvivi_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)194 {195     enumv4l2_field field;196     unsigned intmax_width, max_height;197
198     if (f->fmt.pix.pixelformat !=V4L2_PIX_FMT_YUYV)199         return -EINVAL;200
201     field = f->fmt.pix.field;202     if (field ==V4L2_FIELD_ANY) {203         field =V4L2_FIELD_INTERLACED;204 }205     else if (V4L2_FIELD_INTERLACED !=field) {206         return -EINVAL;207 }208     f->fmt.pix.field =field;209
210     max_width    = 1024;211     max_height    = 768;212
213     v4l_bound_align_image(&f->fmt.pix.width, 48, max_width, 2,214                   &f->fmt.pix.height, 32, max_height, 0, 0);215     f->fmt.pix.bytesperline =
216         (f->fmt.pix.width * 16) >> 3;217     f->fmt.pix.sizeimage =
218         f->fmt.pix.height * f->fmt.pix.bytesperline;219     f->fmt.pix.colorspace =V4L2_COLORSPACE_SMPTE170M;220
221     return 0;222 }223
224 static int myvivi_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)225 {226     intret;227     if (videobuf_queue_is_busy(&myvivi_vb_vidq))228         return -EBUSY;229
230     ret =myvivi_try_fmt_vid_cap(file, priv, f);231     if (ret < 0)232         returnret;233
234     memcpy(&myvivi_format, f, sizeof(myvivi_format));235
236     return 0;237 }238
239 static int myvivi_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p)240 {241     return videobuf_reqbufs(&myvivi_vb_vidq, p);242 }243
244 static int myvivi_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)245 {246     return videobuf_querybuf(&myvivi_vb_vidq, p);247 }248
249 static int myvivi_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)250 {251     return videobuf_qbuf(&myvivi_vb_vidq, p);252 }253
254 static int myvivi_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)255 {256     return videobuf_dqbuf(&myvivi_vb_vidq, p, file->f_flags &O_NONBLOCK);257 }258
259 static int myvivi_streamon(struct file *file, void *priv, enumv4l2_buf_type i)260 {261     return videobuf_streamon(&myvivi_vb_vidq);262 }263
264 static int myvivi_streamoff(struct file *file, void *priv, enumv4l2_buf_type i)265 {266     videobuf_streamoff(&myvivi_vb_vidq);267     return 0;268 }269
270 static const struct v4l2_ioctl_ops myvivi_ioctl_ops ={271     .vidioc_querycap      =myvivi_querycap,272     .vidioc_enum_fmt_vid_cap  =myvivi_enum_fmt_vid_cap,273     .vidioc_g_fmt_vid_cap     =myvivi_g_fmt_vid_cap,274     .vidioc_try_fmt_vid_cap   =myvivi_try_fmt_vid_cap,275     .vidioc_s_fmt_vid_cap     =myvivi_s_fmt_vid_cap,276     .vidioc_reqbufs       =myvivi_reqbufs,277     .vidioc_querybuf      =myvivi_querybuf,278     .vidioc_qbuf          =myvivi_qbuf,279     .vidioc_dqbuf         =myvivi_dqbuf,280     .vidioc_streamon      =myvivi_streamon,281     .vidioc_streamoff     =myvivi_streamoff,282 };283
284 static void myvivi_release(struct video_device *vdev)285 {286     /*myvivi_exit()中调用了video_device_release()287 * 因此myvivi->release不需要设置为video_device_release288      */
289 }290
291 /*此函数用于实现其他文件的thread()*/
292 static void myvivi_timerfunc(unsigned longarg)293 {294     struct videobuf_buffer *vb;295     void *vbuf;296
297     if (list_empty(&myvivi_list_head))298         gotofail;299
300     vb = list_first_entry(&myvivi_list_head, structvideobuf_buffer,301 queue);302
303     if (!waitqueue_active(&vb->done))304         gotofail;305
306     /*Fill buffer*/
307     vbuf =videobuf_to_vmalloc(vb);308     if (!vbuf)309         gotofail;310
311     /*由于是虚拟摄像头驱动,所以假装有数据*/
312     memset(vbuf, 0, vb->size);313
314     vb->field_count++;315     do_gettimeofday(&vb->ts);316     vb->state =VIDEOBUF_DONE;317
318     /*把videobuf从队列中删除*/
319     list_del(&vb->queue);320
321     /*唤醒videobuf->done上的进程*/
322     wake_up(&vb->done);323
324 fail:325     /*30帧/秒*/
326     mod_timer(&myvivi_timer, jiffies + HZ / 30);327 }328
329 static int __init myvivi_init(void)330 {331     intret;332
333     myvivi =video_device_alloc();334
335     myvivi->release        =myvivi_release,336     myvivi->fops        = &myvivi_fops;337     myvivi->ioctl_ops     = &myvivi_ioctl_ops;338
339     /*初始化spinlock*/
340     spin_lock_init(&myvivi_slock);341     /*初始化timer_list*/
342     init_timer(&myvivi_timer);343     myvivi_timer.function =myvivi_timerfunc;344     /*初始化list_head*/
345     INIT_LIST_HEAD(&myvivi_list_head);346
347     ret = video_register_device(myvivi, VFL_TYPE_GRABBER, -1);348     if (ret < 0) {349 video_device_release(myvivi);350         returnret;351 }352
353     return 0;354 }355
356 static void __exit myvivi_exit(void)357 {358 video_unregister_device(myvivi);359 video_device_release(myvivi);360 }361
362 module_init(myvivi_init);363 module_exit(myvivi_exit);364 MODULE_LICENSE("GPL");

View Code

Makefile:

1 KERN_DIR = /work/itop4412/tools/linux-3.5
2
3 all:4     make -C $(KERN_DIR) M=`pwd` modules5
6 clean:7     make -C $(KERN_DIR) M=`pwd` modules clean8     rm -rf modules.order9
10 obj-m    += videobuf-vmalloc.o11 obj-m    += myvivi.o

View Code

由于是虚拟摄像头,所以源代码中的摄像头参数和数据格式是根据内核规则随意选择的,参数的确定和选取会在下一章进行介绍

本章内容较为混乱,推荐读者自行分析linux/drivers/staging/media/solo6x10/v4l2.c第八节:数据的获取过程体验各个过程的调用关系

转载于:https://www.cnblogs.com/Lioker/p/11323630.html

二十四、V4L2框架主要结构体分析和虚拟摄像头驱动编写相关推荐

  1. 【C语言进阶深度学习记录】二十四 指针与数组的本质分析一

    文章目录 1 回顾--数组的本质 2 指针的运算 2.1 指针运算代码案例分析 3 指针的比较 3.1 指针运算的应用代码案例分析 4 总结 1 回顾–数组的本质 在之前的文章,已经学习了数组的本质分 ...

  2. BetaFlight模块设计之二十四:transponder任务分析

    BetaFlight模块设计之二十四:transponder任务分析 transponder任务 配置情况 硬件配置 驱动配置 业务配置 初始化 MSP协议 三种IR transponder type ...

  3. 【软件开发底层知识修炼】二十五 ABI之函数调用约定二之函数返回值为结构体时的约定

    上一篇文章学习了几种函数调用约定的区别,点击链接查看上一篇文章:[软件开发底层知识修炼]二十四 ABI之函数调用约定 本篇文章继续学习函数调用约定中,关于函数返回值的问题.当函数返回值为结构体时,函数 ...

  4. C语言试题五十二之学生的记录由学号和成绩组称个,n名大学生得数据已在主函数中放入结构体数组a中,请编写函数fun,它的功能时:按分数的高低排列学生的记录,高分在前。

    1. 题目 请编写一个函数void function(Student a[], int n),其功能时:学生的记录由学号和成绩组称个,n名大学生得数据已在主函数中放入结构体数组a中,请编写函数fun, ...

  5. [系统安全] 二十四.逆向分析之OllyDbg调试INT3断点、反调试、硬件断点与内存断点

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  6. 华文行楷字帖欣赏_任政书法:行楷字帖《二十四孝组诗》集字版,美不胜收!...

    原标题:任政书法:行楷字帖<二十四孝组诗>集字版,美不胜收! 本次小编分享:任政行楷书法字帖欣赏<二十四孝组诗>集字版图片24张,<二十四孝>集虞舜.黄庭坚等二十四 ...

  7. java从入门到精通二十四(三层架构完成增删改查)

    java从入门到精通二十四(三层架构完成增删改查) 前言 环境准备 创建web项目结构 导入依赖和配置文件 创建层次模型 实现查询 实现添加 实现修改 完成删除 做一个用户登录验证 会话技术 cook ...

  8. 【Visual C++】游戏开发五十七 浅墨DirectX教程二十四 打造游戏GUI界面(二)

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/16922703 作者:毛星 ...

  9. J2EE进阶(二十四)JBoss Web和 Tomcat的区别

    J2EE进阶(二十四)JBoss Web和 Tomcat的区别 在Web2.0的浪潮中,各种页面技术和框架不断涌现,为服务器端的基础架构提出了更高的稳定性和可扩展性的要求.近年来,作为开源中间件的全球 ...

最新文章

  1. FPGA逻辑设计回顾(8)单比特信号的CDC处理方式之Toggle同步器
  2. 时间被空间和运动度量
  3. PHP多种序列化/反序列化的方法 json_encode json_decode
  4. Redis事务与监控
  5. .NET开发人员如何开始使用ML.NET
  6. java获取主机信息大全,网络编程:Java获取网络主机信息
  7. 【CodeForces - 569B】Inventory (标记,乱搞)
  8. PYTHON网络爬虫与信息提取[网络爬虫协议](单元二)
  9. tomcat 使用 memcached管理session ,并且实现统一登录
  10. Go语言基础进阶—程序结构—包和文件
  11. windows 8 Skydrive
  12. Promise及其应用
  13. html人物属性代码,辐射4初始人物超强属性代码一览
  14. 使用Graham扫描法获取一个平面点集的凸包
  15. python制作有道翻译软件
  16. ViewBinding 与 Kotlin 委托双剑合璧
  17. 九招教你完全了解液晶拼接屏
  18. sdut 1309 不老的传说问题(区间DP,难,值得好好看)
  19. 2020-2021的瞻前顾后
  20. 【数据可视化】条形统计图

热门文章

  1. lintel安装成功记与血泪史
  2. 大快搜索大数据可视化平台监控功能深度解析
  3. 水工建筑物类毕业论文文献包含哪些?
  4. qt制作软键盘(虚拟键盘)
  5. 成长笔记1:三层难度步步进阶,我用21部原版动画,带娃积累2000词汇
  6. SPC58芯片的嵌入式开发准备工作——SPC5Studio与Debug软件的安装
  7. 一篇搞懂Java多线程运行机制
  8. python删除文件部分内容_使用Python删除文本文件中的部分内容
  9. 断点回归matlab,断点回归求助 - Stata专版 - 经管之家(原人大经济论坛)
  10. Window对象的说明》