编写USB驱动程序步骤
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编写USB驱动程序步骤:
1所有usb驱动都必须创建主要结构体struct usb_driver
struct usb_driver
->struct module *owner
(有他可正确对该驱动程序引用计数,应为THIS_MODULE)
->const char *name
(驱动名字,运行时可在查看 /sys/bus/usb/drivers/)
->const struct usb_device_id *id_table
(包含该驱动可支持的所有不同类型的驱动设备,没添探测回调函数不会被调用)
->int (*probe)(struct usb_interface *intf,const struct usb_device_id *id)
(usb驱动探测函数,确认后struct usb_interface 应恰当初始化,然后返0,如果出错则返负值) ->void(*disconnect)(struct usb_interface *intf)
(当struct usb_interface 被从系统中移除或驱动正从usb核心中卸载时,usb核心将调用此函数)代码实例:
static struct usb_driver skel_driver={
.owner = THIS_MODULE,
.name = "skeleton",
.id_table = skel_table,
.probe = skel_probe,
.disconnect = skel_disconnect,
};
↓
2usb_register()注册将struct usb_driver 注册到usb核心,传统是在usb驱动程序模块初始化代码中完成该工作的
static int __init usb_skel_init(void)
{
...
usb_register(&skel_driver);
...
}
↓
3struct usb_device_id usb核心用该表判断哪个设备该使用哪个驱动程序,热插拔脚本使用它来确定当一个特定的设备插入到系统时该自动装载哪个驱动程序。
->__u16 match_flags(确定设备和结构体中下列字段中哪一个相匹配)
->__u16 idVendor(设备的usb制造商id)
->__u16 idProduct(设备的usb产品id)
↓
4USB骨架程序的关键几点如下:
1. USB驱动的注册和注销
Usb驱动程序在注册时会发送一个命令给usb_register,通常在驱动程序的初始化函数里。
当要从系统卸载驱动程序时,需要注销usb子系统。即需要usb_unregister 函数处理。
2 当usb设备插入时,为了使linux-hotplug(Linux中PCI、USB等设备热插拔支持)系统自动装载驱动程序,你需要创建一个MODULE_DEVICE_TABLE。代码如下(这个模块仅支持某一特定设备): static struct usb_device_id skel_table [] = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
{ } /* Terminating entry */};
MODULE_DEVICE_TABLE (usb, skel_table);
USB_DEVICE宏利用厂商ID和产品ID为我们提供了一个设备的唯一标识。当系统插入一个ID匹配的USB设备到USB总线时,驱动会在USB core中注册。驱动程序中probe 函数也就会被调用。
usb_device 结构指针、接口号和接口ID都会被传递到函数中。
3 static void * skel_probe(struct usb_device *dev,unsigned int ifnum, const struct
usb_device_id *id)
驱动程序需要确认插入的设备是否可以被接受,如果不接受,或者在初始化的过程中发生任何错误,probe函数返回一个NULL值。否则返回一个含有设备驱动程序状态的指针。通过这个指针,就可以访问所有结构中的回调函数。
4 在骨架驱动程序里,最后一点是我们要注册devfs。我们创建一个缓冲用来保存那些被发送给usb 设备的数据和那些从设备上接受的数据,同时USB urb 被初始化,并且我们在devfs子系统中注册设备,允许devfs用户访问我们的设备。注册过程如下:
/* initialize the devfs node for this device and register it */sprintf(name, "skel%d", skel->;minor);
skel->devfs = devfs_register (usb_devfs_handle, name,DEVFS_FL_DEFAULT,
USB_MAJOR,USB_SKEL_MINOR_BASE + skel->minor,
S_IFCHR | S_IRUSR | S_IWUSR |S_IRGRP | S_IWGRP | S_IROTH, &skel_fops, NULL);
如果devfs_register函数失败,不用担心,devfs子系统会将此情况报告给用户。
当然最后,如果设备从usb总线拔掉,设备指针会调用disconnect 函数。驱动程序就需要清除那些被分配了的所有私有数据、关闭urbs,并且从devfs上注销调自己。
/* remove our devfs node */devfs_unregister(skel->;devfs);
↓
5其他
1 struct usb_host_endpoint(描述usb端点)
→(包含) struct usb_endpoint_descriptor(含真正端点信息,数据格式,是真正驱动关心的字段)
端点描述符: