//协议层
#include <reg52.h>
#include "D12Config.h"
#include "D12CI.h"
#include "Chap_9.h"
#include "Descriptor.h"
CONTROL_XFER ControlData;
EPPFLAGS bEPPflags;
//USB标准设备请求入口地址指针表
code void (*StandardDeviceRequest[])(void) =
{
get_status,
clear_feature,
reserved,
set_feature,
reserved,
set_address,
get_descriptor,
reserved,
get_configuration,
set_configuration,
get_interface,
set_interface,
reserved,
reserved,
reserved,
reserved
};
// USB 协议层函数
void stall_ep0(void)
{
D12_SetEndpointStatus(0, 1);
D12_SetEndpointStatus(1, 1);
}
void reserved(void)
{
stall_ep0(); //返回STALL
}
void init_unconfig(void)
{
D12_SetEndpointEnable(0); //禁止0除外的所有端点
}
void init_config(void)
{
D12_SetEndpointEnable(1);
}
void single_transmit(INT8U * buf, INT8U len)
{
if( len <= EP0_PACKET_SIZE)
D12_WriteEndpoint(1, len, buf);
}
void code_transmit(INT8U *pRomData, INT16U len)
{
ControlData.wCount = 0;
if(ControlData.wLength > len)
ControlData.wLength = len;
ControlData.pData = pRomData;
if( ControlData.wLength >= EP0_PACKET_SIZE)
{
D12_WriteEndpoint(1, EP0_PACKET_SIZE, ControlData.pData);
ControlData.wCount += EP0_PACKET_SIZE;
DISABLE();
bEPPflags.bits.control_state = USB_TRANSMIT;
ENABLE();
}
else
{
D12_WriteEndpoint(1, ControlData.wLength, pRomData);
ControlData.wCount += ControlData.wLength;
DISABLE();
bEPPflags.bits.control_state = USB_IDLE;
ENABLE();
}
}
// USB 标准设备请求服务程序
void get_status(void)
{
INT8U endp, txdat[2], c;
INT8U bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;
if (bRecipient == USB_RECIPIENT_DEVICE)
{
if(bEPPflags.bits.remote_wakeup == 1)
txdat[0] = 3; //支持远程唤醒、自供电
else
txdat[0] = 1;
txdat[1]=0;
single_transmit(txdat, 2); //发送16位的状态到主机
}
else if (bRecipient == USB_RECIPIENT_INTERFACE)
{
txdat[0]=0;
txdat[1]=0;
single_transmit(txdat, 2);
}
else if (bRecipient == USB_RECIPIENT_ENDPOINT)
{
endp = (INT8U)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
if (ControlData.DeviceRequest.wIndex & (INT8U)USB_ENDPOINT_DIRECTION_MASK)
c = D12_SelectEndpoint(endp*2 + 1); //读取输入端点状态
else
c = D12_SelectEndpoint(endp*2); //读取输出端点状态
if(c & D12_STALL)
txdat[0] = 1; //端点禁止
else
txdat[0] = 0; //端点有效
txdat[1] = 0;
single_transmit(txdat, 2);
}
else
stall_ep0(); //非标准请求,发STALL
}
void clear_feature(void)
{
INT8U endp;
INT8U bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;
if (bRecipient == USB_RECIPIENT_DEVICE&&ControlData.DeviceRequest.wValue == USB_FEATURE_REMOTE_WAKEUP)
{
DISABLE(); //清除远程唤醒特性
bEPPflags.bits.remote_wakeup = 0; //清0远程唤醒标志
ENABLE();
single_transmit(0, 0); //返回一个空的数据表示执行完毕
}
else if (bRecipient == USB_RECIPIENT_ENDPOINT&& ControlData.DeviceRequest.wValue == USB_FEATURE_ENDPOINT_STALL)
{ //清除端点禁止特性,恢复其使用
endp = (INT8U)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
if (ControlData.DeviceRequest.wIndex & (INT8U)USB_ENDPOINT_DIRECTION_MASK)
D12_SetEndpointStatus(endp*2 + 1, 0); //清除控制输入端点STALL特性
else
D12_SetEndpointStatus(endp*2, 0); //清除控制输出端点STALL特性
single_transmit(0, 0);
}
else
stall_ep0(); //没有该请求,返回STALL
}
void set_feature(void)
{
INT8U endp;
INT8U bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;//读取请求类型中的接收方
if (bRecipient == USB_RECIPIENT_DEVICE && ControlData.DeviceRequest.wValue == USB_FEATURE_REMOTE_WAKEUP)
{//设置远程唤醒特性
DISABLE();
bEPPflags.bits.remote_wakeup = 1; //置1远程唤醒标志
ENABLE();
single_transmit(0, 0);
}
else if (bRecipient == USB_RECIPIENT_ENDPOINT && ControlData.DeviceRequest.wValue == USB_FEATURE_ENDPOINT_STALL)
{//禁止端点
endp = (INT8U)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
if (ControlData.DeviceRequest.wIndex & (INT8U)USB_ENDPOINT_DIRECTION_MASK)
D12_SetEndpointStatus(endp*2 + 1, 1); //设置输入端点禁止
else
D12_SetEndpointStatus(endp*2, 1); //设置输出端点禁止
single_transmit(0, 0);
}
else
stall_ep0();
}
void set_address(void)
{
D12_SetAddressEnable((INT8U)(ControlData.DeviceRequest.wValue &
DEVICE_ADDRESS_MASK), 1);
single_transmit(0, 0);
}
void get_descriptor(void)
{
INT8U bDescriptor = MSB(ControlData.DeviceRequest.wValue); //读取请求的描述符类型
if (bDescriptor == USB_DEVICE_DESCRIPTOR_TYPE)
{//获取设备描述符
code_transmit((INT8U *)&DeviceDescr, sizeof(USB_DEVICE_DESCRIPTOR));
}
else if (bDescriptor == USB_CONFIGURATION_DESCRIPTOR_TYPE)
{//获取其它描述符
if (ControlData.DeviceRequest.wLength > CONFIG_DESCRIPTOR_LENGTH)
{
ControlData.DeviceRequest.wLength = CONFIG_DESCRIPTOR_LENGTH;
}
code_transmit((INT8U *)&(usb_descr.ConfigDescr), ControlData.DeviceRequest.wLength);
//发送描述符内容
}
else
stall_ep0();
}
void get_configuration(void)
{
INT8U c = bEPPflags.bits.configuration; //取出配置值
single_transmit(&c, 1); //发送配置值
}
void set_configuration(void)
{
if (ControlData.DeviceRequest.wValue == 0)
{//配置值不对,设备进入未配置状态
single_transmit(0, 0);
DISABLE();
bEPPflags.bits.configuration = 0;
ENABLE();
init_unconfig(); //进入地址状态,禁止0除外的所有端点
}
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)
{
INT8U txdat = 0; //本设备只有一个接口
single_transmit(&txdat, 1); //发送一个字节
}
void set_interface(void)
{
if (ControlData.DeviceRequest.wValue == 0 && ControlData.DeviceRequest.wIndex == 0)
single_transmit(0, 0);
else
stall_ep0();
}
void control_handler(void) //协议控制子程序
{
INT8U type, req;
type = ControlData.DeviceRequest.bmRequestType & USB_REQUEST_TYPE_MASK; //读取请求代码
req = ControlData.DeviceRequest.bRequest & USB_REQUEST_MASK;
if (type == USB_STANDARD_REQUEST)
(*StandardDeviceRequest[req])(); //标准请求处理
else
stall_ep0();
}
void ep0_rxdone(void) //端点0接收数据
{
INT8U ep_last, i;
INT8U req[sizeof(DEVICE_REQUEST)];
ep_last = D12_ReadLastTransactionStatus(0); //清除中断寄存器状态,取得最后处理状态
if (ep_last & D12_SETUPPACKET)
{ //如果收到了建立包(Setup包)
ControlData.wLength = 0; //传输字节总数清0
ControlData.wCount = 0; //传输字节计数器清0
if(D12_ReadEndpoint(0, sizeof(ControlData.DeviceRequest),req)
!= sizeof(DEVICE_REQUEST) )
{
//从端点0读8个字节失败
D12_SetEndpointStatus(0, 1); //停止控制端点0
D12_SetEndpointStatus(1, 1); //停止控制端点1
bEPPflags.bits.control_state = USB_IDLE; //设置为等待状态
return;
}
/******* 以下语句通信中的解决大小端问题,使该函数与编译器无关 ****/
ControlData.DeviceRequest.bmRequestType = req[0];
ControlData.DeviceRequest.bRequest = req[1];
ControlData.DeviceRequest.wValue = req[3] * 256 + req[2];
ControlData.DeviceRequest.wIndex = req[5] * 256 + req[4];
ControlData.DeviceRequest.wLength = req[7] * 256 + req[6];
/******** 接收建立包成功 **********/
D12_AcknowledgeEndpoint(0); //对控制端点0进行�