?? usb_setup.c
字號:
#include "c8051F320.h"
#include "stdio.h"
#include "intrins.h"
/////////////////////////////
#include "Usb_Descreptor.h"
#include "Usb_FunDec.h"
#include "Usb_Parameter.h"
#include "Usb_Register.h"
#include "Usb_Request.h"
//全局變量
static unsigned int DataSize; // 需要端點(diǎn)0發(fā)送的數(shù)據(jù)大小
static unsigned int DataSent; // 端點(diǎn)0已經(jīng)發(fā)送的數(shù)據(jù)大小
static unsigned char *DataPtr; // 端點(diǎn)0發(fā)送數(shù)據(jù)的指針
static unsigned char ONES_PACKET[2] = {0x01, 0x00}; // 在Get_Status等命令中應(yīng)用的數(shù)組
static unsigned char ZERO_PACKET[2] = {0x00, 0x00}; // 在Get_Status等命令中應(yīng)用的數(shù)組
unsigned char Ep_Status[3] ={EP_IDLE,EP_STALL,EP_STALL}; // 定義端點(diǎn)的狀態(tài)
unsigned char USB_State =DEV_ATTACHED; // 定義設(shè)備的狀態(tài)
struct Usb_Setup // Setup階段收到的8字節(jié)的命令,此處定義為結(jié)構(gòu)
{
unsigned char bmRequestType;
unsigned char bRequest;
unsigned char wValue[2];
unsigned char wIndex[2];
unsigned char wLength[2];
}Setup;
///////////////////////////////////////////////////////////////////////////////////////////////
void Handle_Setup() //端點(diǎn)0中斷處理函數(shù)
{
unsigned char ControlReg=0; // 存放端點(diǎn)0控制/狀態(tài)寄存器值的變量
UWrite_Byte(INDEX, 0); // 指向端點(diǎn)0
URead_Byte(E0CSR, ControlReg); // 讀端點(diǎn)0控制寄存器
if (ControlReg & rbSUEND) // 如果上次數(shù)據(jù)階段提前結(jié)束
{
UWrite_Byte(E0CSR, rbDATAEND); // 當(dāng)前數(shù)據(jù)傳完
UWrite_Byte(E0CSR, rbSSUEND); // 清除SUEND標(biāo)志
Ep_Status[0] = EP_IDLE; // 端點(diǎn)返回到空閑狀態(tài)
}
if (ControlReg & rbSTSTL) // 如果上次傳輸因錯誤而發(fā)送了STALL使傳輸提前結(jié)束
{
UWrite_Byte(E0CSR, 0); // 清除STALL
Ep_Status[0] = EP_IDLE; // 端點(diǎn)0返回到空閑狀態(tài)
}
if (ControlReg & rbOPRDY) // 如果接收到輸出數(shù)據(jù)包
{
if (Ep_Status[0] == EP_IDLE) // 如果端點(diǎn)0空閑
{
Fifo_Read(FIFO_EP0,8,(unsigned char *)&Setup); // 讀取設(shè)置數(shù)據(jù)包,8個(gè)字節(jié)
switch(Setup.bRequest) // 判斷請求類型
{
case GET_STATUS: Get_Status(); break;
case CLEAR_FEATURE: Clear_Feature(); break;
case SET_FEATURE: Set_Feature(); break;
case SET_ADDRESS: Set_Address(); break;
case GET_DESCRIPTOR: Get_Descriptor(); break;
case GET_CONFIGURATION: Get_Configuration();break;
case SET_CONFIGURATION: Set_Configuration();break;
case GET_INTERFACE: Get_Interface(); break;
case SET_INTERFACE: Set_Interface(); break;
case GET_MAXLUN: Get_Maxlun(); break;
default: Force_Stall(); break;
}
/////////////////////////////////////////////////////////////////////////////////////////////
}
else if(Ep_Status[0]==EP_RX) // 如果在OUT狀態(tài),此程序中不會從端點(diǎn)0接收其它信息,所以沒相關(guān)的操作
{}
}
if (Ep_Status[0] == EP_TX) // 如果在IN狀態(tài)
{
unsigned char ControlReg=0,TempReg=0; // 存放寄存器值的變量
URead_Byte(E0CSR, ControlReg); // 讀端點(diǎn)0控制寄存器
TempReg = rbINPRDY; // 輸出數(shù)據(jù)準(zhǔn)備好
if (DataSize >= EP0_PACKET_SIZE) // 如果待發(fā)送數(shù)據(jù)的長度大于端點(diǎn)0長度
{
Fifo_Write(FIFO_EP0, EP0_PACKET_SIZE,DataPtr); // 發(fā)送數(shù)據(jù)包
DataPtr += EP0_PACKET_SIZE; // 更新數(shù)據(jù)指針
DataSize -= EP0_PACKET_SIZE; // 更新待發(fā)送的數(shù)據(jù)量
DataSent += EP0_PACKET_SIZE; // 更新已發(fā)送的數(shù)據(jù)量
}
else // 如果待發(fā)送數(shù)據(jù)的長度小于端點(diǎn)0長度
{
Fifo_Write(FIFO_EP0, DataSize,DataPtr); // 發(fā)送剩余的數(shù)據(jù)
TempReg |= rbDATAEND; // 指示數(shù)據(jù)發(fā)送完備,進(jìn)入狀態(tài)階段
Ep_Status[0] = EP_IDLE; // 端點(diǎn)返回到空閑狀態(tài)
}
if (DataSent == (Setup.wLength[0]+256*Setup.wLength[1])) //如果發(fā)送的數(shù)據(jù)量正好是端點(diǎn)0的整數(shù)倍
{
TempReg |= rbDATAEND; // 指示數(shù)據(jù)發(fā)送完備,進(jìn)入狀態(tài)階段
Ep_Status[0] = EP_IDLE; // 端點(diǎn)返回到空閑狀態(tài)
}
UWrite_Byte(E0CSR, TempReg); // 寫端點(diǎn)0控制寄存器
}
}
void Force_Stall()
{
UWrite_Byte(INDEX, 0);
UWrite_Byte(E0CSR, rbSDSTL); // 發(fā)送STALL
Ep_Status[0] = EP_STALL; // 端點(diǎn)0到STALL狀態(tài),直到下次復(fù)位
}
//處理標(biāo)準(zhǔn)請求的函數(shù)
void Get_Status()
{
switch(Setup.bmRequestType)
{
case IN_DEVICE: // 如果是設(shè)備的狀態(tài)
DataPtr = ZERO_PACKET; // 發(fā)送 0x00, 總線供電,不支持遠(yuǎn)程喚醒
DataSize = 2;
break;
case IN_INTERFACE: // 接口狀態(tài)
DataPtr = ZERO_PACKET; // 接口狀態(tài)永遠(yuǎn)返回0
DataSize = 2;
break;
case IN_ENDPOINT: // 端點(diǎn)狀態(tài)
if (Setup.wIndex[0] == IN_EP1) // 如果是端點(diǎn)1
{
if (Ep_Status[1] == EP_HALT)
{ // 如果端點(diǎn)1在EN_HALT狀態(tài)
DataPtr = ONES_PACKET; // 發(fā)送ONES_PACKET,指示端點(diǎn)1在HALT狀態(tài)
DataSize = 2;
}
else
{
DataPtr = ZERO_PACKET; // 否則發(fā)送ZERO_PACKET,指示端點(diǎn)1在空閑狀態(tài)
DataSize = 2;
}
}
if (Setup.wIndex[0] == OUT_EP2)
{
if (Ep_Status[2] == EP_HALT)
{
DataPtr = ONES_PACKET;
DataSize = 2;
}
else
{
DataPtr = ZERO_PACKET;
DataSize = 2;
}
}
break;
default: Force_Stall(); break;
}
if (Ep_Status[0] != EP_STALL)
{
UWrite_Byte(E0CSR, rbSOPRDY);
Ep_Status[0] = EP_TX; // 端點(diǎn)0在EP_TX狀態(tài)
DataSent = 0; // 已發(fā)送數(shù)據(jù)量清零
}
}
void Clear_Feature()
{
if ((Setup.bmRequestType & 0x02)&& // 如果是端點(diǎn)
(Setup.wValue[0] == ENDPOINT_HALT) && // 并且這些端點(diǎn)的狀態(tài)是EP_HALT
((Setup.wIndex[0] == IN_EP1) || // 并且選擇的是端點(diǎn)1 IN
(Setup.wIndex[0] == OUT_EP2))) // 或端點(diǎn)2 OUT
{
if (Setup.wIndex[0] == IN_EP1)
{
UWrite_Byte (INDEX, 1); // 使toggle復(fù)位為零
UWrite_Byte (EINCSRL, rbInCLRDT);
Ep_Status[1] = EP_IDLE; // 端點(diǎn)1到空閑狀態(tài)
}
else
{
UWrite_Byte (INDEX, 2);
UWrite_Byte (EOUTCSRL, rbOutCLRDT);
Ep_Status[2] = EP_IDLE;
}
}
else
{
Force_Stall();
}
if (Ep_Status[0] != EP_STALL)
{
UWrite_Byte(E0CSR, rbSOPRDY);
UWrite_Byte(E0CSR, rbDATAEND);
}
}
void Set_Feature()
{
if ((Setup.bmRequestType & 0x02) && // 意義同上
(Setup.wValue[0] == ENDPOINT_HALT) &&
((Setup.wIndex[0] == IN_EP1) ||
(Setup.wIndex[0] == OUT_EP2)))
{
if (Setup.wIndex[0] == IN_EP1)
{
UWrite_Byte (INDEX, 1);
UWrite_Byte (EINCSRL, rbInSDSTL); // rbInSDSTL=1,發(fā)送STALL作為對IN令牌的響應(yīng),
// 在端點(diǎn)1中斷處理函數(shù)中將rbInSDSTl和rbInSTSTL清零
Ep_Status[1] = EP_HALT; // 端點(diǎn)1到HALT狀態(tài)
}
else
{
UWrite_Byte(INDEX, 2);
UWrite_Byte (EOUTCSRL, rbOutSDSTL); // 同上
Ep_Status[2] = EP_HALT;
}
}
else
{
Force_Stall();
}
if (Ep_Status[0] != EP_STALL)
{
UWrite_Byte(E0CSR, rbSOPRDY);
UWrite_Byte(E0CSR, rbDATAEND);
}
}
void Set_Address()
{
if (Setup.wValue[0] != 0)
{
USB_State = DEV_ADDRESS; // 收到不為0的地址,設(shè)備處于地址狀態(tài),此次傳輸?shù)? UWrite_Byte(FADDR, Setup.wValue[0]);// 狀態(tài)階段結(jié)束后新地址將起作用
Ep_Status[0] = EP_IDLE;
}
else
{
USB_State = DEV_DEFAULT; // 收到的地址為0,設(shè)備仍舊處于默認(rèn)狀態(tài)
}
UWrite_Byte(E0CSR, rbSOPRDY);
UWrite_Byte(E0CSR, rbDATAEND);
}
void Get_Descriptor()
{
unsigned int In_DataSize=0; // 要發(fā)送的數(shù)據(jù)總量
In_DataSize=Setup.wLength[0]+Setup.wLength[1]*256;
switch(Setup.wValue[1]) // 判斷描述符的類型
{
case DSC_DEVICE: // 設(shè)備描述符
DataPtr = DeviceDesc;
if(In_DataSize>18)
{DataSize = 18; }
else
{DataSize = In_DataSize;}
break;
case DSC_CONFIG: // 配置描述符
DataPtr = ConfigDesc;
if(In_DataSize==0x09)
{
DataSize=0x09;
}
else if(In_DataSize==0x20)
{
DataSize=0x20;
}
else if(In_DataSize==0xff)
{
DataSize=0x20;
}
break;
case DSC_STRING: // 字符串描述符
DataPtr=&StringDes[Setup.wValue[0]];
DataSize=In_DataSize;
break;
default: break;
}
UWrite_Byte(E0CSR, rbSOPRDY);
Ep_Status[0] = EP_TX; // 端點(diǎn)0在發(fā)送狀態(tài)
DataSent = 0;
}
void Get_Configuration()
{
if (USB_State == DEV_CONFIGURED) // If the device is configured, then return value 0x01
{ // since this software only supports one configuration
DataPtr = ONES_PACKET;
DataSize = 1;
}
if (USB_State == DEV_ADDRESS) // If the device is in address state, it is not
{ // configured, so return 0x00
DataPtr = ZERO_PACKET;
DataSize = 1;
}
if (Ep_Status[0] != EP_STALL)
{
UWrite_Byte(E0CSR, rbSOPRDY);
Ep_Status[0] = EP_TX;
DataSent = 0;
}
}
void Set_Configuration()
{
if (Setup.wValue[0] > 0) // Any positive configuration request
{ // results in configuration being set to 1
USB_State = DEV_CONFIGURED;
///////////////////////////////////////////////////////////////////////////////////
UWrite_Byte(INDEX, 1);
UWrite_Byte(EINCSRH,0xa0); // 雙緩沖、ISO、FIFO分割和強(qiáng)制數(shù)據(jù)Toggle禁止,IN端點(diǎn)
Ep_Status[1]=EP_IDLE;
UWrite_Byte(INDEX, 2);
UWrite_Byte(EOUTCSRH, 0x80); // 雙緩沖和ISO禁止,OUT端點(diǎn)
Ep_Status[2]=EP_IDLE;
///////////////////////////////////////////////////////////////////////////////////
UWrite_Byte(INDEX, 0);
}
else
{
USB_State = DEV_ADDRESS; // 設(shè)備仍舊在地址狀態(tài)
Ep_Status[1]=EP_STALL;
Ep_Status[2]=EP_STALL;
}
if (Ep_Status[0] != EP_STALL)
{
UWrite_Byte(E0CSR, rbSOPRDY);
UWrite_Byte(E0CSR, rbDATAEND);
}
}
void Get_Interface()
{
DataPtr = ZERO_PACKET;
DataSize = 1;
if (Ep_Status[0] != EP_STALL)
{
UWrite_Byte(E0CSR, rbSOPRDY);
Ep_Status[0] = EP_TX;
DataSent = 0;
}
}
void Set_Interface()
{
UWrite_Byte(E0CSR, rbSOPRDY);
UWrite_Byte(E0CSR, rbDATAEND);
}
void Get_Maxlun() // U盤支持一個(gè)邏輯單元,返回1即可
{
DataPtr = ZERO_PACKET;
DataSize = 1;
if (Ep_Status[0] != EP_STALL)
{
Ep_Status[0] = EP_TX;
DataSent = 0;
}
UWrite_Byte(E0CSR, rbSOPRDY);
}////////////////////////////////////////////////////////////////////////////////////////////////////
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -