usb5-写成usb驱动
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                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
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, // bLength0x01, // bDescriptorTypeSWAP16(0x0200), // bcdUSB0x00, // bDeviceClass0x00, // bDeviceSubClass0x00, // bDeviceProtocolEP0_PACKET_SIZE, // bMaxPacketSize0SWAP16(USB_HID_VID), // idVendor 0x0606 和linux側驅動中的對應SWAP16(USB_HID_PID), // idProduct 0x0001 和linux側驅動中的對應0x0001, // bcdDevice0x01, // iManufacturer0x02, // iProduct0x03, // iSerialNumber0x01 // bNumConfigurations }; //end of DeviceDesc {0x09, // bLength0x04, // bDescriptorType0x00, // bInterfaceNumber0x00, // bAlternateSetting0x02, // bNumEndpoints0x03, // bInterfaceClass 指定為hid類0x00, // bInterfaceSubClass 非鼠標鍵盤 00x00, // bInterfaceProcotol 非鼠標鍵盤 00x00 // iInterface}, //end of InterfaceDesc//Report descriptor code unsigned char ReportDesc[] = {// 0x06, 0x00, 0xFF,// ; Usage Page0x05, 0x01, //桌面設備// 0x09, 0x01,// ; Usage0x09, 0x00, //未定義用途,結合接口描述符的bInterfaceClass=03,則為自動以hid0xA1, 0x01, // ; Collection//用未定義用途開集合0x09, 0x01,// ; Usage0x95, 0x20,// ; Report Count0x75, 0x08,// ; Report Size0x15, 0x00,// ; Logical Minimum0x26, 0xFF, 0x00,// ; Logical Maximum0x81, 0x02,// ; Input0x09, 0x02,// ; Usage0x95, 0x20,// ; Report Count0x75, 0x08,// ; Report Size0x91, 0x02,// ; Output0xC0 };
在板子上,先不要插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 endifobj-$(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
 
                        
                        
                        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, // bLength0x01, // bDescriptorTypeSWAP16(0x0200), // bcdUSB0x00, // bDeviceClass0x00, // bDeviceSubClass0x00, // bDeviceProtocolEP0_PACKET_SIZE, // bMaxPacketSize0SWAP16(USB_HID_VID), // idVendor 0x0606 和linux側驅動中的對應SWAP16(USB_HID_PID), // idProduct 0x0001 和linux側驅動中的對應0x0001, // bcdDevice0x01, // iManufacturer0x02, // iProduct0x03, // iSerialNumber0x01 // bNumConfigurations }; //end of DeviceDesc {0x09, // bLength0x04, // bDescriptorType0x00, // bInterfaceNumber0x00, // bAlternateSetting0x02, // bNumEndpoints0x03, // bInterfaceClass 指定為hid類0x00, // bInterfaceSubClass 非鼠標鍵盤 00x00, // bInterfaceProcotol 非鼠標鍵盤 00x00 // iInterface}, //end of InterfaceDesc//Report descriptor code unsigned char ReportDesc[] = {// 0x06, 0x00, 0xFF,// ; Usage Page0x05, 0x01, //桌面設備// 0x09, 0x01,// ; Usage0x09, 0x00, //未定義用途,結合接口描述符的bInterfaceClass=03,則為自動以hid0xA1, 0x01, // ; Collection//用未定義用途開集合0x09, 0x01,// ; Usage0x95, 0x20,// ; Report Count0x75, 0x08,// ; Report Size0x15, 0x00,// ; Logical Minimum0x26, 0xFF, 0x00,// ; Logical Maximum0x81, 0x02,// ; Input0x09, 0x02,// ; Usage0x95, 0x20,// ; Report Count0x75, 0x08,// ; Report Size0x91, 0x02,// ; Output0xC0 };
在板子上,先不要插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 endifobj-$(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
轉載于:https://www.cnblogs.com/-song/archive/2011/10/31/3331936.html
總結
以上是生活随笔為你收集整理的usb5-写成usb驱动的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: usb4-配置usb触摸屏
- 下一篇: 项目经理主要工作职责
