从0写USB摄像头驱动程序
1.构造一个usb_driver结构体
.id_table
.probe
1.分配video_device结构体
2.设置
3.注册
2.下面具体分析probe函数中的内容:
定义:static struct video_device *myuvc_vdev;
myuvc_vdev=video_device_alloc();
注册:video_register_device(myuvc_vdev,VFL_TYPE_GRABBER,-1);
设置操作待会再说。
3.在myuvc_disconnect函数中:
Video_unregister_device(myuvc_vdev);
video_device_release(myuvc_vdev);
4.probe函数中的设置操作有:
myuvc_vdev->release=myuvc_release;
myuvc_vdev->fops=&myuvc_fops;
myuvc_vdev->ioctl_fops=&myuvc_ioctl_fops
涉及的定义有:
static const struct v4l2_file_operations myuvc_fops = {
.owner = THIS_MODULE,
.open = myuvc_open,
.release = myuvc_close,
.mmap = myuvc_mmap,
.ioctl = video_ioctl2, /* V4L2 ioctl handler */
.poll = myuvc_poll,
};
static const struct v4l2_ioctl_ops myuvc_ioctl_ops = {
// 表示它是一个摄像头设备
.vidioc_querycap = myuvc_vidioc_querycap,
/* 用于列举、获得、测试、设置摄像头的数据的格式 */
.vidioc_enum_fmt_vid_cap = myuvc_vidioc_enum_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = myuvc_vidioc_g_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = myuvc_vidioc_try_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = myuvc_vidioc_s_fmt_vid_cap,
/* 缓冲区操作: 申请/查询/放入队列/取出队列 */
.vidioc_reqbufs = myuvc_vidioc_reqbufs,
.vidioc_querybuf = myuvc_vidioc_querybuf,
.vidioc_qbuf = myuvc_vidioc_qbuf,
.vidioc_dqbuf = myuvc_vidioc_dqbuf,
// 启动/停止
.vidioc_streamon = myuvc_vidioc_streamon,
.vidioc_streamoff = myuvc_vidioc_streamoff,
};
当应用层调用open等函数时会执行驱动中myuvc_fops结构体中的相应函数;当应用层调用一些ioctl函数时会执行驱动的myuvc_fops结构体中的成员video_ioctl2,它又会去调用myuvc_ioctl_ops结构体中的相应ioctl函数。
5.注意:ioctl缓冲区操作步骤中:先分配缓冲区,然后再进行mmap地址映射,映射到用户空间中,然后再将缓冲区放入队列。
6.关于poll函数:APP通过poll/select确定有数据后,把缓存从队列中取出来。之前已经通过mmap映射了缓存,APP可以直接读数据。读完数据后再把换酬勤放入队列。然后进行上述循环。
如何打开虚拟机的USB服务:
先点击虚拟机界面中菜单栏中的VM选项。
VM->Removable Devices ->USB2.0Camera -> Connect
如果卸载ubuntu上原来的UVC驱动程序:
Rmmod uvcvideo
所谓的UVC规范就是接到电脑上不用装驱动的摄像头。
下面来细讲每个ioctl函数:
/****************************/
static int myuvc_vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
memset(cap, 0, sizeof *cap);
strcpy(cap->