?? usb_setup.#3
字號:
#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; // 需要端點0發送的數據大小
static unsigned int DataSent; // 端點0已經發送的數據大小
static unsigned char *DataPtr; // 端點0發送數據的指針
static unsigned char ONES_PACKET[2] = {0x01, 0x00}; // 在Get_Status等命令中應用的數組
static unsigned char ZERO_PACKET[2] = {0x00, 0x00}; // 在Get_Status等命令中應用的數組
unsigned char Ep_Status[3] ={EP_IDLE,EP_STALL,EP_STALL}; // 定義端點的狀態
unsigned char USB_State =DEV_ATTACHED; // 定義設備的狀態
struct Usb_Setup // Setup階段收到的8字節的命令,此處定義為結構
{
unsigned char bmRequestType;
unsigned char bRequest;
unsigned char wValue[2];
unsigned char wIndex[2];
unsigned char wLength[2];
}Setup;
///////////////////////////////////////////////////////////////////////////////////////////////
void Handle_Setup() //端點0中斷處理函數
{
unsigned char ControlReg=0; // 存放端點0控制/狀態寄存器值的變量
UWrite_Byte(INDEX, 0); // 指向端點0
URead_Byte(E0CSR, ControlReg); // 讀端點0控制寄存器
if (ControlReg & rbSUEND) // 如果上次數據階段提前結束
{
UWrite_Byte(E0CSR, rbDATAEND); // 當前數據傳完
UWrite_Byte(E0CSR, rbSSUEND); // 清除SUEND標志
Ep_Status[0] = EP_IDLE; // 端點返回到空閑狀態
}
if (ControlReg & rbSTSTL) // 如果上次傳輸因錯誤而發送了STALL使傳輸提前結束
{
UWrite_Byte(E0CSR, 0); // 清除STALL
Ep_Status[0] = EP_IDLE; // 端點0返回到空閑狀態
}
if (ControlReg & rbOPRDY) // 如果接收到輸出數據包
{
if (Ep_Status[0] == EP_IDLE) // 如果端點0空閑
{
Fifo_Read(FIFO_EP0,8,(unsigned char *)&Setup); // 讀取設置數據包,8個字節
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狀態,此程序中不會從端點0接收其它信息,所以沒相關的操作
{}
}
if (Ep_Status[0] == EP_TX) // 如果在IN狀態
{
unsigned char ControlReg=0,TempReg=0; // 存放寄存器值的變量
URead_Byte(E0CSR, ControlReg); // 讀端點0控制寄存器
TempReg = rbINPRDY; // 輸出數據準備好
if (DataSize >= EP0_PACKET_SIZE) // 如果待發送數據的長度大于端點0長度
{
Fifo_Write(FIFO_EP0, EP0_PACKET_SIZE,DataPtr); // 發送數據包
DataPtr += EP0_PACKET_SIZE; // 更新數據指針
DataSize -= EP0_PACKET_SIZE; // 更新待發送的數據量
DataSent += EP0_PACKET_SIZE; // 更新已發送的數據量
}
else // 如果待發送數據的長度小于端點0長度
{
Fifo_Write(FIFO_EP0, DataSize,DataPtr); // 發送剩余的數據
TempReg |= rbDATAEND; // 指示數據發送完備,進入狀態階段
Ep_Status[0] = EP_IDLE; // 端點返回到空閑狀態
}
if (DataSent == (Setup.wLength[0]+256*Setup.wLength[1])) //如果發送的數據量正好是端點0的整數倍
{
TempReg |= rbDATAEND; // 指示數據發送完備,進入狀態階段
Ep_Status[0] = EP_IDLE; // 端點返回到空閑狀態
}
UWrite_Byte(E0CSR, TempReg); // 寫端點0控制寄存器
}
}
void Force_Stall()
{
UWrite_Byte(INDEX, 0);
UWrite_Byte(E0CSR, rbSDSTL); // 發送STALL
Ep_Status[0] = EP_STALL; // 端點0到STALL狀態,直到下次復位
}
//處理標準請求的函數
void Get_Status()
{
switch(Setup.bmRequestType)
{
case IN_DEVICE: // 如果是設備的狀態
DataPtr = ZERO_PACKET; // 發送 0x00, 總線供電,不支持遠程喚醒
DataSize = 2;
break;
case IN_INTERFACE: // 接口狀態
DataPtr = ZERO_PACKET; // 接口狀態永遠返回0
DataSize = 2;
break;
case IN_ENDPOINT: // 端點狀態
if (Setup.wIndex[0] == IN_EP1) // 如果是端點1
{
if (Ep_Status[1] == EP_HALT)
{ // 如果端點1在EN_HALT狀態
DataPtr = ONES_PACKET; // 發送ONES_PACKET,指示端點1在HALT狀態
DataSize = 2;
}
else
{
DataPtr = ZERO_PACKET; // 否則發送ZERO_PACKET,指示端點1在空閑狀態
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; // 端點0在EP_TX狀態
DataSent = 0; // 已發送數據量清零
}
}
void Clear_Feature()
{
if ((Setup.bmRequestType == OUT_ENDPOINT)&&// 如果是端點
(Setup.wValue[0] == ENDPOINT_HALT) && // 并且這些端點的狀態是EP_HALT
((Setup.wIndex[0] == IN_EP1) || // 并且選擇的是端點1 IN
(Setup.wIndex[0] == OUT_EP2))) // 或端點2 OUT
{
if (Setup.wIndex[0] == IN_EP1)
{
UWrite_Byte (INDEX, 1); // 使toggle復位為零
UWrite_Byte (EINCSRL, rbInCLRDT);
Ep_Status[1] = EP_IDLE; // 端點1到空閑狀態
}
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 == OUT_ENDPOINT) && // 意義同上
(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,發送STALL作為對IN令牌的響應,
// 在端點1中斷處理函數中將rbInSDSTl和rbInSTSTL清零
Ep_Status[1] = EP_HALT; // 端點1到HALT狀態
}
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的地址,設備處于地址狀態,此次傳輸的
UWrite_Byte(FADDR, Setup.wValue[0]);// 狀態階段結束后新地址將起作用
Ep_Status[0] = EP_IDLE;
}
else
{
USB_State = DEV_DEFAULT; // 收到的地址為0,設備仍舊處于默認狀態
}
UWrite_Byte(E0CSR, rbSOPRDY);
UWrite_Byte(E0CSR, rbDATAEND);
}
void Get_Descriptor()
{
unsigned int In_DataSize=0; // 要發送的數據總量
In_DataSize=Setup.wLength[0]; // +Setup.wLength[1]*256;
switch(Setup.wValue[1]) // 判斷描述符的類型
{
case DSC_DEVICE: // 設備描述符
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; // 端點0在發送狀態
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分割和強制數據Toggle禁止,IN端點
Ep_Status[1]=EP_IDLE;
UWrite_Byte(INDEX, 2);
UWrite_Byte(EOUTCSRH, 0x80); // 雙緩沖和ISO禁止,OUT端點
Ep_Status[2]=EP_IDLE;
///////////////////////////////////////////////////////////////////////////////////
UWrite_Byte(INDEX, 0);
}
else
{
USB_State = DEV_ADDRESS; // 設備仍舊在地址狀態
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盤支持一個邏輯單元,返回1即可
{
DataPtr = ZERO_PACKET;
DataSize = 1;
if (Ep_Status[0] != EP_STALL)
{
Ep_Status[0] = EP_TX;
DataSent = 0;
}
UWrite_Byte(E0CSR, rbSOPRDY);
}////////////////////////////////////////////////////////////////////////////////////////////////////
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -