Article From:https://www.cnblogs.com/wanghuaijun/p/9218988.html

0.usbAgreement
    usbVersion: Hardware
        usb 1.0     OHCI        Microsoft hardware > software
        usb 1.1     UHCI        intel                Software > hardware
        usb 2.0     EHCI        intel
        usb 3.0     XHCI        intel

        12mpbs/s   480mpbs/s   5gbps/s   10gbps/s
        
        
        usbTransmission type:
            (0)Control transmission: when the USB device is inserted into the host, the host will communicate with the USB to get the USB device information and allocate the relevant resources.
            (1)Interrupt transmission: the data transmission is small, the response speed is fast, USB mouse; [only the name is interruption, in fact, the internal settings will have a polling time, constantly to query the mouse state, whether there is data can be reported]
            (2)Real time transmission: large amount of data, unreliable data, real time is still relatively strong, USB camera;
            (3)Batch transmission: large amount of data, but reliable data, without real-time constraints: U disk;
                
            Transfer —> transaction —-> packet —-> domain
            Transaction: input (IN) transaction processing, output (OUT) transaction processing, setting up (SETUP)
            Package: the basic unit of USB protocol definition on bus is packet.
                1、Token pack phase: start an input, output or set transaction; start
                2、Packet stage: sending corresponding data according to input and output; data
                3、Handshake packet stage: returns data reception, and there is no such phase in synchronous transmission of IN and OUT transactions. ACK
            Domain: synchronous word domain (SYNC), packet identifier domain (PID), data domain, cyclic redundancy check domain (CRC) and packet end domain (EOP).
                
                
            usbThe endpoint is the smallest unit of data transceiver in the USB device, and the destination / data source of the USB data transmission is the endpoint.
            usbIn addition to the endpoint 0 (in+out), the rest of the devices have only one direction (in/out).
            
            pipe:It is the communication channel between the USB host and the USB device endpoint.
            
            
            usbDevice enumeration process:
                (1)usbDevice – insert –> host —> hardware (host 5V d- (15k—> GND) d+ (15k–> GND) GND)
                                                        (Device 5V d- (15k—> VCC) d+ (15k–> VCC) GND)
                (2)usbPower on equipment: [1] mainframe power supply [2] external independent power supply
                (3)usbAfter the device reset:usb is reset, the host will be able to communicate with the device.
                (4)usbThe device enters the default state: the host is communicating with the device. First, the USB device uses addr 0, endpoint 0, and controls the pipeline.
                                          The host communicates, and the USB host assigns a new address.
                (5)usbThe device uses a new address: the host communicates with the USB device through this new address to get the relevant information of the device.
                (6)According to the equipment information obtained, the relevant configuration work is carried out.
                (7)If there is data to interact with the device, it will communicate, otherwise hang the device into the power saving mode.
                
                RZEncoding (return zero)
                    The positive level represents the logic 1, the negative level represents the logic 0, and the signal is 0 when each data is transmitted. [self synchronization]
                NRZEncoding (no return zero)
                    The positive level represents the logic 1, the negative level represents the logic 0, and the signal does not return to 0 if each data is transmitted.
                NRZIEncoding (no return zero in)
                    The data is 0 level flipped, and the data is 1 level without flip.     
1.usbBus
    1.1 transmission mode
    1.2 Host specification

2.linuxThe next USB framework
                           Bus: device driver
            usb            struct bus_type   usb_bus_type                     struct usb_device              struct usb_driver
            i2c            struct bus_type   i2c_bus_type                     struct i2c_client            struct i2c_driver
            platform    struct bus_type   platform_bus_type                struct platform_device       struct platform_driver
        
                
    1.4 usbDevice descriptor
        usbThe device is logically divided into several levels:
        usbHardware connection:
            [1.5.1]usbDevice descriptor: the device descriptor gives general information about the USB device.
            [1.5.2]Configuration Descriptor
                The configuration descriptor gives the configuration information of the USB device. Under one configuration, an endpoint will not be shared between the interfaces.
            Unless the endpoint is used by different configurations of the unified interface.
            [1.5.3]Interface Descriptor
            [1.5.4]Endpoint descriptor
    1.4 nrziCode
    
    
    1.0usbBus framework
        app:      open    read     write
                ————————————-
        kernel:      
                  usbDevice driver: struct usb_driver
                            drv_open drv_read drv_write …
                        ——————————
                   usb core:
                        Provide structure + registration cancellation function + transmission method + device identification
                        ——————————
                   usbHost controller driver: struct hc_driver
                 ————————————-
        hardware:
                        usbHost controller: struct usb_hcd
                        ——————————
                         usbEquipment: struct usb_device
                ————————————–
    2.2 usbDrive
        (2)Bus
        usb.c—>module—>Load
            struct bus_type usb_bus_type = {
                .name =        “usb”,
                .match =    usb_device_match,
                .uevent =    usb_uevent,
            };
            
            subsys_initcall(usb_init);
            usb_init
                retval = bus_register(&usb_bus_type);

                
            #define subsys_initcall(fn)     __define_initcall(fn, 4) //__define_initcall(usb_init, 4)
            
            176 #define __define_initcall(usb_init, 4) \
            177     static initcall_t __initcall_##usb_init##4 __used \                                                                                                                 
            178     __attribute__((__section__(“.initcall” #4 “.init”))) = usb_init
            .initcall4.init = usb_init
            
            
            #define module_init(x)  __initcall(x);
                #define __initcall(fn) device_initcall(fn)
                    #define device_initcall(fn)     __define_initcall(fn, 6)
                    
                    
            vmlinux.lds  

        (1)Drive structure
            struct usb_driver {
                const char *name;/Name
                int (*probe) (struct usb_interface *intf,const struct usb_device_id *id);//Automatic execution of device and driver matching
                void (*disconnect) (struct usb_interface *intf);//When the device or driver on the bus is removed, it automatically executes.
                const struct usb_device_id *id_table;//usbDrive the list of devices supported
            };
            
                (1)Generate matching device specified < manufacturer ID + product ID> usb_dev_id
                    USB_DEVICE(vendor , product);
                    /*
                        #define USB_DEVICE(vend, prod) \
                        .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
                        .idVendor = (vend), \
                        .idProduct = (prod)
                        
                        #define USB_DEVICE_ID_MATCH_DEVICE \
                            (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
                    */
                    
                    
                    
                (2) Generate matching device specified < manufacturer ID + product ID + product version number > usb_dev_id
                    USB_DEVICE_VER(vendor , product , lo ,hi);
                    
                (3)Generate matching device specified < class + subclass + protocol > usb_dev_id
                    USB_DEVICE_INFO(class , subclass , protocol);
                    
                (4)Generate matching interface specified < class + subclass + protocol > usb_dev_id
                    USB_INTERFACE_INFO(class , subclass , protocol);

                    
            #define usb_register(driver) \
                    usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)    
                    
            int usb_register(struct usb_driver *new_driver)
            Function: registration of usb_driver
            Parameter: pointer object of new_driver:usb_driver
            Return value: Success: 0 failure: -ERRNO
            
            void usb_deregister(struct usb_driver *driver)
            Function: the cancellation of usb_driver
            Parameter: pointer object of driver:usb_driver
            Return value: no
            
            static inline struct usb_device *interface_to_usbdev(struct usb_interface *intf)
            Function: get struct usb_device according to struct usb_interface.
            Parameter: intf:struct usb_interface
            Return value: Success: struct usb_device pointer object failed: NULL
            
            Want to write a USB mouse driver: /driver/usb/usbmouse.c
            
            Technological process:
                (0)Delete the configuration item corresponding to the mouse driver
                     Device Drivers  —>
                            HID support  —>
                                 USB HID support  —>  
                                     <*> USB HID transport layer //This item “N”
                                    
                    cp  arch/arm/boot/uImage ~/tftpboot
                    
                (1)Three elements of module
                (2)Structure filling
                (3)Registration cancellation
                
                
            
            
        
        (3)Equipment
            struct usb_device {
                int        devnum;//Current USB’s device address number
                struct usb_bus *bus;//The USB bus object that the device mounts to
                struct usb_host_endpoint ep0;//usbThe end point 0 of the device
                
                struct usb_device_descriptor descriptor;//usbDevice descriptor —->
                
                struct usb_host_config *config;//usbHost configuration [collection of several functions of the current USB device]
                struct usb_host_endpoint *ep_in[16];//usb Set of input endpoints of a device
                struct usb_host_endpoint *ep_out[16];////usb Set of output endpoints of a device
                struct device dev;//linuxDevice model related
            };
            
                To configure:
                    struct usb_host_config {
                        struct usb_config_descriptor    desc;//Configuration Descriptor
                        struct usb_interface *interface[USB_MAXINTERFACES];//Interface: specific functions
                    };
                    
                    Interface:
                        struct usb_interface {
                            struct usb_host_interface *altsetting;//Unused interfaces
                            struct usb_host_interface *cur_altsetting;//The interface that is being used
                            unsigned num_altsetting;//The number of interfaces currently being used
                            int minor;    //Secondary equipment number
                            struct device dev;    //linuxDevice model object
                        };
                        
                            Set up:
                            struct usb_host_interface {
                                struct usb_interface_descriptor    desc;//Interface Descriptor
                                struct usb_host_endpoint *endpoint;  //Endpoint
                            };
                                Endpoint:
                                struct usb_host_endpoint {
                                    struct usb_endpoint_descriptor        desc;
                                };
                        
                lsusb -v:Print the description information of all the USB devices in the system.
            
Create pipe:
            1、Create control pipe (depending on the type of transmission and the direction of transmission (for host to host)).
                usb_sndctrlpipe(dev, endpoint)
                usb_rcvctrlpipe(dev, endpoint)    
                
            2、Create interrupt pipe
                usb_sndintpipe(dev, endpoint)    
                usb_rcvintpipe(dev, endpoint)
                
            3、Create batch pipe
                usb_sndbulkpipe(dev, endpoint)
                usb_rcvbulkpipe(dev, endpoint)
                
            4、Create isochronous pipe
                usb_sndisocpipe(dev, endpoint)
                usb_rcvisocpipe(dev, endpoint)

Fill in urb:
            (1)Use the usb_fill_control_urb function to initialize the urb to communicate with the control endpoint.
            void usb_fill_control_urb(struct urb *urb,
                                          struct usb_device *dev,
                                          unsigned int pipe,
                                          unsigned char *setup_packet,
                                          void *transfer_buffer,                       
                                          int buffer_length,
                                          usb_complete_t complete(Callback function)
                                          void *context,
                                          );
            (2)Use the usb_fill_int_urb function to initialize the urb that is communicated with the interrupt endpoint.
                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,
                                          void *context,
                                         int interval
                                          );
            (3)Use the usb_fill_int_urb function to initialize the urb to communicate with bulk endpoints.
                void usb_fill_bulk_urb(      struct urb *urb,
                                          struct usb_device *dev,
                                          unsigned int pipe,
                                          void *transfer_buffer,                       
                                          int buffer_length,
                                          usb_complete_t complete,
                                          void *context,
                                         int interval
                                          )
            (4)The urb of the isochronous transmission is filled with fixed steps.
                
            void *usb_alloc_coherent(struct usb_device *dev, size_t size, gfp_t mem_flags,dma_addr_t *dma)
            Function: to receive data from host and allocate relevant address space.
            Parameters: objects of dev:struct usb_device
                  size:The size of the distribution space
                  mem_flags:The symbol GFP_KERNEL for the allocation of space
                  dma:The physical address of the return value
            Return value: Success: the first address of the allocation space failed: NULL
                  
            struct urb *usb_alloc_urb(int iso_packets, int mem_flags);
            Function: allocate the struct urb structure
            Parameters:
                iso_packet:urbThe number of sync messages that are included. If it is not synchronous urb, set to 0, indicating that no isochronous packets are created.
                mem_flags: The type of flag that the kernel assigns memory.
            Successful return: urb’s first address failed to return: NULL

            The function of releasing the urb structure:
            void usb_free_urb(struct urb *urb);

            
            int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
            Function: submitting Urb
            Parameter: urb: urb object to be submitted
                  mem_flags:The symbol GFP_KERNEL of the memory space for the Urb
            Return value: Success: 0 failure: -errno
3.usbRequest block
    (1)urbStructure:
    (2)urbcorrelation function
        Apply for release of urb:
        Fill in urb:
        Fill in the pipe parameter settings in the urb function:
        Submit Urb
        Canceling the urb function
4.usbSkeleton program
    
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/usb.h>
#include <linux/mod_devicetable.h>
#include <linux/hid.h>
#include <linux/input.h>
#include <linux/bitops.h>
#include <linux/gfp.h>
/*
Technological process:
(1)Three elements of module
(2)Structure filling
(3)Registration cancellation
(4)Hardware related operations
    [4.1]Because the USB mouse belongs to the input device, it needs to provide the reported data transmitted through the USB data line, so it is necessary to provide input data at this time.
        input_devApplication + filling + registration + cancellation

    [4.2]usbRelevant
        [4.2.1]Get the endpoint of the communication (in the USB device)
        [4.2.2]Get pipe (different transmission types of pipes are different, the pipeline has the direction of transmission).
        [4.2.3]In order to receive incoming data from the endpoint, the host needs to allocate certain space.
        [4.2.4]urb:Apply to urb + fill + submit + receive urb, and then analyze the relevant data.
*/
struct usb_device *usb_key_dev = NULL;
struct input_dev *usb_input_dev = NULL;
char *usb_master_buf = NULL;
dma_addr_t  usb_buf_phy;
struct urb *my_urb = NULL;
int length = 0;

void usb_key_complete(struct urb *urb)
{
    int i = 0;
    for(i = 0; i < length ; i++){
        printk(“usb_master_buf[%d]:%d\t”,i ,usb_master_buf[i] );
    }
    printk(“\n”);
    usb_submit_urb(my_urb,GFP_KERNEL);
}

int usb_key_probe(struct usb_interface *intf,const struct usb_device_id *id)
{
    int ret = 0;
    int pipe = 0;
    
    struct usb_host_interface *interface;
    struct usb_endpoint_descriptor *endpoint;
    
    usb_key_dev = interface_to_usbdev(intf);
    if(usb_key_dev == NULL){
        printk(“%s,%d usb_key_dev fail…\n”,__func__,__LINE__);
        return -ENOMEM;
    }
    
    interface = intf->cur_altsetting;
    endpoint = &interface->endpoint[0].desc;
    /*inputCorrelation * /
    usb_input_dev = input_allocate_device();
    if(usb_input_dev == NULL){
        printk(“input_allocate_device …\n”);
        return -ENOMEM;
    }
    //type
    set_bit( EV_KEY, usb_input_dev->evbit);
    set_bit( EV_REL, usb_input_dev->evbit);
    //code
    set_bit( KEY_L,usb_input_dev->keybit );
    set_bit( KEY_R,usb_input_dev->keybit );
    set_bit( KEY_ENTER,usb_input_dev->keybit);

    ret = input_register_device(usb_input_dev);
    if(ret < 0){
        printk(“input_register_device fail\n”);
        return -EINVAL;
    }

    /*usbCorrelation 1. determines the source + purpose + length of data transmission * /
    pipe= usb_rcvintpipe(usb_key_dev, endpoint->bEndpointAddress);
    length = endpoint->wMaxPacketSize;
    usb_master_buf = usb_alloc_coherent(usb_key_dev,length,GFP_KERNEL,&usb_buf_phy);
    if(usb_master_buf == NULL){
        printk(“usb_alloc_coherent fail\n”);
        return -ENOMEM;
    }

    /*usb  Data transmission preparation: assign urb + fill urb (with transmission type) + submit urb*/
    my_urb = usb_alloc_urb(0,GFP_KERNEL);
    if(my_urb == NULL){
        printk(“usb_alloc_urb fail\n”);
        return -ENOMEM;
    }
    usb_fill_int_urb(my_urb,usb_key_dev,pipe,usb_master_buf,length,usb_key_complete,NULL,endpoint->bInterval);
    my_urb->transfer_dma = usb_master_buf;
    my_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
    
    usb_submit_urb(my_urb,GFP_KERNEL);
    
    printk(“%x,%x\n”,usb_key_dev->descriptor.idVendor,usb_key_dev->descriptor.idProduct);//[   21.545000] 93a,2510
    printk(“%s,%d\n”,__func__,__LINE__);
    return 0;
}
void usb_key_disconnect(struct usb_interface *intf)
{
    usb_kill_urb(my_urb);
    usb_free_urb(my_urb);
    usb_free_coherent(usb_key_dev,length,usb_master_buf,usb_buf_phy);
    input_unregister_device(usb_input_dev);
    input_free_device(usb_input_dev);
    
    printk(“%s,%d\n”,__func__,__LINE__);
}

const struct usb_device_id usb_key_table[] = {
    { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
        USB_INTERFACE_PROTOCOL_MOUSE)},
    //{USB_DEVICE(0x93a , 0x2510)},//Matching the specified vendor ID product ID why does it not implement this function?
};

struct usb_driver usb_key_drv = {
    .name = “usb_key”,
      .probe = usb_key_probe,
    .disconnect = usb_key_disconnect,
    .id_table = usb_key_table,
};

static int __init usbkey_init(void)
{
    int ret = 0;
    ret = usb_register(&usb_key_drv);
    if(ret < 0){
        printk(“%s,%d usb_register fail\n”,__func__,__LINE__);
        return -EINVAL;
    }
    printk(“%s,%d\n”,__func__,__LINE__);
    return 0;
}

static void __exit usbkey_exit(void)
{
    usb_deregister(&usb_key_drv);
    printk(“%s,%d\n”,__func__,__LINE__);
}

module_init(usbkey_init);
module_exit(usbkey_exit);
MODULE_LICENSE(“GPL”);

            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   

Link of this Article: Linux USB driver

Leave a Reply

Your email address will not be published. Required fields are marked *