LINUX摄像驱动三:从零开始写虚拟驱动

本文介绍如何在Ubuntu上从零开始编写虚拟摄像头驱动vivi,包括确定内核版本、下载并修改内核源码、解决编译问题、使用xawtv测试驱动,以及探讨函数队列和定时器的实现细节。
摘要由CSDN通过智能技术生成

测试虚拟摄像头vivi:
1. 确实ubuntu的内核版本

uname -a
Linux book-desktop 2.6.31-14-generic #48-Ubuntu SMP Fri Oct 16 14:04:26 UTC 2009 i686 GNU/Linux

2. 去www.kernel.org下载同版本的内核
https://www.kernel.org/pub/linux/kernel/
解压后把drivers/media/video目录取出
修改它的Makefile为:

KERN_DIR = /usr/src/linux-headers-2.6.31-14-generic

all:
        make -C $(KERN_DIR) M=`pwd` modules

clean:
        make -C $(KERN_DIR) M=`pwd` modules clean
        rm -rf modules.order

obj-m   += vivi.o
obj-m   += videobuf-core.o
obj-m   += videobuf-vmalloc.o
obj-m   += v4l2-common.o

3、 make
4、

sudo insmod videobuf-core.ko
sudo insmod videobuf-vmalloc.ko
sudo insmod v4l2-common.ko

发现在这里编译不通过!浪费我一晚上的时间;
解决方法:

sudo modprobe vivi
sudo rmmod vivi
sudo insmod ./vivi.ko

先安装Ubantu里面自带的vivi程序,它会把它所依赖的驱动程序安装进来

sudo rmmod vivi.ko

6、ls /dev/video*
7、xawtv -c /dev/videoX
假如你自己写的myvivi.ko编译出来之后,对应的是video1
那么就使用xawtv -c /dev/video1


video_ioctl2:
这是v4l2-ioctl.c提供的默认的标准的ioctl,最终就会调用到 我们在init函数里面所设置的结构体:myvivi_device->ioctl_ops = &myvivi_ioctl_ops;


1、函数里面定时器的问题:
add_timer 在哪里add呢?建议在open函数里面,由于我们写驱动程序的规则,这些资源只有在我们真正用到的时候才会去分配;

**先定义该结构体:**
static struct timer_list myvivi_timer
**在open函数里面:**
     myvivi_timer.expires = jiffies + 1;
     add_timer(&myvivi_timer);
**在close函数里面:**
     del_timer(&myvivi_timer);
**在Init函数里面:**
     /* 用定时器产生数据并唤醒进程 */
    init_timer(&myvivi_timer);
    myvivi_timer.function = myvivi_timer_function;

然后就是编写function函数,这个function完成了很多工作,显示的主要工作都是在myvivi_fillbuff()这个函数里面完成的!

function函数:
1. 构造数据: 从队列头部取出第1个videobuf, 填充数据
1.1 从本地队列取出第1个videobuf

这个函数就是从队列头部取出第一个video_buf
         vb = list_entry(myvivi_vb_local_queue.next,struct videobuf_buffer, queue);
    然后进行判断
A:该队列头是否为空
B:是否有人在等待这个缓冲区。在done这个位置,估计是判断它有无被设置
如果都不成立 goto out;

1.2 填充数据

   vbuf = videobuf_to_vmalloc(vb)
   myvivi_fillbuff(vb);
    主要是用了myvivi_fillbuf()函数,这个函数需要我们另自编写
    主要是这个状态要进行设置,不然会出错
        vb->state = VIDEOBUF_DONE;

1.3 把videobuf从本地队列中删除

list_del(&vb->queue);

2. 唤醒进程: 唤醒videobuf->done上的进程

wake_up(&vb->done);

3. 修改timer的超时时间 : 30fps, 1秒里有30帧数据:每1/30 秒产生一帧数据

mod_timer(&myvivi_timer, jiffies + HZ/30);

2、函数队列的问题
①:先讲本地队列

构造一个本地队列头:static struct list_head myvivi_vb_local_queue;
在初始化Init函数里面进行初始化:INIT_LIST_HEAD(&myvivi_vb_local_queue);


在myvivi_buffer_queue函数里 : 
把videobuf放入本地一个队列尾部 ,定时器处理函数就可以从本地队列取出videobuf
      list_add_tail(&vb->queue, &myvivi_vb_local_queue);
      
在timer_function函数里:从本地队列取出第1个videobuf
完成填充数据的操作后

   A: 把videobuf从本地队列中删除
         list_del(&vb->queue);
   B: 唤醒进程: 唤醒videobuf->done上的进程
         wake_up(&vb->done);

这样一来我们的videobuf就可以拿到本地进行编写填充数据,完了之后再放虎归山了!

②:
队列操作1:进行定义

static struct videobuf_queue myvivi_vb_vidqueue;

队列操作2::初始化
在open函数里面进行初始化:
用videobuf_queue_vmalloc_init函数进行队列

videobuf_queue_vmalloc_init(&myvivi_vb_vidqueue, &myvivi_video_qops,
                 NULL, &myvivi_queue_slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED,
                 sizeof(struct videobuf_buffer), NULL);

倒数第2个参数是buffer的头部大小,第四个函数是自旋锁,我们要事先定义它

这个函数的第四个参数是slock:自旋锁

 定义:static spinlock_t myvivi_queue_slock;
 初始化:在入口函数进行初始化,队列的定义/初始化一个队列(会用到一个spinlock)
              spin_lock_init(&myvivi_queue_slock);

这个函数值得深究!
既然是初始化,肯定就要有一系列相关的初始化操作。第二个参数就是对video的初始化操作

包含四个函数

        .buf_setup      = myvivi_buffer_setup, /* 计算大小以免浪费 */
        .buf_prepare    = myvivi_buffer_prepare,
        .buf_queue      = myvivi_buffer_queue,
        .buf_release    = myvivi_buffer_release,

四个函数官方解释为:

  /* 参考documentations/video4linux/v4l2-fram ework.txt:
 *     drivers\media\video\videobuf-core.c
 ops->buf_setup   - calculates the size of the video buffers and avoid they
            to waste more than some maximum limit of RAM;
 ops->buf_prepare - fills the video buffer structs and calls
            videobuf_iolock() to alloc and prepare mmaped memory;
 ops->buf_queue   - advices the driver that another buffer were
            requested (by read() or by QBUF);
 ops->buf_release - frees any buffer that were allocated.
 *

我自己的理解:

1:buf
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值