usb5-写成usb驱动
usb总线驱动模型里也有struct usb_driver和struct usb_device,这点与platform虚拟总线里的struct platform_device和struct platform_driver相似。不同之处是
platform模型中,需要写两个驱动文件,分别是driver.ko和device.ko,然后分别insmod。
usb驱动只需要写一个驱动文件driver,只insmod driver.ko即可,为什么不insmod device.ko了呢?因为没写,恩,不必写。因为usb是实际的总线,当有usb设备插入的时候usbcore就会自动对该设备执行枚举,枚举之后usbcore就获知了该设备的相关资源,然后把资源信息返回给能匹配的驱动。
简言之,
平台驱动的insmod device.ko是一个模仿usb设备插入的动作,device.ko中记录了资源信息,通过insmod device,平台核心获取device的资源信息返回给匹配的驱动。
usb驱动模型中资源信息在储存在设备中呢,在usb设备插入时通过枚举,usbcore把资源信息读出来塞进返回给匹配的驱动。
怎么匹配的呢?对于platform是通过driver的名字和device的名字匹配的。对于usb模型,us_driver中有usb_device_id table,记录该驱动可以处理的设备 的idVerdor和idProduct
当usb设备插入时,usbcore通过枚举过程获知当前设备的信息,包括两个id,然后和注册在usb总线上的各个usb驱动里的usb_device_id table比较,有相同的的话,就调用哪个驱动的probe函数,并把该设备的资源信息(inteface)作为参数交给probe.这样哪个驱动就达到处理这个设备的目的了.
当然,先插入usb设备再insmod driver.ko,这种情况下去匹配两者的实现跟上面类似。
一下是linux/drivers/hid/usbhid/usbmouse.c里的一个usb_device_id table
如果只声明支持一个设备可以用如下宏
linux/include/usb.h
*****************************************************************************************************************************************************************************
一下是一个最简单的usb测试程序(比较完整的见linux-2.6.32.2/drivers/usb/usb-skeleton.c),仅测试一下usbcore对设备枚举玩,是否能够成功和此驱动匹配而进入probe函数
在板子上,先不要插usb设备
****************************************************************************************************************************************************************
另外在mini2440上已经有一个配置,
Device Drivers ---> [*] HID Devices ---> <*> USB Human Interface Device (full HID) support
这个驱动貌似通吃所有hid设备,包括mouse kbd,自定义hid等。所以如果我插入我的自定义hid设备时,就会被usbcore把我的设备优先匹配给这个驱动(即使我自己写的驱动已经insmod),这个驱动会在其probe函数中为我的设备自动创建一个input驱动,设备文件在/dev/input/eventx(x=1 2 3 ...)。但是我的设备没有按鼠标或键盘的数据格式给主机usbcore传送数据(当然我也不想这样传输,因为我的设备是自定义hid设备,当然要自定义的数据及格式,当然也不想让这个驱动去处理我的设备发来的数据)。
目前的解决办法是把这个选项给禁掉。这样usbcore就会把我的自定义hid设备匹配给我自己写的驱动了。
当然禁掉之后,usb鼠标 键盘都不能用了。不过可以配置一下另外一个鼠标和键盘的驱动,也可用的。如下
Device Drivers ---> [*] HID Devices --->USB HID Boot Protocol drivers ---> <*> USB HIDBP Keyboard (simple Boot) support
<*> USB HIDBP Mouse (simple Boot) support
不过要想出现USB HID Boot Protocol drivers项目,需要一些操作,在Kconfig文件line 47如下
USB符号不要选择为空(要选择m或y),USB_HID符号不要选择为y。最后那个符号EMBEDDED暂时没找到在哪里配的,就删掉了。即
再看一下/linux-2.6.32.2/drivers/hid/usbhid/Makefile,
<*> USB Human Interface Device (full HID) support 对应的驱动应该是/linux-2.6.32.2/drivers/hid/usbhid/usbhid.c
<*> USB HIDBP Keyboard (simple Boot) support 对应的驱动是/linux-2.6.32.2/drivers/hid/usbhid/usbkbd.c
<*> USB HIDBP Keyboard (simple Boot) support 对应的驱动是/linux-2.6.32.2/drivers/hid/usbhid/usbmouse.c
后两者还好说,目录下确实有usbkbd.c和usbmouse.c,但是没有usbhid.c文件,那么usbhid.o哪里来的呢?恩,没人规定usbhid.o非得只由usbhid.c才能生成。
同目录下有一个文件.usbhid.o.cmd ,记录了usbhid.o由hid-quirks.o和hid-core.o生成。目前为止感觉很麻烦の。
platform模型中,需要写两个驱动文件,分别是driver.ko和device.ko,然后分别insmod。
usb驱动只需要写一个驱动文件driver,只insmod driver.ko即可,为什么不insmod device.ko了呢?因为没写,恩,不必写。因为usb是实际的总线,当有usb设备插入的时候usbcore就会自动对该设备执行枚举,枚举之后usbcore就获知了该设备的相关资源,然后把资源信息返回给能匹配的驱动。
简言之,
平台驱动的insmod device.ko是一个模仿usb设备插入的动作,device.ko中记录了资源信息,通过insmod device,平台核心获取device的资源信息返回给匹配的驱动。
usb驱动模型中资源信息在储存在设备中呢,在usb设备插入时通过枚举,usbcore把资源信息读出来塞进返回给匹配的驱动。
怎么匹配的呢?对于platform是通过driver的名字和device的名字匹配的。对于usb模型,us_driver中有usb_device_id table,记录该驱动可以处理的设备 的idVerdor和idProduct
当usb设备插入时,usbcore通过枚举过程获知当前设备的信息,包括两个id,然后和注册在usb总线上的各个usb驱动里的usb_device_id table比较,有相同的的话,就调用哪个驱动的probe函数,并把该设备的资源信息(inteface)作为参数交给probe.这样哪个驱动就达到处理这个设备的目的了.
当然,先插入usb设备再insmod driver.ko,这种情况下去匹配两者的实现跟上面类似。
一下是linux/drivers/hid/usbhid/usbmouse.c里的一个usb_device_id table
static struct usb_device_id usb_mouse_id_table [] = { { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, USB_INTERFACE_PROTOCOL_MOUSE) }, { } };在linux/include/hid.h
#define USB_INTERFACE_CLASS_HID 3//在usb协议的接口描述符的bInterfaceClass字段如果为3,表示该设备为hid设备 #define USB_INTERFACE_SUBCLASS_BOOT 1//在usb协议的接口描述符的bInterfaceSubClass字段如果为1,表示是hid的子类:支持bios引导的hid #define USB_INTERFACE_PROTOCOL_MOUSE 2//在usb协议的接口描述符的bInterfaceProtocol字段如果为2,表示协议为鼠标(在支持bios引导时用的,键盘协议为1)USB_INTERFACE_INFO在linux/include/usb.h中定义,如下
#define USB_INTERFACE_INFO(cl, sc, pr) \ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, \ .bInterfaceClass = (cl), \ .bInterfaceSubClass = (sc), \ .bInterfaceProtocol = (pr)所以它表示只要是hid设备,且支持bios引导,且引导时的协议为mouse,则此驱动都可以处理。
如果只声明支持一个设备可以用如下宏
linux/include/usb.h
#define USB_DEVICE(vend,prod) \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \ .idVendor = (vend), \ .idProduct = (prod)比如在usb_device_id里 添加一项,USB_DEVICE(0606,0001)
*****************************************************************************************************************************************************************************
一下是一个最简单的usb测试程序(比较完整的见linux-2.6.32.2/drivers/usb/usb-skeleton.c),仅测试一下usbcore对设备枚举玩,是否能够成功和此驱动匹配而进入probe函数
#include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/init.h> #include <linux/usb/input.h> #include <linux/hid.h> /* * Version Information */ #define DRIVER_VERSION "v1.0" #define DRIVER_AUTHOR "song" #define DRIVER_DESC "usb test" #define DRIVER_LICENSE "GPL" MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE(DRIVER_LICENSE); static int test_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { printk("probe\n"); return 0; } static void test_usb_disconnect(struct usb_interface *intf) { printk("disconnect\n"); } static struct usb_device_id test_usb_id_table [] = { {USB_DEVICE(0x0606,0x0001) }, {} }; MODULE_DEVICE_TABLE (usb, test_usb_id_table); static struct usb_driver test_usb_driver = { .name = "test_song", .probe = test_usb_probe, .disconnect = test_usb_disconnect, .id_table = test_usb_id_table, }; static int __init test_usb_init(void) { int retval = usb_register(&test_usb_driver); if (retval == 0) printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" DRIVER_DESC "\n"); return retval; } static void __exit test_usb_exit(void) { usb_deregister(&test_usb_driver); } module_init(test_usb_init); module_exit(test_usb_exit);makefile
ifneq ($(KERNELRELEASE),) obj-m := test_usb.o else KDIR := /opt/FriendlyARM/mini2440/linux-2.6.32.2 #KDIR := /lib/modules/`uname -r`/build all: make -C $(KDIR) M=$(PWD) modules clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers endif而设备侧(我的是sic8051f320单片机,内含usb从接口)的设备描述符和接口描述符,报告描述符设置如下,一下是一个自定义hid设备的部分描述符的设置
code DEVICE_DESCRIPTOR DeviceDesc = { 18, // bLength 0x01, // bDescriptorType SWAP16(0x0200), // bcdUSB 0x00, // bDeviceClass 0x00, // bDeviceSubClass 0x00, // bDeviceProtocol EP0_PACKET_SIZE, // bMaxPacketSize0 SWAP16(USB_HID_VID), // idVendor 0x0606 和linux侧驱动中的对应 SWAP16(USB_HID_PID), // idProduct 0x0001 和linux侧驱动中的对应 0x0001, // bcdDevice 0x01, // iManufacturer 0x02, // iProduct 0x03, // iSerialNumber 0x01 // bNumConfigurations }; //end of DeviceDesc
{ 0x09, // bLength 0x04, // bDescriptorType 0x00, // bInterfaceNumber 0x00, // bAlternateSetting 0x02, // bNumEndpoints 0x03, // bInterfaceClass 指定为hid类 0x00, // bInterfaceSubClass 非鼠标键盘 0 0x00, // bInterfaceProcotol 非鼠标键盘 0 0x00 // iInterface }, //end of InterfaceDesc
//Report descriptor code unsigned char ReportDesc[] = { // 0x06, 0x00, 0xFF,// ; Usage Page 0x05, 0x01, //桌面设备 // 0x09, 0x01,// ; Usage 0x09, 0x00, //未定义用途,结合接口描述符的bInterfaceClass=03,则为自动以hid 0xA1, 0x01, // ; Collection//用未定义用途开集合 0x09, 0x01,// ; Usage 0x95, 0x20,// ; Report Count 0x75, 0x08,// ; Report Size 0x15, 0x00,// ; Logical Minimum 0x26, 0xFF, 0x00,// ; Logical Maximum 0x81, 0x02,// ; Input 0x09, 0x02,// ; Usage 0x95, 0x20,// ; Report Count 0x75, 0x08,// ; Report Size 0x91, 0x02,// ; Output 0xC0 };
在板子上,先不要插usb设备
[root@FriendlyARM plg]# insmod test_usb.ko usbcore: registered new interface driver test_song test_usb: v1.0:usb test插上设备,信息如下,出现probe信息,说明成功匹配到驱动
[root@FriendlyARM plg]# usb 1-1.1: new full speed USB device using s3c2410-ohci and address 8 usb 1-1.1: New USB device found, idVendor=0606, idProduct=0001//厂商和产品id。不要受迷惑,是0x0606和0x0001 usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 usb 1-1.1: Product: nRF24LU1 ADapter usb 1-1.1: Manufacturer: Weisdigital usb 1-1.1: SerialNumber: Ver1.0 N000 usb 1-1.1: configuration #1 chosen from 1 choice//以上这些信息由usbcore在枚举完设备打印出来 probe拔出设备,触发函数test_usb_disconnect,信息如下
usb 1-1.1: USB disconnect, address 8 disconnect
****************************************************************************************************************************************************************
另外在mini2440上已经有一个配置,
Device Drivers ---> [*] HID Devices ---> <*> USB Human Interface Device (full HID) support
这个驱动貌似通吃所有hid设备,包括mouse kbd,自定义hid等。所以如果我插入我的自定义hid设备时,就会被usbcore把我的设备优先匹配给这个驱动(即使我自己写的驱动已经insmod),这个驱动会在其probe函数中为我的设备自动创建一个input驱动,设备文件在/dev/input/eventx(x=1 2 3 ...)。但是我的设备没有按鼠标或键盘的数据格式给主机usbcore传送数据(当然我也不想这样传输,因为我的设备是自定义hid设备,当然要自定义的数据及格式,当然也不想让这个驱动去处理我的设备发来的数据)。
目前的解决办法是把这个选项给禁掉。这样usbcore就会把我的自定义hid设备匹配给我自己写的驱动了。
当然禁掉之后,usb鼠标 键盘都不能用了。不过可以配置一下另外一个鼠标和键盘的驱动,也可用的。如下
Device Drivers ---> [*] HID Devices --->USB HID Boot Protocol drivers ---> <*> USB HIDBP Keyboard (simple Boot) support
<*> USB HIDBP Mouse (simple Boot) support
不过要想出现USB HID Boot Protocol drivers项目,需要一些操作,在Kconfig文件line 47如下
menu "USB HID Boot Protocol drivers" depends on USB!=n && USB_HID!=y && EMBEDDED即
USB符号不要选择为空(要选择m或y),USB_HID符号不要选择为y。最后那个符号EMBEDDED暂时没找到在哪里配的,就删掉了。即
menu "USB HID Boot Protocol drivers" depends on USB!=n && USB_HID!=y按照上面设置以后就会make menuconfig里就会出现USB HID Boot Protocol drivers项目。
再看一下/linux-2.6.32.2/drivers/hid/usbhid/Makefile,
# Multipart objects. usbhid-objs := hid-core.o hid-quirks.o # Optional parts of multipart objects. ifeq ($(CONFIG_USB_HIDDEV),y) usbhid-objs += hiddev.o endif ifeq ($(CONFIG_HID_PID),y) usbhid-objs += hid-pidff.o endif obj-$(CONFIG_USB_HID) += usbhid.o obj-$(CONFIG_USB_KBD) += usbkbd.o obj-$(CONFIG_USB_MOUSE) += usbmouse.可知
<*> USB Human Interface Device (full HID) support 对应的驱动应该是/linux-2.6.32.2/drivers/hid/usbhid/usbhid.c
<*> USB HIDBP Keyboard (simple Boot) support 对应的驱动是/linux-2.6.32.2/drivers/hid/usbhid/usbkbd.c
<*> USB HIDBP Keyboard (simple Boot) support 对应的驱动是/linux-2.6.32.2/drivers/hid/usbhid/usbmouse.c
后两者还好说,目录下确实有usbkbd.c和usbmouse.c,但是没有usbhid.c文件,那么usbhid.o哪里来的呢?恩,没人规定usbhid.o非得只由usbhid.c才能生成。
同目录下有一个文件.usbhid.o.cmd ,记录了usbhid.o由hid-quirks.o和hid-core.o生成。目前为止感觉很麻烦の。
arm-linux-ld -EL -r -o drivers/hid/usbhid/usbhid.o drivers/hid/usbhid/hid-core.o drivers/hid/usbhid/hid-quirks.o