static FF_ERROR FF_ReadClusters(FF_FILE *pFile, FF_T_UINT32 Count, FF_T_UINT8 *buffer) { FF_T_UINT32 ulSectors; FF_T_UINT32 SequentialClusters = 0; FF_T_UINT32 nItemLBA; FF_T_SINT32 slRetVal; FF_ERROR Error; while(Count != 0) { if((Count - 1) > 0) { SequentialClusters = FF_GetSequentialClusters(pFile->pIoman, pFile->AddrCurrentCluster, (Count - 1), &Error); if(Error) { return Error; } } ulSectors = (SequentialClusters + 1) * pFile->pIoman->pPartition->SectorsPerCluster; nItemLBA = FF_Cluster2LBA(pFile->pIoman, pFile->AddrCurrentCluster); nItemLBA = FF_getRealLBA(pFile->pIoman, nItemLBA); slRetVal = FF_BlockRead(pFile->pIoman, nItemLBA, ulSectors, buffer); if(slRetVal < 0) { return slRetVal; } Count -= (SequentialClusters + 1); pFile->AddrCurrentCluster = FF_TraverseFAT(pFile->pIoman, pFile->AddrCurrentCluster, (SequentialClusters + 1), &Error); if(Error) { return Error; } pFile->CurrentCluster += (SequentialClusters + 1); buffer += ulSectors * pFile->pIoman->BlkSize; SequentialClusters = 0; } return FF_ERR_NONE; }
/** * @public * @brief Writes a char to a FILE. * * @param pFile FILE Pointer. * @param pa_cValue Char to be placed in the file. * * @return Returns the value written to the file, or a value less than 0. * **/ FF_T_SINT32 FF_PutC(FF_FILE *pFile, FF_T_UINT8 pa_cValue) { FF_BUFFER *pBuffer; FF_T_UINT32 iItemLBA; FF_T_UINT32 iRelPos; FF_T_UINT32 nClusterDiff; FF_ERROR Error; if(!pFile) { // Ensure we don't have a Null file pointer on a Public interface. return FF_ERR_NULL_POINTER; } if(!(pFile->Mode & FF_MODE_WRITE)) { return FF_ERR_FILE_NOT_OPENED_IN_WRITE_MODE; } // Make sure a write is after the append point. if((pFile->Mode & FF_MODE_APPEND)) { if(pFile->FilePointer < pFile->Filesize) { FF_Seek(pFile, 0, FF_SEEK_END); } } iRelPos = FF_getMinorBlockEntry(pFile->pIoman, pFile->FilePointer, 1); // Handle File Space Allocation. Error = FF_ExtendFile(pFile, pFile->FilePointer + 1); if(Error) { return Error; } nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pFile->pIoman, pFile->AddrCurrentCluster, nClusterDiff, &Error); if(Error) { return Error; } pFile->CurrentCluster += nClusterDiff; } } iItemLBA = FF_Cluster2LBA(pFile->pIoman, pFile->AddrCurrentCluster) + FF_getMajorBlockNumber(pFile->pIoman, pFile->FilePointer, (FF_T_UINT16) 1); iItemLBA = FF_getRealLBA (pFile->pIoman, iItemLBA) + FF_getMinorBlockNumber(pFile->pIoman, pFile->FilePointer, (FF_T_UINT16) 1); pBuffer = FF_GetBuffer(pFile->pIoman, iItemLBA, FF_MODE_WRITE); { if(!pBuffer) { return FF_ERR_DEVICE_DRIVER_FAILED; } FF_putChar(pBuffer->pBuffer, (FF_T_UINT16) iRelPos, pa_cValue); } FF_ReleaseBuffer(pFile->pIoman, pBuffer); pFile->FilePointer += 1; if(pFile->Filesize < (pFile->FilePointer)) { pFile->Filesize += 1; } return pa_cValue; }
/** * @public * @brief Equivalent to fgetc() * * @param pFile FF_FILE object that was created by FF_Open(). * * @return The character that was read (cast as a 32-bit interger). -1 on EOF. * @return -2 If a null file pointer was provided. * @return -3 Device access failed. * **/ FF_T_SINT32 FF_GetC(FF_FILE *pFile) { FF_T_UINT32 fileLBA; FF_BUFFER *pBuffer; FF_T_UINT8 retChar; FF_T_UINT32 relMinorBlockPos; FF_T_UINT32 clusterNum; FF_T_UINT32 nClusterDiff; FF_ERROR Error; if(!pFile) { return FF_ERR_NULL_POINTER; } if(!(pFile->Mode & FF_MODE_READ)) { return FF_ERR_FILE_NOT_OPENED_IN_READ_MODE; } if(pFile->FilePointer >= pFile->Filesize) { return -1; // EOF! } relMinorBlockPos = FF_getMinorBlockEntry(pFile->pIoman, pFile->FilePointer, 1); clusterNum = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1); nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pFile->pIoman, pFile->AddrCurrentCluster, nClusterDiff, &Error); if(Error) { return Error; } pFile->CurrentCluster += nClusterDiff; } } fileLBA = FF_Cluster2LBA(pFile->pIoman, pFile->AddrCurrentCluster) + FF_getMajorBlockNumber(pFile->pIoman, pFile->FilePointer, (FF_T_UINT16) 1); fileLBA = FF_getRealLBA (pFile->pIoman, fileLBA) + FF_getMinorBlockNumber(pFile->pIoman, pFile->FilePointer, (FF_T_UINT16) 1); pBuffer = FF_GetBuffer(pFile->pIoman, fileLBA, FF_MODE_READ); { if(!pBuffer) { return FF_ERR_DEVICE_DRIVER_FAILED; } retChar = pBuffer->pBuffer[relMinorBlockPos]; } FF_ReleaseBuffer(pFile->pIoman, pBuffer); pFile->FilePointer += 1; return (FF_T_INT32) retChar; }
static FF_T_SINT32 FF_WriteClusters(FF_FILE *pFile, FF_T_UINT32 Count, FF_T_UINT8 *buffer) { FF_T_UINT32 Sectors; FF_T_UINT32 SequentialClusters = 0; FF_T_UINT32 nItemLBA; FF_T_SINT32 RetVal; while(Count != 0) { if((Count - 1) > 0) { SequentialClusters = FF_GetSequentialClusters(pFile->pIoman, pFile->AddrCurrentCluster, (Count - 1)); } Sectors = (SequentialClusters + 1) * pFile->pIoman->pPartition->SectorsPerCluster; nItemLBA = FF_Cluster2LBA(pFile->pIoman, pFile->AddrCurrentCluster); nItemLBA = FF_getRealLBA(pFile->pIoman, nItemLBA); do { if(pFile->pIoman->pBlkDevice->fnWriteBlocks) { #ifdef FF_BLKDEV_USES_SEM FF_PendSemaphore(pFile->pIoman->pSemaphore); #endif // Called from FF_Write, sem not claimed RetVal = pFile->pIoman->pBlkDevice->fnWriteBlocks(buffer, nItemLBA, Sectors, pFile->pIoman->pBlkDevice->pParam); #ifdef FF_BLKDEV_USES_SEM FF_ReleaseSemaphore(pFile->pIoman->pSemaphore); #endif if(RetVal == FF_ERR_DRIVER_BUSY) { FF_Yield(); FF_Sleep(FF_DRIVER_BUSY_SLEEP); } } else { RetVal = FF_ERR_DEVICE_DRIVER_FAILED; } }while(RetVal == FF_ERR_DRIVER_BUSY); Count -= (SequentialClusters + 1); pFile->AddrCurrentCluster = FF_TraverseFAT(pFile->pIoman, pFile->AddrCurrentCluster, (SequentialClusters + 1)); pFile->CurrentCluster += (SequentialClusters + 1); buffer += Sectors * pFile->pIoman->BlkSize; SequentialClusters = 0; } return 0; }
/** * @public * @brief Equivalent to fread() * * @param pFile FF_FILE object that was created by FF_Open(). * @param ElementSize The size of an element to read. * @param Count The number of elements to read. * @param buffer A pointer to a buffer of adequate size to be filled with the requested data. * * @return Number of bytes read. * **/ FF_T_SINT32 FF_Read(FF_FILE *pFile, FF_T_UINT32 ElementSize, FF_T_UINT32 Count, FF_T_UINT8 *buffer) { FF_T_UINT32 nBytes = ElementSize * Count; FF_T_UINT32 nBytesRead = 0; FF_T_UINT32 nBytesToRead; FF_IOMAN *pIoman; FF_BUFFER *pBuffer; FF_T_UINT32 nRelBlockPos; FF_T_UINT32 nItemLBA; FF_T_SINT32 RetVal = 0; FF_T_UINT16 sSectors; FF_T_UINT32 nRelClusterPos; FF_T_UINT32 nBytesPerCluster; FF_T_UINT32 nClusterDiff; if(!pFile) { return FF_ERR_NULL_POINTER; } if(!(pFile->Mode & FF_MODE_READ)) { return FF_ERR_FILE_NOT_OPENED_IN_READ_MODE; } pIoman = pFile->pIoman; if(pFile->FilePointer == pFile->Filesize) { return 0; } if((pFile->FilePointer + nBytes) > pFile->Filesize) { nBytes = pFile->Filesize - pFile->FilePointer; } nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff); pFile->CurrentCluster += nClusterDiff; } } nRelBlockPos = FF_getMinorBlockEntry(pIoman, pFile->FilePointer, 1); // Get the position within a block. nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster); nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1); if((nRelBlockPos + nBytes) < pIoman->BlkSize) { // Bytes to read are within a block and less than a block size. pBuffer = FF_GetBuffer(pIoman, nItemLBA, FF_MODE_READ); { memcpy(buffer, (pBuffer->pBuffer + nRelBlockPos), nBytes); } FF_ReleaseBuffer(pIoman, pBuffer); pFile->FilePointer += nBytes; return nBytes; // Return the number of bytes read. } else { //---------- Read (memcpy) to a Sector Boundary if(nRelBlockPos != 0) { // Not on a sector boundary, at this point the LBA is known. nBytesToRead = pIoman->BlkSize - nRelBlockPos; pBuffer = FF_GetBuffer(pIoman, nItemLBA, FF_MODE_READ); { // Here we copy to the sector boudary. memcpy(buffer, (pBuffer->pBuffer + nRelBlockPos), nBytesToRead); } FF_ReleaseBuffer(pIoman, pBuffer); nBytes -= nBytesToRead; nBytesRead += nBytesToRead; pFile->FilePointer += nBytesToRead; buffer += nBytesToRead; } //---------- Read to a Cluster Boundary nRelClusterPos = FF_getClusterPosition(pIoman, pFile->FilePointer, 1); nBytesPerCluster = (pIoman->pPartition->SectorsPerCluster * pIoman->BlkSize); if(nRelClusterPos != 0 && nBytes >= nBytesPerCluster) { // Need to get to cluster boundary nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff); pFile->CurrentCluster += nClusterDiff; } } nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster); nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1); sSectors = (FF_T_UINT16) (pIoman->pPartition->SectorsPerCluster - (nRelClusterPos / pIoman->BlkSize)); do { if(pIoman->pBlkDevice->fnReadBlocks) { #ifdef FF_BLKDEV_USES_SEM FF_PendSemaphore(pFile->pIoman->pSemaphore); #endif RetVal = pFile->pIoman->pBlkDevice->fnReadBlocks(buffer, nItemLBA, sSectors, pIoman->pBlkDevice->pParam); #ifdef FF_BLKDEV_USES_SEM FF_ReleaseSemaphore(pFile->pIoman->pSemaphore); #endif } if(RetVal == FF_ERR_DRIVER_BUSY) { FF_Yield(); FF_Sleep(FF_DRIVER_BUSY_SLEEP); } }while(RetVal == FF_ERR_DRIVER_BUSY); nBytesToRead = sSectors * pIoman->BlkSize; nBytes -= nBytesToRead; buffer += nBytesToRead; nBytesRead += nBytesToRead; pFile->FilePointer += nBytesToRead; } //---------- Read Clusters if(nBytes >= nBytesPerCluster) { //----- Thanks to Christopher Clark of DigiPen Institute of Technology in Redmond, US adding this traversal check. nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff); pFile->CurrentCluster += nClusterDiff; } } //----- End of Contributor fix. FF_ReadClusters(pFile, (nBytes / nBytesPerCluster), buffer); nBytesToRead = (nBytesPerCluster * (nBytes / nBytesPerCluster)); pFile->FilePointer += nBytesToRead; nBytes -= nBytesToRead; buffer += nBytesToRead; nBytesRead += nBytesToRead; } //---------- Read Remaining Blocks if(nBytes >= pIoman->BlkSize) { sSectors = (FF_T_UINT16) (nBytes / pIoman->BlkSize); nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff); pFile->CurrentCluster += nClusterDiff; } } nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster); nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1); do { if(pIoman->pBlkDevice->fnReadBlocks) { #ifdef FF_BLKDEV_USES_SEM FF_PendSemaphore(pFile->pIoman->pSemaphore); #endif RetVal = pFile->pIoman->pBlkDevice->fnReadBlocks(buffer, nItemLBA, sSectors, pIoman->pBlkDevice->pParam); #ifdef FF_BLKDEV_USES_SEM FF_ReleaseSemaphore(pFile->pIoman->pSemaphore); #endif } if(RetVal == FF_ERR_DRIVER_BUSY) { FF_Yield(); FF_Sleep(FF_DRIVER_BUSY_SLEEP); } }while(RetVal == FF_ERR_DRIVER_BUSY); nBytesToRead = sSectors * pIoman->BlkSize; pFile->FilePointer += nBytesToRead; nBytes -= nBytesToRead; buffer += nBytesToRead; nBytesRead += nBytesToRead; } //---------- Read (memcpy) Remaining Bytes if(nBytes > 0) { nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff); pFile->CurrentCluster += nClusterDiff; } } nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster); nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1); pBuffer = FF_GetBuffer(pIoman, nItemLBA, FF_MODE_READ); { memcpy(buffer, pBuffer->pBuffer, nBytes); } FF_ReleaseBuffer(pIoman, pBuffer); nBytesToRead = nBytes; pFile->FilePointer += nBytesToRead; nBytes -= nBytesToRead; buffer += nBytesToRead; nBytesRead += nBytesToRead; } } return nBytesRead; }
/** * @public * @brief Writes data to a File. * * @param pFile FILE Pointer. * @param ElementSize Size of an Element of Data to be copied. (in bytes). * @param Count Number of Elements of Data to be copied. (ElementSize * Count must not exceed ((2^31)-1) bytes. (2GB). For best performance, multiples of 512 bytes or Cluster sizes are best. * @param buffer Byte-wise buffer containing the data to be written. * * @return **/ FF_T_SINT32 FF_Write(FF_FILE *pFile, FF_T_UINT32 ElementSize, FF_T_UINT32 Count, FF_T_UINT8 *buffer) { FF_T_UINT32 nBytes = ElementSize * Count; FF_T_UINT32 nBytesWritten = 0; FF_T_UINT32 nBytesToWrite; FF_IOMAN *pIoman; FF_BUFFER *pBuffer; FF_T_UINT32 nRelBlockPos; FF_T_UINT32 nItemLBA; FF_T_SINT32 RetVal = 0; FF_T_UINT16 sSectors; FF_T_UINT32 nRelClusterPos; FF_T_UINT32 nBytesPerCluster, nClusterDiff, nClusters; FF_ERROR Error; if(!pFile) { return FF_ERR_NULL_POINTER; } if(!(pFile->Mode & FF_MODE_WRITE)) { return FF_ERR_FILE_NOT_OPENED_IN_WRITE_MODE; } // Make sure a write is after the append point. if((pFile->Mode & FF_MODE_APPEND)) { if(pFile->FilePointer < pFile->Filesize) { FF_Seek(pFile, 0, FF_SEEK_END); } } pIoman = pFile->pIoman; nBytesPerCluster = (pIoman->pPartition->SectorsPerCluster * pIoman->BlkSize); // Extend File for atleast nBytes! // Handle file-space allocation Error = FF_ExtendFile(pFile, pFile->FilePointer + nBytes); if(Error) { return Error; } nRelBlockPos = FF_getMinorBlockEntry(pIoman, pFile->FilePointer, 1); // Get the position within a block. nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster != FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff); pFile->CurrentCluster += nClusterDiff; } } nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster); nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1); if((nRelBlockPos + nBytes) < pIoman->BlkSize) { // Bytes to read are within a block and less than a block size. pBuffer = FF_GetBuffer(pIoman, nItemLBA, FF_MODE_WRITE); { memcpy((pBuffer->pBuffer + nRelBlockPos), buffer, nBytes); } FF_ReleaseBuffer(pIoman, pBuffer); pFile->FilePointer += nBytes; nBytesWritten = nBytes; //return nBytes; // Return the number of bytes read. } else { //---------- Write (memcpy) to a Sector Boundary if(nRelBlockPos != 0) { // Not on a sector boundary, at this point the LBA is known. nBytesToWrite = pIoman->BlkSize - nRelBlockPos; pBuffer = FF_GetBuffer(pIoman, nItemLBA, FF_MODE_WRITE); { // Here we copy to the sector boudary. memcpy((pBuffer->pBuffer + nRelBlockPos), buffer, nBytesToWrite); } FF_ReleaseBuffer(pIoman, pBuffer); nBytes -= nBytesToWrite; nBytesWritten += nBytesToWrite; pFile->FilePointer += nBytesToWrite; buffer += nBytesToWrite; } //---------- Write to a Cluster Boundary nRelClusterPos = FF_getClusterPosition(pIoman, pFile->FilePointer, 1); if(nRelClusterPos != 0 && nBytes >= nBytesPerCluster) { // Need to get to cluster boundary nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff); pFile->CurrentCluster += nClusterDiff; } } nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster); nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1); sSectors = (FF_T_UINT16) (pIoman->pPartition->SectorsPerCluster - (nRelClusterPos / pIoman->BlkSize)); do { if(pIoman->pBlkDevice->fnWriteBlocks) { #ifdef FF_BLKDEV_USES_SEM FF_PendSemaphore(pFile->pIoman->pSemaphore); #endif RetVal = pFile->pIoman->pBlkDevice->fnWriteBlocks(buffer, nItemLBA, sSectors, pIoman->pBlkDevice->pParam); #ifdef FF_BLKDEV_USES_SEM FF_ReleaseSemaphore(pFile->pIoman->pSemaphore); #endif } if(RetVal == FF_ERR_DRIVER_BUSY) { FF_Yield(); FF_Sleep(FF_DRIVER_BUSY_SLEEP); } }while(RetVal == FF_ERR_DRIVER_BUSY); nBytesToWrite = sSectors * pIoman->BlkSize; nBytes -= nBytesToWrite; buffer += nBytesToWrite; nBytesWritten += nBytesToWrite; pFile->FilePointer += nBytesToWrite; } //---------- Write Clusters if(nBytes >= nBytesPerCluster) { //----- Thanks to Christopher Clark of DigiPen Institute of Technology in Redmond, US adding this traversal check. nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff); pFile->CurrentCluster += nClusterDiff; } } //----- End of Contributor fix. nClusters = (nBytes / nBytesPerCluster); FF_WriteClusters(pFile, nClusters, buffer); nBytesToWrite = (nBytesPerCluster * nClusters); pFile->FilePointer += nBytesToWrite; nBytes -= nBytesToWrite; buffer += nBytesToWrite; nBytesWritten += nBytesToWrite; } //---------- Write Remaining Blocks if(nBytes >= pIoman->BlkSize) { sSectors = (FF_T_UINT16) (nBytes / pIoman->BlkSize); nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff); pFile->CurrentCluster += nClusterDiff; } } nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster); nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1); do { if(pIoman->pBlkDevice->fnWriteBlocks) { #ifdef FF_BLKDEV_USES_SEM FF_PendSemaphore(pFile->pIoman->pSemaphore); #endif RetVal = pFile->pIoman->pBlkDevice->fnWriteBlocks(buffer, nItemLBA, sSectors, pIoman->pBlkDevice->pParam); #ifdef FF_BLKDEV_USES_SEM FF_ReleaseSemaphore(pFile->pIoman->pSemaphore); #endif } if(RetVal == FF_ERR_DRIVER_BUSY) { FF_Yield(); FF_Sleep(FF_DRIVER_BUSY_SLEEP); } }while(RetVal == FF_ERR_DRIVER_BUSY); nBytesToWrite = sSectors * pIoman->BlkSize; pFile->FilePointer += nBytesToWrite; nBytes -= nBytesToWrite; buffer += nBytesToWrite; nBytesWritten += nBytesToWrite; } //---------- Write (memcpy) Remaining Bytes if(nBytes > 0) { nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster; if(nClusterDiff) { if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) { pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff); pFile->CurrentCluster += nClusterDiff; } } nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster); nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1); pBuffer = FF_GetBuffer(pIoman, nItemLBA, FF_MODE_WRITE); { memcpy(pBuffer->pBuffer, buffer, nBytes); } FF_ReleaseBuffer(pIoman, pBuffer); nBytesToWrite = nBytes; pFile->FilePointer += nBytesToWrite; nBytes -= nBytesToWrite; buffer += nBytesToWrite; nBytesWritten += nBytesToWrite; } } if(pFile->FilePointer > pFile->Filesize) { pFile->Filesize = pFile->FilePointer; } return nBytesWritten; }
/** * @private **/ FF_T_SINT32 FF_getFatEntry(FF_IOMAN *pIoman, FF_T_UINT32 nCluster) { FF_BUFFER *pBuffer; FF_T_UINT32 FatOffset; FF_T_UINT32 FatSector; FF_T_UINT32 FatSectorEntry; FF_T_UINT32 FatEntry; FF_T_UINT8 LBAadjust; FF_T_UINT16 relClusterEntry; #ifdef FF_FAT12_SUPPORT FF_T_UINT8 F12short[2]; // For FAT12 FAT Table Across sector boundary traversal. #endif if(pIoman->pPartition->Type == FF_T_FAT32) { FatOffset = nCluster * 4; } else if(pIoman->pPartition->Type == FF_T_FAT16) { FatOffset = nCluster * 2; }else { FatOffset = nCluster + (nCluster / 2); } FatSector = pIoman->pPartition->FatBeginLBA + (FatOffset / pIoman->pPartition->BlkSize); FatSectorEntry = FatOffset % pIoman->pPartition->BlkSize; LBAadjust = (FF_T_UINT8) (FatSectorEntry / pIoman->BlkSize); relClusterEntry = (FF_T_UINT32) (FatSectorEntry % pIoman->BlkSize); FatSector = FF_getRealLBA(pIoman, FatSector); #ifdef FF_FAT12_SUPPORT if(pIoman->pPartition->Type == FF_T_FAT12) { if(relClusterEntry == (FF_T_UINT32)(pIoman->BlkSize - 1)) { // Fat Entry SPANS a Sector! // First Buffer get the last Byte in buffer (first byte of our address)! pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust, FF_MODE_READ); { if(!pBuffer) { return FF_ERR_DEVICE_DRIVER_FAILED; } F12short[0] = FF_getChar(pBuffer->pBuffer, (FF_T_UINT16)(pIoman->BlkSize - 1)); } FF_ReleaseBuffer(pIoman, pBuffer); // Second Buffer get the first Byte in buffer (second byte of out address)! pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust + 1, FF_MODE_READ); { if(!pBuffer) { return FF_ERR_DEVICE_DRIVER_FAILED; } F12short[1] = FF_getChar(pBuffer->pBuffer, 0); } FF_ReleaseBuffer(pIoman, pBuffer); FatEntry = (FF_T_UINT32) FF_getShort((FF_T_UINT8*)&F12short, 0); // Guarantee correct Endianess! if(nCluster & 0x0001) { FatEntry = FatEntry >> 4; } FatEntry &= 0x0FFF; return (FF_T_SINT32) FatEntry; }