码迷,mamicode.com
首页 > 其他好文 > 详细

20150409 IMX257 USB鼠标驱动程序编写

时间:2015-04-10 17:19:11      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:

20150409 IMX257 USB鼠标驱动程序编写

2015-03-14 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_mouse_key_1.c

 

二.打印出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结构体

在这个结构体里面包含了鼠标的硬件信息.

/* USB_DT_DEVICE: Device descriptor */

struct usb_device_descriptor {

    __u8 bLength;

    __u8 bDescriptorType;

 

    __le16 bcdUSB;

    __u8 bDeviceClass;

    __u8 bDeviceSubClass;

    __u8 bDeviceProtocol;

    __u8 bMaxPacketSize0;

    __le16 idVendor;

    __le16 idProduct;

    __le16 bcdDevice;

    __u8 iManufacturer;

    __u8 iProduct;

    __u8 iSerialNumber;

    __u8 bNumConfigurations;

} __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 */
usb_mouse_key_2.c

 

三.获取鼠标的硬件信息

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 */
usb_mouse_key_3.c

 

四.最终程序

    从上面的驱动程序中,我们得知了按键数据的含义,于是我们再完成函数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 */
usb_mouse_key_4.c

 

20150409 IMX257 USB鼠标驱动程序编写

标签:

原文地址:http://www.cnblogs.com/lihaiyan/p/4414787.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!