201504010 IMX257 USB鼠标驱动程序编写
2015-04-10 Lover雪儿
USB驱动程序包括为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 <linux/kernel.h> 4 #include <linux/slab.h> 5 #include <linux/module.h> 6 #include <linux/init.h> 7 #include <linux/usb/input.h> 8 #include <linux/hid.h> 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 <linux/kernel.h> 4 #include <linux/slab.h> 5 #include <linux/module.h> 6 #include <linux/init.h> 7 #include <linux/usb/input.h> 8 #include <linux/hid.h> 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 = %x\n",dev->descriptor.bcdUSB); 25 printk("VID = 0x%x\n",dev->descriptor.idVendor); 26 printk("PID = 0x%x\n",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函数中
如图所示,这个函数中,由于各个厂家的鼠标的数据定义可能不一样,所以,此处我们先打印测试,分别按下鼠标的左右中键,以及移动鼠标,测试鼠标数据的函数
如下图所示:
接收到的鼠标数据:
00 00 00 00 00 00 00 00
按键 X方向 Y方向 滚轮数据
其中每两个代表着不同的数据,正方向的数据为正,负方向的数据为负
我们得到数据含义如下:
/* USB鼠标数据含义
* data[0]: bit0左键 1-按下 0-松开
* bit1右键 1-按下 0-松开
* bit2中键 1-按下 0-松开
*/
附驱动程序3如下:
1 /* 将鼠标模拟按键,实现 L S ENTER 三个按键 2 * drivers/hid/usbhid/usbmouse.c 3 */ 4 #include <linux/kernel.h> 5 #include <linux/slab.h> 6 #include <linux/module.h> 7 #include <linux/init.h> 8 #include <linux/usb/input.h> 9 #include <linux/hid.h> 10 11 static struct input_dev *uk_dev; //usb_key 输入设备结构体 12 static char *usb_buff; //usb的数据保存地址 13 static dma_addr_t usb_buff_phys; //usb的物理地址 u32 14 static int len; //数据的长度 15 static struct urb *uk_urb; //usb请求块,usb request block 16 17 static struct usb_device_id usb_mouse_key_id_table [] = { 18 { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID /*usb接口描述符的类为HID*/ 19 , USB_INTERFACE_SUBCLASS_BOOT, /*子类为BOOT*/ 20 USB_INTERFACE_PROTOCOL_MOUSE) }, /*协议为MOUSE*/ 21 /*{USB_DEVICE(vend,prod)} //若要自定义驱动支持某一款usb,在此处填充 */ 22 { } /* Terminating entry */ 23 }; 24 25 static void usb_mouse_key_irq(struct urb *urb) 26 { 27 int i; 28 static int cnt = 0; 29 printk("data cnt %d: ",++cnt); //打印数据 30 for(i = 0; i<len; i++){ 31 printk("%02x ",usb_buff[i]); 32 } 33 printk("\n"); 34 35 /*重新提交urb*/ 36 usb_submit_urb (urb, GFP_ATOMIC); 37 } 38 39 static int usb_mouse_key_probe(struct usb_interface *intf, const struct usb_device_id *id) 40 { 41 //获取USB的接口,设备描述符,在.usb_device_descriptor里面就包含的设备的ID号等信息。 42 struct usb_device *dev = interface_to_usbdev(intf); 43 struct usb_host_interface *interface; //主机接口 44 struct usb_endpoint_descriptor *endpoint; //USB端点 45 int pipe; //源端点和目的端点 46 //int len; //数据的长度 47 48 printk("<0>found usbmouse !\n"); 49 50 printk("<0>USB接口信息如下:\n"); 51 printk("bcdUSB = %x\n",dev->descriptor.bcdUSB); 52 printk("VID = 0x%x\n",dev->descriptor.idVendor); 53 printk("PID = 0x%x\n",dev->descriptor.idProduct); 54 55 interface = intf->cur_altsetting; //获得接口的当前设置 56 endpoint = &interface->endpoint[0].desc; //得到端点0之外的第一个端点的端点描述符 57 58 /*a. 分配一个input_dev结构体*/ 59 uk_dev = input_allocate_device(); 60 61 /*b. 设置*/ 62 /*b.1 能长生哪类事件*/ 63 set_bit(EV_KEY,uk_dev->evbit); //产生按键类事件 64 set_bit(EV_REP,uk_dev->evbit); //产生重复类事件 65 /*b.2 能长生哪些事件*/ 66 set_bit(KEY_L,uk_dev->keybit); //L键 67 set_bit(KEY_S,uk_dev->keybit); //S键 68 set_bit(KEY_ENTER,uk_dev->keybit); //ENTER键 69 70 /*c. 注册*/ 71 if(input_register_device(uk_dev)) 72 printk("register error!\n"); 73 74 /*d. 硬件相关 利用总线驱动程序提供的函数来收发USB数据*/ 75 /* 数据传输3要素 源 目的 长度 */ 76 /* 源: USB设备的某个端点 */ 77 pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); //usb源端点 78 /* 长度: */ 79 len = endpoint->wMaxPacketSize; 80 /* 目的: USB设备的某个端点 */ 81 usb_buff = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buff_phys); 82 /* 使用3要素 */ 83 /* 分配一个usb请求块 usb request block */ 84 uk_urb = usb_alloc_urb(0, GFP_KERNEL); 85 /* 设置urb 源,目的,长度,完成函数(查询),查询频率*/ 86 usb_fill_int_urb(uk_urb, dev, pipe, usb_buff,len,usb_mouse_key_irq, NULL, endpoint->bInterval); //bInterval:查询的频率 87 uk_urb->transfer_dma = usb_buff_phys; //设置usb的物理地址 88 uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; //设置标记 89 /* 使用urb ,提交urb*/ 90 usb_submit_urb(uk_urb, GFP_KERNEL); 91 92 return 0; 93 } 94 95 static void usb_mouse_key_disconnect(struct usb_interface *intf) 96 { 97 struct usb_device *dev = interface_to_usbdev(intf); 98 99 printk("<0>disconnect usbmouse !\n"); 100 101 usb_kill_urb(uk_urb); //杀死urb 102 usb_free_urb(uk_urb); //释放urb申请的内存 103 usb_buffer_free( dev , len, usb_buff, usb_buff_phys); //释放usb存放数据的buff 104 input_unregister_device(uk_dev); //反注册device 105 input_free_device(uk_dev); 106 //kfree(uk_dev); 107 } 108 109 110 //1. 分配/设置/注册一个USB结构体usb_driver 111 static struct usb_driver usb_mouse_key_driver = { 112 .name = "usb_mouse_key", 113 .probe = usb_mouse_key_probe, 114 .disconnect = usb_mouse_key_disconnect, 115 .id_table = usb_mouse_key_id_table, 116 }; 117 118 static int usb_mouse_key_init(void){ 119 120 121 /*2.注册USB结构体*/ 122 usb_register(&usb_mouse_key_driver); 123 124 return 0; 125 } 126 127 static void usb_mouse_key_exit(void){ 128 129 //卸载USB结构体 130 usb_deregister(&usb_mouse_key_driver); 131 } 132 133 module_init(usb_mouse_key_init); 134 module_exit(usb_mouse_key_exit); 135 136 MODULE_LICENSE("GPL"); 137 138 139 /* 140 测试 1th/2th: 141 1. make menuconfig 去掉原来鼠标的驱动程序 142 --> Device Drivers 143 --> HID Device 144 <>USB Human Interface Device(full HID) support 145 2. make uImage 使用新的内核启动 146 3. insmod usb_mouse_key.ko 147 4. 在开发板上接入和拔除USB设备 148 149 测试 3th: 150 1. insmod usb_mouse_key.ko 151 2. ls /dev/event* 152 3. 接上usb鼠标 153 4. ls /dev/event0 154 5. 操作鼠标,观察数据 155 接收到的鼠标数据: 156 00 00 00 00 00 00 00 00 157 按键 X方向 Y方向 滚轮数据 158 其中每两个代表着不同的数据,正方向的数据为正,负方向的数据为负 159 */
四.最终程序
从上面的驱动程序中,我们得知了按键数据的含义,于是我们再完成函数irq函数中分别对鼠标数据进行解析,程序如下:
当检测到我们按下鼠标左键时,上报键盘的L键
当检测到我们按下鼠标右键时,上报键盘的S键
当检测到我们按下鼠标中键时,上报键盘的ENTER键
加载驱动,接上鼠标,按下鼠标按键,测试结果如下:
附上驱动程序4:
1 /* 将鼠标模拟按键,实现 L S ENTER 三个按键 2 * drivers/hid/usbhid/usbmouse.c 3 */ 4 #include <linux/kernel.h> 5 #include <linux/slab.h> 6 #include <linux/module.h> 7 #include <linux/init.h> 8 #include <linux/usb/input.h> 9 #include <linux/hid.h> 10 11 static struct input_dev *uk_dev; //usb_key 输入设备结构体 12 static char *usb_buff; //usb的数据保存地址 13 static dma_addr_t usb_buff_phys; //usb的物理地址 u32 14 static int len; //数据的长度 15 static struct urb *uk_urb; //usb请求块,usb request block 16 17 static struct usb_device_id usb_mouse_key_id_table [] = { 18 { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID /*usb接口描述符的类为HID*/ 19 , USB_INTERFACE_SUBCLASS_BOOT, /*子类为BOOT*/ 20 USB_INTERFACE_PROTOCOL_MOUSE) }, /*协议为MOUSE*/ 21 /*{USB_DEVICE(vend,prod)} //若要自定义驱动支持某一款usb,在此处填充 */ 22 { } /* Terminating entry */ 23 }; 24 25 static void usb_mouse_key_irq(struct urb *urb) 26 { 27 static unsigned char pre_val = 0x00; 28 #if 0 29 int i; 30 static int cnt = 0; 31 printk("data cnt %d: ",++cnt); //打印数据 32 for(i = 0; i<len; i++){ 33 printk("%02x ",usb_buf[i]); 34 } 35 printk("\n"); 36 #endif 37 /* USB鼠标数据含义 38 * data[0]: bit0左键 1-按下 0-松开 39 * bit1右键 1-按下 0-松开 40 * bit2中键 1-按下 0-松开 41 */ 42 if( (pre_val & (1<<0)) != ( usb_buff[0] & (1<<0) )) 43 { 44 /* 左键发生了变化 */ 45 input_event(uk_dev, EV_KEY, KEY_L, (usb_buff[0] & (1<<0))? 1 : 0); 46 printk("\n L %d\n",KEY_L); 47 input_sync(uk_dev); 48 } 49 if( (pre_val & (1<<1)) != ( usb_buff[0] & (1<<1) )) 50 { 51 /* 右键发生了变化 */ 52 input_event(uk_dev, EV_KEY, KEY_S, (usb_buff[0] & (1<<1))? 1 : 0); 53 printk("\n S %d\n",KEY_S); 54 input_sync(uk_dev); 55 } 56 if( (pre_val & (1<<2)) != ( usb_buff[0] & (1<<2) )) 57 { 58 /* 中键发生了变化 */ 59 input_event(uk_dev, EV_KEY, KEY_ENTER, (usb_buff[0] & (1<<2))? 1 : 0); 60 printk("\n ENTER %d\n",KEY_ENTER); 61 input_sync(uk_dev); 62 } 63 pre_val = usb_buff[0]; //保存当前值 64 65 /* 重新提交urb */ 66 usb_submit_urb (urb, GFP_ATOMIC); 67 } 68 69 static int usb_mouse_key_probe(struct usb_interface *intf, const struct usb_device_id *id) 70 { 71 //获取USB的接口,设备描述符,在.usb_device_descriptor里面就包含的设备的ID号等信息。 72 struct usb_device *dev = interface_to_usbdev(intf); 73 struct usb_host_interface *interface; //主机接口 74 struct usb_endpoint_descriptor *endpoint; //USB端点 75 int pipe; //源端点和目的端点 76 //int len; //数据的长度 77 78 printk("<0>found usbmouse !\n"); 79 80 printk("<0>USB接口信息如下:\n"); 81 printk("bcdUSB = %x\n",dev->descriptor.bcdUSB); 82 printk("VID = 0x%x\n",dev->descriptor.idVendor); 83 printk("PID = 0x%x\n",dev->descriptor.idProduct); 84 85 interface = intf->cur_altsetting; //获得接口的当前设置 86 endpoint = &interface->endpoint[0].desc; //得到端点0之外的第一个端点的端点描述符 87 88 /*a. 分配一个input_dev结构体*/ 89 uk_dev = input_allocate_device(); 90 91 /*b. 设置*/ 92 /*b.1 能长生哪类事件*/ 93 set_bit(EV_KEY,uk_dev->evbit); //产生按键类事件 94 set_bit(EV_REP,uk_dev->evbit); //产生重复类事件 95 /*b.2 能长生哪些事件*/ 96 set_bit(KEY_L,uk_dev->keybit); //L键 97 set_bit(KEY_S,uk_dev->keybit); //S键 98 set_bit(KEY_ENTER,uk_dev->keybit); //ENTER键 99 100 /*c. 注册*/ 101 if(input_register_device(uk_dev)) 102 printk("register error \n"); 103 104 /*d. 硬件相关 利用总线驱动程序提供的函数来收发USB数据*/ 105 /* 数据传输3要素 源 目的 长度 */ 106 /* 源: USB设备的某个端点 */ 107 pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); //usb源端点 108 /* 长度: */ 109 len = endpoint->wMaxPacketSize; 110 /* 目的: USB设备的某个端点 */ 111 usb_buff = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buff_phys); 112 /* 使用3要素 */ 113 /* 分配一个usb请求块 usb request block */ 114 uk_urb = usb_alloc_urb(0, GFP_KERNEL); 115 /* 设置urb 源,目的,长度,完成函数(查询),查询频率*/ 116 usb_fill_int_urb(uk_urb, dev, pipe, usb_buff,len,usb_mouse_key_irq, NULL, endpoint->bInterval); //bInterval:查询的频率 117 uk_urb->transfer_dma = usb_buff_phys; //设置usb的物理地址 118 uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; //设置标记 119 /* 使用urb ,提交urb*/ 120 usb_submit_urb(uk_urb, GFP_KERNEL); 121 122 return 0; 123 } 124 125 static void usb_mouse_key_disconnect(struct usb_interface *intf) 126 { 127 struct usb_device *dev = interface_to_usbdev(intf); 128 129 printk("<0>disconnect usbmouse !\n"); 130 131 usb_kill_urb(uk_urb); //杀死urb 132 usb_free_urb(uk_urb); //释放urb申请的内存 133 usb_buffer_free( dev , len, usb_buff, usb_buff_phys); //释放usb存放数据的buff 134 input_unregister_device(uk_dev); //反注册device 135 input_free_device(uk_dev); 136 //kfree(uk_dev); 137 } 138 139 140 //1. 分配/设置/注册一个USB结构体usb_driver 141 static struct usb_driver usb_mouse_key_driver = { 142 .name = "usb_mouse_key", 143 .probe = usb_mouse_key_probe, 144 .disconnect = usb_mouse_key_disconnect, 145 .id_table = usb_mouse_key_id_table, 146 }; 147 148 static int usb_mouse_key_init(void){ 149 150 151 /*2.注册USB结构体*/ 152 usb_register(&usb_mouse_key_driver); 153 154 return 0; 155 } 156 157 static void usb_mouse_key_exit(void){ 158 159 //卸载USB结构体 160 usb_deregister(&usb_mouse_key_driver); 161 } 162 163 module_init(usb_mouse_key_init); 164 module_exit(usb_mouse_key_exit); 165 166 MODULE_LICENSE("GPL"); 167 168 169 /* 170 测试 1th/2th: 171 1. make menuconfig 去掉原来鼠标的驱动程序 172 --> Device Drivers 173 --> HID Device 174 <>USB Human Interface Device(full HID) support 175 2. make uImage 使用新的内核启动 176 3. insmod usb_mouse_key.ko 177 4. 在开发板上接入和拔除USB设备 178 179 测试 3th: 180 1. insmod usb_mouse_key.ko 181 2. ls /dev/event* 182 3. 接上usb鼠标 183 4. ls /dev/event0 184 5. 操作鼠标,观察数据 185 接收到的鼠标数据: 186 00 00 00 00 00 00 00 00 187 按键 X方向 Y方向 滚轮数据 188 其中每两个代表着不同的数据,正方向的数据为正,负方向的数据为负 189 190 测试 4th: 191 1. insmod usb_mouse_key.ko 192 2. ls /dev/event* 193 3. 接上usb鼠标 194 4. ls /dev/event0 195 5. 操作鼠标,观察数据 196 6. hexdump /dev/event0 197 0000 0000 0000 0000 0000 0000 198 秒 微秒 按键类 哪个按键 199 200 USB总线驱动程序: 201 1.识别 2.找到匹配的设备驱动程序 3.提供USB读写函数(不知道数据的含义) 202 USB设备驱动程序: 分析USB的数据,上报相应的事件 203 204 */