WebUSB通讯协议

一、说明

  • WebUSB是Vllink产品中预留的专用接口,其数据通过端点0传输,可以与其他上位机同时使用,甚至能实现访问目标芯片的功能

  • 本文所有数据结构皆为小端模式,为方便撰写,部分内容以伪代码或者C语言呈现

1.1 适用硬件

  • Vllink Basic2,且固件版本>=V00.40

1.2 查找接口

  • {vendorId, productId} :{0x1209, 0x6666} 或者 {0x0d28, 0x0204}

  • interfaceClass == 0xFF

  • interfaceSubclass == 0x03

  • 满足上述条件后,claimInterface,检查:interfaceName == "WebUSB: CMSIS-DAP"

1.3 接口参数

  • 控制传输、端点0

  • 包最大长度为512字节,且DAP请求及应答长度都限制在512字节

1.4 限制

  • 本接口为专用单一接口,未防止出现多主机干扰,通讯前需要claimInterface,独占该接口

二、通讯

  • bRequestType == (USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_IN)

  • bRequest 为 命令,见协议章节

  • wValue 为 命令参数,见协议章节

  • wIndex 为 "1.2节中获得的接口号"

  • wLength 为 数据长度,不得超过512,可以统一为512字节,USB设备会返回实际长度

  • bRequestType == (USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT)

  • bRequest 为 命令,见协议章节

  • wValue 为 命令参数,见协议章节

  • wIndex == "1.2节中获得的接口号"

  • wLength 为 数据长度,不得超过512

三、协议

3.1 读命令

3.1.1 调试器查询 bRequest == 0x00

  • 获取调试器及其已连接的无线调试器信息,数据结构如下:

    struct {
        uint8_t select_idx;
        uint8_t reserved[27];
    
        struct {
            uint64_t us;
            uint32_t delay_us;
            uint8_t alias[32];
        } local, remote[10];
    } __attribute__((packed)) debugger_info;
    
  • debugger_info.select_idx表示选定的调试器

  • debugger_info.local.us表示应答时间戳,单位为微秒,每次应答时更新

  • debugger_info.remote[i].us表示远端建立连接时的时间戳,单位为微秒,建立连接时更新;若为0,表示未连接

  • debugger_info.*.delay_us表示DAP命令响应延迟,基于简易查询命令测量,仅对已选定的调试器测量

  • debugger_info.*.alias表示调试器的别名

3.1.2 DAP应答 bRequest == 0x10

  • wValue无意义

  • 获取DAP应答,应答数据在DAP请求完成后更新

  • 此命令需配合DAP查询使用

  • 数据格式遵循DAP协议

3.1.3 DAP查询 bRequest == 0x11

  • wValue无意义

  • 获取DAP请求的结果,数据结构如下:

    struct {
        int16_t result;
    } dap_result;
    
  • dap_result.result < 0表示DAP请求错误,无应答数据

  • dap_result.result == 0表示DAP请求未完成

  • dap_result.result > 0表示DAP请求完成,可以继续执行DAP应答

  • 注意:dap_result.result > 0时,dap_result.result的值可以作为DAP应答的最大长度,但实际应答长度可能小于此最大长度,甚至为0

3.2 写命令

3.2.1 调试器选定 bRequest == 0x00

  • wValue 数据结构如下:

    union {
        uint16_t wValue;
        struct {
            uint8_t select_idx;
            uint8_t reserved;
        };
    } debugger_select;
    
  • debugger_select.select_idx == 0表示选定有线调试器

  • debugger_select.select_idx > 0表示选定无线调试器,对应调试器查询命令中的debugger_info.remote[select.select_idx - 1],且要求debugger_info.remote[select.select_idx - 1].us != 0

3.2.2 DAP请求 bRequest == 0x10

  • 通过wValue指定调试器,数据结构如下:

    union {
        uint16_t wValue;
        struct {
            uint8_t select_idx;
            uint8_t reserved;
        };
    } req_select;
    
  • 支持req_select.select_idx == 0,表示DAP请求传递给有线调试器

  • 支持req_select.select_idx == debugger_info.select_idx,表示DAP请求传递给当前选定的调试器

  • 发送DAP请求

  • 数据格式遵循DAP协议

3.3 建议

  • 调试器查询 的轮询间隔推荐250毫秒

  • DAP查询 的轮询间隔推荐2毫秒,仅在 DAP请求 之后进行