1. USB is a master-slave structure
All USB transmissions are initiated from the USB host side, and the USB device does not have the ability to "proactively" notify the USB host.
Example: A USB mouse to swipe a moment to generate data, but it does not have the ability to notify the PC to read data, can only passively wait for the PC to read.
2. USB Transmission Type:
A. Control transmission: Reliable, time is guaranteed, such as: USB device identification process
B. Batch transfer: Reliable, time is not guaranteed, such as: U disk
C. Interrupt transmission: Reliable, real-time, such as: USB mouse
D. Real-time transmission: unreliable, real-time, such as: USB camera
3. USB-Transmitted objects: endpoints (Endpoint)
We say "Read U disk", "Write U Disk", can be refined to: write the data to the USB flash drive Endpoint 1, from the end of the USB stick 2 read the data
In addition to endpoint 0, each endpoint supports only one direction of data transfer
Endpoint 0 is used to control the transmission and can be either output or input
4. Each endpoint has a transmission type, transmission direction
5. The term, the program said input (in), the output (out) "are" based on the USB host position said.
For example, the mouse data is transmitted from the mouse to the PC, the corresponding endpoint is called "Input endpoint"
6. The role of the USB bus driver
A. Identify the USB device
B. Find and install the corresponding device driver
C. provide USB read-write function
/*
* DRIVERS\HID\USBHID\USBMOUSE.C
*/
#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 *uk_dev;
static char *usb_buf;
Static dma_addr_t Usb_buf_phys;
static int len;
static struct URB *uk_urb;
static struct usb_device_id usbmouse_as_key_id_table [] = {
{Usb_interface_info (Usb_interface_class_hid, Usb_interface_subclass_boot,
Usb_interface_protocol_mouse)},
/* Terminating entry */
};
static void Usbmouse_as_key_irq (struct URB *urb)
{
static unsigned char pre_val;
/* USB mouse data meaning
* Data[0]: bit0-left button, 1-Press, 0-loosen
* bit1-Right button, 1-Press, 0-loosen
* bit2-middle button, 1-Press, 0-release
*
*/
if (Pre_val & (1<<0)! = (Usb_buf[0] & (1<<0)))
{
/* Left key changed */
Input_event (Uk_dev, Ev_key, key_l, (Usb_buf[0] & (1<<0))? 1:0);
Input_sync (Uk_dev);
}
if (Pre_val & (1<<1)! = (Usb_buf[0] & (1<<1)))
{
/* The right Key has changed */
Input_event (Uk_dev, Ev_key, key_s, (Usb_buf[0] & (1<<1))? 1:0);
Input_sync (Uk_dev);
}
if (Pre_val & (1<<2)! = (Usb_buf[0] & (1<<2)))
{
/* Medium key changed */
Input_event (Uk_dev, Ev_key, Key_enter, (Usb_buf[0] & (1<<2))? 1:0);
Input_sync (Uk_dev);
}
Pre_val = usb_buf[0];
/* Resubmit URB */
Usb_submit_urb (Uk_urb, Gfp_kernel);
}
static int usbmouse_as_key_probe (struct usb_interface *intf, const struct USB_DEVICE_ID *id)
{
struct Usb_device *dev = Interface_to_usbdev (intf);
struct Usb_host_interface *interface;
struct Usb_endpoint_descriptor *endpoint;
int pipe;
interface = intf->cur_altsetting;
Endpoint = &interface->endpoint[0].desc;
/* A. Assign a Input_dev */
Uk_dev = Input_allocate_device ();
/* b. Set */
/* What kind of events can be produced by B.1 */
Set_bit (Ev_key, uk_dev->evbit);
Set_bit (Ev_rep, uk_dev->evbit);
/* What events B.2 can generate */
Set_bit (key_l, uk_dev->keybit);
Set_bit (key_s, uk_dev->keybit);
Set_bit (Key_enter, uk_dev->keybit);
/* C. Registration */
Input_register_device (Uk_dev);
/* d. Hardware-related Operations */
/* Data transfer 3 elements: source, purpose, length */
/* Source: One of the endpoints of the USB device */
Pipe = Usb_rcvintpipe (dev, endpoint->bendpointaddress);
/* Length: */
Len = endpoint->wmaxpacketsize;
/* Purpose: */
Usb_buf = Usb_buffer_alloc (Dev, Len, gfp_atomic, &usb_buf_phys);
/* Use "3 features" */
/* Assign USB request block */
Uk_urb = usb_alloc_urb (0, Gfp_kernel);
/* Use "3 feature settings Urb" */
Usb_fill_int_urb (uk_urb, Dev, pipe, usb_buf, Len, Usbmouse_as_key_irq, NULL, Endpoint->binterval);
UK_URB->TRANSFER_DMA = Usb_buf_phys;
Uk_urb->transfer_flags |= Urb_no_transfer_dma_map;
/* Use URB */
Usb_submit_urb (Uk_urb, Gfp_kernel);
return 0;
}
static void Usbmouse_as_key_disconnect (struct usb_interface *intf)
{
struct Usb_device *dev = Interface_to_usbdev (intf);
PRINTK ("Disconnect usbmouse!\n");
Usb_kill_urb (UK_URB);
Usb_free_urb (UK_URB);
Usb_buffer_free (Dev, Len, usb_buf, Usb_buf_phys);
Input_unregister_device (Uk_dev);
Input_free_device (Uk_dev);
}
/* 1. Assign/Set Usb_driver */
static struct Usb_driver Usbmouse_as_key_driver = {
. Name= "Usbmouse_as_key_",
. probe= Usbmouse_as_key_probe,
. disconnect= Usbmouse_as_key_disconnect,
. id_table= Usbmouse_as_key_id_table,
};
static int usbmouse_as_key_init (void)
{
/* 2. Register */
Usb_register (&usbmouse_as_key_driver);
return 0;
}
static void Usbmouse_as_key_exit (void)
{
Usb_deregister (&usbmouse_as_key_driver);
}
Module_init (Usbmouse_as_key_init);
Module_exit (Usbmouse_as_key_exit);
Module_license ("GPL");
Linux Driver usb Driver