zoukankan      html  css  js  c++  java
  • 201504010 IMX257 USB鼠标驱动程序编写

    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 !
    ");
    21 
    22     return 0;
    23 }
    24 
    25 static void usb_mouse_key_disconnect(struct usb_interface *intf)
    26 {
    27     printk("<0>disconnect usbmouse !
    ");
    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结构体

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

     
     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 !
    ");
    22     
    23     printk("<0>USB接口信息如下:
    ");
    24     printk("bcdUSB = %x
    ",dev->descriptor.bcdUSB);
    25     printk("VID = 0x%x
    ",dev->descriptor.idVendor);
    26     printk("PID = 0x%x
    ",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 !
    ");
    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("
    ");
     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 !
    ");
     49     
     50     printk("<0>USB接口信息如下:
    ");
     51     printk("bcdUSB = %x
    ",dev->descriptor.bcdUSB);
     52     printk("VID = 0x%x
    ",dev->descriptor.idVendor);
     53     printk("PID = 0x%x
    ",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!
    ");
     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 !
    ");
    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("
    ");
     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("
     L %d
    ",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("
     S %d
    ",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("
     ENTER %d
    ",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 !
    ");
     79     
     80     printk("<0>USB接口信息如下:
    ");
     81     printk("bcdUSB = %x
    ",dev->descriptor.bcdUSB);
     82     printk("VID = 0x%x
    ",dev->descriptor.idVendor);
     83     printk("PID = 0x%x
    ",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 
    ");
    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 !
    ");
    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
  • 相关阅读:
    HDU 5583 Kingdom of Black and White 水题
    HDU 5578 Friendship of Frog 水题
    Codeforces Round #190 (Div. 2) E. Ciel the Commander 点分治
    hdu 5594 ZYB's Prime 最大流
    hdu 5593 ZYB's Tree 树形dp
    hdu 5592 ZYB's Game 树状数组
    hdu 5591 ZYB's Game 博弈论
    HDU 5590 ZYB's Biology 水题
    cdoj 1256 昊昊爱运动 预处理/前缀和
    cdoj 1255 斓少摘苹果 贪心
  • 原文地址:https://www.cnblogs.com/lihaiyan/p/4414787.html
Copyright © 2011-2022 走看看