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
  • 相关阅读:
    关于docker日常操作(一)
    html基础
    Java6开发WebService进阶
    Java6开发WebService入门
    jsp session
    jsp中的request
    java文件上传下载
    javaweb文件上传下载
    struts2文件上传下载
    springMVC文件上传下载
  • 原文地址:https://www.cnblogs.com/lihaiyan/p/4414787.html
Copyright © 2011-2022 走看看