The purpose of this section : take USB The left mouse button acts as L Key , take USB The right mouse button acts as S Key , The middle key acts as the Enter key


 

Reference resources /drivers/hid/usbhid/usbmouse.c( Built in kernel USB Mouse drive )

1. The macros needed in this section are as follows :

struct usb_device_id usbmouse_id_table []=USB_INTERFACE_INFO(cl,sc,pr);

USB_INTERFACE_INFO() Set up usb_driver Driven id_table member

cl: Interface class , We USB Mouse for HID class , So fill in 0X03, That is to say USB_INTERFACE_CLASS_HID

sc: The interface subclass is the boot device , fill USB_INTERFACE_SUBCLASS_BOOT

pr: The interface protocol is mouse protocol , fill USB_INTERFACE_PROTOCOL_MOUSE 

 

        

struct usb_device *dev=interface_to_usbdev(intf);

  adopt usb_ interface Interface acquisition usb_device equipment , Set... For the back USB For data transmission

 

 

pipe=usb_rcvintpipe(dev,endpoint);

Create a receive (rcv) interrupt (int) End pipe of type (pipe), Used to connect between endpoints and data buffers , Mouse to receive interrupt type

dev: usb_device Equipment structure

endpoint: Is a member of the endpoint descriptor endpoint->bEndpointAddress   // Endpoint address

  • For end pipe of control type, use : usb_sndctrlpipe()/usb_rcvctrlpipe()
  • For real-time type endpoint pipes, use : usb_sndisocpipe()/usb_sndisocpipe()
  • For batch type end pipe use : usb_sndbulkpipe()/usb_rcvbulkpipe()

 

2. The functions used in this section are as follows :

usb_deregister(struct usb_driver *driver);

Sign up for a usb_driver drive , And then the kernel goes through usb_driver Members of .id_table The function matches once USB equipment , If the match is successful, it will call usb_driver Members of .probe function

 

usb_deregister(struct usb_driver *driver);

Cancel one usb_driver drive , Write... In the exit function

 

*usb_buffer_alloc(struct usb_device *dev,size_t size,gfp_t mem_flags,dma_addr_t *dma);

Allocate one usb buffer , The physical address of the cache will be consistent with the data of the virtual address , The assignment was successful and returned a char Type buffer virtual address

*dev: usb_device Equipment structure

size: The size of the allocated buffer , Fill in the members of the endpoint descriptor here endpoint->wMaxPacketSize          // The maximum packet length of the endpoint

mem_flags: Parameters for allocating memory , Fill in here GFP_ATOMIC, Never sleep

dma: If the assignment is successful, a DMA The physical address of the buffer

void usb_buffer_free(struct usb_device *dev,size_t size,void *addr,dma_addr_t dma);

Write off the allocated usb buffer , stay usb_driver Of disconnect Member function

addr: The virtual address of the buffer to unregister

dma: To log off DMA Buffer virtual address

 

struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags);

Allocate one urb Data structures , The assignment was successful and returned a urb Structure

urb Its full name is usb request block,USB Data transfer , It's packaged into urb Structure to transmit

iso_packets: Express iso Number of packages of type , Here we are not iso Type package , Directly fill in 0

mem_flags: Parameters for allocating memory , Fill in here GFP_KERNEL, Normal distribution

among urb The structure is as follows :

 

struct urb
{
 ... ...
 struct usb_device *dev;             // Point to usb equipment
 struct usb_host_endpoint *ep;    // Data structures that point to endpoints  
 unsigned int pipe;                  // Point to the end pipe (pipe),  Of this section pipe adopt usb_rcvintpipe() Macro get
 int status;                                 // state , When status==0, Indicates that the data has been successfully received / send out
 
 unsigned int transfer_flags;     // Transmission status
 ... ...
/* The following two buffers pass through usb_buffer_alloc () Function to obtain  */
//urb Structure default transfer_flags yes URB_NO_SETUP_DMA_MAP , That is to say, it is not provided DMA The buffer
// Will use transfer_buffer Virtual address buffer to be a buffer
// When supported DMA Buffer time , You need to set it manually transfer_flags =URB_NO_TRANSFER_DMA_MAP, And set it manually transfer_dma It's equal to what you get DMA Physical address
 void *transfer_buffer;                // Virtual buffer
 dma_addr_t transfer_dma;          //DMA Physical buffer  
... ...
};

 

void usb_free_urb(struct urb *urb);

The application for release urb, stay usb_driver Of disconnect Member function

 

static inline void usb_fill_int_urb(struct urb *urb,struct usb_device *dev,unsigned int pipe,
void *transfer_buffer,int buffer_length, 
usb_complete_t complete_fn,void *context,int interval);

 

Initialize the interrupt type endpoint urb Data structures

For batch endpoints urb Use usb_fill_bulk_urb()
For controlling endpoints urb Use usb_fill_control_urb()
For isochronous endpoints urb   Manual initialization is required .

urb: Point to the urb

dev: Point to the usb equipment

pipe: The end pipe to transfer , Of this section pipe adopt usb_rcvintpipe() Macro get

transfer_buffer: Point to the virtual address buffer to transfer data

buffer_length: data size , Fill in the members of the endpoint descriptor here endpoint->wMaxPacketS // The maximum packet length of the endpoint

complete_fn: Interrupt function generated after data transmission

context: It will be placed in urb->context Among the members of the structure , Used for interrupt functions , This section does not require , fill NULL that will do

interval: Time interval between , Indicates the time interval between reading data , fill endpoint-> bInterval that will do

 

int usb_submit_urb(struct urb *urb,gfp_t mem_flags);

 

Submit urb To kernel , initialization urb And interrupt function exit , You have to submit it again , Tell the kernel to initialize the memory cache, etc

 

 

void usb_kill_urb(struct urb *urb);

kill urb, stay usb_driver Of disconnect Member function

 

3. Steps are as follows :

First, define global variables :usb_driver Structure ,input_dev Pointer structure , Virtual address buffer ,DMA Address buffer

3.1 The function is in the entry

1) adopt usb_register() Function registration usb_driver Structure

3.2 stay usb_driver Of probe Function

1) Allocate one input_dev Structure

2) Set up input_dev Support L、S、 enter 、3 A key event

3) register input_dev Structure

4) Set up USB The data transfer :

 ->4.1) adopt usb_rcvintpipe() Create an endpoint pipeline to receive interrupt types , Used to connect between endpoints and data buffers

 ->4.2) adopt usb_buffer_alloc() apply USB buffer

 ->4.3) Apply and initialize urb Structure ,urb: Used to transmit data

 ->4.4) Because we 2440 Support DMA, So tell urb Structure , Use DMA Buffer address

 ->4.5) Use usb_submit_urb() Submit urb

3.3 In the mouse interrupt function

1) Determine whether the buffer data has changed , If it changes, the mouse event will be uploaded

2) Use usb_submit_urb() Submit urb

3.4. stay usb_driver Of disconnect Function

1) adopt usb_kill_urb() Kill those submitted to the kernel urb

2) Release urb

3) Release USB Buffer zone

4) Cancellation input_device, Release input_device

3.5 In the exit function

1) adopt usb_deregister () Function logout usb_driver Structure

 

4. The code is as follows :

 

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb/input.h>
#include <linux/hid.h>
static struct input_dev *myusb_mouse_dev;              //input_dev 
static char *myusb_mouse_buf;                         // Virtual address buffer
static dma_addr_t myusb_mouse_phyc;                     //DMA Buffer zone ;
static __le16 myusb_mouse_size;                        // Packet length
static struct urb  *myusb_mouse_urb;                     //urb
static void myusb_mouse_irq(struct urb *urb)               // Mouse interrupt function
{
   static char buf1=0;
   //for(i=0;i<myusb_mouse_size;i++)
  // printk("%02x  ",myusb_mouse_buf[i]);
 //  printk("\n");
    /*bit 1- Left and right middle key   0X01: left-click    0X02: Right click      0x04: In the key    */
     if((buf1&(0X01))    !=      (myusb_mouse_buf[1]&(0X01)))
        {         
                input_report_key(myusb_mouse_dev, KEY_L, buf1&(0X01)? 1:0);
                input_sync(myusb_mouse_dev);  
        }
     if((buf1&(0X02))    !=    (myusb_mouse_buf[1]&(0X02)))
        {
                input_report_key(myusb_mouse_dev, KEY_S, buf1&(0X02)? 1:0);
                input_sync(myusb_mouse_dev);  
        }
     if((buf1&(0X04))    !=    (myusb_mouse_buf[1]&(0X04))  )
          {
                input_report_key(myusb_mouse_dev, KEY_ENTER, buf1&(0X04)? 1:0);
                input_sync(myusb_mouse_dev);  
          }
     buf1=myusb_mouse_buf[1];                                   // Update data
     usb_submit_urb(myusb_mouse_urb, GFP_KERNEL);
}
static int myusb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
       struct usb_device *dev = interface_to_usbdev(intf);             // equipment
       struct usb_endpoint_descriptor *endpoint;                            
       struct usb_host_interface *interface;                         // Current interface
       int pipe;                                                   // End pipe
       interface=intf->cur_altsetting;                                                                   
       endpoint = &interface->endpoint[0].desc;                                    // The endpoint descriptor under the current interface
   
       printk("VID=%x,PID=%x\n",dev->descriptor.idVendor,dev->descriptor.idProduct); // Print VID,PID
 
 /*   1) Allocate one input_dev Structure   */
       myusb_mouse_dev=input_allocate_device();
 
 /*   2) Set up input_dev Support L、S, enter 、3 A key event */
       set_bit(EV_KEY, myusb_mouse_dev->evbit);
       set_bit(EV_REP, myusb_mouse_dev->evbit);        // Support the function of repeated press
       set_bit(KEY_L, myusb_mouse_dev->keybit);       
       set_bit(KEY_S, myusb_mouse_dev->keybit);
       set_bit(KEY_ENTER, myusb_mouse_dev->keybit);    
 /*   3) register input_dev Structure */
       input_register_device(myusb_mouse_dev);
 
 /*   4) Set up USB The data transfer  */
 /*->4.1) adopt usb_rcvintpipe() Create an end pipe */
       pipe=usb_rcvintpipe(dev,endpoint->bEndpointAddress); 
  /*->4.2) adopt usb_buffer_alloc() apply USB buffer */
       myusb_mouse_size=endpoint->wMaxPacketSize;
       myusb_mouse_buf=usb_buffer_alloc(dev,myusb_mouse_size,GFP_ATOMIC,&myusb_mouse_phyc);
  /*->4.3) adopt usb_alloc_urb() and usb_fill_int_urb() Apply and initialize urb Structure  */
       myusb_mouse_urb=usb_alloc_urb(0,GFP_KERNEL);
       usb_fill_int_urb (myusb_mouse_urb,                       //urb Structure
                                 dev,                           //usb equipment
                                 pipe,                          // End pipe
                                 myusb_mouse_buf,               // Cache address
                                 myusb_mouse_size,              // Data length
                                 myusb_mouse_irq,               // Interrupt function
                                 0,
                                 endpoint->bInterval);          // Interrupt interval time
  /*->4.4)  Because we 2440 Support DMA, So tell urb Structure , Use DMA Buffer address */
        myusb_mouse_urb->transfer_dma   =myusb_mouse_phyc;             // Set up DMA Address
        myusb_mouse_urb->transfer_flags   =URB_NO_TRANSFER_DMA_MAP;     // Set to use DMA Address
  /*->4.5) Use usb_submit_urb() Submit urb*/
        usb_submit_urb(myusb_mouse_urb, GFP_KERNEL);
       return 0;
}
static void myusb_mouse_disconnect(struct usb_interface *intf)
{
    struct usb_device *dev = interface_to_usbdev(intf);                  // equipment
    usb_kill_urb(myusb_mouse_urb);
    usb_free_urb(myusb_mouse_urb);
    usb_buffer_free(dev, myusb_mouse_size, myusb_mouse_buf,myusb_mouse_phyc);
    input_unregister_device(myusb_mouse_dev);         // Unregister... From the kernel input_dev
    input_free_device(myusb_mouse_dev);             // Release input_dev
} 
static struct usb_device_id myusb_mouse_id_table [] = {
       { USB_INTERFACE_INFO(
              USB_INTERFACE_CLASS_HID,                 // Interface class :hid class
              USB_INTERFACE_SUBCLASS_BOOT,             // Subclass : Start device class
              USB_INTERFACE_PROTOCOL_MOUSE) },      //USB agreement : Mouse protocol
};
static struct usb_driver myusb_mouse_drv = {
       .name            = "myusb_mouse",
       .probe           = myusb_mouse_probe,                           
       .disconnect     = myusb_mouse_disconnect,
       .id_table  = myusb_mouse_id_table,
};
 
/* Entry function */
static int myusb_mouse_init(void)
{
       usb_register(&myusb_mouse_drv);
       return 0;
}
/* Exit function */
static void myusb_mouse_exit(void)
{
       usb_deregister(&myusb_mouse_drv);
}
 
module_init(myusb_mouse_init);
module_exit(myusb_mouse_exit);
MODULE_LICENSE("GPL");

 

5. test run

5.1  Reset the compilation kernel ( Remove the default hid_USB drive )

make menuconfig , Get into menu Menu reset kernel parameters :

Get into -> Device Drivers -> HID Devices 

<> USB Human Interface Device (full HID) support //hid: Human computer interaction USB drive , For example, mouse. , Keyboard, etc

then make uImage  Compiling the kernel

Put the new touch screen driver module into nfs In the file system directory

5.2 Then burn the kernel , Load the touch screen driver module

Here's the picture , When we plug in USB Mouse time , You can see that VID and PID, It's the same parameters as the mouse on the computer

 

5.3 Use hexdump Command to debug

(hexdump Command debug code detailed address :http://www.cnblogs.com/lifexy/p/7553550.html)

 

5.4  Use tty1 Process testing