📄 rio.cpp
字号:
{
CDirHeader& cDirHeader = m_cDirBlock.m_cDirHeader;
// init directory header
memset( &m_cDirBlock.m_cDirHeader, 0, sizeof(m_cDirBlock.m_cDirHeader) );
// set version (so compatible with Rio Manager v1.01)
cDirHeader.m_usVersion = 0x0100;
// init directory entries
memset( &m_cDirBlock.m_acDirEntry, 0, sizeof(m_cDirBlock.m_acDirEntry) );
// init block used flags
memset( &m_cDirBlock.m_auc32KBlockUsed, CRIO_ID_32KBLOCK_FREE, sizeof(m_cDirBlock.m_auc32KBlockUsed) );
// init FAT
memset( &m_cDirBlock.m_ausFAT, 0, sizeof(m_cDirBlock.m_ausFAT) );
// if mark bad block request
if ( bMarkBadBlock )
{
if ( !MarkBadBlocks(pfProgress, cookie) )
return FALSE;
}
// available blocks
if ( m_bUseExternalFlash )
cDirHeader.m_usCount32KBlockAvailable = m_uiCount32KBlockAvailableExternal;
else
cDirHeader.m_usCount32KBlockAvailable = m_bSpecialEdition ? CRIO_COUNT_32KBLOCKIN64M : CRIO_COUNT_32KBLOCKIN32M;
// blocks remaining (taking into account bad blocks)
cDirHeader.m_usCount32KBlockRemaining =
cDirHeader.m_usCount32KBlockAvailable -
cDirHeader.m_usCount32KBlockBad;
return TRUE;
}
BOOL CRio::RemoveFile( const char* pszFile )
{
// get directory entry for file
CDirEntry* pDirEntry = FindFile( pszFile );
if ( !pDirEntry )
{
LogError( CRIO_ERROR_FILENOTFOUND, "file '%s' not present on device", pszFile );
return FALSE;
}
// free FAT and blocks used
USHORT usPos32KBlock = pDirEntry->m_usPos32KBlock;
while( usPos32KBlock )
{
m_cDirBlock.m_auc32KBlockUsed[ usPos32KBlock ] = CRIO_ID_32KBLOCK_FREE;
USHORT usTemp = m_cDirBlock.m_ausFAT[ usPos32KBlock ];
m_cDirBlock.m_ausFAT[ usPos32KBlock ] = 0;
usPos32KBlock = usTemp;
}
// adjust directory header
CDirHeader& cDirHeader = m_cDirBlock.m_cDirHeader;
--cDirHeader.m_usCountEntry;
cDirHeader.m_usCount32KBlockUsed -= pDirEntry->m_usCount32KBlock;
cDirHeader.m_usCount32KBlockRemaining += pDirEntry->m_usCount32KBlock;
// clear directory entry
memset( pDirEntry, 0, sizeof(CDirEntry) );
// shuffle directory entries
int iPosEntry = pDirEntry - m_cDirBlock.m_acDirEntry;
int iCount = (int)cDirHeader.m_usCountEntry - iPosEntry;
for( int iA=0; iA<iCount; ++iA )
{
memcpy(
&m_cDirBlock.m_acDirEntry[ iPosEntry+iA ],
&m_cDirBlock.m_acDirEntry[ iPosEntry+iA+1 ],
sizeof(CDirEntry)
);
}
return TRUE;
}
BOOL CRio::RemoveAllFiles( void )
{
CDirHeader& cDirHeader = m_cDirBlock.m_cDirHeader;
// init entries
cDirHeader.m_usCountEntry = 0;
// init block used flags
UCHAR* pauc = m_cDirBlock.m_auc32KBlockUsed;
for( int iA=0; iA<CRIO_MAX_32KBLOCK; ++iA, ++pauc )
{
if ( *pauc != CRIO_ID_32KBLOCK_BAD )
*pauc = CRIO_ID_32KBLOCK_FREE;
}
// init FAT
memset( &m_cDirBlock.m_ausFAT, 0, sizeof(m_cDirBlock.m_ausFAT) );
// available blocks
if ( m_bUseExternalFlash )
cDirHeader.m_usCount32KBlockAvailable = m_uiCount32KBlockAvailableExternal;
else
cDirHeader.m_usCount32KBlockAvailable = m_bSpecialEdition ? CRIO_COUNT_32KBLOCKIN64M : CRIO_COUNT_32KBLOCKIN32M;
// used
cDirHeader.m_usCount32KBlockUsed = cDirHeader.m_usCount32KBlockBad;
// blocks remaining
cDirHeader.m_usCount32KBlockRemaining =
cDirHeader.m_usCount32KBlockAvailable -
cDirHeader.m_usCount32KBlockUsed;
return TRUE;
}
BOOL CRio::SetFileOrder( UINT* pauiPosOrder, UINT uiCount )
{
// create copy of directory entries
CDirEntry* paDirEntry = m_cDirBlock.m_acDirEntry;
CDirEntry* paDirEntryNew = new CDirEntry[ CRIO_MAX_DIRENTRY ];
if ( !paDirEntryNew )
{
LogError( CRIO_ERROR_ALLOC, "new failed" );
return FALSE;
}
memcpy( paDirEntryNew, paDirEntry, CRIO_MAX_DIRENTRY * sizeof(CDirEntry) );
// current entry count
UINT uiCountEntry = m_cDirBlock.m_cDirHeader.m_usCountEntry;
// move entries
for( UINT uiPosNew=0; uiPosNew<uiCount; ++uiPosNew )
{
UINT uiPosOld = pauiPosOrder[ uiPosNew ];
if ( uiPosOld >= uiCountEntry || uiPosNew >= uiCountEntry )
{
LogError( CRIO_ERROR_INVALIDFILEPOSITION, "invalid file position" );
DELETEARRAY paDirEntryNew;
return FALSE;
}
memcpy( &paDirEntryNew[uiPosNew], &paDirEntry[uiPosOld], sizeof(CDirEntry) );
}
// update current directory entries
memcpy( paDirEntry, paDirEntryNew, CRIO_MAX_DIRENTRY * sizeof(CDirEntry) );
DELETEARRAY paDirEntryNew;
return TRUE;
}
BOOL CRio::TxDirectory( void )
{
// create zero initialized temp block
UCHAR* paucBlock;
ZERONEWBLOCK( paucBlock );
// directory header
CDirHeader& cDirHeader = m_cDirBlock.m_cDirHeader;
// update directory header time
cDirHeader.m_lTimeLastUpdate = time( NULL );
// create checksums (note: second checksum needs to be calculated first as
// this makes up part of the first checksum)
cDirHeader.m_usChecksum2 = CalculateChecksum2();
cDirHeader.m_usChecksum1 = CalculateChecksum1();
// copy directory block to temp block
memcpy( paucBlock, &m_cDirBlock, sizeof(m_cDirBlock) );
// send block
BOOL bResult = Tx32KBlock( paucBlock, 0, 0, 0 );
if ( bResult )
{
// IO outro
IOOutro();
}
// release temp block
DELETEBLOCK( paucBlock );
return bResult;
}
BOOL CRio::RxDirectory( void )
{
// create temp block
UCHAR* paucBlock;
NEWBLOCK( paucBlock );
// get block
BOOL bResult = Rx32KBlock( paucBlock, 0 );
if ( bResult )
{
// io outro
IOOutro();
// store directory
memcpy( &m_cDirBlock, paucBlock, sizeof(m_cDirBlock) );
// validate checksums
USHORT usChecksum1 = (USHORT)CalculateChecksum1();
USHORT usChecksum2 = (USHORT)CalculateChecksum2();
if (
usChecksum1 != m_cDirBlock.m_cDirHeader.m_usChecksum1 ||
usChecksum2 != m_cDirBlock.m_cDirHeader.m_usChecksum2
)
{
LogError( CRIO_ERROR_CORRUPT, "invalid directory checksum, initialization recommended" );
bResult = FALSE;
}
}
// release temp block
DELETEBLOCK( paucBlock );
return bResult;
}
BOOL CRio::TxFile( const char* pszPathFile, BOOL (*pfProgress)(int iPos, int iCount, void* cookie), void* cookie)
{
// directory header
CDirHeader& cDirHeader = m_cDirBlock.m_cDirHeader;
// if no enough room in directory for entry
if ( cDirHeader.m_usCountEntry >= CRIO_MAX_DIRENTRY )
{
LogError( CRIO_ERROR_MAXDIRENTRY, "max number of directory entries (%d) already in use", CRIO_MAX_DIRENTRY );
return FALSE;
}
// open file for read
FILE* fpFile = fopen( pszPathFile, "rb" );
if ( !fpFile )
{
LogError( CRIO_ERROR_OPEN, "unable to open '%s' for read", pszPathFile );
return FALSE;
}
// get fileinfo
struct stat sStat;
if ( stat(pszPathFile, &sStat) )
{
LogError( CRIO_ERROR_STAT, "stat() failed for '%s'", pszPathFile );
fclose( fpFile );
return FALSE;
}
// determine if enough room to store file
USHORT usCount32KBlock = (sStat.st_size/CRIO_SIZE_32KBLOCK) +
(sStat.st_size % CRIO_SIZE_32KBLOCK ? 1 : 0);
if ( usCount32KBlock > cDirHeader.m_usCount32KBlockRemaining )
{
LogError( CRIO_ERROR_MEMORY, "not enough memory on device to upload '%s'", pszPathFile );
fclose( fpFile );
return FALSE;
}
// get first four bytes of file which determine mp3 properties
UCHAR aucProperty[ 4 ];
if ( fread(aucProperty, sizeof(aucProperty), 1, fpFile) < 1 )
{
LogError( CRIO_ERROR_READ, "error reading from file '%s'", pszPathFile );
fclose( fpFile );
return FALSE;
}
rewind( fpFile );
// point to directory entry that will be used
CDirEntry& cDirEntry = m_cDirBlock.m_acDirEntry[ cDirHeader.m_usCountEntry ];
// update directory header
if ( !cDirHeader.m_usCountEntry )
{
// adjust for dir block
++cDirHeader.m_usCount32KBlockUsed;
--cDirHeader.m_usCount32KBlockRemaining;
// mark first block as used by directory
m_cDirBlock.m_auc32KBlockUsed[ 0 ] = CRIO_ID_32KBLOCK_USED;
// first entry in FAT used by directory
m_cDirBlock.m_ausFAT[ 0 ] = 0;
}
++cDirHeader.m_usCountEntry;
cDirHeader.m_usCount32KBlockUsed += usCount32KBlock;
cDirHeader.m_usCount32KBlockRemaining -= usCount32KBlock;
// find first free 32K block
USHORT usPos32KBlockFree = FindFirstFree32KBlock();
if ( usPos32KBlockFree == 0xffff )
{
LogError( CRIO_ERROR_CORRUPT, "no free 32K blocks, initialization recommended" );
fclose( fpFile );
return FALSE;
}
// update directory entry
memset( &cDirEntry, 0, sizeof(CDirEntry) );
cDirEntry.m_usPos32KBlock = usPos32KBlockFree;
cDirEntry.m_usCount32KBlock = usCount32KBlock;
cDirEntry.m_usSize32KMod = sStat.st_size % CRIO_SIZE_32KBLOCK;
cDirEntry.m_lSize = sStat.st_size;
cDirEntry.m_lTimeUpload = time( NULL );
cDirEntry.m_aucProperty[ 0 ] = aucProperty[ 3 ];
cDirEntry.m_aucProperty[ 1 ] = aucProperty[ 2 ];
cDirEntry.m_aucProperty[ 2 ] = aucProperty[ 1 ];
cDirEntry.m_aucProperty[ 3 ] = aucProperty[ 0 ];
strncpy( cDirEntry.m_szName, GetFile(pszPathFile), sizeof(cDirEntry.m_szName) );
// create zero initialized temp block
UCHAR* paucBlock;
ZERONEWBLOCK( paucBlock );
// default return
BOOL bResult = FALSE;
// process all 32K blocks of file
USHORT usPos32KBlockCurrent = cDirEntry.m_usPos32KBlock;
USHORT usPos32KBlockPrev = 0xffff;
USHORT usPos32KBlockEnd = cDirEntry.m_usCount32KBlock;
USHORT usPos32KBlockNext;
USHORT usPos32KBlock;
for( usPos32KBlock=0; usPos32KBlock<usPos32KBlockEnd; ++usPos32KBlock )
{
// progress callback
if ( pfProgress )
{
if ( !pfProgress(usPos32KBlock, usPos32KBlockEnd, cookie) )
{
LogError( CRIO_ERROR_INTERRUPTED, "operation interrupted" );
break;
}
}
// mark as block used
m_cDirBlock.m_auc32KBlockUsed[ usPos32KBlockCurrent ] = CRIO_ID_32KBLOCK_USED;
// get next block and update FAT
if ( usPos32KBlock == (usPos32KBlockEnd-1) )
{
usPos32KBlockNext = 0xffff;
m_cDirBlock.m_ausFAT[ usPos32KBlockCurrent ] = 0;
}
else
{
usPos32KBlockNext = FindFirstFree32KBlock();
if ( usPos32KBlockNext == 0xffff )
{
LogError( CRIO_ERROR_CORRUPT, "no free 32K blocks, initialization recommended" );
break;
}
m_cDirBlock.m_ausFAT[ usPos32KBlockCurrent ] = usPos32KBlockNext;
}
// determine read size
UINT uiSize;
if ( usPos32KBlock == (usPos32KBlockEnd-1) && cDirEntry.m_usSize32KMod )
{
uiSize = cDirEntry.m_usSize32KMod;
memset( paucBlock+uiSize, 0, CRIO_SIZE_32KBLOCK-uiSize );
}
else
uiSize = CRIO_SIZE_32KBLOCK;
// read block
if ( fread(paucBlock, uiSize, 1, fpFile) < 1 )
{
LogError( CRIO_ERROR_READ, "error reading from file '%s'", pszPathFile );
break;
}
// tx block
if ( !Tx32KBlock(paucBlock, usPos32KBlockCurrent, usPos32KBlockPrev,
usPos32KBlockNext) )
break;
// update current and prev block markers
usPos32KBlockPrev = usPos32KBlockCurrent;
usPos32KBlockCurrent = usPos32KBlockNext;
}
// if transfer ok
if ( usPos32KBlock == usPos32KBlockEnd )
{
// flag as ok
bResult = TRUE;
// IO outro
IOOutro();
}
// release temp block
DELETEBLOCK( paucBlock );
// close file
fclose( fpFile );
return bResult;
}
BOOL CRio::RxFile( const char* pszPathFile, BOOL (*pfProgress)(int iPos, int iCount, void* cookie), void* cookie)
{
// get directory entry for file
const char* pszFile = GetFile( pszPathFile );
CDirEntry* pDirEntry = FindFile( pszFile );
if ( !pDirEntry )
{
LogError( CRIO_ERROR_FILENOTFOUND, "file '%s' not present on device", pszFile );
return FALSE;
}
// open file for write
FILE* fpFile = fopen( pszPathFile, "wb" );
if ( !fpFile )
{
LogError( CRIO_ERROR_OPEN, "unable to open '%s' for write", pszPathFile );
return FALSE;
}
// create temp block
UCHAR* paucBlock;
NEWBLOCK( paucBlock );
// default return
BOOL bResult = FALSE;
// get all blocks
USHORT usPos32KBlockCurrent = pDirEntry->m_usPos32KBlock;
USHORT usPos32KBlockEnd = pDirEntry->m_usCount32KBlock;
USHORT usPos32KBlock;
for( usPos32KBlock=0; usPos32KBlock<usPos32KBlockEnd; ++usPos32KBlock )
{
// progress callback
if ( pfProgress )
{
if ( !pfProgress(usPos32KBlock, usPos32KBlockEnd, cookie) )
{
LogError( CRIO_ERROR_INTERRUPTED, "operation interrupted" );
break;
}
}
// rx block
if ( !Rx32KBlock(paucBlock, usPos32KBlockCurrent) )
break;
// determine write size
int iSizeWrite;
if ( usPos32KBlock == (usPos32KBlockEnd-1) && pDirEntry->m_usSize32KMod )
iSizeWrite = pDirEntry->m_usSize32KMod;
else
iSizeWrite = CRIO_SIZE_32KBLOCK;
// save block
if ( fwrite(paucBlock, iSizeWrite, 1, fpFile) < 1 )
{
LogError( CRIO_ERROR_WRITE, "error writing to file '%s'", pszPathFile );
break;
}
// next block
usPos32KBlockCurrent = m_cDirBlock.m_ausFAT[ usPos32KBlockCurrent ];
}
// if transfer ok
if ( usPos32KBlock == usPos32KBlockEnd )
{
// flag as ok
bResult = TRUE;
// IO outro
IOOutro();
}
// release temp block
DELETEBLOCK( paucBlock );
// close file
fclose( fpFile );
return bResult;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -