📄 usbcore.c
字号:
case 2: //产品字符串的索引值为2,所以这里为产品字符串
#ifdef DEBUG0
Prints("(产品描述)。\r\n");
#endif
pSendData=ProductStringDescriptor;
SendLength=ProductStringDescriptor[0];
break;
case 3: //产品序列号的索引值为3,所以这里为序列号
#ifdef DEBUG0
Prints("(产品序列号)。\r\n");
#endif
pSendData=SerialNumberStringDescriptor;
SendLength=SerialNumberStringDescriptor[0];
break;
default :
#ifdef DEBUG0
Prints("(未知的索引值)。\r\n");
#endif
//对于未知索引值的请求,返回一个0长度的包
SendLength=0;
NeedZeroPacket=1;
break;
}
//判断请求的字节数是否比实际需要发送的字节数多
//如果请求的比实际的长,那么只返回实际长度的数据
if(wLength>SendLength)
{
if(SendLength%DeviceDescriptor[7]==0) //并且刚好是整数个数据包时
{
NeedZeroPacket=1; //需要返回0长度的数据包
}
}
else
{
SendLength=wLength;
}
//将数据通过EP0返回
UsbEp0SendData();
break;
default: //其它描述符
#ifdef DEBUG0
Prints("其他描述符,描述符代码:");
PrintHex((wValue>>8)&0xFF);
Prints("\r\n");
#endif
break;
}
break;
case GET_INTERFACE: //获取接口
#ifdef DEBUG0
Prints("获取接口。\r\n");
#endif
break;
case GET_STATUS: //获取状态
#ifdef DEBUG0
Prints("获取状态。\r\n");
#endif
break;
case SYNCH_FRAME: //同步帧
#ifdef DEBUG0
Prints("同步帧。\r\n");
#endif
break;
default: //未定义的标准请求
#ifdef DEBUG0
Prints("错误:未定义的标准输入请求。\r\n");
#endif
break;
}
break;
case 1: //类请求
#ifdef DEBUG0
Prints("USB类输入请求:");
#endif
switch(bRequest)
{
case GET_LINE_CODING: //GET_LINE_CODING请求
#ifdef DEBUG0
Prints("GET_LINE_CODING。\r\n");
#endif
SendLength=0x07; //7字节的LineCoding
pSendData=LineCoding;
break;
case SERIAL_STATE: //获取SERIAL_STATE请求
//本来该请求是获取串口状态的,但是圈圈在实际使用中,
//发现主机从来未发送过该请求,因而这里并不对它进行处理,
//只是简单地发送一个0长度的数据包。
#ifdef DEBUG0
Prints("SERIAL_STATE。\r\n");
#endif
SendLength=0;
NeedZeroPacket=1;
break;
default:
#ifdef DEBUG0
Prints("未知类请求。\r\n");
#endif
SendLength=0;
NeedZeroPacket=1;
break;
}
//判断请求的字节数是否比实际需要发送的字节数多
//如果请求的比实际的长,那么只返回实际长度的数据
if(wLength>SendLength)
{
if(SendLength%DeviceDescriptor[7]==0) //并且刚好是整数个数据包时
{
NeedZeroPacket=1; //需要返回0长度的数据包
}
}
else
{
SendLength=wLength;
}
//将数据通过EP0返回
UsbEp0SendData();
break;
case 2: //厂商请求
#ifdef DEBUG0
Prints("USB厂商输入请求:\r\n");
#endif
break;
default: //未定义的请求。这里只显示一个报错信息。
#ifdef DEBUG0
Prints("错误:未定义的输入请求。\r\n");
#endif
break;
}
}
//否则说明是输出请求
else //if(bmRequestType&0x80==0x80)之else
{
//根据bmRequestType的D6~5位散转,D6~5位表示请求的类型
//0为标准请求,1为类请求,2为厂商请求。
switch((bmRequestType>>5)&0x03)
{
case 0: //标准请求
#ifdef DEBUG0
Prints("USB标准输出请求:");
#endif
//USB协议定义了几个标准输出请求,我们实现这些标准请求即可
//请求的代码在bRequest中,对不同的请求代码进行散转
switch(bRequest)
{
case CLEAR_FEATURE: //清除特性
#ifdef DEBUG0
Prints("清除特性。\r\n");
#endif
break;
case SET_ADDRESS: //设置地址
#ifdef DEBUG0
Prints("设置地址。地址为:");
PrintHex(wValue&0xFF); //显示所设置的地址
Prints("\r\n");
#endif
D12SetAddress(wValue&0xFF); //wValue中的低字节是设置的地址值
//设置地址没有数据过程,直接进入到状态过程,返回一个0长度的数据包
SendLength=0;
NeedZeroPacket=1;
//将数据通过EP0返回
UsbEp0SendData();
break;
case SET_CONFIGURATION: //设置配置
#ifdef DEBUG0
Prints("设置配置。\r\n");
#endif
//使能非0端点。非0端点只有在设置为非0的配置后才能使能。
//wValue的低字节为配置的值,如果该值为非0,才能使能非0端点。
//保存当前配置值
ConfigValue=wValue&0xFF;
D12SetEndpointEnable(ConfigValue);
//返回一个0长度的状态数据包
SendLength=0;
NeedZeroPacket=1;
//将数据通过EP0返回
UsbEp0SendData();
break;
case SET_DESCRIPTOR: //设置描述符
#ifdef DEBUG0
Prints("设置描述符。\r\n");
#endif
break;
case SET_FEATURE: //设置特性
#ifdef DEBUG0
Prints("设置特性。\r\n");
#endif
break;
case SET_INTERFACE: //设置接口
#ifdef DEBUG0
Prints("设置接口。\r\n");
#endif
break;
default: //未定义的标准请求
#ifdef DEBUG0
Prints("错误:未定义的标准输出请求。\r\n");
#endif
break;
}
break;
case 1: //类请求
#ifdef DEBUG0
Prints("USB类输出请求:");
#endif
switch(bRequest)
{
case SET_CONTROL_LINE_STATE:
#ifdef DEBUG0
Prints("SET_CONTROL_LINE_STATE。\r\n");
#endif
//该请求没有数据输出阶段,其中wValue字段的D0位表示DTR,
//D1位表示RTS。但是我们的板上的串口并没有这两引脚,因而
//对该请求我们仅是简单地返回一个0长度的状态过程数据包即可
SendLength=0;
NeedZeroPacket=1;
//将数据通过EP0返回
UsbEp0SendData();
break;
case SET_LINE_CODING:
//该请求设置串口的属性,但是实际的数据并不在设置过程发出,
//而是在之后的数据过程发出。这里不用做任何处理,在数据过程
//完成后返回0长度的状态包。
#ifdef DEBUG0
Prints("SET_LINE_CODING。\r\n");
#endif
break;
default:
#ifdef DEBUG0
Prints("未知请求。\r\n");
#endif
break;
}
break;
case 2: //厂商请求
#ifdef DEBUG0
Prints("USB厂商输出请求:\r\n");
#endif
break;
default: //未定义的请求。这里只显示一个报错信息。
#ifdef DEBUG0
Prints("错误:未定义的输出请求。\r\n");
#endif
break;
}
}
}
//普通数据输出
else //if(D12ReadEndpointLastStatus(0)&0x20)之else
{
UsbEp0DataOut();
}
}
////////////////////////End of function//////////////////////////////
/********************************************************************
函数功能:端点0输入中断处理函数。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
void UsbEp0In(void)
{
#ifdef DEBUG0
Prints("USB端点0输入中断。\r\n");
#endif
//读最后发送状态,这将清除端点0的中断标志位
D12ReadEndpointLastStatus(1);
//发送剩余的字节数
UsbEp0SendData();
}
////////////////////////End of function//////////////////////////////
/********************************************************************
函数功能:端点1输出中断处理函数。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
void UsbEp1Out(void)
{
#ifdef DEBUG0
Prints("USB端点1输出中断。\r\n");
#endif
//读端点最后状态,这将清除端点1输出的中断标志位
D12ReadEndpointLastStatus(2);
//清除端点缓冲区
D12ClearBuffer();
}
////////////////////////End of function//////////////////////////////
/********************************************************************
函数功能:端点1输入中断处理函数。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
void UsbEp1In(void)
{
#ifdef DEBUG0
Prints("USB端点1输入中断。\r\n");
#endif
//读最后发送状态,这将清除端点1输入的中断标志位
D12ReadEndpointLastStatus(3);
//端点1输入处于空闲状态
Ep1InIsBusy=0;
}
////////////////////////End of function//////////////////////////////
/********************************************************************
函数功能:端点2输出中断处理函数。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
void UsbEp2Out(void)
{
#ifdef DEBUG0
Prints("USB端点2输出中断。\r\n");
#endif
//如果缓冲区中的数据还未通过串口发送完毕,则暂时不处理该中断,直接返回。
if(UsbEp2ByteCount!=0) return;
/*在原来的程序中,虽然对端点的双缓冲区清除中断时有判断,但是还是
存在着刚好读回时,双缓冲没满,但是写入时双缓冲区满的情况。这样的
话就会丢失中断,导致一些数据在缓冲区拿不出来,要等下一次接收到数
据时才能拿出来。*/
/*下面部分为圈圈勘误中指出,好像是有BEG,说明见上*/
/* //读最后接收状态,这将清除端点2输出的中断标志位。
//注意端点2有个双缓冲机制,在清除中断之前,先检查是否两个缓冲区
//是否全满了,如果两个缓冲区全满的话,就不用清除中断标志。只有当
//两个缓冲区不全满的时候才需要清除中断标志。
if((D12ReadEndpointStatus(4)&0x60)!=0x60)
{
D12ReadEndpointLastStatus(4);
} */
//读取端点2的数据。返回值为实际读到的数据字节数
UsbEp2ByteCount=D12ReadEndpointBuffer(4,BUF_LEN,UsbEp2Buffer);
//清除端点缓冲区
D12ClearBuffer();
//输出位置设为0
UsbEp2BufferOutputPoint=0;
if(!(D12ReadEndpointStatus(4)&0x60)) //如果任何一个缓冲区又有数据,则不要清除中断
{
D12ReadEndpointLastStatus(4); //清除端点中断
}
}
////////////////////////End of function//////////////////////////////
/********************************************************************
函数功能:端点2输入中断处理函数。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
void UsbEp2In(void)
{
#ifdef DEBUG0
Prints("USB端点2输入中断。\r\n");
#endif
//读最后发送状态,这将清除端点2输入的中断标志位
D12ReadEndpointLastStatus(5);
//端点2输入处于空闲状态
Ep2InIsBusy=0;
}
////////////////////////End of function//////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -