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
};
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获取的内容对应起来即可。
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模拟请求
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模拟请求:
最终效果
HID人机交互QQ群:564808376
UAC音频QQ群:218581009
UVC相机QQ群:331552032
BOT&UASP大容量存储QQ群:258159197
STC-USB单片机QQ群:315457461
USB技术交流QQ群2:580684376
USB技术交流QQ群:952873936