从零写USB摄像头驱动之实现数据传输1_框架
来源:互联网 发布:驯化狼 知乎 编辑:程序博客网 时间:2024/06/15 00:24
dmesg命令缺点:
1 每次都去要输入查看
2 驱动程序有问题导致内核崩溃,无法私有dmesg命令
A. 设置ubuntu让它从串口0输出printk信息
a. 设置vmware添加serial port, 使用文件作为串口
b. 启动ubuntu,修改/etc/default/grub
vi /etc/default/grubGRUB_CMDLINE_LINUX_DEFAULT=""GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,115200n8"
sudo update-grubsudo reboot
c. ubuntu禁止root用户登录
先修改root密码: sudo passwd root
然后执行”su root”就可以用root登录了
d. echo "8 4 1 7" > /proc/sys/kernel/printk
完成以上四步就可以在输出文件看到内核的信息
B. 写代码:
1.构造一个usb_driver2.设置 probe: 2.1. 分配video_device:video_device_alloc 2.2. 设置 .fops .ioctl_ops (里面需要设置11项) 如果要用内核提供的缓冲区操作函数,还需要构造一个videobuf_queue_ops 2.3. 注册: video_register_device 3.注册: usb_register
注:id_table: 表示支持哪些USB设备
参考 myvivi.c写myuvc.c
static int myuvc_probe(struct usb_interface *intf, const struct usb_device_id *id){ ... if(cnt == 2) //myuvc_ids有VideoControl Interface、VideoStreaming Interface,在第二个注册 { /*1.分配一个video_device结构体*/ myuvc_vdev =video_device_alloc(); /*2.设置*/ /*2.1*/ myuvc_vdev->release =myuvc_release; /*2.2*/ myuvc_vdev->fops =&myuvc_fops; /*2.3*/ myuvc_vdev->ioctl_ops =&myuvc_ioctl_ops; /*3.注册*/ video_register_device(myuvc_vdev,VFL_TYPE_GRABBER, -1); }}
注:缺少myuvc_release将无法注册,v4l2-dev.c
/* the release callback MUST be present */ if (WARN_ON(!vdev->release)) return -EINVAL;
写一个空函数
/**写一个myuvc_release空函数/ static void myuvc_release(struct video_device *vdev){}
static void myuvc_disconnect(struct usb_interface *intf){ static int cnt = 0; printk("myuvc_disconnect : cnt = %d\n", cnt++); if (cnt == 2) { video_unregister_device(myuvc_vdev); video_device_release(myuvc_vdev); } }
linux驱动之–fops的关联
http://blog.csdn.net/zssmcu/article/details/6746770
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 int myuvc_open(struct file *file){ return 0;}
myuvc_fops video_ioctl2 __video_do_ioctl v4l2_ioctl_ops 找到v4l2_ioctl_ops结构体
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, };
注:整体流程
应用程程序(app)打开设备(调用myuvc_open),确定(调用myuvc_vidioc_querycap)它是视频设备,获取格式信息,申请缓冲区,查询缓冲区信息,将缓冲区映射到用户空间,把缓冲区放入队列,
启动传输。
下面是关于myuvc_ioctl_ops结构体中各个单元的实现
/* A2 查询性能*/static int myuvc_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap){ return 0;}/* A3 列举支持哪种格式 */static int myuvc_vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f){ return 0;}/* A4 返回当前所使用的格式 */static int myuvc_vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f){ return (0);}/* A5 测试驱动程序是否支持某种格式 */static int myuvc_vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f){ return 0;}/* A6 */static int myuvc_vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f){ return 0;}/* A7 APP调用该ioctl让驱动程序分配若干个缓存, APP将从这些缓存中读到视频数据 */static int myuvc_vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p){ return 0;}/* A8 查询缓存状态, 比如地址信息(APP可以用mmap进行映射)*/static int myuvc_vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p){ return 0;}/* A10 把缓冲区放入队列, 底层的硬件操作函数将会把数据放入这个队列的缓存 */static int myuvc_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p){ return 0;}/* A11 启动传输 */static int myuvc_vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i){ return 0;}/* A13 APP通过poll/select确定有数据后, 把缓存从队列中取出来 */static int myuvc_vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p){ return 0;}/* * A14 之前已经通过mmap映射了缓存, APP可以直接读数据 * A15 再次调用myuvc_vidioc_qbuf把缓存放入队列 * A16 poll... *//* A17 停止 */static int myuvc_vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i){ return 0;}
插上摄像头,ls /dev/vid*
linux系统自动装载了摄像
sudo rmmod uvcvideo
su rootinsmod myuvc.koecho "8 4 1 7" > /proc/sys/kernel/printk
可以在输出文件看到内核的信息
阅读全文
0 0
- 从零写USB摄像头驱动之实现数据传输1_框架
- 从零写USB摄像头驱动之分析描述符
- 摄像头驱动之实现数据传输1_框架_学习笔记
- 摄像头驱动之实现数据传输2_简单函数_学习笔记
- 摄像头驱动之实现数据传输3_设置参数_学习笔记
- 摄像头驱动之实现数据传输5_调试_学习笔记
- linux应用项目(二)摄像头(2)从零写一个V4L2虚拟摄像头驱动之详细分析
- 摄像头驱动之实现数据传输4_URB_学习笔记
- USB摄像头驱动框架分析
- ALSA声卡10_从零编写之数据传输_学习笔记
- 摄像头驱动笔记3---从零写虚拟驱动(仿照vivi.c)
- 从零实现MVC框架之需求篇(1)
- linux设备驱动之USB数据传输分析
- linux设备驱动之USB数据传输分析
- linux设备驱动之USB数据传输分析
- linux设备驱动之USB数据传输分析
- 4.USB摄像头驱动框架分析
- 从0写USB摄像头驱动程序
- JavaScript,点击其他区域隐藏
- Ubuntu 14.04 下OpenDayLight SFC 配置
- crc32校验文件数据
- E
- linux 安装telnet命令及使用
- 从零写USB摄像头驱动之实现数据传输1_框架
- Listener refused the connection with the following error 错误解决
- 中层视觉:使用随机方法的分割与拟合
- Dubbo 并发调优的几个参数
- 查询中文时,mariadb报‘UnicodeEncodeError:'latin-1' codec can't encode character’
- 一些简单的程序
- DevOps助力云原生应用开发实战分享
- 高数 08.03 齐次方程
- 队列(链表实现)