Linux USB子系统(2) 设备、配置、接口、端点

本文详细介绍了Linux USB设备结构中的配置、接口和端点描述符,从设备枚举到接口驱动匹配的过程。内容涵盖描述符数据结构、读取设备描述符、初始化设备、解析配置、接口及端点。通过对内核源码的分析,揭示了设备结构体中成员变化及其意义。
摘要由CSDN通过智能技术生成

Linux USB设备结构中的配置、接口、设置、端点


内核版本:linux-3.4.2

## 1.描述符数据结构 ##

描述符存储在USB设备结构体中,USB设备结构中与描述符相关的成员如下:

struct usb_device {
    struct usb_host_endpoint ep0;

    struct usb_device_descriptor descriptor;        /* SPEC中定义的设备描述符 */
    struct usb_host_bos *bos;
    struct usb_host_config *config;                 /* 配置描述符 */

    struct usb_host_config *actconfig;
    struct usb_host_endpoint *ep_in[16];
    struct usb_host_endpoint *ep_out[16];

    char **rawdescriptors;
};

从上面的成员的类型可以看出,struct usb_device_descriptor对应的是USB规范中的设备描述符,而struct usb_host_config并没有对应USB规范中的配置描述符,一般名字为usb_xxx_descriptor的结构体对应的是USB规范中的描述符,而名字为usb_host_xxx的结构体则代表主机侧的一个描述符,而具体的USB规范中的描述符则是一个usb_host_xxx结构体中的成员。

可以预见的是:
struct usb_config_descriptor 对应SPEC中的配置描述符
struct usb_interface_descriptor 对应SPEC中的接口描述符
struct usb_endpoint_descriptor 对应SPEC中的端点描述符

struct usb_host_config 对应主机侧的一个配置
struct usb_host_interface 对应主机侧的一个接口
struct usb_host_endpoint 对应主机侧的一个端点

那么这些描述符是怎么存储的,config和actconfig有什么区别,这得看从设备枚举的时候读取设备描述符开始到USB接口设备匹配到接口驱动为止的代码来看struct usb_device结构体中成员的变化。

## 2. 读取设备描述符,设置设备 ##

读取设备描述符是在hub_port_connect_change函数中,大概过程如下:

static void hub_port_connect_change(struct usb_hub *hub, int port1, u16 portstatus, u16 portchange)
{
    for (i = 0; i < SET_CONFIG_TRIES; i++) {
        udev = usb_alloc_dev(hdev, hdev->bus, port1);       /* 分配一个usb_device,此时设备的状态是 USB_STATE_ATTACHED */
        ...
        choose_devnum(udev);                     /* 选择设备编号 */
        hub_port_init(hub, udev, port1, i);      /* hub端口的初始化 */
        ...
        usb_new_device(udev);                    /* 向系统添加新的USB设备 */
    }
}

### 2.1 分配初始化USB设备对象 ###
首先看设备是怎么分配的:

parent:这个参数指向了设备插入的hub的设备结构体
bus:这个参数指向了物理上的一个usb总线
port1:这个参数指设备插入的hub的端口号
struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
{
    dev = kzalloc(sizeof(*dev), GFP_KERNEL);      /* 这里分配了一个usb_device结构体,代表了一个USB设备 */
    ...
    dev->state = USB_STATE_ATTACHED;     /* 设备的状态为ATTACHED */
    ...
    dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;       /* 设置端点0的描述符的长度 */
    dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;    /* 设置端点0的描述符的类型 */
}

此时的usb_device里的成员是这样的情况:

描述符1
图1

### 2.2 读取设备描述符 ###
分配了usb_device之后,就会进入hub_port_init函数读取设备描述符:

static int hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, int retry_counter)
{
    int devnum = udev->devnum;
    for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) { //如果第一次就成功了,那就退出循环了
        if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3)) {
#define GET_DESCRIPTOR_BUFSIZE  64
            buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);   /* 首先分配64字节的空间 */

            buf->bMaxPacketSize0 = 0;
            usb_control_msg(udev, usb_rcvaddr0pipe(),
                    USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
                    USB_DT_DEVICE << 8, 0,
                    buf, GET_DESCRIPTOR_BUFSIZE,
                    initial_descriptor_timeout);      /* 发送一个控制传输请求,请求64字节的数据 */
            udev->descriptor.bMaxPacketSize0 = buf->bMaxPacketSize0;    /* 记录端点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值