in ff_dir.c [1374:1622]
FF_Error_t FF_PopulateLongDirent( FF_IOManager_t * pxIOManager,
FF_DirEnt_t * pxDirEntry,
uint16_t usEntry,
FF_FetchContext_t * pxFetchContext )
{
/* First get the entire name as UTF-16 from the LFN's.
* Then transform into the API's native string format. */
FF_Error_t xError;
BaseType_t xNumLFNs;
uint8_t ucCheckSum;
/* A 32 byte directory entry. */
uint8_t pucEntryBuffer[ FF_SIZEOF_DIRECTORY_ENTRY ];
char pcShortName[ 13 ];
#if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
UBaseType_t uiLfnLength = 0;
#endif
#if ( ffconfigUNICODE_UTF16_SUPPORT == 0 )
BaseType_t xIndex, y;
#endif
#if ( ffconfigUNICODE_UTF16_SUPPORT == 0 ) && ( ffconfigUNICODE_UTF8_SUPPORT == 0 )
char * pcLastPtr = pxDirEntry->pcFileName + sizeof( pxDirEntry->pcFileName );
char * pcCurPtr;
#endif
#if ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
uint16_t nLfnBegin;
uint16_t usUtf8Len = 0;
#endif /* ffconfigUNICODE_UTF8_SUPPORT */
do
{
xError = FF_FetchEntryWithContext( pxIOManager, usEntry++, pxFetchContext, pucEntryBuffer );
if( FF_isERR( xError ) )
{
/* After breaking from this do {} while ( pdFALSE ) loop, xResult will be returned. */
break;
}
xNumLFNs = ( BaseType_t ) ( pucEntryBuffer[ 0 ] & ~0x40 );
ucCheckSum = FF_getChar( pucEntryBuffer, FF_FAT_LFN_CHECKSUM );
#if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
{
/* UTF-16 Can simply get segments of the UTF-16 sequence
* going forward in the directory entries ( but reversed order ). */
while( xNumLFNs > 0 )
{
/* Avoid stack intensive use of a UTF-16 buffer. Stream direct to FileName dirent field in correct format. */
/* memcpy direct! -UTF-16 support. */
memcpy( pxDirEntry->pcFileName + ( ( xNumLFNs - 1 ) * 13 ) + 0, &( pucEntryBuffer[ FF_FAT_LFN_NAME_1 ] ), 10 );
memcpy( pxDirEntry->pcFileName + ( ( xNumLFNs - 1 ) * 13 ) + 5, &( pucEntryBuffer[ FF_FAT_LFN_NAME_2 ] ), 12 );
memcpy( pxDirEntry->pcFileName + ( ( xNumLFNs - 1 ) * 13 ) + 11, &( pucEntryBuffer[ FF_FAT_LFN_NAME_3 ] ), 4 );
uiLfnLength += 13;
xError = FF_FetchEntryWithContext( pxIOManager, usEntry++, pxFetchContext, pucEntryBuffer );
if( FF_isERR( xError ) )
{
break;
}
xNumLFNs--;
}
if( FF_isERR( xError ) )
{
break;
}
pxDirEntry->pcFileName[ uiLfnLength ] = '\0';
}
#endif /* ffconfigUNICODE_UTF16_SUPPORT */
#if ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
{
/* UTF-8 Sequence, we can only convert this from the beginning, must receive entries in reverse. */
nLfnBegin = usEntry - 1;
for( xIndex = 0; xIndex < xNumLFNs; xIndex++ )
{
xError = FF_FetchEntryWithContext( pxIOManager, ( nLfnBegin + ( xNumLFNs - 1 ) - xIndex ), pxFetchContext, pucEntryBuffer );
if( FF_isERR( xError ) )
{
break;
}
/* Now have the first part of the UTF-16 sequence. Stream into a UTF-8 sequence. */
for( y = 0; y < 5; y++ )
{
xError = FF_Utf16ctoUtf8c( ( uint8_t * ) &pxDirEntry->pcFileName[ usUtf8Len ],
( uint16_t * ) &pucEntryBuffer[ FF_FAT_LFN_NAME_1 + ( y * 2 ) ], sizeof( pxDirEntry->pcFileName ) - usUtf8Len );
if( xError > 0 )
{
usUtf8Len += ( uint16_t ) xError;
}
}
for( y = 0; y < 6; y++ )
{
xError = FF_Utf16ctoUtf8c( ( uint8_t * ) &pxDirEntry->pcFileName[ usUtf8Len ],
( uint16_t * ) &pucEntryBuffer[ FF_FAT_LFN_NAME_2 + ( y * 2 ) ], sizeof( pxDirEntry->pcFileName ) - usUtf8Len );
if( xError > 0 )
{
usUtf8Len += ( uint16_t ) xError;
}
}
for( y = 0; y < 2; y++ )
{
xError = FF_Utf16ctoUtf8c( ( uint8_t * ) &pxDirEntry->pcFileName[ usUtf8Len ],
( uint16_t * ) &pucEntryBuffer[ FF_FAT_LFN_NAME_3 + ( y * 2 ) ], sizeof( pxDirEntry->pcFileName ) - usUtf8Len );
if( xError > 0 )
{
usUtf8Len += ( uint16_t ) xError;
}
}
usEntry++;
}
if( FF_isERR( xError ) )
{
break;
}
pxDirEntry->pcFileName[ usUtf8Len ] = '\0';
/* Put Entry context to correct position. */
xError = FF_FetchEntryWithContext( pxIOManager, usEntry - 1, pxFetchContext, pucEntryBuffer );
if( FF_isERR( xError ) )
{
break;
}
}
#endif /* ( ffconfigUNICODE_UTF8_SUPPORT != 0 ) */
#if ( ffconfigUNICODE_UTF16_SUPPORT == 0 ) && ( ffconfigUNICODE_UTF8_SUPPORT == 0 ) /* No Unicode, simple ASCII. */
{
pcLastPtr[ -1 ] = '\0';
y = xNumLFNs;
while( xNumLFNs-- )
{
pcCurPtr = pxDirEntry->pcFileName + ( xNumLFNs * 13 );
for( xIndex = 0; ( xIndex < 10 ) && ( pcCurPtr < pcLastPtr ); xIndex += 2 )
{
*( pcCurPtr++ ) = pucEntryBuffer[ FF_FAT_LFN_NAME_1 + xIndex ];
}
for( xIndex = 0; ( xIndex < 12 ) && ( pcCurPtr < pcLastPtr ); xIndex += 2 )
{
*( pcCurPtr++ ) = pucEntryBuffer[ FF_FAT_LFN_NAME_2 + xIndex ];
}
for( xIndex = 0; ( xIndex < 4 ) && ( pcCurPtr < pcLastPtr ); xIndex += 2 )
{
*( pcCurPtr++ ) = pucEntryBuffer[ FF_FAT_LFN_NAME_3 + xIndex ];
}
if( ( xNumLFNs == ( y - 1 ) ) && ( pcCurPtr < pcLastPtr ) )
{
*pcCurPtr = '\0';
}
xError = FF_FetchEntryWithContext( pxIOManager, usEntry++, pxFetchContext, pucEntryBuffer );
if( FF_isERR( xError ) )
{
break;
}
}
if( FF_isERR( xError ) )
{
break;
}
}
#endif /* ( ffconfigUNICODE_UTF16_SUPPORT == 0 ) && ( ffconfigUNICODE_UTF8_SUPPORT == 0 ) */
/* Process the Shortname. -- LFN Transformation is now complete.
* Process the ShortName Entry. */
/* if SHORTNAMES must be included, simple byte copy into shortname buffer. */
#if ( ffconfigLFN_SUPPORT != 0 ) && ( ffconfigINCLUDE_SHORT_NAME != 0 )
{
memcpy( pxDirEntry->pcShortName, pucEntryBuffer, 11 );
pxDirEntry->pcShortName[ 11 ] = '\0';
FF_ProcessShortName( pxDirEntry->pcShortName );
}
#endif /* ( != 0 ffconfigLFN_SUPPORT ) && ( ffconfigINCLUDE_SHORT_NAME != 0 ) */
memcpy( pcShortName, pucEntryBuffer, 11 );
FF_ProcessShortName( pcShortName );
if( ucCheckSum != FF_CreateChkSum( pucEntryBuffer ) )
{
strcpy( pxDirEntry->pcFileName, pcShortName );
#if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
{
FF_ShortNameExpand( pxDirEntry->pcFileName );
}
#endif /* ffconfigUNICODE_UTF16_SUPPORT */
}
/* Finally fill in the other details. */
pxDirEntry->ulObjectCluster =
( ( uint32_t ) FF_getShort( pucEntryBuffer, FF_FAT_DIRENT_CLUS_HIGH ) << 16 ) |
( uint32_t ) FF_getShort( pucEntryBuffer, FF_FAT_DIRENT_CLUS_LOW );
#if ( ffconfigTIME_SUPPORT != 0 )
{
/* Get the creation Time & Date. */
FF_GetTime( &pxDirEntry->xCreateTime, pucEntryBuffer, FF_FAT_DIRENT_CREATE_TIME );
FF_GetDate( &pxDirEntry->xCreateTime, pucEntryBuffer, FF_FAT_DIRENT_CREATE_DATE );
/* Get the modified Time & Date. */
/* HT Here xCreateTime has become xModifiedTime, as it should: */
FF_GetTime( &pxDirEntry->xModifiedTime, pucEntryBuffer, FF_FAT_DIRENT_LASTMOD_TIME );
FF_GetDate( &pxDirEntry->xModifiedTime, pucEntryBuffer, FF_FAT_DIRENT_LASTMOD_DATE );
/* Get the last accessed Date. */
FF_GetDate( &pxDirEntry->xAccessedTime, pucEntryBuffer, FF_FAT_DIRENT_LASTACC_DATE );
/* HT Why should these times be zero'd ? */
pxDirEntry->xAccessedTime.Hour = 0;
pxDirEntry->xAccessedTime.Minute = 0;
pxDirEntry->xAccessedTime.Second = 0;
}
#endif /* ffconfigTIME_SUPPORT */
/* Get the filesize. */
pxDirEntry->ulFileSize = FF_getLong( pucEntryBuffer, ( uint16_t ) ( FF_FAT_DIRENT_FILESIZE ) );
/* Get the attribute. */
pxDirEntry->ucAttrib = FF_getChar( pucEntryBuffer, ( uint16_t ) ( FF_FAT_DIRENT_ATTRIB ) );
pxDirEntry->usCurrentItem = usEntry;
}
while( pdFALSE );
return xError;
} /* FF_PopulateLongDirent() */