📄 usb.c
字号:
/*******************************Copyright (c)***************************************
U盘操作.
************************************************************************************/
#include "common.h"
#include "usb.H"
/*---------------------------------------------------------------------------------*/
UBYTE xdata FatBuf[512];
UBYTE xdata CurFatSector[512];
UBYTE xdata opLun;
UWORD xdata FreeClusterNum;
UWORD xdata FreeSecNum;
UWORD xdata StartSec2Write;
UBYTE xdata *BufStartAddress;
UWORD xdata OldClusterPointer;
USBFLAGS bdata DiskFlags;
USBPKG xdata usbstack;
pUSBDEV xdata uDev;
DIR_INFO xdata ThisDir;
FILE_INFO xdata ThisFile;
SYS_INFO_BLOCK xdata DeviceInfo;
TPBLK_STRUC xdata TPBulk_Block;
/*---------------------------------------------------------------------------------*/
UBYTE SL811Read(UBYTE a)
{
UBYTE nVal;
SL811H_ADDR=a;
nVal=SL811H_DATA;
return nVal;
}
void SL811Write(UBYTE a, UBYTE d)
{
SL811H_ADDR=a;
SL811H_DATA=d;
}
void SL811BufRead(UBYTE addr, UBYTE *s, UBYTE c)
{
UBYTE i;
SL811H_ADDR=addr;
for(i=0;i<c;i++)
*s++ =SL811H_DATA;
}
void SL811BufWrite(UBYTE addr, UBYTE *s, UBYTE c)
{
SL811H_ADDR=addr;
while (c--)
SL811H_DATA = *s++;
}
UHWORD WordSwap(UHWORD input)
{
return(((input&0x00FF)<<8)|((input&0xFF00)>>8));
}
void DelayMs(UBYTE nFactor)
{
UBYTE i;
UHWORD j;
for(i=0; i<nFactor; i++)
{
for(j=0;j<1000;j++)
j=j;
}
}
UWORD SwapINT32(UWORD dData)
{
dData = (dData&0xff)<<24|(dData&0xff00)<<8|(dData&0xff000000)>>24|(dData&0xff0000)>>8;
return dData;
}
UHWORD SwapINT16(UHWORD dData)
{
dData = (dData&0xff00)>>8|(dData&0x00ff)<<8;
return dData;
}
UWORD MakeWord(UBYTE d3,UBYTE d2,UBYTE d1,UBYTE d0)
{
UWORD temp,result;
temp=d3;
result=temp<<24;
temp=d2;
result=result|temp<<16;
temp=d1;
result=result|temp<<8|d0;
return result;
}
void USBReset(void)
{
UBYTE temp;
temp=SL811Read(CtrlReg);
temp=temp&0xE7;
SL811Write(CtrlReg,temp|0x08);
DelayMs(125);
SL811Write(CtrlReg,temp);
}
UBYTE usbXfer(void)
{
UBYTE xferLen, data0, data1,cmd,offset;
UBYTE intr,result,remainder,dataX,bufLen,addr,timeout;
UBYTE bEnd;
dataX=timeout=bEnd=0;
offset=0;
data0 = EP0_Buf;
data1=EP1_Buf;
if (usbstack.wLen >= usbstack.wPayload)
xferLen = usbstack.wPayload;
else
xferLen = usbstack.wLen;
if (usbstack.pid==PID_IN)
{
cmd = sDATA0_RD;
}
else if(usbstack.pid==PID_OUT)
{
SL811BufWrite(data0,usbstack.buffer,xferLen);
cmd = sDATA0_WR;
DiskFlags.bData1 = uDev.bData1[usbstack.endpoint];
uDev.bData1[usbstack.endpoint] = (uDev.bData1[usbstack.endpoint] ? 0 : 1);
if(DiskFlags.bData1==1)
cmd |= 0x40;
}
else
{
if(xferLen)
{
intr=usbstack.setup.wLength;
usbstack.setup.wValue=WordSwap(usbstack.setup.wValue);
usbstack.setup.wIndex=WordSwap(usbstack.setup.wIndex);
usbstack.setup.wLength=WordSwap(usbstack.setup.wLength);
SL811BufWrite(data0,(UBYTE *)&usbstack.setup,xferLen);
usbstack.setup.wLength=intr;
}
cmd = sDATA0_WR;
}
if (usbstack.endpoint == 0 && usbstack.pid != PID_SETUP)
cmd |= 0x40;
SL811Write(EP0Status,((usbstack.endpoint&0x0F)|usbstack.pid));
SL811Write(EP0Counter,usbstack.usbaddr);
SL811Write(EP0Address,data0);
SL811Write(EP0XferLen,xferLen);
SL811Write(IntStatus,INT_CLEAR);
SL811Write(EP0Control,cmd);
SL811Write(EP1Status,((usbstack.endpoint&0x0F)|usbstack.pid));
SL811Write(EP1Counter,usbstack.usbaddr);
SL811Write(EP1Address,data1);
SL811Write(EP1XferLen,64);
while(1)
{
while(1)
{
intr = SL811Read(IntStatus);
if((intr & USB_RESET) || (intr & INSERT_REMOVE))
return false;
if((intr & USB_A_DONE)&&((offset==0)))
break;
if((intr & USB_B_DONE)&&((offset>0)))
break;
}
SL811Write(IntStatus,INT_CLEAR);
result = SL811Read(EP0Status);
remainder = SL811Read(EP0Counter);
if (result & EP0_ACK)
{
if(usbstack.pid == PID_SETUP)
break;
else if(usbstack.pid == PID_OUT)
{
usbstack.wLen -= (UHWORD)xferLen;
usbstack.buffer += xferLen;
if(!usbstack.wLen)
break;
if (usbstack.wLen >= usbstack.wPayload)
xferLen = usbstack.wPayload;
else
xferLen = usbstack.wLen;
addr=data0;
SL811BufWrite(addr,usbstack.buffer,xferLen);
cmd = sDATA0_WR;
DiskFlags.bData1 = uDev.bData1[usbstack.endpoint];
uDev.bData1[usbstack.endpoint] = (uDev.bData1[usbstack.endpoint] ? 0 : 1);
if(DiskFlags.bData1==1)
cmd |= 0x40;
SL811Write(EP0XferLen, xferLen);
SL811Write(EP0Address, addr);
SL811Write(IntStatus,INT_CLEAR);
SL811Write(EP0Control,cmd);
}
else if(usbstack.pid == PID_IN)
{
usbstack.wLen -= (UHWORD)xferLen;
cmd ^= 0x40;
dataX++;
if(remainder==xferLen)
bufLen = 0;
else
bufLen = xferLen;
if(!remainder && usbstack.wLen)
{
addr = (dataX & 1) ? data1:data0;
xferLen = (UBYTE)(usbstack.wLen>=usbstack.wPayload) ? usbstack.wPayload:usbstack.wLen;
cmd |= 0x20;
SL811Write(EP0XferLen, xferLen);
SL811Write(EP0Address, addr);
SL811Write(IntStatus,INT_CLEAR);
SL811Write(EP0Control,cmd);
}
if(bufLen)
{
SL811BufRead(((dataX&1)?data0:data1), usbstack.buffer, bufLen);
usbstack.buffer += bufLen;
}
if(remainder || !usbstack.wLen)
break;
}
else if((usbstack.pid == PID_OUT)&&(bEnd))
break;
else if(usbstack.pid == PID_SETUP)
break;
}
if (result & EP0_NAK)
{
offset=0;
SL811Write(IntStatus,INT_CLEAR);
SL811Write(EP0Control+offset,cmd);
}
if (result & EP0_TIMEOUT)
{
if(usbstack.endpoint==0)
{
if(++timeout >= TIMEOUT_RETRY)
{
timeout--;
break;
}
SL811Write(IntStatus,INT_CLEAR);
SL811Write(EP0Control,cmd);
}
else
{
break;
}
}
if (result & EP0_STALL)
return true;
if (result & EP0_OVERFLOW)
break;
}
if (result & EP0_ACK)
return true;
return false;
}
UBYTE ep0Xfer(void)
{
usbstack.endpoint=0;
usbstack.pid=PID_SETUP;
usbstack.wLen=8;
if (!usbXfer())
return false;
usbstack.pid = PID_IN;
usbstack.wLen = usbstack.setup.wLength;
if (usbstack.wLen)
{
if (usbstack.setup.bmRequest & 0x80)
{
usbstack.pid = PID_IN;
if(!usbXfer())
return false;
usbstack.pid = PID_OUT;
}
else
{
usbstack.pid = PID_OUT;
if(!usbXfer())
return false;
usbstack.pid = PID_IN;
}
}
usbstack.wLen=0;
if(!usbXfer())
return false;
return true;
}
UBYTE epBulkSend(UBYTE *pBuffer,UHWORD len)
{
usbstack.usbaddr=0x1;
usbstack.endpoint=usbstack.epbulkout;
usbstack.pid=PID_OUT;
usbstack.wPayload=64;
usbstack.wLen=len;
usbstack.buffer=pBuffer;
if(usbstack.wLen)
return usbXfer();
return true;
}
UBYTE epBulkRcv(UBYTE *pBuffer,UHWORD len)
{
usbstack.usbaddr=0x1;
usbstack.endpoint=usbstack.epbulkin;
usbstack.pid=PID_IN;
usbstack.wPayload=64;
usbstack.wLen=len;
usbstack.buffer=pBuffer;
if(usbstack.wLen)
return usbXfer();
return true;
}
UBYTE SetAddress(UBYTE addr)
{
usbstack.usbaddr=0;
usbstack.setup.bmRequest=0;
usbstack.setup.bRequest=SET_ADDRESS;
usbstack.setup.wValue=addr;
usbstack.setup.wIndex=0;
usbstack.setup.wLength=0;
return ep0Xfer();
}
UBYTE Set_Configuration(void)
{
usbstack.setup.bmRequest=0;
usbstack.setup.bRequest=SET_CONFIG;
usbstack.setup.wValue=DEVICE;
usbstack.setup.wIndex=0;
usbstack.setup.wLength=0;
usbstack.buffer=NULL;
return ep0Xfer();
}
UBYTE Set_Interface(void)
{
usbstack.setup.bmRequest=1;
usbstack.setup.bRequest=SET_INTERFACE;
usbstack.setup.wValue=0;
usbstack.setup.wIndex=0;
usbstack.setup.wLength=0;
usbstack.buffer=NULL;
return ep0Xfer();
}
UBYTE GetDesc(void)
{
usbstack.setup.bmRequest=0x80;
usbstack.setup.bRequest=GET_DESCRIPTOR;
usbstack.setup.wValue=WordSwap(usbstack.setup.wValue);
usbstack.wPayload=uDev.wPayLoad[0];
return ep0Xfer();
}
UHWORD GetMaxLUN(void)
{
usbstack.setup.bmRequest=0xa1;
usbstack.setup.bRequest=0xfe;
usbstack.setup.wValue=0;
usbstack.setup.wIndex=0;
usbstack.setup.wLength=1;
return ep0Xfer();
}
UBYTE EnumUsbDev(UBYTE usbaddr)
{
UBYTE i;
UBYTE uAddr = 0;
UBYTE epLen;
pDevDesc pDev;
pCfgDesc pCfg;
pIntfDesc pIfc;
pEPDesc pEnp;
uDev.wPayLoad[0] = 8;
if(usbaddr == 1)
USBReset();
DelayMs(25);
pDev =(pDevDesc)DBUF;
usbstack.usbaddr=uAddr;
usbstack.setup.wValue=DEVICE;
usbstack.setup.wIndex=0;
usbstack.setup.wLength=18;
usbstack.buffer=DBUF;
if (!GetDesc())
return false;
uDev.wPayLoad[0]=pDev->bMaxPacketSize0;
if (!SetAddress(usbaddr))
return false;
uAddr = usbaddr;
pDev =(pDevDesc)DBUF;
usbstack.usbaddr=uAddr;
usbstack.setup.wLength=pDev->bLength;
usbstack.setup.wValue=DEVICE;
usbstack.setup.wIndex=0;
usbstack.buffer=DBUF;
if (!GetDesc())
return false;
uDev.wVID = pDev->idVendor;
uDev.wPID = pDev->idProduct;
uDev.iMfg = pDev->iManufacturer;
uDev.iPdt = pDev->iProduct;
pCfg = (pCfgDesc)DBUF;
usbstack.usbaddr=uAddr;
usbstack.setup.wValue=CONFIGURATION;
usbstack.setup.wIndex=0;
usbstack.setup.wLength=64;
usbstack.buffer=DBUF;
if (!GetDesc())
return false;
pIfc = (pIntfDesc)(DBUF + 9);
uDev.bClass = pIfc->iClass;
uDev.bNumOfEPs = (pIfc->bEndPoints <= MAX_EP) ? pIfc->bEndPoints : MAX_EP;
if(uDev.bClass!=8)
return false;
usbstack.usbaddr=uAddr;
if (!Set_Configuration())
return false;
if (!Set_Interface())
return false;
epLen = 0;
for (i=1; i<=uDev.bNumOfEPs; i++)
{
pEnp = (pEPDesc)(DBUF + 9 + 9 + epLen);
uDev.bEPAddr[i] = pEnp->bEPAdd;
uDev.bAttr[i] = pEnp->bAttr;
uDev.wPayLoad[i] = WordSwap(pEnp->wPayLoad);
uDev.bInterval[i] = pEnp->bInterval;
uDev.bData1[i] = 0;
epLen += 7;
uDev.bData1[i]=0;
DiskFlags.bData1=0;
if(uDev.bAttr[i]==0x2)
{
if(uDev.bEPAddr[i]&0x80)
usbstack.epbulkin=uDev.bEPAddr[i];
else
usbstack.epbulkout=uDev.bEPAddr[i];
}
}
usbstack.buffer=DBUF;
if(!GetMaxLUN())
return false;
opLun=DBUF[0]&0x03;
return true;
}
void SL811Init(void)
{
opLun = 0;
DiskFlags.bData1 = false;
DiskFlags.UDiskOK = false;
DiskFlags.bIsFat32 = false;
DiskFlags.bFatChanged = false;
DiskFlags.SLAVE_ONLINE = false;
SL811Write(cDATASet,0xe0);
SL811Write(cSOFcnt,0xae);
SL811Write(CtrlReg,0x5);
SL811Write(EP0Status,0x50);
SL811Write(EP0Counter,0);
SL811Write(EP0Control,0x01);
SL811Write(IntEna,0x20);
SL811Write(IntStatus,INT_CLEAR);
}
void CheckUsbDevice(void)
{
UBYTE intr;
intr = SL811Read(IntStatus);
SL811Write(IntStatus,INT_CLEAR);
SL811Write(IntStatus,INSERT_REMOVE);
if(intr & 0x40) // This bit is "1" -> Device not present
{
if(DiskFlags.SLAVE_ONLINE == true)
{
USB_LED = 1;
DiskFlags.UDiskOK = false;
DiskFlags.SLAVE_ONLINE = false;
USBReset();
}
}
else // This bit is "0" -> Device is present
{
if(DiskFlags.SLAVE_ONLINE == false)
{
DelayMs(250);
if(!EnumUsbDev(1))
{
USBReset();
return;
}
USB_LED = 0;
if(EnumMassDev())
{
DiskFlags.UDiskOK = true;
}
else
{
DiskFlags.UDiskOK = false;
USBReset();
}
DiskFlags.SLAVE_ONLINE = true;
}
}
}
UBYTE EnumMassDev(void)
{
PMBR_BLOCK pMBR;
PBPB_BLOCK pBPB;
PFSINFO_BLOCK pFSInfo;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -