/**
******************************************************************************
* File Name : exfuns.c
* Description : This file provides code for the configuration
* of the External Functions instances.
******************************************************************************
* @attention
*
*
© Copyright (c) 2019 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include
#include "malloc.h"
#include "exfuns.h"
//#include "fattester.h"
#include "usart.h"
#define FILE_MAX_TYPE_NUM 7 //Most FILE_MAX_TYPE_NUM categories
#define FILE_MAX_SUBT_NUM 4 //Up to FILE_MAX_SUBT_NUM a small class
//File types list
char * const FILE_TYPE_TBL[FILE_MAX_TYPE_NUM][FILE_MAX_SUBT_NUM]=
{
{"BIN"}, //BIN file
{"LRC"}, //LRC files
{"NES"}, //NES file
{"TXT","C","H"}, //Text file
{"WAV","MP3","APE","FLAC"},//Supported music files
{"BMP","JPG","JPEG","GIF"},//Picture files
{"AVI"}, //Video file
};
///////////////////////////////Public files area, when using the malloc////////////////////////////////////////////
FATFS *fs[_VOLUMES]; //Logical disk.
FIL *file; //File 1
FIL *ftemp; //File 2.
UINT br,bw; //Read and write variables
FILINFO fileinfo; //File information
DIR dir; //Directory
uint8_t *fatbuf; //SD card data buffer
///////////////////////////////////////////////////////////////////////////////////////
//Exfuns for the memory
//Return values: 0-success
// 1 failure
uint8_t exfuns_init(void)
{
uint8_t i;
for (i = 0; i < _VOLUMES; i++)
{
fs[i] = (FATFS*)mymalloc(sizeof(FATFS)); //Applications for disk I workspace memory
if (!fs[i]) break;
}
file = (FIL*)mymalloc(sizeof(FIL)); //Applications for file memory
ftemp = (FIL*)mymalloc(sizeof(FIL)); //Ftemp application memory
fatbuf = (uint8_t*) mymalloc(512); //Fatbuf for the memory
if (i == _VOLUMES && file && ftemp && fatbuf) return 0; //Success
else return 1; //Failed
}
//Lowercase letters to uppercase letters if numbers remained unchanged.
uint8_t char_upper(uint8_t c)
{
if (c < 'A') return c; //Numbers remain the same.
if (c >= 'a') return c - 0x20; //Uppercase.
else return c; //Capital, remains unchanged
}
//Report file type
//Fname: file name
//Return value: 0XFF, said it could not identify the type of file number.
// Other four member categories, low said four member categories.
uint8_t f_typetell(uint8_t *fname)
{
uint8_t tbuf[5];
uint8_t *attr = (uint8_t*)'\0';//Extension name
uint8_t i=0,j;
while(i<250)
{
i++;
if(*fname=='\0')break;//Offset at the end of the.
fname++;
}
if(i==250)return 0XFF;//Error string.
for(i=0;i<5;i++)//Get extension
{
fname--;
if(*fname=='.')
{
fname++;
attr=fname;
break;
}
}
strcpy((char *)tbuf,(const char*)attr);//copy
for(i=0;i<4;i++)tbuf[i]=char_upper(tbuf[i]);//All uppercase
for(i=0;in_fatent-2)*fs1->csize; //Total number of sectors
fre_sect=fre_clust*fs1->csize; //Get number of spare sectors
#if _MAX_SS!=512 //Sector size other than 512 bytes, then the conversion is 512 bytes
tot_sect*=fs1->ssize/512;
fre_sect*=fs1->ssize/512;
#endif
*total=tot_sect>>1; //Unit is KB
*free=fre_sect>>1; //Unit is KB
}
return res;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//File replication
//Note the file size should not exceed 4GB.
//The pSrc file, copy to pdst.
//fcpymsg,A function pointer to implement copy information display
// pname:File/folder name
// pct:Percentage
// mode:
// [0]:Update file name
// [1]:Update percentage of PCT
// [2]:Update folder
// [3~7]:Reservation
//psrc,pdst:Source and target files
//totsize:Total size (when totsize 0 when says just to copy a single file)
//cpdsize:The size of replicated.
//fwmode:File in write mode
//0:Do not overwrite existing file
//1:Overwrite the original file
//Return values: 0 normal,
// Other, errors, 0XFF, force quit
uint8_t exf_copy(uint8_t(*fcpymsg)(uint8_t*pname,uint8_t pct,uint8_t mode),uint8_t *psrc,uint8_t *pdst,uint32_t totsize,uint32_t cpdsize,uint8_t fwmode)
{
uint8_t res;
uint16_t br=0;
uint16_t bw=0;
FIL *fsrc=0;
FIL *fdst=0;
uint8_t *fbuf=0;
uint8_t curpct=0;
fsrc=(FIL*)mymalloc(sizeof(FIL));//For the memory
fdst=(FIL*)mymalloc(sizeof(FIL));
fbuf=(uint8_t *)mymalloc(8192);
if(fsrc==NULL||fdst==NULL||fbuf==NULL)res=100;//Front left fatfs
else
{
if(fwmode==0)fwmode=FA_CREATE_NEW;//Do not overwrite
else fwmode=FA_CREATE_ALWAYS; //Overwrite the existing file
res=f_open(fsrc,(const TCHAR*)psrc,FA_READ|FA_OPEN_EXISTING); //Open a read-only file
if(res==0)res=f_open(fdst,(const TCHAR*)pdst,FA_WRITE|fwmode); //First open success, began to open the second
if(res==0)//Both open succeeded
{
if(totsize==0)//Only is a single file copy
{
totsize=fsrc->obj.objsize;
cpdsize=0;
curpct=0;
}else curpct=(cpdsize*100)/totsize; //Percentage of new
fcpymsg(psrc,curpct,0X02); //Update percentage
while(res==0)//Start copying
{
res=f_read(fsrc,fbuf,8192,(UINT*)&br); //The source read 512 bytes
if(res||br==0)break;
res=f_write(fdst,fbuf,(UINT)br,(UINT*)&bw); //Write destination file
cpdsize+=bw;
if(curpct!=(cpdsize*100)/totsize)//Do you need to update the percentage
{
curpct=(cpdsize*100)/totsize;
if(fcpymsg(psrc,curpct,0X02))//Update percentage
{
res=0XFF;//Force quit
break;
}
}
if(res||bw
fsize = _MAX_LFN * 2 + 1;
pathname = mymalloc(MAX_PATHNAME_DEPTH);
if(finfo->fname == NULL || pathname == NULL) res=101;
if(res==0)
{
pathname[0]=0;
strcat((char*)pathname,(const char*)fdname); //Copy path
res=f_opendir(fddir,(const TCHAR*)fdname); //Open source directory
if(res==0)//Open Directory successfully
{
while(res==0)//Start copying folders inside stuff
{
res=f_readdir(fddir,finfo); //Read a file directory
if(res!=FR_OK||finfo->fname[0]==0)break; //Errors/to the end of the exit
if(finfo->fname[0]=='.')continue; //Ignoring superior directory
if(finfo->fattrib&0X10)//Is the subdirectory (file attributes, 0X20, archive; 0X10, subdirectories;)
{
fn=(uint8_t*)(finfo->fname);//Get file name
pathlen=strlen((const char*)pathname); //Get the current path length
strcat((char*)pathname,(const char*)"/"); //Add a slash
strcat((char*)pathname,(const char*)fn); //Source path and directory name
//printf("\r\nsub folder:%s\r\n",pathname); //Print a directory name
fdsize+=exf_fdsize(pathname); //Get directory size, recursive calls
pathname[pathlen]=0; //Join the terminator
}
else fdsize+=finfo->fsize; //Non-catalog direct plus the size of the file
}
}
myfree(pathname);
}
}
myfree(fddir);
myfree(finfo);
if(res)return 0;
else return fdsize;
}
//Folder replication
//Note the folder size not to exceed 4GB.
//The pSrc folder, copy to pdst folder.
//Pdst: must be shaped like "x:"/"X:XX"/"X:XX/XX" or something like that. but also the confirm folder one level up
//Fcpymsg, function pointer, used to implement a copy of information display
// pname:File/folder name
// pct:Percentage
// mode:
// [0]:Update file name
// [1]:Update percentage of PCT
// [2]:Update folder
// [3~7]:Reservation
//psrc,pdst:Source and destination folders
//totsize:Total size (when totsize 0 when says just to copy a single file)
//cpdsize:Total size of the copied.
//fwmode:File in write mode
//0:Do not overwrite existing file
//1:Overwrite the original file
//Return values: 0-success
// Other error code 0XFF, a forced exit
uint8_t exf_fdcopy(uint8_t(*fcpymsg)(uint8_t*pname,uint8_t pct,uint8_t mode),uint8_t *psrc,uint8_t *pdst,uint32_t *totsize,uint32_t *cpdsize,uint8_t fwmode)
{
#define MAX_PATHNAME_DEPTH 512+1 //Maximum depth of target file path + file name
uint8_t res=0;
DIR *srcdir=0; //The source directory
DIR *dstdir=0; //The destination directory
FILINFO *finfo=0; //File information
uint8_t *fn=0; //Long file names
uint8_t * dstpathname=0; //destination folder path + file name
uint8_t * srcpathname=0; //Source folder path + filename
uint16_t dstpathlen=0; //Destination path length
uint16_t srcpathlen=0; //Source path length
srcdir=(DIR*)mymalloc(sizeof(DIR));//For the memory
dstdir=(DIR*)mymalloc(sizeof(DIR));
finfo=(FILINFO*)mymalloc(sizeof(FILINFO));
if(srcdir==NULL||dstdir==NULL||finfo==NULL)res=100;
if(res==0)
{
finfo->fsize=_MAX_LFN*2+1;
dstpathname=mymalloc(MAX_PATHNAME_DEPTH);
srcpathname=mymalloc(MAX_PATHNAME_DEPTH);
if(finfo->fname==NULL||dstpathname==NULL||srcpathname==NULL)res=101;
if(res==0)
{
dstpathname[0]=0;
srcpathname[0]=0;
strcat((char*)srcpathname,(const char*)psrc); //A copy of the original source file path
strcat((char*)dstpathname,(const char*)pdst); //A copy of the original target file path
res=f_opendir(srcdir,(const TCHAR*)psrc); //Open source directory
if(res==0)//Open Directory successfully
{
strcat((char*)dstpathname,(const char*)"/");//Join slash
fn=exf_get_src_dname(psrc);
if(fn==0)//Label copy
{
dstpathlen=strlen((const char*)dstpathname);
dstpathname[dstpathlen]=psrc[0]; //Record label
dstpathname[dstpathlen+1]=0; //Terminator
}
else strcat((char*)dstpathname,(const char*)fn);//Add filename
fcpymsg(fn,0,0X04);//Update the folder name
res=f_mkdir((const TCHAR*)dstpathname);//If the folder already exists, is not created. create a new folder if it does not exist.
if(res==FR_EXIST)res=0;
while(res==0)//Start copying folders inside stuff
{
res=f_readdir(srcdir,finfo); //Read a file directory
if(res!=FR_OK||finfo->fname[0]==0)break; //Errors/to the end of the exit
if(finfo->fname[0]=='.')continue; //Ignoring superior directory
fn=(uint8_t*)(finfo->fname); //Get file name
dstpathlen=strlen((const char*)dstpathname); //Get the length of the path to the current target
srcpathlen=strlen((const char*)srcpathname); //Get the source path length
strcat((char*)srcpathname,(const char*)"/");//Source path in slash
if(finfo->fattrib&0X10)//Is the subdirectory (file attributes, 0X20, archive; 0X10, subdirectories;)
{
strcat((char*)srcpathname,(const char*)fn); //Source path and directory name
res=exf_fdcopy(fcpymsg,srcpathname,dstpathname,totsize,cpdsize,fwmode); //Copy folder
}
else //Non-catalog
{
strcat((char*)dstpathname,(const char*)"/");//Target path in slash
strcat((char*)dstpathname,(const char*)fn); //Destination path and file name
strcat((char*)srcpathname,(const char*)fn); //Source path and file name
fcpymsg(fn,0,0X01);//Update file name
res=exf_copy(fcpymsg,srcpathname,dstpathname,*totsize,*cpdsize,fwmode);//Copy the files
*cpdsize+=finfo->fsize;//Add a file size
}
srcpathname[srcpathlen]=0;//Join the terminator
dstpathname[dstpathlen]=0;//Join the terminator
}
}
myfree(dstpathname);
myfree(srcpathname);
}
}
myfree(srcdir);
myfree(dstdir);
myfree(finfo);
return res;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////