从主机侧的立场来看,在Linux驱动中,USB驱动处于最底层的是USB主机控制器硬件,在其之上运行的是USB主机控制器驱动,主机控制器之上为USB核心层,再上层为USB设备驱动层(插入主机上的U盘、鼠标、USB转串口等设备驱动)。因此,在主机侧的层次结构中,要实现的USB驱动包括两类:USB主机控制器驱动和USB设备驱动,前者控制插入其中的USB设备,后者控制USB设备如何与主机通信。Linux内核USB核心负责USB驱动管理和协议处理的主要工作。主机控制器驱动和设备驱动之间的USB核心非常重要,其功能包括:通过定义一些数据结构、宏和功能函数,向上为设备驱动提供编程接口,向下为USB主机控制器驱动提供编程接口;通过全局变量维护整个系统的USB设备信息;完成设备热插拔控制、总线数据传输控制等。
设备通常有一个或多个配置;
配置通常有一个或多个接口;
接口通常有一个或多个设置;
接口有零或多个端点。
一般的通用的Linux设备(如U盘、USB鼠标、USB键盘等)都不需要工程师再编写驱动,需要编写的是特定厂商、特定芯片的驱动,而且往往也可以参考内核中已提供的驱动的模板。
USB设备驱动程序编写步骤
1、分配/设置usb_driver结构体
1 static struct usb_driver xxx_usb_driver = 2 { 3 .name = "xxx_name", 4 .probe = xxx_usb_probe, 5 .disconnect = xxx_usb_disconnect, 6 .id_table = xxx_usb_id_table, 7 };
2、注册usb_driver结构体,一般发生在模块加载函数中,如:
1 static int __init xxx_init(void) 2 { 3 usb_register(&xxx_usb_driver); 4 ... 5 6 return 0; 7 }
同样,模块卸载函数中也要将其卸载
1 static void __exit xxx_exit(void) 2 { 3 usb_deregister(&xxx_usb_driver); 4 ... 5 }
3、初始化设备驱动所支持的USB设备的列表数组xxx_usb_id_table[]
usb_device_id结构体用于包含USB设备的制造商ID、产品ID、产品版本、设备类、接口类等信息及其要匹配标志成员match_flags(标明要与哪些成员匹配,包含DEV_LO、DEV_HI、DEV_CLASS、DEV_SUBCLASS、DEV_PROTOCOL、INT_CLASS、INT_SUBCLASS、INT_PROTOCOL)。
1 static struct usb_device_id xxx_usb_id_table[] = 2 { 3 { 4 //该宏用于创建一个匹配接口指定类型的usb_device_id结构体实例 5 USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, USB_INTERFACE_PROTOCOL_MOUSE) 6 }, 7 /* 8 { 9 //该宏根据制造商ID 和产品ID 生成一个usb_device_id 结构体的实例,在数组中增加该元素将意味着该驱动可支持匹配制造商ID、产品ID的设备。 10 USB_DEVICE(vendor, product) 11 }, 12 { 13 //该宏根据制造商ID、产品ID、产品版本的最小值和最大值生成一个usb_device_id结构体的实例, 14 //在数组中增加该元素将意味着该驱动可支持匹配制造商ID、产品ID和lo~hi范围内版本的设备。 15 USB_DEVICE_VER(vendor, product, lo, hi) 16 }, 17 { 18 //该宏用于创建一个匹配设备指定类型的usb_device_id结构体实例。 19 USB_DEVICE_INFO(class, subclass, protocol) 20 }, 21 */ 22 { } /* Terminating entry */ 23 };
4、实现探测函数xxx_usb_probe
1 static int xxx_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) 2 { 3 ... 4 }