WinUSB
+ -

CH569设备USB2.0支持WCID-WINUSB-基于MSOS-V1.0

2025-09-03 0 0

CH569是USB3.0设备,WCH给的示例CH372Device本身USB3.0是支持WINUSB的,但是USB2.0不支持(不是不支持,是代码没有写)。故这里对USB2.0代码完善支持,让其通过微软系统描述符1.0支持WINUSB.

关于微软系统描述符1.0详见https://www.usbzh.com/article/detail-1068.html

由于MSOS1.0是通过0xee的字符串触发的,且需要设备描述符bcdUSB的值设为0x200,在获取信息时需要:

  • 获取字符串描述符(0xee),解析出vendorId
  • 发送vendor控制请求,Index=04 00 获取兼容ID的内容
  • 发送vendor控制请求,Index=05 00 获取Winusb驱动设备的DeviceInterfaceGUIDs(实际好像不发生)

0xee字符串的支持

首先USB2.0设备的描述符将bcdUSB改为2.0

const UINT8 hs_device_descriptor[] =
{
    0x12,   // bLength
    0x01,   // DEVICE descriptor type
    0x00,   // 2.00
    0x02,
    0x00,   // device class
    0x00,   // device sub-class
    0x00,   // vendor specific protocol
    0x40,   // max packet size 512B
    0xd1,   // vendor id-0x1A86(qinheng)
    0x19,
    0xff,   // product id 0x5537
    0x9d,
    0x00,   //bcdDevice
    0x22,
    0x01,   // manufacturer index string
    0x02,   // product index string
    0x00,   // serial number index string
    0x01    // number of configurations
};

其次,在获取字符串描述符处支持编号为0xee的字符串描述符

case USB_DESCR_TYP_STRING:
     switch( UsbSetupBuf->wValueL )
     {
         case USB_DESCR_LANGID_STRING:
             pDescr = (UINT8 *)hs_string_descriptor0;
             SetupLen = ( SetupReqLen > sizeof(hs_string_descriptor0) )? sizeof(hs_string_descriptor0):SetupReqLen;
             break;
         case USB_DESCR_VENDOR_STRING:
             pDescr = (UINT8 *)hs_string_descriptor1;
             SetupLen = ( SetupReqLen > sizeof(hs_string_descriptor1) )? sizeof(hs_string_descriptor1):SetupReqLen;
             break;
            ...
         case 0xee:
             pDescr =(UINT8 *) hs_string_descriptor_vendor;
             SetupLen = ( SetupReqLen > sizeof(hs_string_descriptor_vendor) )? sizeof(hs_string_descriptor_vendor):SetupReqLen;;
             break;
         default:
             SetupLen = USB_DESCR_UNSUPPORTED;
             break;
     }

索引为0xee的字符串描述符内容为:

const UINT8 hs_string_descriptor_vendor[]=
{
        0x12, // length of this descriptor
        0x03,
        'M',        0x00,
        'S',        0x00,
        'F',        0x00,
        'T',        0x00,
        '1',        0x00,
        '0',        0x00,
        '0',        0x00,
        0x01,  //vendor id
        0x00
};

注意,这里的vendorid为1,当然也可以改为其它值,只需要与后面的兼容ID获取的内容对应起来即可。
16501886832

verndor请求兼容ID-0x04

对USB2.0的Vendor请求

UINT16 U20_NonStandard_Request_Deal()
{   
    UINT8 endp_dir;

    SetupLen = UsbSetupBuf->wLength;
    endp_dir = UsbSetupBuf->bRequestType & 0x80;
    UINT16 len = 0;

    SetupLen = USB_DESCR_UNSUPPORTED;
    switch(SetupReq)
    {
        case 0x01://vendor id
            switch(UsbSetupBuf->wIndexL)
            {
                case 0x04: //兼容ID
                    pDescr = (UINT8 *)CompactId20;
                    SetupLen = ( SetupReqLen > sizeof(CompactId20) )? sizeof(CompactId20):SetupReqLen;
                   break;
                case 0x05: //接口GUID
                    pDescr = (UINT8 *)COMP_IF3_WCIDProperties;
                    SetupLen = sizeof(COMP_IF3_WCIDProperties);//( SetupReqLen > sizeof(COMP_IF3_WCIDProperties) )? sizeof(COMP_IF3_WCIDProperties):SetupReqLen;
               default:
                   break;
               }
               break;
        default:
            break;
    }

  if( (SetupLen != USB_DESCR_UNSUPPORTED) && (SetupLen != 0))
  {
      len = (SetupLen >= U20_UEP0_MAXSIZE ) ? U20_UEP0_MAXSIZE : SetupLen;
      if(endp_dir)
      {
          memcpy(endp0RTbuff, pDescr, len );
          pDescr += len;
      }
      SetupLen -= len;
  }

   printf("SetupLen=%d\r\n",SetupLen);

   return len;
}

内容为:

const UINT8 CompactId20[] =
    {
        0x28, 0x00, 0x00, 0x00, //descriptor length (40 bytes)
        0x00, 0x01,  //V1.0
        0x04, 0x00,  //Compatibility ID Descriptor index (0x0004)
        0x01,   //Number of sections (1)
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//Reserved
        0x00,                                   //Interface Number (Interface #0)
        0x01,                                   //Reserved
        0x57, 0x49, 0x4e, 0x55, 0x53, 0x42, 0x00, 0x00,//WINUSB\0\0”
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //ASCII String Sub-Compatible ID(unused)
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00             //Reserved
    };

这样将可以了。

可以通BUSHOUND模拟请求
164919170190

Vendor支持接口GUID-0x05

功能虽支持,但实际不在注册表下生成GUIDS

由于接口GUID结构体的长度大于64字节,故需要多个事务才能返回数据,故在IN中断中修改代码如下:

UINT16 U20_Endp0_IN_Callback(void)
{
    UINT16 len = 0;
    //setup是全局变量,记录着setup事务的请求类型
    printf("begin U20_Endp0_IN_Callback=%d\r\n",SetupLen);
    switch(SetupReq)
    {
        //SetupLen是全局变量,在SETU事务中设置描述符的长度,然后通过IN返回数据,可能有多次的IN
      case USB_GET_DESCRIPTOR:
      case 0x01:  //vendor id
          len = SetupLen >= U20_UEP0_MAXSIZE ? U20_UEP0_MAXSIZE : SetupLen;
          memcpy(endp0RTbuff, pDescr, len);
          SetupLen -= len;
          pDescr += len;
          break;
      case USB_SET_ADDRESS:
          USB20_Device_Setaddress(g_devInfo.dev_addr);
          break;
      default:
          break;
    }
    printf("end U20_Endp0_IN_Callback=%d\r\n",SetupLen);

    //返回IN的事务长度
    return len;
}

其内容如下:

const uint8_t COMP_IF3_WCIDProperties [142]  = 
{
    ///////////////////////////////////////
    /// WCID property descriptor
    ///////////////////////////////////////
    0x8e, 0x00, 0x00, 0x00,                           /* dwLength */
    0x00, 0x01,                                       /* bcdVersion */
    0x05, 0x00,                                       /* wIndex */
    0x01, 0x00,                                       /* wCount */
    ///////////////////////////////////////
    /// registry propter descriptor
    ///////////////////////////////////////
    0x84, 0x00, 0x00, 0x00,                           /* dwSize */
    0x01, 0x00, 0x00, 0x00,                           /* dwPropertyDataType */
    0x28, 0x00,                                       /* wPropertyNameLength */
    /* DeviceInterfaceGUID */
    'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00,       /* wcName_20 */
    'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00,       /* wcName_20 */
    't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00,       /* wcName_20 */
    'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00,       /* wcName_20 */
    'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00,      /* wcName_20 */
    0x4e, 0x00, 0x00, 0x00,                           /* dwPropertyDataLength */
    /* {1D4B2365-4749-48EA-B38A-7C6FDDDD7E26} */
    '{', 0x00, '1', 0x00, 'D', 0x00, '4', 0x00,       /* wcData_39 */
    'B', 0x00, '2', 0x00, '3', 0x00, '6', 0x00,       /* wcData_39 */
    '5', 0x00, '-', 0x00, '4', 0x00, '7', 0x00,       /* wcData_39 */
    '4', 0x00, '9', 0x00, '-', 0x00, '4', 0x00,       /* wcData_39 */
    '8', 0x00, 'E', 0x00, 'A', 0x00, '-', 0x00,       /* wcData_39 */
    'B', 0x00, '3', 0x00, '8', 0x00, 'A', 0x00,       /* wcData_39 */
    '-', 0x00, '7', 0x00, 'C', 0x00, '6', 0x00,       /* wcData_39 */
    'F', 0x00, 'D', 0x00, 'D', 0x00, 'D', 0x00,       /* wcData_39 */
    'D', 0x00, '7', 0x00, 'E', 0x00, '2', 0x00,       /* wcData_39 */
    '6', 0x00, '}', 0x00, 0x00, 0x00,                 /* wcData_39 */
};

bushound模拟请求:
181139998804

最终效果

165131588315

165119904172

HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936   

0 篇笔记 写笔记

USB WCID设备中特殊字符描述符
WCID全称”Windows Compatible ID,中文名为“Windows兼容ID”。 WCID设备是一种向Windows系统提供额外信息的USB设备,以便于自动安装驱动程序,并在某些情况下允许立即访问。USB设备驱动的匹配安装一般是以VID/PID进行驱动匹配的,但WCID设备却是根据C......
使用WinUSB读写USB设备
Windows为WinUSB设备提供了API,主要通过以下几个步骤访问设备。通过扩展描述符中的GUID查看接口的路径用接口的路径作为参数,调用CreateFile打开接口使用WinUsb_Initialize得到WinUSB句柄通过WinUsb_WritePipe和WinUsb_ReadPipe对......
WinUSB 简介
WinUSB是Windows从Vista操作系统版本以来,新增加的一个USB设备功能驱动程序。使用该驱动,可以将设备变成一个自定义通讯的设备,当然该驱动也可应用于自定义设备驱动程序。WinUSB的组成WinUSB包括两大部分,分别为内核部分和应用层部分:内核部分,主要是WinUSB.sys,该......
WinUSB的安装方法
使用工具zadig进行安装winusb以管理员方式运行zadig-2.4.exe,然后在菜单的选择中选择列出所有设备。这会软件会枚举系统中所有的USB设备,并显示在下列组合对话框中。我们选中我们需要安装winusb的设备,然后点击ReInstallDriver按钮进行安装。如本人选中一个USB扬声器......
USB Packet Viewer 连接方式及驱动安装
典型的设备连接方式监听 PC 上运行 USB Packet Viewer 协议解析软件,通过 Type-C 数据线与抓包设备相连,同时也向抓包设备提供电源。待测试的 USB 主设备通过 Type-C 数据线与抓包设备的 Host 接口相连待测试的 USB 从设备通过 USB-A 数据线与抓包设备......
WinUsb优缺点
WinUSB是Microsoft提供的通用USB 驱动程序,适用于从Windows Vista开始但也可用于 Windows XP 的操作系统。它针对的是一次只能由一个应用程序访问的简单设备。它使应用程序能够通过一个简单的软件库直接访问设备。该库提供对设备管道的访问。WinUSB 公开了一个客户端 ......
VS2019使用WinUSB模板创建WinUSB应用程序
当USB设备使用WinUSB驱动之后,可以使用WinUSB提供的应用层库winusb.lig来进行应用程序的开发,这样在应用层可以通过Winusb驱动程序与USB设备进行通讯。开发WinUSB应用程序时需要使用VS开发,不过在建一个示例WinUSB应用程序时,首先得安装WDK,安装完成之后会在创建......
使用WinUSB检测USB设备是什么设备速率?高速、低速、全速
WinUSB提供了检测USB设备的速率代码,详见:// Device Information types#define DEVICE_SPEED 0x01// Device Speeds#define LowSpeed 0x01#def......
WinUSB获取USB设备端点信息
使用WinUsb_QueryInterfaceSettings函数获取指定接口下的所有信息,然后解析端点信息并打印。struct PIPE_ID{ UCHAR PipeInId; UCHAR PipeOutId;};BOOL QueryDeviceEndpoints (......
WinUSB使用控制端点0发送USB标准请求
向默认端点发出控制请求来与设备通信。除了与接口关联的端点外,所有 USB 设备还有一个默认端点。 默认端点的主要用途是为主机提供可用来配置设备的信息。 不过,设备还可以将默认端点用于设备特定的用途。控制命令包含一个 8 字节设置数据包,其中包括指定特定请求的请求代码和可选的数据缓冲区。 请求代码......
WinUSB使用WinUsb_WritePipe给USB设备写数据
WinUSB 提供了以下用于发送写入请求请求的函数:WinUsb_WritePipe写数据WinUsb_WritePipe分配一个缓冲区并使用要写入到设备的数据进行填充。 如果应用程序未将缓冲区大小设置为管道的策略RAW_IO,则缓冲区大小没有限制。 如有必要,WinUSB 会将缓冲区划分为......
WinUSB释放设备句柄
完成对设备的全部所需调用后,需要释放设备的文件句柄和 WinUSB 接口句柄。 为此,请调用以下函数:CloseHandle 释放由 CreateFile 创建的句柄。WinUsb_Free释放设备的 WinUSB 接口句柄,该句柄由 WinUsb_Initialize。VOIDClose......
WinUSB使用WinUsb_ReadPipe从USB设备读数据
WinUSB 提供了以下用于接收读取请求请求的函数:WinUsb_ReadPipe调用 WinUsb_ReadPipe 从设备的批量终结点读取数据。 传递设备的 WinUSB 接口句柄、用于批量传入终结点的管道标识符,以及适当大小的空缓冲区。 当函数返回时,缓冲区会包含已从设备读取的数据。 已......
WinUSB与设备通讯的代码流程
int _tmain(int argc, _TCHAR* argv[]){ GUID guidDeviceInterface = OSR_DEVICE_INTERFACE; //in the INF file BOOL bResult = TRUE; PIPE_ID ......
WinUSB枚举和打开设备
打开设备之前,得先枚举到设备,获取到设备的链接名,然后才能通过CreateFile打开设备,与之通讯。设备接口GUID枚举设备是通过winsub驱动的inf文件中的DeviceInterfaceGUIDs来实现的。在WinUSB驱动设备时,会使用该GUID来注册设备接口,所以我们也需要此接口来枚举......
关注公众号
  • HID人机交互
  • Linux&USB
  • UAC音频
  • CDC
  • TYPE-C
  • USB规范
  • USB大容量存储
  • USB百科
  • USB周边
  • UVC摄像头
  • Windows系统USB
  • 音视频博客
  • 取消
    感谢您的支持,我会继续努力的!
    扫码支持
    扫码打赏,你说多少就多少

    打开支付宝扫一扫,即可进行扫码打赏哦

    您的支持,是我们前进的动力!