USB设备控制请求
2026-08-18
本文链接为:http://www.usbzh.com/article/detail-1796.html ,欢迎转载,转载请附上本文链接。
USB设备标准控制请求有点多,一般有
GET_DESCRIPTOR
GET_DESCRIPTOR一般用于获取设备相关的描述符,主要的请求有:
SET_ADDRESS
SET_ADDRESS包括2个事务,分别为SETUP事务和0长度数据包确认事务(ZLP),按USB规格书定义,其实应在ZLP之后再写入SETUP发送过来的地址,但实际有些设备是在SETUP事务中就完成了写入,这在主机是兼容支持的。
SET_CONFIGURATION
- 当配置index=0时表示反向选择配置,然后设备进入ADDRESSED阶段。
- 当配置index!=0时表示选择配置,并打开其它的端点(非同步),开始进行通讯
static void USBD_SetConfig(USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req)
{
static uint8_t cfgidx;
cfgidx = (uint8_t)(req->wValue);
if (cfgidx > USBD_CFG_MAX_NUM )
{
USBD_CtlError(pdev , req);
}
else
{
switch (pdev->dev.device_status)
{
case USB_OTG_ADDRESSED:
if (cfgidx)
{
pdev->dev.device_config = cfgidx;
pdev->dev.device_status = USB_OTG_CONFIGURED;
USBD_SetCfg(pdev , cfgidx);
USBD_CtlSendStatus(pdev);
}
else
{
USBD_CtlSendStatus(pdev);
}
break;
case USB_OTG_CONFIGURED:
if (cfgidx == 0)
{
pdev->dev.device_status = USB_OTG_ADDRESSED;
pdev->dev.device_config = cfgidx;
USBD_ClrCfg(pdev , cfgidx);
USBD_CtlSendStatus(pdev);
}
else if (cfgidx != pdev->dev.device_config)
{
/* Clear old configuration */
USBD_ClrCfg(pdev , pdev->dev.device_config);
/* set new configuration */
pdev->dev.device_config = cfgidx;
USBD_SetCfg(pdev , cfgidx);
USBD_CtlSendStatus(pdev);
}
else
{
USBD_CtlSendStatus(pdev);
}
break;
default:
USBD_CtlError(pdev , req);
break;
}
}
}
GET_STATUS
设备状态2字节,可以按位或
#define USB_CONFIG_REMOTE_WAKEUP 2
#define USB_CONFIG_SELF_POWERED 1
参考代码:
static void USBD_GetStatus(USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req)
{
switch (pdev->dev.device_status)
{
case USB_OTG_ADDRESSED:
case USB_OTG_CONFIGURED:
#ifdef USBD_SELF_POWERED
USBD_cfg_status = USB_CONFIG_SELF_POWERED;
#else
USBD_cfg_status = 0x00;
#endif
if (pdev->dev.DevRemoteWakeup)//参见设备的SET_FEATUER和CLEAR_FEATUER
{
USBD_cfg_status |= USB_CONFIG_REMOTE_WAKEUP;
}
USBD_CtlSendData (pdev,(uint8_t *)&USBD_cfg_status,2);
break;
default :
USBD_CtlError(pdev , req);
break;
}
}
SET_FEATURE
设备的SET_FEATUER可以有2种
- USB_FEATURE_REMOTE_WAKEUP
- USB_FEATURE_TEST_MODE
static void USBD_SetFeature(USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req)
{
USB_OTG_DCTL_TypeDef dctl;
uint8_t test_mode = 0;
if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
{
pdev->dev.DevRemoteWakeup = 1;
pdev->dev.class_cb->Setup (pdev, req);
USBD_CtlSendStatus(pdev);
}
else if ((req->wValue == USB_FEATURE_TEST_MODE) && ((req->wIndex & 0xFF) == 0))
{
dctl.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DCTL);
test_mode = req->wIndex >> 8;
switch (test_mode)
{
case 1: // TEST_J
dctl.b.tstctl = 1;
break;
case 2: // TEST_K
dctl.b.tstctl = 2;
break;
case 3: // TEST_SE0_NAK
dctl.b.tstctl = 3;
break;
case 4: // TEST_PACKET
dctl.b.tstctl = 4;
break;
case 5: // TEST_FORCE_ENABLE
dctl.b.tstctl = 5;
break;
}
SET_TEST_MODE = dctl;
pdev->dev.test_mode = 1;
USBD_CtlSendStatus(pdev);
}
}
CLEAR_FEATUER
清除设备的远程唤醒,这一般发生在主机唤配设备之后https://www.usbzh.com/article/detail-1083.html
static void USBD_ClrFeature(USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req)
{
switch (pdev->dev.device_status)
{
case USB_OTG_ADDRESSED:
case USB_OTG_CONFIGURED:
if (req->wValue == USB_FEATURE_REMOTE_WAKEUP)
{
pdev->dev.DevRemoteWakeup = 0;
pdev->dev.class_cb->Setup (pdev, req);
USBD_CtlSendStatus(pdev);
}
break;
default :
USBD_CtlError(pdev , req);
break;
}
}
本文链接为:http://www.usbzh.com/article/detail-1796.html ,欢迎转载,转载请附上本文链接。
HID人机交互QQ群:564808376
UAC音频QQ群:218581009
UVC相机QQ群:331552032
BOT&UASP大容量存储QQ群:258159197
STC-USB单片机QQ群:315457461
USB技术交流QQ群2:580684376
USB技术交流QQ群:952873936 USB技术交流3:1031974172
USB2.0规范





