4. 同步端点配置与带宽计算

任务说明

在USB音频设备中,同步端点(Isochronous Endpoint)负责实时传输音频采样数据。本案例完成:为USB音频设备配置一个等时输入端点(用于音频数据从设备到主机),计算该端点所需的USB总线带宽,并设置端点描述符的关键属性。

环境与依赖

  • 使用 Linux UVC/Gadget API(linux/usb/ch9.h 与 linux/usb/gadget.h)进行端点配置,适用于基于 Gadget 框架的USB设备驱动开发。
  • 需要内核头文件支持,编译环境为Linux内核模块或基于Gadget的用户态函数fs。

核心实现

以下代码完成:定义音频采样参数,计算等时端点所需带宽,并配置端点描述符。带宽计算遵循USB 2.0规范:每帧字节数 = 采样率 × 字节/采样 / 1000帧/秒,并向上取整到端点最大包长度整数倍。

#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/errno.h>

/* 音频参数配置 */
#define AUDIO_SAMPLE_RATE   48000   /* 48kHz */
#define AUDIO_CHANNELS      2        /* 立体声 */
#define AUDIO_BYTES_PER_SAMPLE 2     /* 16bit */

/* 计算等时端点每帧需要的字节数(USB全速/高速帧周期为1ms) */
static int calc_isoc_burst_size(void)
{
    uint32_t bytes_per_ms;
    uint32_t packet_size;

    bytes_per_ms = (AUDIO_SAMPLE_RATE * AUDIO_CHANNELS *
                    AUDIO_BYTES_PER_SAMPLE) / 1000;
    /* 等时端点最大包长度必须是wMaxPacketSize的整数倍,
       此处按高速USB(HS)取512字节对齐 */
    packet_size = (bytes_per_ms + 511) & ~511;
    if (packet_size > 1024)   /* HS等时端点上限 */
        return -EINVAL;
    return packet_size;
}

/* 配置等时输入端点 */
static int config_audio_isoc_ep(struct usb_ep *ep)
{
    struct usb_endpoint_descriptor ep_desc;
    int burst_size;

    burst_size = calc_isoc_burst_size();
    if (burst_size < 0)
        return burst_size;

    /* 填充端点描述符 */
    memset(&ep_desc, 0, sizeof(ep_desc));
    ep_desc.bLength = USB_DT_ENDPOINT_SIZE;
    ep_desc.bDescriptorType = USB_DT_ENDPOINT;
    ep_desc.bEndpointAddress = 0x81;      /* IN端点, 地址1 */
    ep_desc.bmAttributes = USB_ENDPOINT_XFER_ISOC |
                           USB_ENDPOINT_SYNC_ASYNC; /* 异步同步等时端点 */
    ep_desc.wMaxPacketSize = cpu_to_le16(burst_size);
    ep_desc.bInterval = 1;                /* 每1ms帧轮询一次 */

    /* 将描述符绑定到gadget端点 */
    ep->desc = &ep_desc;
    ep->maxpacket = burst_size;

    /* 请求端点使能 */
    return usb_ep_enable(ep);
}

运行与验证

  1. 编译:将上述代码放入内核模块或Gadget驱动源文件,使用内核构建系统编译:make -C /lib/modules/$(uname -r)/build M=$PWD modules
  2. 调用路径:在USB Gadget的bind回调中,获取端点实例后调用config_audio_isoc_ep()。
  3. 验证方法:
    • 检查函数返回值:返回0表示端点配置成功,返回-EINVAL表示带宽超限。
    • 在主机端使用lsusb -v查看设备描述符,确认端点0x81的wMaxPacketSize为计算值(48kHz×2ch×2B/ms = 192B,向上对齐到512B后为512)。
    • 通过dmesg观察内核日志,确认无端点使能错误。

预期输出

当音频参数为48kHz/双声道/16bit时,calc_isoc_burst_size()返回512。端点描述符中wMaxPacketSize字段值为0x0200(512字节),bInterval为1,端点类型为等时(0x05)。

关键说明

  • 带宽计算基于USB全速/高速的1ms帧周期;若使用USB 3.0的微帧(125µs),需将除数改为8000并相应调整对齐逻辑。
  • 实际音频数据在端点上的调度由USB控制器处理,驱动只需正确配置描述符并提交URB。
  • 若采样率或通道数改变,需同步更新AUDIO_SAMPLE_RATE等宏定义后重新编译。