📄 chap_9.c
字号:
//*************************************************************************
// USB Protocol Layer
//*************************************************************************
void reserved(void)
{
stall_ep0();
}
//*************************************************************************
// USB standard device requests
//*************************************************************************
//*************************************************************************
//获取设备状态,Get Status请求要求接收方返回一个相应的状态,设备返回16位的状态描述.
//*************************************************************************
void get_status(void)
{
unsigned char endp, txdat[2];
unsigned char bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;
unsigned char c;
if (bRecipient == USB_RECIPIENT_DEVICE)
{
//获取设备的状态状态,返回值信息如下:
//Bit0: 0 总线供电 1 自供电
//Bit1: 0 不支持远程唤醒 1 支持远程唤醒
//Bit2~bit15:
if(bEPPflags.bits.remote_wakeup == 1) //获取远程唤醒状态
txdat[0] = 3;
else
txdat[0] = 1;
txdat[1]=0;
single_transmit(txdat, 2);
}
else if (bRecipient == USB_RECIPIENT_INTERFACE)
{
//获取接口状态,16位全部保留,返回全0即可
txdat[0]=0;
txdat[1]=0;
single_transmit(txdat, 2);
}
else if (bRecipient == USB_RECIPIENT_ENDPOINT)
{
//获取端点状态,一个端点有输入和输出两个端点号,用Bit7区分: 0 要求返回输出端点的状态 1 要求返回输入端点的状态
//Bit0: 0 端点允许 1 端点禁止
endp = (unsigned char)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
if (ControlData.DeviceRequest.wIndex & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
c = D12_SelectEndpoint(endp*2 + 1); //Control-in 端点
else
c = D12_SelectEndpoint(endp*2); // Control-out 端点
if(c & D12_STALL)
txdat[0] = 1; //端点禁止
else
txdat[0] = 0; //端点允许
txdat[1] = 0;
single_transmit(txdat, 2);
}
else
stall_ep0();
}
//*************************************************************************
//特性清除
//*************************************************************************
//Clear Feature用来清除或禁止设备一个特定的特性.当接收到这个请求后设备就执行相应的操作,
//并返回一个空的数据表示执行完毕.如果请求的特性不存在或不能清除就发出一个STALL的握手.
//请求的值: 1 清除设备的远程唤醒功能;
// 0 清除索引号对应的输入或输出端点的禁止功能,恢复其使用
void clear_feature(void)
{
unsigned char endp;
unsigned char bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;
if (bRecipient == USB_RECIPIENT_DEVICE
&& ControlData.DeviceRequest.wValue == USB_FEATURE_REMOTE_WAKEUP)
{
//清除设备的远程唤醒功能
DISABLE;
bEPPflags.bits.remote_wakeup = 0;
ENABLE;
single_transmit(0, 0);
}
else if (bRecipient == USB_RECIPIENT_ENDPOINT
&& ControlData.DeviceRequest.wValue == USB_FEATURE_ENDPOINT_STALL)
{
//清除端点的禁止功能
endp = (unsigned char)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
if (ControlData.DeviceRequest.wIndex & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
/* clear TX stall for IN on EPn. */
D12_SetEndpointStatus(endp*2 + 1, 0); //使能输入端点
else
/* clear RX stall for OUT on EPn. */
D12_SetEndpointStatus(endp*2, 0); //使能输出端点
single_transmit(0, 0);
}
else
stall_ep0();
}
//*************************************************************************
//特性设置
//*************************************************************************
//Set Feature用来设置或允许一个特性,当接收到这个请求后设备就执行相应的操作,
//并返回一个空的数据表示执行完毕.如果请求的特性不存在或不能清除就发出一个STALL的握手.
//请求的值: 1 启动设备的远程唤醒功能;
// 0 禁止索引号对应的输入或输出端点
void set_feature(void)
{
unsigned char endp;
unsigned char bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;
if (bRecipient == USB_RECIPIENT_DEVICE
&& ControlData.DeviceRequest.wValue == USB_FEATURE_REMOTE_WAKEUP)
{
//设置远程唤醒功能
DISABLE;
bEPPflags.bits.remote_wakeup = 1;
ENABLE;
single_transmit(0, 0);
}
else if (bRecipient == USB_RECIPIENT_ENDPOINT
&& ControlData.DeviceRequest.wValue == USB_FEATURE_ENDPOINT_STALL)
{
//禁止端点
endp = (unsigned char)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
if (ControlData.DeviceRequest.wIndex & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
/* clear TX stall for IN on EPn. */
D12_SetEndpointStatus(endp*2 + 1, 1); //禁止输入端点
else
/* clear RX stall for OUT on EPn. */
D12_SetEndpointStatus(endp*2, 1); //禁止输出端点
single_transmit(0, 0);
}
else
stall_ep0();
}
//*************************************************************************
////设置地址
//*************************************************************************
//在USB设备枚举时,主机会分配一个新的地址给设备,以取代默认地址(0).当设备接收
//到这个设备请求时就把设备的当前地址改为分配的地址,以让设备对新的地址做出响应,
//此请求不含数据阶段,固件需要向主机写一个零长度的数据包作为应答
void set_address(void)
{
D12_SetAddressEnable((unsigned char)(ControlData.DeviceRequest.wValue &
DEVICE_ADDRESS_MASK), 1);
single_transmit(0, 0);
}
//*************************************************************************
//获取描述符
//*************************************************************************
//用来获取USB设备相对应的描述符设备,请求的高位字节为要求的描述符类型
void get_descriptor(void)
{
unsigned char bDescriptor = MSB(ControlData.DeviceRequest.wValue);
if (bDescriptor == USB_DEVICE_DESCRIPTOR_TYPE)
{
//获取设备描述符
code_transmit((unsigned char *)&DeviceDescr, sizeof(USB_DEVICE_DESCRIPTOR));
}
else if (bDescriptor == USB_CONFIGURATION_DESCRIPTOR_TYPE)
{
//获取配置描述符或描述符集合,
//配置描述符的返回可长可短,要视主机的长度要求而定
code_transmit((unsigned char *)&DescriptorSet, CONFIG_DESCRIPTOR_LENGTH);
//***NOTE****: 上句中,将原来的ConfigDescr换为DescriptorSet
//使意义更清晰,固件根据上位机的请求来决定是返回单一个配置描述符,还是返回一个描述符集合
}
else
stall_ep0();
}
//*************************************************************************
//获取配置状态
//*************************************************************************
//如果设备已经配置,则返回信息为当前的配置值(一个字节);否则返回为0,表示设备还没有配置
void get_configuration(void)
{
unsigned char c = bEPPflags.bits.configuration;
single_transmit(&c, 1);
}
//*************************************************************************
//设置配置状态
//*************************************************************************
//此请求用来选择设备的工作配置值域只能是0,或与配置描述符中与
//bConfigureation Value字段(在本固件中设置为1)相同的值,固件应向主机发送零数
//据包作为应答
void set_configuration(void)
{
if (ControlData.DeviceRequest.wValue == 0)
{
//设备进入地址状态,所有端点除控制端点外,都应被禁止.
//需要新的Set Configuration请求来配置
single_transmit(0, 0);
DISABLE;
bEPPflags.bits.configuration = 0;
ENABLE;
init_unconfig();
}
else if (ControlData.DeviceRequest.wValue == 1)
{
//配置设备且置标志
single_transmit(0, 0);
init_unconfig();
init_config();
DISABLE;
bEPPflags.bits.configuration = 1;
ENABLE;
} else
stall_ep0();
}
//*************************************************************************
//获取接口状态
//*************************************************************************
void get_interface(void)
{
unsigned char txdat = 0; /* Only /Current interface = 0 */
single_transmit(&txdat, 1);
}
//*************************************************************************
//设置接口状态
//*************************************************************************
//用于设备支持多接口的时候,主机用来选择一个接口.选择正确,设备发送一个空的数
//据表示执行完毕;当接口不存在时,设备返回STALL.
void set_interface(void)
{
if (ControlData.DeviceRequest.wValue == 0 && ControlData.DeviceRequest.wIndex == 0)
single_transmit(0, 0);
else
stall_ep0();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -