返回首页

USB 配置描述符学习笔记

概述

USB 配置描述符定义了设备的完整配置,包括接口、端点和设备功能。主机通过获取配置描述符来了解设备的能力。

描述符层次结构

设备描述符 (Device Descriptor)
    └── 配置描述符 1 (Configuration Descriptor)
            ├── 接口描述符 1-0 (Interface Descriptor - Setting 0)
            │       ├── 端点描述符 1 (Endpoint Descriptor)
            │       └── 端点描述符 2 (Endpoint Descriptor)
            │
            ├── 接口描述符 1-1 (Interface Descriptor - Setting 1)
            │       └── ...
            │
            └── 接口描述符 2 (Interface Descriptor)
                    └── ...
    
    └── 配置描述符 2 (可选)
            └── ...

设备描述符 (Device Descriptor)

结构定义

struct usb_device_descriptor {
    uint8_t  bLength;            /* 18 */
    uint8_t  bDescriptorType;    /* 0x01 (DEVICE) */
    uint16_t bcdUSB;            /* USB 版本: 2.0 = 0x0200 */
    uint8_t  bDeviceClass;       /* 设备类 */
    uint8_t  bDeviceSubClass;    /* 设备子类 */
    uint8_t  bDeviceProtocol;    /* 设备协议 */
    uint8_t  bMaxPacketSize0;    /* EP0 最大包大小: 8/16/32/64 */
    uint16_t idVendor;          /* 厂商 ID */
    uint16_t idProduct;         /* 产品 ID */
    uint16_t bcdDevice;         /* 设备版本 */
    uint8_t  iManufacturer;      /* 厂商字符串索引 */
    uint8_t  iProduct;           /* 产品字符串索引 */
    uint8_t  iSerialNumber;      /* 序列号字符串索引 */
    uint8_t  bNumConfigurations; /* 配置数量 */
} __packed;

典型值

const struct usb_device_descriptor device_desc = {
    .bLength = sizeof(struct usb_device_descriptor),
    .bDescriptorType = USB_DESC_DEVICE,
    .bcdUSB = sys_cpu_to_le16(0x0200),      /* USB 2.0 */
    .bDeviceClass = USB_BCC_MISCELLANEOUS,  /* 使用接口类 */
    .bDeviceSubClass = 0,
    .bDeviceProtocol = 0,
    .bMaxPacketSize0 = 64,
    .idVendor = sys_cpu_to_le16(0x2FE3),    /* Nordic */
    .idProduct = sys_cpu_to_le16(0x0100),
    .bcdDevice = sys_cpu_to_le16(0x0100),   /* Version 1.0 */
    .iManufacturer = 1,                      /* String index 1 */
    .iProduct = 2,                           /* String index 2 */
    .iSerialNumber = 3,                      /* String index 3 */
    .bNumConfigurations = 1,
};

配置描述符 (Configuration Descriptor)

结构定义

struct usb_config_descriptor {
    uint8_t  bLength;             /* 9 */
    uint8_t  bDescriptorType;     /* 0x02 (CONFIGURATION) */
    uint16_t wTotalLength;       /* 总长度(包括接口和端点描述符) */
    uint8_t  bNumInterfaces;      /* 接口数量 */
    uint8_t  bConfigurationValue; /* 配置值 */
    uint8_t  iConfiguration;      /* 配置字符串索引 */
    uint8_t  bmAttributes;        /* 属性 */
    uint8_t  bMaxPower;           /* 最大功耗 (2mA 单位) */
} __packed;

属性标志

#define USB_CONFIGURATION_ATTRIBUTES      BIT(7)   /* 必须为 1 */
#define USB_CONFIGURATION_SELF_POWERED    BIT(6)   /* 自供电 */
#define USB_CONFIGURATION_REMOTE_WAKEUP   BIT(5)   /* 远程唤醒 */

典型配置描述符

const struct usb_config_descriptor config_desc = {
    .bLength = sizeof(struct usb_config_descriptor),
    .bDescriptorType = USB_DESC_CONFIGURATION,
    .wTotalLength = sizeof(struct usb_config_descriptor) +
                    sizeof(struct usb_if_descriptor) +
                    sizeof(struct usb_ep_descriptor) * 2,
    .bNumInterfaces = 1,
    .bConfigurationValue = 1,
    .iConfiguration = 0,          /* 无配置字符串 */
    .bmAttributes = USB_CONFIGURATION_ATTRIBUTES,  /* 总线供电 */
    .bMaxPower = 50,              /* 100mA (50 * 2mA) */
};

接口描述符 (Interface Descriptor)

结构定义

struct usb_if_descriptor {
    uint8_t  bLength;            /* 9 */
    uint8_t  bDescriptorType;    /* 0x04 (INTERFACE) */
    uint8_t  bInterfaceNumber;   /* 接口编号 */
    uint8_t  bAlternateSetting;  /* 备用设置 */
    uint8_t  bNumEndpoints;      /* 端点数量(不包括 EP0) */
    uint8_t  bInterfaceClass;    /* 接口类 */
    uint8_t  bInterfaceSubClass; /* 接口子类 */
    uint8_t  bInterfaceProtocol; /* 接口协议 */
    uint8_t  iInterface;         /* 接口字符串索引 */
} __packed;

接口类定义

#define USB_IFACE_CLASS_AUDIO       0x01
#define USB_IFACE_CLASS_CDC         0x02
#define USB_IFACE_CLASS_HID         0x03
#define USB_IFACE_CLASS_PHYSICAL    0x05
#define USB_IFACE_CLASS_IMAGE       0x06
#define USB_IFACE_CLASS_PRINTER     0x07
#define USB_IFACE_CLASS_MASS_STORAGE 0x08
#define USB_IFACE_CLASS_HUB         0x09
#define USB_IFACE_CLASS_CDC_DATA    0x0A
#define USB_IFACE_CLASS_SMART_CARD  0x0B
#define USB_IFACE_CLASS_CONTENT_SECURITY 0x0D
#define USB_IFACE_CLASS_VIDEO       0x0E
#define USB_IFACE_CLASS_PERSONAL_HEALTHCARE 0x0F
#define USB_IFACE_CLASS_AUDIO_VIDEO 0x10
#define USB_IFACE_CLASS_DIAGNOSTIC_DEVICE 0xDC
#define USB_IFACE_CLASS_WIRELESS_CONTROLLER 0xE0
#define USB_IFACE_CLASS_MISCELLANEOUS 0xEF
#define USB_IFACE_CLASS_APPLICATION_SPECIFIC 0xFE
#define USB_IFACE_CLASS_VENDOR_SPECIFIC 0xFF

HID 接口示例

const struct usb_if_descriptor hid_iface = {
    .bLength = sizeof(struct usb_if_descriptor),
    .bDescriptorType = USB_DESC_INTERFACE,
    .bInterfaceNumber = 0,
    .bAlternateSetting = 0,
    .bNumEndpoints = 1,
    .bInterfaceClass = USB_IFACE_CLASS_HID,
    .bInterfaceSubClass = 0,       /* No subclass */
    .bInterfaceProtocol = 0,       /* No protocol */
    .iInterface = 0,
};

端点描述符 (Endpoint Descriptor)

结构定义

struct usb_ep_descriptor {
    uint8_t  bLength;            /* 7 */
    uint8_t  bDescriptorType;    /* 0x05 (ENDPOINT) */
    uint8_t  bEndpointAddress;   /* 端点地址 */
    uint8_t  bmAttributes;       /* 端点属性 */
    uint16_t wMaxPacketSize;    /* 最大包大小 */
    uint8_t  bInterval;          /* 轮询间隔(中断/等时端点) */
} __packed;

端点地址

#define USB_EP_ADDR_MASK    0x0F
#define USB_EP_DIR_MASK     0x80
#define USB_EP_DIR_IN       0x80    /* 设备到主机 */
#define USB_EP_DIR_OUT      0x00    /* 主机到设备 */

/* 端点地址示例 */
#define EP0_IN_ADDR     0x80    /* 控制端点 IN */
#define EP0_OUT_ADDR    0x00    /* 控制端点 OUT */
#define EP1_IN_ADDR     0x81    /* 端点 1 IN */
#define EP1_OUT_ADDR    0x01    /* 端点 1 OUT */

端点属性

#define USB_EP_TRANSFER_TYPE_MASK   0x03
#define USB_EP_TYPE_CONTROL         0x00
#define USB_EP_TYPE_ISOCHRONOUS     0x01
#define USB_EP_TYPE_BULK            0x02
#define USB_EP_TYPE_INTERRUPT       0x03

/* 同步类型(仅等时端点) */
#define USB_EP_SYNC_TYPE_MASK       0x0C
#define USB_EP_SYNC_NONE            0x00
#define USB_EP_SYNC_ASYNC           0x04
#define USB_EP_SYNC_ADAPTIVE        0x08
#define USB_EP_SYNC_SYNC            0x0C

/* 使用类型(仅等时端点) */
#define USB_EP_USAGE_TYPE_MASK      0x30
#define USB_EP_USAGE_DATA           0x00
#define USB_EP_USAGE_FEEDBACK       0x10
#define USB_EP_USAGE_EXPLICIT_FB    0x20

端点描述符示例

/* HID 中断输入端点 */
const struct usb_ep_descriptor hid_ep_in = {
    .bLength = sizeof(struct usb_ep_descriptor),
    .bDescriptorType = USB_DESC_ENDPOINT,
    .bEndpointAddress = 0x81,           /* EP 1 IN */
    .bmAttributes = USB_EP_TYPE_INTERRUPT,
    .wMaxPacketSize = sys_cpu_to_le16(8),  /* 8 bytes */
    .bInterval = 10,                    /* 10ms polling */
};

/* CDC 批量端点 */
const struct usb_ep_descriptor cdc_ep_in = {
    .bLength = sizeof(struct usb_ep_descriptor),
    .bDescriptorType = USB_DESC_ENDPOINT,
    .bEndpointAddress = 0x82,
    .bmAttributes = USB_EP_TYPE_BULK,
    .wMaxPacketSize = sys_cpu_to_le16(64),
    .bInterval = 0,                     /* N/A for bulk */
};

完整配置描述符示例

HID 设备完整描述符

/* 复合描述符 */
const uint8_t hid_config_desc[] = {
    /* Configuration Descriptor */
    0x09,                               /* bLength */
    USB_DESC_CONFIGURATION,             /* bDescriptorType */
    0x22, 0x00,                         /* wTotalLength (34 bytes) */
    0x01,                               /* bNumInterfaces */
    0x01,                               /* bConfigurationValue */
    0x00,                               /* iConfiguration */
    0x80,                               /* bmAttributes (Bus Powered) */
    0x32,                               /* bMaxPower (100mA) */

    /* Interface Descriptor */
    0x09,                               /* bLength */
    USB_DESC_INTERFACE,                 /* bDescriptorType */
    0x00,                               /* bInterfaceNumber */
    0x00,                               /* bAlternateSetting */
    0x01,                               /* bNumEndpoints */
    USB_IFACE_CLASS_HID,                /* bInterfaceClass */
    0x00,                               /* bInterfaceSubClass */
    0x00,                               /* bInterfaceProtocol */
    0x00,                               /* iInterface */

    /* HID Descriptor */
    0x09,                               /* bLength */
    0x21,                               /* bDescriptorType (HID) */
    0x11, 0x01,                         /* bcdHID (1.11) */
    0x00,                               /* bCountryCode */
    0x01,                               /* bNumDescriptors */
    0x22,                               /* bDescriptorType (Report) */
    sizeof(hid_report_desc), 0x00,      /* wDescriptorLength */

    /* Endpoint Descriptor */
    0x07,                               /* bLength */
    USB_DESC_ENDPOINT,                  /* bDescriptorType */
    0x81,                               /* bEndpointAddress (EP1 IN) */
    USB_EP_TYPE_INTERRUPT,              /* bmAttributes */
    0x08, 0x00,                         /* wMaxPacketSize (8 bytes) */
    0x0A,                               /* bInterval (10ms) */
};

CDC ACM 完整描述符

/* CDC ACM 复合描述符 */
const uint8_t cdc_acm_config_desc[] = {
    /* Configuration Descriptor */
    0x09,
    USB_DESC_CONFIGURATION,
    0x43, 0x00,                         /* Total length: 67 bytes */
    0x02,                               /* 2 interfaces */
    0x01,
    0x00,
    0x80,
    0x32,

    /* Interface 0: CDC Control */
    0x09,
    USB_DESC_INTERFACE,
    0x00,                               /* Interface 0 */
    0x00,
    0x01,                               /* 1 endpoint */
    USB_IFACE_CLASS_CDC,                /* CDC Class */
    USB_CDC_SUBCLASS_ACM,               /* Abstract Control Model */
    USB_CDC_PROTOCOL_NONE,
    0x00,

    /* CDC Header Functional Descriptor */
    0x05,
    USB_DESC_CS_INTERFACE,
    USB_CDC_HEADER_FUNC_DESC,
    0x10, 0x01,                         /* CDC Version 1.10 */

    /* CDC ACM Functional Descriptor */
    0x04,
    USB_DESC_CS_INTERFACE,
    USB_CDC_ACM_FUNC_DESC,
    0x02,                               /* Set_Line_Coding, Set_Control_Line_State */

    /* CDC Union Functional Descriptor */
    0x05,
    USB_DESC_CS_INTERFACE,
    USB_CDC_UNION_FUNC_DESC,
    0x00,                               /* Master interface */
    0x01,                               /* Slave interface */

    /* CDC Call Management Functional Descriptor */
    0x05,
    USB_DESC_CS_INTERFACE,
    USB_CDC_CALL_MGMT_FUNC_DESC,
    0x00,
    0x01,                               /* Data interface */

    /* Endpoint: Interrupt IN */
    0x07,
    USB_DESC_ENDPOINT,
    0x82,                               /* EP 2 IN */
    USB_EP_TYPE_INTERRUPT,
    0x08, 0x00,
    0x10,                               /* 16ms interval */

    /* Interface 1: CDC Data */
    0x09,
    USB_DESC_INTERFACE,
    0x01,                               /* Interface 1 */
    0x00,
    0x02,                               /* 2 endpoints */
    USB_IFACE_CLASS_CDC_DATA,
    0x00,
    0x00,
    0x00,

    /* Endpoint: Bulk OUT */
    0x07,
    USB_DESC_ENDPOINT,
    0x01,                               /* EP 1 OUT */
    USB_EP_TYPE_BULK,
    0x40, 0x00,                         /* 64 bytes */
    0x00,

    /* Endpoint: Bulk IN */
    0x07,
    USB_DESC_ENDPOINT,
    0x81,                               /* EP 1 IN */
    USB_EP_TYPE_BULK,
    0x40, 0x00,
    0x00,
};

字符串描述符

字符串描述符 0(语言 ID)

/* 支持的语言 */
const uint8_t lang_desc[] = {
    0x04,                           /* bLength */
    USB_DESC_STRING,                /* bDescriptorType */
    0x09, 0x04,                     /* English (US) */
};

字符串描述符

/* USB 字符串使用 UTF-16LE 编码 */

/* "MyCompany" */
const uint8_t manufacturer_str[] = {
    0x14,                           /* bLength (20 bytes) */
    USB_DESC_STRING,
    'M', 0, 'y', 0, 'C', 0, 'o', 0,
    'm', 0, 'p', 0, 'a', 0, 'n', 0,
    'y', 0,
};

/* "USB Device" */
const uint8_t product_str[] = {
    0x16,
    USB_DESC_STRING,
    'U', 0, 'S', 0, 'B', 0, ' ', 0,
    'D', 0, 'e', 0, 'v', 0, 'i', 0,
    'c', 0, 'e', 0,
};

/* "123456" */
const uint8_t serial_str[] = {
    0x0E,
    USB_DESC_STRING,
    '1', 0, '2', 0, '3', 0, '4', 0,
    '5', 0, '6', 0,
};

描述符大小计算

/* 计算配置描述符总长度 */
#define CONFIG_DESC_SIZE \
    (sizeof(struct usb_config_descriptor) + \
     sizeof(struct usb_if_descriptor) + \
     sizeof(struct usb_hid_descriptor) + \
     sizeof(struct usb_ep_descriptor))

/* 验证 */
BUILD_ASSERT(CONFIG_DESC_SIZE == 34, "Config descriptor size mismatch");

参考链接


*学习笔记创建时间: 2026-03-19*