www.pudn.com > UDISK.rar > API.C
//************************************************************************
//author:dragon
//web:8dragon.com
//2004.2.5完成于桃龙源
//*************************************************************************
#include "AT89X52.h"
#include "api.h"
#include "file.h"
#include "host_811.h"
#include "ufi.h"
#include "string.h"
#include "math.h"
struct _FILE ApiFileControl;
extern struct _BPB SimpleBpb;
extern FAT_PARAMETER FatParameter;
BYTE BuffFile[8*512];
extern WORD FatCache[2][256];
BYTE CreateFile(char* filename, BYTE attribute)
{
struct _DIR dir,*pdir;
BYTE name[11];
struct _FILE file;
// WORD NewCluster;
BYTE Cache[512];
static char NewFileName[12];
char * p=NewFileName;
////////////////////////////////////////////////////////////////////////
//*Get valid filen name
if(!CheckFileName(filename,p))
return FALSE;
//*核对该文件是否已经存在
if(LocateFile(filename, NULL)!=0xffffffff)
return FALSE;
strncpy(name, p, 11);
memset(&dir, 0, sizeof(dir));
memcpy(dir.Name, name, 11);
dir.Attr = attribute;
dir.CrtDate =0;
dir.CrtTime =0;
dir.CrtTimeTenth =0;
dir.FileSize =0;
DelayMs(5);
if(!LocateDir(&dir, &file))
return FALSE;
// NewCluster=SeekEmptyCluseter();
// if(NewCluster==0xffff)
// return FALSE;
DelayMs(15);
if(!Read(file.DirSectorNum,1,(BYTE *)Cache))
return FALSE;
pdir = (struct _DIR *)Cache;
pdir += file.DirIndex;
pdir->FstClusLO =0x00;//WordSwap(NewCluster);
pdir->FileSize=0;
if(!Write(file.DirSectorNum,1,Cache,TRUE))
if(!Write(file.DirSectorNum,1,Cache,TRUE))
return FALSE;
return OpenFile(filename);
}
BYTE WriteFile(const char* buffer, UINT bytes)
{
BYTE *pCache;
WORD Cache[512];
UINT write_bytes =0,flag=0;
UINT max_write_bytes_in_sector;
WORD Cluster;
////////////////////////////////////////////////////////////////////////
//如果打开的文件是一个空文件,则进入下面
//为其寻找一个开始的数据蔟,标记为0xffff
//数据直接填在该簇对应的扇区内
if(ApiFileControl.StartSectorNum (bytes - write_bytes))
max_write_bytes_in_sector = (bytes - write_bytes);
else
max_write_bytes_in_sector=(SimpleBpb.BytsPerSec*SimpleBpb.SecPerClus - ApiFileControl.SectorOffset);
memcpy(pCache, buffer, max_write_bytes_in_sector);
ApiFileControl.SectorOffset += max_write_bytes_in_sector;
if(ApiFileControl.SectorOffset>=SimpleBpb.BytsPerSec*SimpleBpb.SecPerClus)
{
if(!Write(ApiFileControl.CurrentSectorNum,SimpleBpb.SecPerClus,(BYTE*)BuffFile,FALSE))
if(!Write(ApiFileControl.CurrentSectorNum,SimpleBpb.SecPerClus,(BYTE*)BuffFile,FALSE))
return FALSE;
if((write_bytes+max_write_bytes_in_sector)= bytes)
return TRUE;
}//end for cycle
return FALSE;
}
BYTE AddWriteFile(const char* buffer, UINT bytes)
{
UINT write_bytes =0;
UINT max_write_bytes_in_sector;
////////////////////////////////////////////////////////////////////////
// WORD Cluster;
// DWORD Sector;
BYTE *pCache;
// BYTE BuffFile[4*512];
/////////////////////////////////////////////////////////////////////////////
//
//****如果文件的大小不是SimpleBpb.BytsPerSec*SimpleBpb.SecPerClus
//的整数倍,则进入下面的语句可以保证加写的东西精确到到字节
//
//////////////////////////////////////////////////////////////////////////////
if(0 (bytes - write_bytes))
max_write_bytes_in_sector = (bytes - write_bytes);
else
max_write_bytes_in_sector=(SimpleBpb.BytsPerSec*SimpleBpb.SecPerClus - ApiFileControl.SectorOffset);
// Cluster=SecToCluster(ApiFileControl.CurrentSectorNum);
// Sector=ClusterToSec(Cluster);
if(!Read(ApiFileControl.CurrentSectorNum,SimpleBpb.SecPerClus,(BYTE *)BuffFile))
return FALSE;
pCache += ApiFileControl.SectorOffset;
memcpy(pCache, buffer, max_write_bytes_in_sector);
if(!Write(ApiFileControl.CurrentSectorNum,SimpleBpb.SecPerClus,(BYTE *)BuffFile,TRUE))
if(!Write(ApiFileControl.CurrentSectorNum,SimpleBpb.SecPerClus,(BYTE *)BuffFile,TRUE))
return FALSE;
write_bytes += max_write_bytes_in_sector;
buffer = (char*)buffer + max_write_bytes_in_sector;
ApiFileControl.dir.FileSize += max_write_bytes_in_sector;
if((bytes-max_write_bytes_in_sector)>0)
ApiFileControl.SectorOffset=0;
}
if(!WriteFile(buffer,(bytes -write_bytes)))
return FALSE;
return TRUE;
}
BYTE OpenFile(const char* filename)
{
DWORD FileFirstSector;
WORD Cluster;
////////////////////////////////////////////////////////////////////////
FileFirstSector=LocateFile(filename, &ApiFileControl);
if(FileFirstSector==0xffffffff)
return FALSE;
ApiFileControl.StartSectorNum = FileFirstSector;
Cluster=WordSwap(ApiFileControl.dir.FstClusLO);
for(;;)
{
if((GetListCluster(Cluster)==0xffff)||(Cluster==0))
break;
Cluster=GetListCluster(Cluster);
}
//ApiFileControl.CurrentSectorNum为该簇对应的第一个扇区
ApiFileControl.CurrentSectorNum = ClusterToSec(Cluster);
ApiFileControl.SectorOffset=(DWordSwap(ApiFileControl.dir.FileSize)%(SimpleBpb.BytsPerSec*SimpleBpb.SecPerClus));
ApiFileControl.dir.FileSize=DWordSwap(ApiFileControl.dir.FileSize);
return TRUE;
}
BYTE ReadFile(void* buffer, UINT bytes)
{
BYTE*pCache;
UINT read_bytes =0;
UINT max_copy_bytes_in_sector;
WORD Cluster,i;
DWORD FileSize;
// BYTE buf[600];
// for(i=0;i<600;i++)
// buf[i]='a';
// memcpy(buffer,buf,400);
// return TRUE;
////////////////////////////////////////////////////////////////////////
FileSize = ApiFileControl.dir.FileSize;
if(bytes>=FileSize)
bytes=FileSize;
Cluster=SecToCluster(ApiFileControl.CurrentSectorNum);
// Sector=ClusterToSec(Cluster);
ApiFileControl.SectorOffset=ApiFileControl.SectorOffset%(SimpleBpb.BytsPerSec*SimpleBpb.SecPerClus);
for(; ; )
{
pCache=BuffFile;
pCache+=ApiFileControl.SectorOffset;
if((SimpleBpb.BytsPerSec*SimpleBpb.SecPerClus - ApiFileControl.SectorOffset) > (bytes - read_bytes))
max_copy_bytes_in_sector = (bytes - read_bytes);
else
max_copy_bytes_in_sector=(SimpleBpb.BytsPerSec*SimpleBpb.SecPerClus - ApiFileControl.SectorOffset);
ApiFileControl.SectorOffset+=max_copy_bytes_in_sector;
if(!Read(ApiFileControl.CurrentSectorNum,SimpleBpb.SecPerClus,(BYTE *)BuffFile))
return FALSE;
memcpy((char *)buffer, pCache, max_copy_bytes_in_sector);
// return TRUE;
read_bytes+=max_copy_bytes_in_sector;
if(read_bytes>=bytes)
return TRUE;
buffer = (char*)buffer + max_copy_bytes_in_sector;
Cluster=GetListCluster(Cluster);
ApiFileControl.SectorOffset=0;
ApiFileControl.CurrentSectorNum=ClusterToSec(Cluster);
}//---------end for cycle
return FALSE;
}
BYTE CloseFile()
{
BYTE Cache[512];
struct _DIR *dir;
////////////////////////////////////////////////////////////////////////
if(ApiFileControl.SectorOffset!=0)
{
if(!Write(ApiFileControl.CurrentSectorNum,SimpleBpb.SecPerClus,(unsigned char *)BuffFile,TRUE))
if(!Write(ApiFileControl.CurrentSectorNum,SimpleBpb.SecPerClus,(unsigned char *)BuffFile,TRUE))
return FALSE;
}
DelayMs(50);
if(!Read(ApiFileControl.DirSectorNum,1,Cache))
if(!Read(ApiFileControl.DirSectorNum,1,Cache))
return FALSE;
dir = (struct _DIR *)Cache;
dir += ApiFileControl.DirIndex;
ApiFileControl.dir.FileSize=DWordSwap(ApiFileControl.dir.FileSize);
memcpy(dir, &ApiFileControl.dir, sizeof(struct _DIR));
DelayMs(50);
if(!Write(ApiFileControl.DirSectorNum,1,Cache,TRUE))
if(!Write(ApiFileControl.DirSectorNum,1,Cache,TRUE))
return FALSE;
if(FatCache[0][256]!=0)
{
if(!Write(FatCache[0][256],1,(BYTE *)FatCache[0],0))
if(!Write(FatCache[0][256],1,(BYTE *)FatCache[0],0))
return FALSE;
}
return TRUE;
}
BYTE SetFileSector(const char * filename,DWORD fileSector,DWORD offset)
{
DWORD FileFirstSector;
WORD Cluster;
////////////////////////////////////////////////////////////////////////
FileFirstSector=LocateFile(filename, &ApiFileControl);
if(FileFirstSector==0xffffffff)
return FALSE;
ApiFileControl.StartSectorNum = FileFirstSector;
Cluster=WordSwap(ApiFileControl.dir.FstClusLO);
for(;;)
{
if((GetListCluster(Cluster)==0xffff)||(Cluster==0))
break;
Cluster=GetListCluster(Cluster);
}
//ApiFileControl.CurrentSectorNum为该簇对应的第一个扇区
//扇区号移到到了该文件最后一簇的第一个扇区
if((ClusterToSec(Cluster))>=fileSector>=0)
ApiFileControl.CurrentSectorNum =fileSector;
else
return FALSE;
ApiFileControl.SectorOffset=offset;
// ApiFileControl.SectorOffset=(DWordSwap(ApiFileControl.dir.FileSize)%(SimpleBpb.BytsPerSec*SimpleBpb.SecPerClus));
ApiFileControl.dir.FileSize=DWordSwap(ApiFileControl.dir.FileSize);
return TRUE;
}
BYTE DisplayFile()
{
WORD i,j=0,k=0;
BYTE buf[512];
struct _DIR *dir;
for(i=0;iName[0] !='\0')
{
// buf=buf+32;
memcpy((BuffFile+k), (buf+j), 11);
j+=sizeof(struct _DIR);
k+=11;
}
else if(dir->Name[0]==0)
return TRUE;
}
}
return FALSE;
}
BYTE DelFile(const char * filename)
{
DWORD FileFirstSector;
BYTE buf[512];
WORD Cluster,Cache[256];
struct _DIR *dir;
FileFirstSector=LocateFile(filename, &ApiFileControl);
if(FileFirstSector==0xffffffff)
return FALSE;
dir=(struct _DIR *)buf;
if(!Read(ApiFileControl.DirSectorNum,1,buf))
return FALSE;
ApiFileControl.dir.Name[0]=0xe5;
dir=dir+ApiFileControl.DirIndex;
memcpy(dir,&ApiFileControl.dir,sizeof(struct _DIR));
if(!Write(ApiFileControl.DirSectorNum ,1,buf))
return FALSE;
Cluster=WordSwap(ApiFileControl.dir.FstClusLO);
if(!Read(((2*Cluster/SimpleBpb.BytsPerSec)+FatParameter.FirstFatSecNum),1,(BYTE *)Cache))
return FALSE;
for(;;)
{
// Cluster=GetListCluster(Cluster);
Cache[(Cluster%(SimpleBpb.BytsPerSec/2))]=0;
if((Cluster%(SimpleBpb.BytsPerSec/2))==0)
{
if(!Write((2*Cluster/SimpleBpb.BytsPerSec)+FatParameter.FirstFatSecNum,1,(BYTE *)Cache))
return FALSE;
if(!Read((2*Cluster/SimpleBpb.BytsPerSec)+FatParameter.FirstFatSecNum),1,(BYTE *)Cache)
return FALSE;
}
Cluster=GetListCluster(Cluster);
if((GetListCluster(Cluster)==0xffff)||(Cluster==0))
{
Cache[(Cluster%(SimpleBpb.BytsPerSec/2))]=0;
break;
}
}
if(!Write((2*Cluster/SimpleBpb.BytsPerSec)+FatParameter.FirstFatSecNum,1,(BYTE *)Cache))
return FALSE;
return TRUE;
}
BYTE CreateDir(const char * dirname)
{
BYTE Dotname[]={0X2E,0X20,0X20,0X20,0X20,0X20,0X20,0X20,0X20,0X20,0X20};
BYTE DotDotname[]={0x2e,0x2e,0X20,0X20,0X20,0X20,0X20,0X20,0X20,0X20,0X20};
WORD NewCluster,buf[256];
struct _DIR dir,*pdir;
BYTE temp[12],NewDirName[11],NewFileName[12],name[11],Cache[512],path[22],i;
BYTE * p=temp,*p1=NewFileName,*p2;
struct _FILE file;
////////////////////////////////////////////////////////////////////////
i=0;
memset(NewDirName,0,11);
strcpy(path, dirname);
while(path[i]!='\\')
{
NewDirName[i]=path[i];
i++;
if(i>=strlen(dirname))
break;
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
//核对目录名是否正确
if(!CheckFileName(NewDirName,p))
return FALSE;
//*核对该目录是否已经存在
if(LocateFile(NewDirName, NULL)!=0xffffffff)
return FALSE;
strncpy(name, p, 11);
memset(&dir, 0, sizeof(dir));
memcpy(dir.Name, name, 11);
//定位该目录并获取必要信息
if(!LocateDir(&dir,&file))
return FALSE;
//为该目录寻找一个空簇
NewCluster= SeekEmptyCluster();
if(NewCluster==0xffff)
return FALSE;
//在FAT里标记该簇
if(!Read((2*NewCluster/SimpleBpb.BytsPerSec)+FatParameter.FirstFatSecNum,1,(BYTE *)buf))
return FALSE;
buf[NewCluster%(SimpleBpb.BytsPerSec/2)]=0xfffff;
if(!Write((2*NewCluster/SimpleBpb.BytsPerSec)+FatParameter.FirstFatSecNum,1,(BYTE *)buf))
return FALSE;
DelayMs(15);
//Root dir
if(!Read(file.DirSectorNum,1,(BYTE *)Cache))
return FALSE;
pdir = (struct _DIR *)Cache;
pdir += file.DirIndex;
pdir->FstClusLO =WordSwap(NewCluster);
pdir->FileSize=0;
pdir->Attr=ATTR_DIRECTORY;
if(!Write(file.DirSectorNum,1,Cache,TRUE))
if(!Write(file.DirSectorNum,1,Cache,TRUE))
return FALSE;
// dot dir
memset(Cache,0,512);
pdir = (struct _DIR *)Cache;
memset(pdir, 0, sizeof(dir));
pdir->Attr=ATTR_DIRECTORY;
pdir->FstClusLO=WordSwap(NewCluster);
memcpy(pdir->Name, Dotname, 11);
// dot dot dir;
pdir++;
memcpy(pdir->Name, DotDotname, 11);
pdir->FstClusLO=0;
for(i=0;iName[0]=='\0')
{
memcpy((BYTE *)pdir->Name,name,11);
if(!Write(ClusterToSec(NewCluster)+i,1,Cache))
return FALSE;
// memcpy(&ApiFileControl.dir.Name,name,11);
memcpy(&ApiFileControl.dir,pdir,sizeof(struct _DIR));
ApiFileControl.StartSectorNum=ClusterToSec(WordSwap(pdir->FstClusLO));
ApiFileControl.SectorOffset=0;
ApiFileControl.DirSectorNum=ClusterToSec(NewCluster)+i;
//ApiFileControl.isDir=1;
// ApiFileControl.dir.FileSize=0;
ApiFileControl.DirIndex = ((BYTE*)pdir - Cache)/sizeof(struct _DIR);
return TRUE;
}
pdir++;
}
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
//*所有测试工作从这里开始
BYTE ApiDemo(void)
{
BYTE buf[5120],buf1[1024],buf2[1024];
WORD i;
////////////////////////////////////////////////////////////////////////
PollDisk(); //首先配置U盘:获取它的基本信息,测试盘是否已经准备好
//DemlayMs(100); //根据不同情况需要延迟同的时间。
InitFsys(); //读取FAT信息然,初始化必要的FAT参数
//************************************************************************
//////////////////////////////////////////////////////////////////////////
//
//去调注释线,打开下函数设置断点是可测试创建文件
// if(!CreatFile("demo.txt",0x20))
// return FALSE;
//
///////////////////////////////////////////////////////////////////////////
// if(!OpenFile("demo.txt"))
// return FALSE;
//************************************************************************
//测试一:创建一个空文件
//
//去调注释线,打开下函数设置断点是可测试创建文件
// if(!CreatFile("demo.txt",0x20))
// return FALSE;
//////////////////////////////////////////////////////////////////////////
//************************************************************************
//测试二:创建文件demo.txt并写上少量数据
//
// for(i=0;i<5120;i++)
// buf[i]='j';
// if(!CreateFile("demo.txt",0x20))
// return FALSE;
// if(!WriteFile(buf,1000))
// return FALSE;
// if(!CloseFile())
// return FALSE;
/////////////////////////////////////////////////////////////////////////////
//**************************************************************************
//测试三:写大批量数据
// for(i=0;i<5120;i++)
// buf[i]='c';
// if(!CreateFile("demo.txt",0x20))
// return FALSE;
// for(i=0;i<5;i++)
// if(!WriteFile(buf,1000))
// return FALSE;
// if(!CloseFile())
// return FALSE;
///////////////////////////////////////////////////////////////////////////
//**************************************************************************
//测试四:打开一个文件并在文件后面接着写上一些少量数据可以精确到到字节
//
// for(i=0;i<5120;i++)
// buf[i]='c';
// if(!OpenFile("demo.txt"))
// return FALSE;
// if(!AddWriteFile(buf,1024))
// return FALSE;
// if(!CloseFile())
// return FALSE;
/////////////////////////////////////////////////////////////////////
//**************************************************************************
//测试五:打开一个文件并在文件后面接着写上大量数据可以精确到到字节
//
// for(i=0;i<2048;i++)
// buf[i]='h';
// if(!OpenFile("demo.txt"))
// return FALSE;
// if(!AddWriteFile(buf,1024))
// return FALSE;
// for(i=0;i<2048;i++)
// buf[i]='j';
// for(i=0;i<10;i++)
// if(!WriteFile(buf,1000))
// return FALSE;
// if(!CloseFile())
// return FALSE;
//////////////////////////////////////////////////////////////////////////////
//***************************************************************************
//测试六:打开一个文件并读取数量到缓存buf
//
// if(!OpenFile("demo.txt"))
// return FALSE;
// ApiFileControl.CurrentSectorNum=ApiFileControl.StartSectorNum;
// ApiFileControl.SectorOffset=0;
// if(!ReadFile(buf,500))
// return FALSE;
//////////////////////////////////////////////////////////////////////////////
//****************************************************************************
//测试七:打开一个大文件文件并读取数量到到多个buf
//
// if(!OpenFile("demo.txt"))
// return FALSE;
// ApiFileControl.CurrentSectorNum=ApiFileControl.StartSectorNum;
// ApiFileControl.SectorOffset=0;
// if(!ReadFile(buf1,500))
// return FALSE;
// if(!ReadFile(buf2,500))
// return FALSE;
///////////////////////////////////////////////////////////////////////////////
//****************************************************************************
//测试八:显示U盘的文件,执行完后请看全局变量BuffFile里的值
// if(!DisplayFile())
// return FALSE;
///////////////////////////////////////////////////////////////////////////
//***************************************************************************
//测试:九删除指定的文件
// if(!DelFile("demo.txt"))
// return FALSE;
///////////////////////////////////////////////////////////////////////////////
//**************************************************************************
//测试十:创建一个目录
// if(!CreateDir("demot"))
// return FALSE;
///////////////////////////////////////////////////////////////////////////////
//********************************************************************************
//测试十一:创建一个目录同时创建好一个空文件
// if(!CreateDir("www\\demo.txt"))
// return FALSE;
////////////////////////////////////////////////////////////////////////////////////
//***********************************************************************************
//测试十二:创建好一个目录同时创建一个文件并写上数据
// for(i=0;i<5120;i++)
// buf[i]='c';
// if(!CreateDir("www\\demo.txt"))
// return FALSE;
// if(!WriteFile(buf,666))
// return FALSE;
// if(!CloseFile())
// return FALSE;
return TRUE;
}
//************************************************************************
//author:dragon
//web:8dragon.com
//2004.2.5完成于桃龙源
//*************************************************************************