006USB Device Drivers

First, the concept of USB driver Introduction (Lesson 17 / Section)

Phenomenon:
Under WINDOWS, the USB device connected to the PC:

  1. The lower right corner will pop up "what new USB device discovery." Found "android phone".
  2. Jump out of a dialog box prompts to install the driver.

Question 1: Since he has no "drivers", why can know "android phone"?

    答1:Windows里已经有了USB的总线驱动程序,接入USB设备后,是"总线驱动程序"知道你是"android phone"。提示你安装的是"设备驱动程序"。
    USB总线驱动程序负责:识别USB设备,给USB设备找到对应的驱动程序。

Q 2: USB device type is very large, Why access a computer, you can identify it?

    答2:PC和USB设备都得遵守一些规范。比如:USB设备接入电脑后,PC机就会发出"你是什么?"   USB设备就必须回答"我是xxx"。
    USB总线驱动程序会发出某些命令想获取设备信息(描述符),USB设备必须返回(描述符)给PC机。

Question 3: then there is a lot of USB devices on a PC, how to distinguish them?

    答3:USB接口只有四根线:5V,GND,D-,D+
    每一个USB设备接入PC机时,USB总线驱动程序都会给它分配一个编号,接在USB总线上的每一个USB设备都有自己的编号(地址),PC机想访问某个USB设备时,发出的命令都含有对应的编号(地址)。

Q 4: USB devices just access to a PC, there is no number, then the PC how to "assigned numbers" tell it?

    答4:新接入的USB设备的默认编号是0,在未分配新编号前,PC机使用0编号和它通信。

Q5: Why access a USB device, PC machines will be able to find it?

    答5:PC机的USB口内部,D-和D+都接有15K的下拉电阻,未接USB设备时为低电平;USB设备的USB口内部,D-或D+接有1.5K的上拉电阻。当USB设备一接入PC机,就会把PC的USB口的D-或D+拉高,从硬件的角度通知PC机有新设备接入


Other concepts:

    一、 USB是主从结构的:
    所有的USB传输,都是从USB主机这方发起,USB设备没有"主动"通知USB主机的能力。
    例:USB鼠标滑动一下立刻产生数据,但是它没有能力通知PC机来读数据,只能被动的等待PC机来读取。

    二、 USB的传输类型:
    a.控制传输:可靠,实时,比如:USB设备的识别过程
    b.批量传输:可靠,时间没有保证,比如:U盘(从PC机上删除U盘时有时快有时慢)
    c.中断传输:可靠,实时,比如:USB鼠标。(只是借助了中断的概念,实质是用USB主机查询方式来实现实时性,不断读USB鼠标。USB设备并不能发起中断,USB设备并没有发起通知给USB主机的能力。)
    d.实时传输:不可靠,实时,比如:USB摄像头。(数据的不可靠可以接受,如果要可靠,可能因为某一帧发送错误时会因可靠机制来重传,就会带来滞后感。)

    三、 USB传输的对象:端点(endpoint)
    我们说"读U盘"、"写U盘",可以细化为:把数据写到U盘的端点1,从U盘的端点2里读出数据;除了端点0外,每一个端点只支持一个方向的数据传输。端点0用于控制传输,既能输入也能输出。

    四、 每一个端点都有(只有一个)传输类型,传输方向

    五、 术语里、程序里说的输入(IN)、输出(OUT)都是基于USB主机的立场说的。比如鼠标的数据是从鼠标传到PC机,对应的端点称为"输入端点"。(对于USB主机来说这是输入)。

    六、 USB总线驱动程序的作用:
    a. 识别USB设备。
    b. 查找并安装对应的设备驱动程序。
    c. 提供USB读写函数。(只是提供读写函数,数据的含义不知道。就像"送信人"一样,不了解数据含义。USB设备驱动程序知道数据含义。)

USB driver framework:

Two, USB bus driver for the USB driver (Lesson 17 / II)

There are three USB host controller specification: 1.UHCI; 2.OHCI; 3.EHCI

    UHCI:intel   适用于(USB1.1)低速(1.5Mbps)/(USB2.0)全速(12Mbps)     (当说到USB2.0还得分全速和高速)
    OHCI:microsoft 适用低速/全速
    EHICI:        适用于高速(480Mbps)

intel chip to do, do it with this specification UHCI host controller hardware is powerful, the software is simple point; the contrary, microsoft software to do, do it with this specification OHCI hardware will almost, but software more complex.

The USB device (mobile phone) to the development board, view the output:

Unplug

here (full speed) will be unreliable, the kind of speed might be "% s", so a search for "USB device using" in the kernel driver directory

HUB concept:

each USB host controller comes with a USB HUB, USB devices connected to the HUB, HUB can be considered a special USB devices
found in the search to the print (hub.c) this file statement

view the statement in which function in the

hub port initialization, this function is called to see where

port changes, this function has been invoked where

hub event function is invoked where

hub thread, it is a kernel thread, usually is dormant, when something happens will be awakened, then it is who is going to wake up

search from the queue who wake up to it

this (kick_khubd) is whom to call

Note: this interrupt is registered in the host controller, USB device is not interrupted
when connected to a USB device, such that the D + or D- will have a low level to the high level, and be aware of the hardware device is connected to a USB, the host controller will produce in Off.
All the way down inside the interrupt function is performed, the final will be executed to (hub_port_init), it will print out a new USB device found inside the function

according to the role of USB drive bus, take a look at is how to tell the USB device

from the (hub_port_connet_change) function analysis begins

assigned structure usb_device a

bus structure of this type is "usb_bus_type"

followed by the allocation number (address)

Then enters (hub_port_init) function, and acquires the address set descriptor

set address

acquisition descriptor
information descriptor may be in the (include \ linux \ usb \ Ch9.h ) see, Chapter IX represents Ch9 USB protocol specification
device descriptor : every hardware device has a USB descriptors, I can issue some commands to get these devices descriptors USB devices. A device may have multiple configurations


Configuration Descriptor


Interface Descriptor: a logical device on
each of a plurality of interfaces may be disposed below, may be only one. For example: a USB sound card, it is only a hardware, but logically there may be two functions (recording, playback). This is divided into two logical devices, with two "interface descriptor" describe the logical device "recording" and "playback" .


Endpoint Descriptor


each hardware has a device descriptor, a device may have a plurality of the following configuration, the following configuration may have a plurality of interfaces, the interface is a logical device, we write driver is to the interface (logical device) written , so a USB hardware may be more than one driver. An interface which has a plurality of points, which represents how the descriptor will be a one-time transmission of data, its endpoint number, its direction, its transmission type information.
After we put all these descriptor information can be read out of the USB device well aware of, you can find this information in accordance with the driver

asked: why only get 8 bytes it?

A: Because you do not know how much this endpoint 0-time data transmission.

Again device descriptor obtained

here (hub_port_init) function is finished. And then return to the previous function (hub_port_connet_change), to see what other work, call (usb_new_devie) function
in (usb_get_configuration) function in all the descriptors are read out, and resolve them


Finally jump (usb_new_device) function in execution (device_add)

(device_add) function to the bus device driver model to add USB devices. Dev list the devices into the bus, remove the driver-one comparison with a match function by id_table bus from the bus's driver list, if the match is successful, driver of the "probe" function is called.
Sum up this process:

    当接上一个USB设备时,就会产生由硬件产生一个中断(hub_irq),在中断里会分配一个编号(choose_address),然后把这个地址告诉USB设备(hub_set_address),接着发出各种命令获取USB设备的"设备描述符"。再然后注册一个device(device_add),这个被注册的device会被放到USB总线(usb_bus_type)的"设备链表",然后从总线的"驱动链表"中取出"usb_driver",把usb_interface和usb_driver的id_table比较,若匹配成功则调用"usb_driver"结构中的probe函数。

Three, USB device driver for the USB driver of a simple writing (Lesson 17 / III)


USB bus driver, when we access the USB device will help us construct a new usb_dev, registered to the (usb_bus_type) go left this part of the kernel has helped us to do, we have to do is the right side of this one, construction a usb_driver structure, then register to (usb_bus_type) years. There id_table in usb_driver structure, the device represents what it can support, when (usb_bus_type) structure will be called usb_driver structure probe function after match function successfully matched; it will call usb_driver structure disconnet function when unplugging a USB device.
(usb_bus_type) bus driver model only provides a framework that can hook up to both sides.
Goal:
the USB mouse is used as a key input subsystem :( equivalent)
Left - L
Right - S
CCT - Enter
things to do in the probe function:

    1. 分配一个input_dev结构体。
    2. 设置,使其产生哪类事件,该类事件的哪些事件。
    3. 注册
    4.硬件相关操作:
    写按键或触摸屏驱动程序时是注册某中断,在按键的中断里读引脚确定是按下还是松开然后读按键值。
    在USB鼠标里,是使用USB总线驱动程序提供的读写函数来收发数据。

How to write USB device drivers?
1. Allocate / set usb_driver structure
.id_table indicate which devices can support
.probe if id_table supports calls the probe function
calls this function when unplugging a USB device .disconnet
2. Registration

Referring first to someone else's code: (driver \ hid \ usbhid \ usbmouse.c)
entry function inside a register (usb_driver structure)

assumption can be matched, the function calls the probe




before the touchscreen driver was 2440adc data from the controller inside the current USB drivers want the data packet is sent USB. By (USB host controller) to obtain data that
is now written to the frame:

1th, simple print statement

一、 id_table:

    ".match_flags":表示要匹配设备描述符中的哪一项。"USB_DEVICE_ID_MATCH_INT_INFO":INT是接口的意思,INT_INFO就是指接口的信息;接口的信息就在接口描述符里。
    ".bInterfaceClass":接口描述符里的类
    ".bInterfaceSubClass":接口描述符的子类
    ".bInterfaceProtocol":接口描述符的协议

As long as the device interface descriptor class is inside HID class; subclass is the BOOT; protocol is MOUSE, then this can be id_table support.

Manufacturers may also support ID, device ID

Two, the probe function filling

a USB hardware device may have multiple logical devices, the logical device is to use "usb_interface" represented by the structure. As a recording and playback sound card has two logical interfaces, requires two drivers.
Three, disconnect function

test 1th:
The first step: make menuconfig remove the original USB mouse driver, or a USB mouse connected to the kernel will find the original drive, the new drive is unable to load registration.


Step two: USB kernel compiles without

third step: do not use the kernel boot USB


Step Four: Mount the file system, load the driver


Step five: Insert, pull out the mouse

2th, print vendor ID and the device ID

When we access the USB device, USB bus driver has put all these devices descriptor information read out.


Print information descriptor

Test 2th:
re-loading drive

insert, pull mouse

USB mouse descriptor information on the computer

3th, USB mouse print raw data

Continue to analyze examples (usbmouse.c) function of probe


Q: how to know whether the endpoint is an input type?
A: each endpoint of the endpoint descriptor has a property indicating its direction.
Continue to write code, in my own code would not have to make a judgment, and it is considered a mouse
in accordance with the routine to finish the first three steps

before the hardware operation is to register an interrupt pin and then register to read, and now need to use the underlying read and write functions provided by the USB host controller to transmit and receive USB data
a, the data transfer three elements: source, destination, length.
1. Source: an endpoint of the USB device.



This macro (usb_rcvintpipe) contains the USB device address and which endpoint (endpoint address)
own guess: This type int pipe variable contains the endpoint type, device address, endpoint address endpoint direction, because these four to split portion 4 bytes

    PIPE_INTERRUPT:中断类型端点
    USB_DIR_IN:端点的方向
    devnum:设备地址(USB设备编号)
    endpoint:端点地址(bEndpointAddress)

2. Objective: USB device to read data from a read buffer. So to allocate a buffer can not be used (kalloc), with (usb_buffer_alloc) to allocate, a return (void *) of the virtual address

3. Length: endpoint descriptor maximum packet size

B, using three elements
1. Allocate a urb (the USB Request Block)

2. use three elements to set urb mark and set some



USB host controller after obtaining the data, to go to a memory write (write data to query the contents of the USB device), but the host the controller is not so bright, we need to tell the physical address of a memory host controller.
USB devices do not have the ability to generate an interrupt, it is through the USB host controller constantly query, the query after the data is sent to the interrupt request CUP by the USB host controller.
3. Use the urb; submit urb

own guess: In the instance of the program do not see this function, when the suspect is a registered input_dev will call the structure in the open function
C, complete interrupt function (USB device does not have the ability to interrupt, the interrupt request is ) USB host controller sent

D, disconnect function

test 3th:
reload drive

connect USB mouse

operation of the mouse observations

    第一个字节:数据"01"里的"1"是bit0,表示左键按下;"02"里的"2"是bit1,表示右键按下;"04"里的"4"是bit2,表示中键按下;"03"里的"3"是bit0和bit1,表示左右键同时按下。
    第二个字节:X方向,正值表示往右移,负值表示往左移。
    第三个字节:Y方向,往上移是负数,往下移是正数。
    第四个字节:滑轮,往前滑是正数,往后滑是负数。

USB mouse driver -3th

#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>
/*
 *参考 F:\编程之路\编程之路(Linux)\link_to_term1_and_term2\kernels\linux-2.6.22.6\drivers\hid\usbhid\usbmouse.c
 */
static struct input_dev* uk_dev;
static char* usb_buffer_vir;
static dma_addr_t usb_buffer_pys;
static struct urb* usb_urb;
static int len;

static struct usb_device_id usbmouse_id_table [] = {
    { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
        USB_INTERFACE_PROTOCOL_MOUSE) },
    { } /* Terminating entry */
};

/* 当USB主机控制器查询到信息后,保存到buffer然后产生中断 */
static void usbmouse_irq(struct urb *urb)
{
    int i;
    static int cnt = 0;
    printk("usb_buffer_vir data cnt: %d\n", cnt++);
    for(i=0; i<len; i++)
    {
        printk("%02x", usb_buffer_vir[i]);
    }
    printk("\n");
    /* 重新提交urb */
    usb_submit_urb(usb_urb, GFP_KERNEL);
}
static int usbmouse_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;

    /* 1.分配一个input_dev结构体 */
    uk_dev = input_allocate_device();
    /* 2. 设置 */
    /* 2.1 设置能产生哪类事件:按键类、重复类 */
    set_bit(EV_KEY, uk_dev->evbit);
    set_bit(EV_REP, uk_dev->evbit);
    /* 2.2 设置产生该类的哪些事件:L、S、回车 */
    set_bit(KEY_L, uk_dev->keybit);
    set_bit(KEY_S, uk_dev->keybit);
    set_bit(KEY_ENTER, uk_dev->keybit);
    /* 3. 注册 */
    input_register_device(uk_dev);
    /* 4. 硬件相关操作 */
    /* 数据传输三要素:源、目的、长度 */
    /* 4.1 源*/
    pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
    /* 4.2 长度 */
    len = endpoint->wMaxPacketSize;
    /* 4.3 目的:分配一个缓冲区 */
    usb_buffer_vir = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buffer_pys);
    /* 使用三要素 */
    /* 1. 分配 usb   request block */
    usb_urb = usb_alloc_urb(0, GFP_KERNEL);
    /* 2. 使用三要素来设置urb */
    usb_fill_int_urb(usb_urb, dev, pipe, usb_buffer_vir, len, usbmouse_irq, NULL, endpoint->bInterval);
    usb_urb->transfer_dma = usb_buffer_pys;
    usb_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
    /* 3. 提交urb */
    usb_submit_urb(usb_urb, GFP_KERNEL);
    return 0;
}

static void usbmouse_disconnect(struct usb_interface *intf)
{
    struct usb_device *dev = interface_to_usbdev(intf);

    printk("usbmouse is disconnet!\n");
    usb_kill_urb(usb_urb);
    usb_free_urb(usb_urb);
    usb_buffer_free(dev, len, usb_buffer_vir, usb_buffer_pys);
    input_unregister_device(uk_dev);
    input_free_device(uk_dev);
}

static struct usb_driver usbmouse_as_key_driver = {
    .name        = "usbmouse_as_key",
    .probe        = usbmouse_probe,
    .disconnect    = usbmouse_disconnect,
    .id_table    = usbmouse_id_table,
};

static int usbmouse_as_key_init(void)
{
    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");
4th, achieve left L, right-S, the ENTER key functions with a USB Mouse

Through the above experiment, it is known to realize key operation, only for the first to the array for analysis usb_buffer_vir.

Test 4th:
do not plug, you can just reload the new drive

cat / dev / tty1 and press the right mouse button

hexdump / dev / event0

to sum up:


The bus driver device model, this (usb_bus_type) which has a ".match" function, the left is a USB bus driver to help us to discover new USB device, a USB device and it will be registered from the list on the right of the driver inside the bus inside the ".match" interface function that compares the right to the left (usb_interface) structure (usb_driver) structure "id_table", if consistent, then call (usb_driver) in ".probe" function. (usb_bus_type) provides this mechanism.
Is obtained from previous data or reads the interrupt register, data in the USB driver is now obtained from the read and write functions provided by the USB bus. Once the data is saved data, and an interrupt request issued by the host controller
data transfer three elements: a source (terminal address), object (allocated buffers), length (endpoint descriptor maximum packet size), then a configuration " usb_urb = usb_alloc_urb (0, GFP_KERNEL) ", followed by the three elements of padding to" usb_urb ", and finally you have to submit in order to use urb.

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

Guess you like

Origin www.cnblogs.com/luosir520/p/11457311.html