SB驱动程序包括为USB总线驱动程序以及USB设备驱动程序.
USB总线驱动程序的功能是:
1.识别
2.找到匹配的设备驱动程序
3.提供USB读写函数(不知道数据的含义)
USB设备驱动程序功能是: 分析USB的数据,上报相应的事件
今天,我们来实现一个USB鼠标的设备驱动程序,让鼠标的左键模拟为键盘的L键,鼠标的右键模拟为键盘的S键,鼠标的中键模拟为键盘的ENTER键,接下来我们先来实现一个简单程序,让操作系统找到USB鼠标.
一.简单的USB鼠标设备驱动程序
1.分配/注册一个USB结构体usb_driver
如图所示,定义一个usb_driver结构体,里面分别有三个函数:
usb_mouse_key_probe usb鼠标探测函数
usb_mouse_key_disconnect usb鼠标移出函数
usb_mouse_key_id_table 里面包含了usb鼠标的协议等信息
接下来分别实现上面的三个函数:
如图所示:我们现在先不做什么复杂的操作,知识简单的让它打印信息.
2.注册一个USB结构体usb_driver
3.调试:
make menuconfig去除自带的鼠标驱动程序:
1. make menuconfig 去掉原来鼠标的驱动程序
--> Device Drivers
--> HID Device
<>USB Human Interface Device(full HID) support
2. make uImage 使用新的内核启动
3. insmod usb_mouse_key.ko
4. 在开发板上接入和拔除USB设备
插入鼠标:打印出found usbmouse!
拔出鼠标:打印出disconnect usbmouse!
附上驱动程序1如下:
1 /*drivers/hid/usbhid/usbmouse.c
2 */
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9
10 static struct usb_device_id usb_mouse_key_id_table [] = {
11 { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID /*usb接口描述符的类为HID*/
12 , USB_INTERFACE_SUBCLASS_BOOT, /*子类为BOOT*/
13 USB_INTERFACE_PROTOCOL_MOUSE) }, /*协议为MOUSE*/
14 /*{USB_DEVICE(vend,prod)} //若要自定义驱动支持某一款usb,在此处填充 */
15 { } /* Terminating entry */
16 };
17
18 static int usb_mouse_key_probe(struct usb_interface *intf, const struct usb_device_id *id)
19 {
20 printk('<0>found usbmouse !n');
21
22 return 0;
23 }
24
25 static void usb_mouse_key_disconnect(struct usb_interface *intf)
26 {
27 printk('<0>disconnect usbmouse !n');
28 }
29
30
31 //1. 分配/设置/注册一个USB结构体usb_driver
32 static struct usb_driver usb_mouse_key_driver = {
33 .name = 'usb_mouse_key',
34 .probe = usb_mouse_key_probe,
35 .disconnect = usb_mouse_key_disconnect,
36 .id_table = usb_mouse_key_id_table,
37 };
38
39 static int usb_mouse_key_init(void){
40
41
42 /*2.注册USB结构体*/
43 usb_register(&usb_mouse_key_driver);
44
45 return 0;
46 }
47
48 static void usb_mouse_key_exit(void){
49
50 //卸载USB结构体
51 usb_deregister(&usb_mouse_key_driver);
52 }
53
54 module_init(usb_mouse_key_init);
55 module_exit(usb_mouse_key_exit);
56
57 MODULE_LICENSE('GPL');
58
59
60 /*
61 测试:
62 1. make menuconfig 去掉原来鼠标的驱动程序
63 --> Device Drivers
64 --> HID Device
65 <>USB Human Interface Device(full HID) support
66 2. make uImage 使用新的内核启动
67 3. insmod usb_mouse_key.ko
68 4. 在开发板上接入和拔除USB设备
69
70 */
二.打印出USB鼠标的硬件信息.
1.usb_device 结构体
struct usb_device {
int devnum;
char devpath [16];
u32 route;
enum usb_device_state state;
enum usb_device_speed speed;
struct usb_tt *tt;
int ttport;
unsigned int toggle[2];
struct usb_device *parent;
struct usb_bus *bus;
struct usb_host_endpoint ep0;
struct device dev;
struct usb_device_descriptor descriptor; //硬件的信息
struct usb_host_config *config;
struct usb_host_config *actconfig;
struct usb_host_endpoint *ep_in[16];
struct usb_host_endpoint *ep_out[16];
char **rawdescriptors;
unsigned short bus_mA;
u8 portnum;
u8 level;
unsigned can_submit:1;
unsigned discon_suspended:1;
unsigned persist_enabled:1;
unsigned have_langid:1;
unsigned authorized:1;
unsigned authenticated:1;
unsigned wusb:1;
int string_langid;
/* static strings from the device */
char *product;
char *manufacturer;
char *serial;
struct list_head filelist;
#ifdef CONFIG_USB_DEVICE_CLASS
struct device *usb_classdev;
#endif
#ifdef CONFIG_USB_DEVICEFS
struct dentry *usbfs_dentry;
#endif
int maxchild;
struct usb_device *children[USB_MAXCHILDREN];
int pm_usage_cnt;
u32 quirks;
atomic_t urbnum;
unsigned long active_duration;
#ifdef CONFIG_PM
struct delayed_work autosuspend;
struct work_struct autoresume;
struct mutex pm_mutex;
unsigned long last_busy;
int autosuspend_delay;
unsigned long connect_time;
unsigned auto_pm:1;
unsigned do_remote_wakeup:1;
unsigned reset_resume:1;
unsigned autosuspend_disabled:1;
unsigned autoresume_disabled:1;
unsigned skip_sys_resume:1;
#endif
struct wusb_dev *wusb_dev;
int slot_id;
};
2.struct usb_device_descriptor结构体
在这个结构体里面包含了鼠标的硬件信息.
1 /* USB_DT_DEVICE: Device descriptor */
2 struct usb_device_descriptor {
3 __u8 bLength;
4 __u8 bDescriptorType;
5 __le16 bcdUSB;
6 __u8 bDeviceClass;
7 __u8 bDeviceSubClass;
8 __u8 bDeviceProtocol;
9 __u8 bMaxPacketSize0;
10 __le16 idVendor;
11 __le16 idProduct;
12 __le16 bcdDevice;
13 __u8 iManufacturer;
14 __u8 iProduct;
15 __u8 iSerialNumber;
16 __u8 bNumConfigurations;
17 } __attribute__ ((packed));
3.在上面程序的基础上,我们在probe函数中打印出上面结构体的信息,如下图所示:
4.测试
如下图所示,正常的打印出了鼠标的硬件ID号
附上驱动程序2如下:
1 /*drivers/hid/usbhid/usbmouse.c
2 */
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9
10 static struct usb_device_id usb_mouse_key_id_table [] = {
11 { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID /*usb接口描述符的类为HID*/
12 , USB_INTERFACE_SUBCLASS_BOOT, /*子类为BOOT*/
13 USB_INTERFACE_PROTOCOL_MOUSE) }, /*协议为MOUSE*/
14 /*{USB_DEVICE(vend,prod)} //若要自定义驱动支持某一款usb,在此处填充 */
15 { } /* Terminating entry */
16 };
17
18 static int usb_mouse_key_probe(struct usb_interface *intf, const struct usb_device_id *id)
19 {
20 struct usb_device *dev = interface_to_usbdev(intf); //获取USB的接口,设备描述符,在.usb_device_descriptor里面就包含的设备的ID号等信息。
21 printk('<0>found usbmouse !n');
22
23 printk('<0>USB接口信息如下:n');
24 printk('bcdUSB = %xn',dev->descriptor.bcdUSB);
25 printk('VID = 0x%xn',dev->descriptor.idVendor);
26 printk('PID = 0x%xn',dev->descriptor.idProduct);
27
28 return 0;
29
30 }
31
32 static void usb_mouse_key_disconnect(struct usb_interface *intf)
33 {
34 printk('<0>disconnect usbmouse !n');
35 }
36
37
38 //1. 分配/设置/注册一个USB结构体usb_driver
39 static struct usb_driver usb_mouse_key_driver = {
40 .name = 'usb_mouse_key',
41 .probe = usb_mouse_key_probe,
42 .disconnect = usb_mouse_key_disconnect,
43 .id_table = usb_mouse_key_id_table,
44 };
45
46 static int usb_mouse_key_init(void){
47
48
49 /*2.注册USB结构体*/
50 usb_register(&usb_mouse_key_driver);
51
52 return 0;
53 }
54
55 static void usb_mouse_key_exit(void){
56
57 //卸载USB结构体
58 usb_deregister(&usb_mouse_key_driver);
59 }
60
61 module_init(usb_mouse_key_init);
62 module_exit(usb_mouse_key_exit);
63
64 MODULE_LICENSE('GPL');
65
66
67 /*
68 测试:
69 1. make menuconfig 去掉原来鼠标的驱动程序
70 --> Device Drivers
71 --> HID Device
72 <>USB Human Interface Device(full HID) support
73 2. make uImage 使用新的内核启动
74 3. insmod usb_mouse_key.ko
75 4. 在开发板上接入和拔除USB设备
76
77 */
三.获取鼠标的硬件信息
1.定义一个input_dev结构体,设置产生的事件类型,如图所示
2.定义urb(usb请求块usb request block)结构体,设置数据传输三要素,然后提交urb,如图所示
实现上面定义的usb_mouse_key_irq完成查询函数,当usb数据读取成功时,就会自动进入usb_mouse_key_irq函数中
如图所示,这个函数中,由于各个厂家的鼠标的数据定义可能不一样,所以,此处我们先打印测试,分别按下鼠标的左右中键,以及移动鼠标,测试鼠标数据的函数