20150409 IMX257 USB鼠标驱动程序编写

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

时间: 2024-10-10 04:58:57

20150409 IMX257 USB鼠标驱动程序编写的相关文章

IMX257实现Ramblock驱动程序编写

2015-04-12 Lover雪儿 记得以前三月份就开始学习块设备,但是一直弄不出来,今天我们接着以前写的块设备驱动,抱着坚定的信心把它实现. 今天,我们再内存中申请一片内存,模拟作为块设备,程序如下: 程序一:简单的一个小程序 1.定义gendisk结构体与request_queue请求队列结构体,以及file-operation结构体 gendisk结构体,主要是用于定义与内核,硬件有关的一些重要信息,还有就是,告诉内核定义请求队列的结构体以及操作函数的结构体. 请求队列:主要是提供读写能

学习Linux下s3c2440的USB鼠标驱动笔记

USB驱动学习笔记: 2 1.ARM-Linux下USB驱动程序开发 3 1.1.1.linux下USB配置: 4 *********(MassStorage:存储设备)************************************ 5 -> Device Drivers 6 -> SCSI device support(通用设备) 7 -> SCSI disk support (磁盘支持) 8 -> SCSI device support(设备支持) 9 10 ->

Linux驱动之USB总线驱动程序框架简析

通用串行总线(USB)是主机和外围设备之间的一种连接.USB总线规范有1.1版和2.0版,当然现在已经有了3.0版本.USB1.1支持两种传输速度:低速为1.5Mbps,高速为12Mbps.USB2.0的传输速度可以高达480Mbps.USB2.0向下兼容USB1.1,可以将USB1.1的设备连接到USB2.0控制器上,也可以把USB2.0的设备连接到USB1.1控制器上.S3C2440的USB主机控制器支持USB1.1总线规范. USB总线的拓扑结构如下图所示:USB主机控制器(USB Hos

USB鼠标设备简单驱动设计

USB(Universal Serial Bus ),通用串行总线,是一种外部总线标准,用于规范电脑与外部设备的连接和通讯.是在1994年底由英特尔.康柏.IBM.Microsoft等多家公司联合提出的,自1996年推出后,已成功替代串口和并口,成为当今个人电脑和大量智能设备的必配接口之一. linux内核支持两种类型的USB驱动程序,一种是PC机的USB驱动程序控制插入其中的USB设备,另一种是USB设备和主机通信. 第一种软件架构                               

Linux USB 鼠标输入驱动详解

平台:mini2440 内核:linux 2.6.32.2 USB设备插入时,内核会读取设备信息,接着就把id_table里的信息与读取到的信息做比较,看是否匹配,如果匹配,就调用probe函数.USB设备拔出时会调用disconnect函数.URB在USB设备驱动程序中用来描述与USB设备通信时用到的基本载体和核心数据结构. URB(usb request block)处理流程: ①USB设备驱动程序创建并初始化一个访问特定USB设备特定端点的urb并提交给USB core. ②USB cor

20150429 S3C实现DMA驱动程序编写

20150429 S3C实现DMA驱动程序编写 2015-04-29 Lover雪儿 在IMX257上只有SDMA,SDMA比DMA的功能更加强大,但是为了学习的目的,如果直接学习SDMA,可能会不能消化, 所以,此处,我们从简单到复杂,从S3C2440的DMA驱动程序开始学习,等学懂它之后,我们再进军IMX257的SDMA. 一.一个简单的程序框架 1.定义一些指针 1 static int major = 0; 2 3 #define MEM_CPY_NO_DMA 0 4 #define M

转:Linux网卡驱动程序编写

Linux网卡驱动程序编写 [摘自 LinuxAID] 工作需要写了我们公司一块网卡的Linux驱动程序.经历一个从无到有的过程,深感技术交流的重要.Linux作为挑战微软垄断的强有力武器,日益受到大家的喜爱.真希望她能在中国迅速成长.把程序文档贴出来,希望和大家探讨Linux技术和应用,促进Linux在中国的普及. Linux操作系统网络驱动程序编写 一.Linux系统设备驱动程序概述 1.1 Linux设备驱动程序分类 1.2 编写驱动程序的一些基本概念 二.Linux系统网络设备驱动程序

USB设备驱动程序1

目的:USB鼠标用作按键,左键相当于字母L,右键相当于字母S,中键相当于Enter.如何来实现?用到输入子系统:1)分配input_dev2)设置3)注册4)硬件相关操作对于USB鼠标来说,硬件操作应该怎么做呢?使用USB总线驱动程序提供的读写函数来收发数据,主要针对于硬件相关的这一部分.怎么写USB设备驱动程序?1)分配/设置usb_drv结构体 .id_table .probe .disconnect2)注册首先来看一个例子:usbmouse.c 1.史上最简单的USB设备驱动程序 /* *

synaptics驱动,插入USB鼠标禁用触控板注册表

Title:synaptics驱动,插入USB鼠标禁用触控板注册表 --2010-11-01 22:21 记得以前用过一个synaptics的驱动,自带有插入USB鼠标禁用触控板的选项的,有些没有自带. 今天下了个最新的触控板驱动,再去找了个注册表数据,可以用禁用触控板的功能了.以下是代码. -------------------------------------------------------------------------------------------------------