* “本文写的是USB摄像机linux驱动层简单介绍,linux的USB驱动非常复杂,坑很大,搞懂全部的七八成就是大神级别的人物了。我刚开始上手UVC驱动非常晕,超多结构体,还是指针形式,封装层数庞大,各种bind,以前linux驱动基本没碰过,只看过开发板手册里的LED驱动,现在直接做USB驱动,只能一步步来,不心急。”*
我们现在要做的是驱动一个USB接口摄像机,所以写的是USB设备的代码,而不是USB主机host。
这个驱动名称可以称作Linux USB Gadget类软件。
Linux USB Gadget软件分为三层。这三层其中两层是与硬件无关的,分别是Gadget功能驱动层、USB设备层。UDC层与硬件有关。
代码很复杂,我们简化一下,三个层主要用到的结构体如下,各项参数设置都与他们有关系
Gadget功能驱动层:usb_composite_driver
USB设备层: usb_composite_dev与usb_gadget_driver
UDC层: usb_gadget
1. linux驱动程序框架
这是给新手看的,高手略过
module_init(webcam_init);//初始化
module_exit(webcam_cleanup);//卸载
本驱动是用的平台驱动,webcam_cleanup是卸载入口,很简单,我们先从简单的来
2. 两个入口
webcam_cleanup(void)
{
usb_composite_unregister(&webcam_driver);
}
里面调用的是usb_gadget_unregister_driver方法,这是Linux USB Gadget系统的方法,我们完全不用看,了解他的作用就行。
接下来看
webcam_init(void)
{
return usb_composite_probe(&webcam_driver, webcam_bind);
}
代码很简单,就一个函数,很轻松,这个心态要保持
这里的webcam_driver就是usb_composite_driver类型的结构体,是最上层的Gadget功能驱动层
3. 进入初始化
static struct usb_composite_driver webcam_driver = {
.name = "g_webcam",
.dev = &webcam_device_descriptor,
.strings = webcam_device_strings,
.max_speed = USB_SPEED_HIGH,
.unbind = webcam_unbind,
};
在usb_composite_probe里面填充composite_driver结构体。composite_driver是usb_gadget_driver结构体,所以开始连接USB设备层,之后执行此函数
usb_gadget_probe_driver(&composite_driver, composite_bind);
这里面定义了usb_gadget结构体,出现了最底层的UDC层。之后把它传到。
composite_bind(struct usb_gadget *gadget)
这里面定义了一个usb_composite_dev结构体cdev,这是USB设备层的,所以关系挺复杂的,我们暂时不去理解。
之后填充cdev结构体,毫无疑问,它保存了上层的很多信息。
这个函数有点复杂,主要用到了这几个接口
composite_gadget_bind(cdev);//这个函数里面内容有点多,之后我会再发一篇文作基础介绍
override_id(cdev, &cdev->desc.iManufacturer);
device_create_file(&gadget->dev, &dev_attr_suspended);
这些是三个层里最底层的,最后一个函数都是创建文件了
4.之后
composite_bind结束之后回到了usb_gadget_probe_driver,然后执行
usb_gadget_start(udc->gadget, driver, bind);
这是库里面的方法,很简单易懂,就是开始运行。
结语
一些参数都是围绕这3层的4个结构体相关的,linux已经做好了框架,我们只需要填充进去就行。细看里面的参数,会发现非常庞大,全部看完肯定晕,所以先去看你想了解的地方,一块一块慢慢啃,一口啃完大象绝对会吐出来的。
学习LiunxC语言书写方法
1.结构体作形参
fun(*struct x){
struct *example = &x;
}
2.指针函数
int foo(int x,int y);
int fun(char a,int (*pfun)(int x,inty)){
pfun(1,2);
}
调用:fun('c',foo);