in ff_file.c [1732:1952]
int32_t FF_Read( FF_FILE * pxFile,
uint32_t ulElementSize,
uint32_t ulCount,
uint8_t * pucBuffer )
{
uint32_t ulBytesLeft = ulElementSize * ulCount;
uint32_t ulBytesRead = 0;
uint32_t ulBytesToRead;
FF_IOManager_t * pxIOManager;
uint32_t ulRelBlockPos;
uint32_t ulItemLBA;
int32_t lResult;
uint32_t ulSectors;
uint32_t ulRelClusterPos;
uint32_t ulBytesPerCluster;
FF_Error_t xError;
if( pxFile == NULL )
{
xError = ( FF_Error_t ) ( FF_ERR_NULL_POINTER | FF_READ );
}
else
{
/* Check validity of the handle and the current position within the file. */
xError = FF_CheckValid( pxFile );
if( FF_isERR( xError ) == pdFALSE )
{
if( ( pxFile->ucMode & FF_MODE_READ ) == 0 )
{
/* File was not opened with READ mode access. */
xError = ( FF_Error_t ) ( FF_ERR_FILE_NOT_OPENED_IN_READ_MODE | FF_READ );
}
else if( pxFile->ulFilePointer >= pxFile->ulFileSize )
{
/* The end-of-file is reached. The error READ_ZERO will not be
* returned, it is just used to avoid further processing. */
xError = ( FF_Error_t ) ( FF_ERR_FILE_READ_ZERO | FF_READ );
}
else if( ( pxFile->ulFilePointer + ulBytesLeft ) > pxFile->ulFileSize )
{
/* Note that many bytes can be read. */
ulBytesLeft = pxFile->ulFileSize - pxFile->ulFilePointer;
}
}
else
{
/* The file handle is not valid. */
}
} /* else pxFile != NULL */
if( FF_isERR( xError ) == pdFALSE )
{
pxIOManager = pxFile->pxIOManager;
/* And calculate the Logical Block Address. */
ulItemLBA = FF_SetCluster( pxFile, &xError );
/* Get the position within a block. */
ulRelBlockPos = FF_getMinorBlockEntry( pxIOManager, pxFile->ulFilePointer, 1 );
/* Open a do {} while( 0 ) loop to allow easy breaks: */
do
{
if( ( ulRelBlockPos + ulBytesLeft ) <= ( uint32_t ) pxIOManager->usSectorSize )
{
/*---------- A small read within the current block only. */
ulBytesRead = FF_ReadPartial( pxFile, ulItemLBA, ulRelBlockPos, ulBytesLeft, pucBuffer, &xError );
break;
}
/*---------- Read (memcpy) to a Sector Boundary. */
if( ulRelBlockPos != 0 )
{
/* Not on a sector boundary, at this point the LBA is known. */
ulBytesToRead = pxIOManager->usSectorSize - ulRelBlockPos;
ulBytesRead = FF_ReadPartial( pxFile, ulItemLBA, ulRelBlockPos, ulBytesToRead, pucBuffer, &xError );
if( FF_isERR( xError ) )
{
break;
}
ulBytesLeft -= ulBytesRead;
pucBuffer += ulBytesRead;
}
/*---------- Read sectors, up to a Cluster Boundary. */
ulBytesPerCluster = ( pxIOManager->xPartition.ulSectorsPerCluster * pxIOManager->usSectorSize );
ulRelClusterPos = pxFile->ulFilePointer % ( ulBytesPerCluster * pxIOManager->xPartition.ucBlkFactor );
if( ( ulRelClusterPos != 0 ) && ( ( ulRelClusterPos + ulBytesLeft ) >= ulBytesPerCluster ) )
{
/* Need to get to cluster boundary. */
ulItemLBA = FF_SetCluster( pxFile, &xError );
if( FF_isERR( xError ) )
{
break;
}
ulSectors = pxIOManager->xPartition.ulSectorsPerCluster - ( ulRelClusterPos / pxIOManager->usSectorSize );
xError = FF_BlockRead( pxIOManager, ulItemLBA, ulSectors, pucBuffer, pdFALSE );
if( FF_isERR( xError ) )
{
break;
}
ulBytesToRead = ulSectors * pxIOManager->usSectorSize;
ulBytesLeft -= ulBytesToRead;
pucBuffer += ulBytesToRead;
ulBytesRead += ulBytesToRead;
pxFile->ulFilePointer += ulBytesToRead;
}
/*---------- Read entire clusters. */
if( ulBytesLeft >= ulBytesPerCluster )
{
uint32_t ulClusters;
FF_SetCluster( pxFile, &xError );
if( FF_isERR( xError ) )
{
break;
}
ulClusters = ulBytesLeft / ulBytesPerCluster;
xError = FF_ReadClusters( pxFile, ulClusters, pucBuffer );
if( FF_isERR( xError ) )
{
break;
}
ulBytesToRead = ulBytesPerCluster * ulClusters;
pxFile->ulFilePointer += ulBytesToRead;
ulBytesLeft -= ulBytesToRead;
pucBuffer += ulBytesToRead;
ulBytesRead += ulBytesToRead;
}
/*---------- Read Remaining Blocks. */
while( ulBytesLeft >= ( uint32_t ) pxIOManager->usSectorSize )
{
ulSectors = ulBytesLeft / pxIOManager->usSectorSize;
{
/* HT: I'd leave these pPart/ulOffset for readability */
/* and shorter code lines */
FF_Partition_t * pPart = &( pxIOManager->xPartition );
uint32_t ulOffset = ( pxFile->ulFilePointer / pxIOManager->usSectorSize ) % pPart->ulSectorsPerCluster;
uint32_t ulRemain = pPart->ulSectorsPerCluster - ulOffset;
if( ulSectors > ulRemain )
{
ulSectors = ulRemain;
}
}
ulItemLBA = FF_SetCluster( pxFile, &xError );
if( FF_isERR( xError ) )
{
break;
}
xError = FF_BlockRead( pxIOManager, ulItemLBA, ulSectors, pucBuffer, pdFALSE );
if( FF_isERR( xError ) )
{
break;
}
ulBytesToRead = ulSectors * pxIOManager->usSectorSize;
pxFile->ulFilePointer += ulBytesToRead;
ulBytesLeft -= ulBytesToRead;
pucBuffer += ulBytesToRead;
ulBytesRead += ulBytesToRead;
}
/*---------- Read (memcpy) Remaining Bytes */
if( ulBytesLeft == 0 )
{
break;
}
ulItemLBA = FF_SetCluster( pxFile, &xError );
if( FF_isERR( xError ) )
{
break;
}
/* Bytes to read are within a block and less than a block size. */
FF_ReadPartial( pxFile, ulItemLBA, 0, ulBytesLeft, pucBuffer, &xError );
if( FF_isERR( xError ) == pdFALSE )
{
ulBytesRead += ulBytesLeft;
}
}
while( pdFALSE );
} /* if( FF_isERR( xError ) == pdFALSE ) */
if( FF_GETERROR( xError ) == FF_ERR_FILE_READ_ZERO )
{
lResult = 0;
}
else if( FF_isERR( xError ) )
{
lResult = xError;
}
else
{
lResult = ( int32_t ) ( ulBytesRead / ulElementSize );
}
return lResult;
} /* FF_Read() */