从零写USB摄像头驱动之实现数据传输1_框架
2017-12-13 17:35
603 查看
dmesg命令缺点:
1 每次都去要输入查看
2 驱动程序有问题导致内核崩溃,无法使用dmesg命令
A. 设置ubuntu让它从串口0输出printk信息
a. 设置vmware添加serial port, 使用文件作为串口
01.
02.
03.
b. 启动ubuntu,修改/etc/default/grub如下:
完成后
sudo insmod myuvc.ko //安装驱动
dmesg //查看信息
kernel_log.txt中并没有输出装载驱动的信息。
原因分析:cat /proc/sys/kernel/printk
c.修改打印级别
问题:
d. ubuntu禁止root用户登录
先修改root密码:
然后执行”su root”就可以用root登录了
B. 写代码:
usb摄像头驱动程序框架:
注:id_table: 表示支持哪些USB设备
关于2.2参考myvivi.c
参考 myvivi.c写myuvc.c
注:缺少myuvc_release将无法注册
这里写一个myuvc_release空函数:
linux驱动之–fops的关联
http://blog.csdn.net/zssmcu/article/details/6746770
由myuvc_fops 结构,接下里逐个完成 myuvc_open,video_ioctl2, myuvc_poll。
这里完成框架性的东西,不写内容
v4l2_ioctl_ops结构体调用过程:
注:整体流程
应用程程序(app)打开设备(调用myuvc_open),确定(调用myuvc_vidioc_querycap)它是视频设备,获取格式信息,申请缓冲区,查询缓冲区信息,将缓冲区映射到用户空间,把缓冲区放入队列,启动传输。
下面是关于myuvc_ioctl_ops结构体中各个单元的实现
rmmod myuvc.ko //删除以前的驱动,将usb摄像头插入电脑,可以看到usb设备。
ls /dev/vid*
linux系统自动装载了摄像头驱动,将它删除,装入myuvc.ko
可以在输出文件看到内核的信息
1 每次都去要输入查看
2 驱动程序有问题导致内核崩溃,无法使用dmesg命令
A. 设置ubuntu让它从串口0输出printk信息
a. 设置vmware添加serial port, 使用文件作为串口
01.
02.
03.
b. 启动ubuntu,修改/etc/default/grub如下:
vi /etc/default/grub GRUB_CMDLINE_LINUX_DEFAULT="" GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,115200n8" //可以从屏幕、串口0上输出信息
完成后
sudo update-grub //更新 sudo reboot //重启
sudo insmod myuvc.ko //安装驱动
dmesg //查看信息
kernel_log.txt中并没有输出装载驱动的信息。
原因分析:cat /proc/sys/kernel/printk
c.修改打印级别
echo "8 4 1 7" > /proc/sys/kernel/printk
问题:
d. ubuntu禁止root用户登录
先修改root密码:
sudo passwd root
然后执行”su root”就可以用root登录了
rmmod myuvc.ko insmod myuvc.ko dmesg
B. 写代码:
usb摄像头驱动程序框架:
1.构造一个usb_driver 2. .id_table: .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设备
关于2.2参考myvivi.c
static const struct v4l2_ioctl_ops myvivi_ioctl_ops = { // 表示它是一个摄像头设备 .vidioc_querycap = myvivi_vidioc_querycap, /* 用于列举、获得、测试、设置摄像头的数据的格式 */ .vidioc_enum_fmt_vid_cap = myvivi_vidioc_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap = myvivi_vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = myvivi_vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = myvivi_vidioc_s_fmt_vid_cap, /* 缓冲区操作: 申请/查询/放入队列/取出队列 */ .vidioc_reqbufs = myvivi_vidioc_reqbufs, .vidioc_querybuf = myvivi_vidioc_querybuf, .vidioc_qbuf = myvivi_vidioc_qbuf, .vidioc_dqbuf = myvivi_vidioc_dqbuf, // 启动/停止 .vidioc_streamon = myvivi_vidioc_streamon, .vidioc_streamoff = myvivi_vidioc_streamoff, };
参考 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将无法注册
video_register_device(myuvc_vdev, VFL_TYPE_GRABBER, -1);//在myuvc.c中 video_register_device_index /* the release callback MUST be present */ if (WARN_ON(!vdev->release)) return -EINVAL;
这里写一个myuvc_release空函数:
/**写一个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, };
由myuvc_fops 结构,接下里逐个完成 myuvc_open,video_ioctl2, myuvc_poll。
这里完成框架性的东西,不写内容
static int myuvc_open(struct file *file) { return 0; }
v4l2_ioctl_ops结构体调用过程:
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; }
rmmod myuvc.ko //删除以前的驱动,将usb摄像头插入电脑,可以看到usb设备。
ls /dev/vid*
linux系统自动装载了摄像头驱动,将它删除,装入myuvc.ko
sudo rmmod uvcvideo
su root insmod myuvc.ko echo "8 4 1 7" > /proc/sys/kernel/printk
可以在输出文件看到内核的信息
相关文章推荐
- 从零写USB摄像头驱动之实现数据传输3_设置参数
- 从零写USB摄像头驱动之实现数据传输2_简单函数
- 软件无线电实现的收音机,实测音质清晰,IQ数据采集及解调过程如下(RF前端e4000, ADC及USB数据传输rtl2830)
- (转)linux设备驱动之USB数据传输分析 一
- linux设备驱动之USB数据传输分析
- Android开发-通过ADB+Socket实现USB数据传输
- WebService CXF框架的使用(实现JSON与XML数据传输)
- ROS下获取USB免驱动高速摄像头图像数据
- (转)linux设备驱动之USB数据传输分析 二
- 和菜鸟一起学linux总线驱动之初识USB的数据传输方式
- linux设备驱动之USB数据传输分析
- 基于嵌入式linux的usb摄像头的驱动及采集程序的实现
- 和菜鸟一起学linux总线驱动之初识USB的数据传输方式
- Linux USB 驱动开发实例(一) —— USB摄像头驱动实现源码分析
- linux设备驱动之USB数据传输分析(续)
- 使用React前端框架结合js-ipfs-api实现IPFS的文本数据流传输
- linux设备驱动之USB数据传输分析 二
- 基于S3C2440的USB摄像头应用简单实现之应用层框架(一)
- USB摄像头驱动框架分析
- linux设备驱动之USB数据传输分析 一