Linux之 USB驱动框架-USB总线核心和主控驱动(4)

一、USB设备描述符

一个USB设备描述符中可以有多个配置描述符,即USB设备可以有多种配置;一个配置描述符中可以有多个接口描述符,即USB设备可以支持多种功能(接口);一个接口描述符中可以有多个端点描述符。
一设备至少要包含设备描述符、配置描述符和接口描述符,如果USB设备没有端点描述符,则它仅仅用默认管道与主机进行数据传输。
接口,表示逻辑上的设备,比如USB声卡可以分为接口1-录音设备,接口2-播放设备。
访问设备时,即访问某个接口,接口表示逻辑设备。
传输数据时,即读写某个端口,端口是数据通道。

1.1 设备描述符

/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor {
    __u8  bLength; //该结构体大小
    __u8  bDescriptorType; //描述符类型 (此处应为0x01,即设备描述符)
 
    __le16 bcdUSB; //usb版本号 200 -> USB2.0
    __u8  bDeviceClass; //设备类 
    __u8  bDeviceSubClass; //设备类子类
    __u8  bDeviceProtocol; //设备协议,以上三点都是USB官方定义
    __u8  bMaxPacketSize0; //端点0最大包大小 (只能为8,16,32,64)
    __le16 idVendor; //厂家id
    __le16 idProduct; //产品id
    __le16 bcdDevice; //设备出厂编号
    __u8  iManufacturer; //描述厂商信息的字符串描述符的索引值
    __u8  iProduct; //描述产品信息的字串描述符的索引值
    __u8  iSerialNumber; //描述设备序列号信息的字串描述符的索引值 
    __u8  bNumConfigurations; //可能的配置描述符的数目
} __attribute__ ((packed));
 

1.2 配置描述符

 struct usb_config_descriptor {
    __u8  bLength; //该结构体大小
    __u8  bDescriptorType;//描述符类型(本结构体中固定为0x02)  
 
    __le16 wTotalLength; //该配置下,信息的总长度(包括配置,接口,端点和设备类及厂商定义的描述符)
    __u8  bNumInterfaces; //接口的个数
    __u8  bConfigurationValue; //Set_Configuration命令所需要的参数值,用来选定此配置
    __u8  iConfiguration; //描述该配置的字符串描述的索引值 
    __u8  bmAttributes;//供电模式的选择  
    __u8  bMaxPower;//设备从总线提取的最大电流
} __attribute__ ((packed));

1.3 接口描述符

 struct usb_interface_descriptor {
    __u8  bLength;        //该结构体大小
    __u8  bDescriptorType;//接口描述符的类型编号(0x04)
 
    __u8  bInterfaceNumber;  //该接口的编号  
    __u8  bAlternateSetting; //备用的接口描述符编号  
    __u8  bNumEndpoints; //该接口使用的端点数,不包括端点0  
    __u8  bInterfaceClass; //接口类
    __u8  bInterfaceSubClass; //子类
    __u8  bInterfaceProtocol; //协议
    __u8  iInterface;//描述此接口的字串描述表的索引值  
} __attribute__ ((packed));

 配置描述符中包含了一个或多个接口描述符,这里的“接口”并不是指物理存在的接口,在这里把它称之为“功能”更易理解些,例如一个设备既有录音的功能又有扬声器的功能,则这个设备至少就有两个“接口”。

1.4 端点描述符

/* USB_DT_ENDPOINT: Endpoint descriptor */
struct usb_endpoint_descriptor {
    __u8  bLength;        //端点描述符字节数大小(7个字节)
    __u8  bDescriptorType;//端点描述符类型编号(0x05) 
 
    __u8  bEndpointAddress; //此描述表所描述的端点的地址、方向 : 
                            // bit3~bit0:端点号,bit6~bit4:保留,
                            // bit7:方向,如果是控制端点则忽略,0-输出端点(主机到设备)1-输入端点(设备到主机)
    __u8  bmAttributes; // 端点特性,bit1~bit0 表示传输类型,其他位保留
                        // 00-控制传输  01-实时传输   10-批量传输 11-中断传输
    __le16 wMaxPacketSize;  //端点收、发的最大包大小
    __u8  bInterval; // 中断传输模式中主机查询端点的时间间隔。
                     // 对于实时传输的端点此域必需为1,表示周期为1ms。对于中断传输的端点此域值的范围为1ms到255ms
 
    /* NOTE:  these two are _only_ in audio endpoints. */
    /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
    __u8  bRefresh;
    __u8  bSynchAddress;
} __attribute__ ((packed));
 

 端点是设备与主机之间进行数据传输的逻辑接口,除配置使用的端点0(控制端点,一般一个设备只有一个控制端点)为双向端口外,其它均为单向。端点描述符描述了数据的传输类型、传输方向、数据包大小和端点号(也可称为端点地址)等。

除了描述符中描述的端点外,每个设备必须要有一个默认的控制型端点,地址为0,它的数据传输为双向,而且没有专门的描述符,只是在设备描述符中定义了它的最大包长度。主机通过此端点向设备发送命令,获得设备的各种描述符的信息,并通过它来配置设备。

1.5 字符描述符

struct usb_string_descriptor {
    __u8  bLength;  // 此描述表的字节数(bString域的数值N+2)
    __u8  bDescriptorType; // 字串描述表类型(此处应为0x03)

    __le16 wData[1];        /* UTF-16LE encoded */  
} __attribute__ ((packed));
 

1.6 人机接口描述符

USB 设备中有一大类就是 HID 设备,即 Human Interface Devices,人机接口设备。这类设备包括鼠标、键盘等,主要用于人与计算机进行交互。 它是 USB 协议最早支持的一种设备类。 HID 设备可以作为低速、全速、高速设备用。由于 HID 设备要求用户输入能得到及时响应,故其传输方式通常采用中断方式。
在 USB 协议中, HID 设备的定义放置在接口描述符中, USB 的设备描述符和配置描述符中不包含 HID 设备的信息。因此,对于某些特定的 HID 设备,可以定义多个接口,只有其中一个接口为 HID 设备类即可。

1.7 USB描述符的类型值

二、USB总线驱动程序

2.1 usb core

初始化内核USB总线及提供USB相关API,为设备驱动和HCD的交互提供桥梁。

usb_init

static int __init usb_init(void)
{
        int retval;
        if (usb_disabled()) {
                pr_info("%s: USB support disabled\n", usbcore_name);
                return 0;
        }
        usb_init_pool_max();

        usb_debugfs_init();

        usb_acpi_register();
        retval = bus_register(&usb_bus_type);         -----------------(1)
        if (retval)
                goto bus_register_failed;
        retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb);
        if (retval)
                goto bus_notifier_failed;
        retval = usb_major_init();
        if (retval)
                goto major_init_failed;
        retval = usb_register(&usbfs_driver);   ---------------------------(2)
        if (retval)
                goto driver_register_failed;
        retval = usb_devio_init();
        if (retval)
                goto usb_devio_init_failed;
        retval = usb_hub_init();                 -----------------------------------(3)        
        if (retval)
                goto hub_init_failed;
        retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);-------(4)
        if (!retval)
                goto out;

        usb_hub_cleanup();
hub_init_failed:
        usb_devio_cleanup();
usb_devio_init_failed:
        usb_deregister(&usbfs_driver);
driver_register_failed:
        usb_major_cleanup();
major_init_failed:
        bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);
bus_notifier_failed:
        bus_unregister(&usb_bus_type);
bus_register_failed:
        usb_acpi_unregister();
        usb_debugfs_cleanup();
out:
        return retval;
}
 

 (1)USB是基于总线-驱动-设备模型的框架,其初始化阶段一个重点任务就是完成USB总线的创建。usb_bus_type提供了驱动和设备匹配的匹配函数,后面注册设备和驱动时会调用到。

usb_bus_type

struct bus_type usb_bus_type = {
        .name =         "usb",
        .match =        usb_device_match,    //调用这个匹配函数
        .uevent =       usb_uevent,
        .need_parent_lock =

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值