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”);