{FULLFAT]

- Update FullFat to the latest stable release (1.0.5)
- I'm awaiting a reply from James as to when 1.1.0 will be released as it have some nice improvements.

svn path=/trunk/; revision=51227
This commit is contained in:
Ged Murphy 2011-04-02 15:22:48 +00:00
parent 542a951d46
commit 91e657f782
14 changed files with 456 additions and 170 deletions

View file

@ -74,13 +74,24 @@
// within the same path. E.g. a copy \dir1\*.* \dir2\*.* command.
// This command requires FF_MAX_PATH number of bytes of memory. (Defined below, default 2600).
//---------- BLKDEV USES SEMAPHORE
#define FF_BLKDEV_USES_SEM // When defined, each call to fnReadBlocks and fnWriteBlocks will be done while semaphore is locked
// See also ff_safety.c
// (HT addition)
#define FF_PATH_CACHE_DEPTH 2 // The Number of PATH's to Cache.
//---------- DON'T USE MALLOC
//#define FF_NO_MALLOC
//---------- DON'T
#define FF_MALLOC(aSize) malloc(aSize)
#define FF_FREE(apPtr) free(apPtr)
//#define FF_INLINE_MEMORY_ACCESS
//#define FF_INLINE static __forceinline // Keywords to inline functions (Windows)
#define FF_INLINE static inline // Standard for GCC
//---------- Hash Table Support
@ -117,7 +128,7 @@
//---------- AUTOMATIC SETTINGS DO NOT EDIT -- These configure your options from above, and check sanity!
#ifdef FF_LFN_SUPPORT
#define FF_MAX_FILENAME 260
#define FF_MAX_FILENAME (129)
#else
#define FF_MAX_FILENAME 13
#endif

View file

@ -43,7 +43,7 @@
#include "ff_ioman.h"
#include "ff_blk.h"
#include "ff_fat.h"
#include "fat.h"
#include "ff_fatdef.h"
#include "ff_memory.h"
#include "ff_time.h"
#include "ff_hash.h"

View file

@ -39,7 +39,7 @@
#define _FF_FAT_H_
#include "ff_config.h"
#include "fat.h"
#include "ff_fatdef.h"
#include "ff_ioman.h"
#include "ff_blk.h"
#include "ff_types.h"

View file

@ -0,0 +1,90 @@
/*****************************************************************************
* FullFAT - High Performance, Thread-Safe Embedded FAT File-System *
* Copyright (C) 2009 James Walmsley (james@worm.me.uk) *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
* IMPORTANT NOTICE: *
* ================= *
* Alternative Licensing is available directly from the Copyright holder, *
* (James Walmsley). For more information consult LICENSING.TXT to obtain *
* a Commercial license. *
* *
* See RESTRICTIONS.TXT for extra restrictions on the use of FullFAT. *
* *
* Removing the above notice is illegal and will invalidate this license. *
*****************************************************************************
* See http://worm.me.uk/fullfat for more information. *
* Or http://fullfat.googlecode.com/ for latest releases and the wiki. *
*****************************************************************************/
#ifndef _FF_FATDEF_H_
#define _FF_FATDEF_H_
/*
This file defines offsets to various data for the FAT specification.
*/
// MBR / PBR Offsets
#define FF_FAT_BYTES_PER_SECTOR 0x00B
#define FF_FAT_SECTORS_PER_CLUS 0x00D
#define FF_FAT_RESERVED_SECTORS 0x00E
#define FF_FAT_NUMBER_OF_FATS 0x010
#define FF_FAT_ROOT_ENTRY_COUNT 0x011
#define FF_FAT_16_TOTAL_SECTORS 0x013
#define FF_FAT_32_TOTAL_SECTORS 0x020
#define FF_FAT_16_SECTORS_PER_FAT 0x016
#define FF_FAT_32_SECTORS_PER_FAT 0x024
#define FF_FAT_ROOT_DIR_CLUSTER 0x02C
#define FF_FAT_16_VOL_LABEL 0x02B
#define FF_FAT_32_VOL_LABEL 0x047
#define FF_FAT_PTBL 0x1BE
#define FF_FAT_PTBL_LBA 0x008
#define FF_FAT_PTBL_ACTIVE 0x000
#define FF_FAT_PTBL_ID 0x004
#define FF_FAT_MBR_SIGNATURE 0x1FE
#define FF_FAT_DELETED 0xE5
// Directory Entry Offsets
#define FF_FAT_DIRENT_SHORTNAME 0x000
#define FF_FAT_DIRENT_ATTRIB 0x00B
#define FF_FAT_DIRENT_CREATE_TIME 0x00E ///< Creation Time.
#define FF_FAT_DIRENT_CREATE_DATE 0x010 ///< Creation Date.
#define FF_FAT_DIRENT_LASTACC_DATE 0x012 ///< Date of Last Access.
#define FF_FAT_DIRENT_CLUS_HIGH 0x014
#define FF_FAT_DIRENT_LASTMOD_TIME 0x016 ///< Time of Last modification.
#define FF_FAT_DIRENT_LASTMOD_DATE 0x018 ///< Date of Last modification.
#define FF_FAT_DIRENT_CLUS_LOW 0x01A
#define FF_FAT_DIRENT_FILESIZE 0x01C
#define FF_FAT_LFN_ORD 0x000
#define FF_FAT_LFN_NAME_1 0x001
#define FF_FAT_LFN_CHECKSUM 0x00D
#define FF_FAT_LFN_NAME_2 0x00E
#define FF_FAT_LFN_NAME_3 0x01C
// Dirent Attributes
#define FF_FAT_ATTR_READONLY 0x01
#define FF_FAT_ATTR_HIDDEN 0x02
#define FF_FAT_ATTR_SYSTEM 0x04
#define FF_FAT_ATTR_VOLID 0x08
#define FF_FAT_ATTR_DIR 0x10
#define FF_FAT_ATTR_ARCHIVE 0x20
#define FF_FAT_ATTR_LFN 0x0F
#endif

View file

@ -100,10 +100,10 @@ typedef struct {
**/
typedef struct {
FF_T_UINT32 Sector; ///< The LBA of the Cached sector.
FF_T_UINT8 Mode; ///< Read or Write mode.
FF_T_UINT32 LRU; ///< For the Least Recently Used algorithm.
FF_T_UINT16 NumHandles; ///< Number of objects using this buffer.
FF_T_UINT16 Persistance; ///< For the persistance algorithm.
FF_T_UINT32 LRU; ///< For the Least Recently Used algorithm.
FF_T_UINT8 Mode; ///< Read or Write mode.
FF_T_BOOL Modified; ///< If the sector was modified since read.
FF_T_BOOL Valid; ///< Initially FALSE.
FF_T_UINT8 *pBuffer; ///< Pointer to the cache block.
@ -129,7 +129,7 @@ typedef struct {
FF_T_UINT16 BlkSize; ///< Size of a Sector Block in bytes.
FF_T_UINT8 BlkFactor; ///< Scale Factor for blocksizes above 512!
//FF_T_INT8 Name[FF_MAX_PARTITION_NAME]; ///< Partition Identifier e.g. c: sd0: etc.
//FF_T_INT8 VolLabel[12]; ///< Volume Label of the partition.
FF_T_INT8 VolLabel[12]; ///< Volume Label of the partition.
FF_T_UINT32 BeginLBA; ///< LBA start address of the partition.
FF_T_UINT32 PartSize; ///< Size of Partition in number of sectors.
FF_T_UINT32 FatBeginLBA; ///< LBA of the FAT tables.
@ -182,14 +182,15 @@ typedef struct {
FF_BLK_DEVICE *pBlkDevice; ///< Pointer to a Block device description.
FF_PARTITION *pPartition; ///< Pointer to a partition description.
FF_BUFFER *pBuffers; ///< Pointer to the first buffer description.
FF_T_UINT32 LastReplaced; ///< Marks which sector was last replaced in the cache.
FF_T_UINT16 BlkSize; ///< The Block size that IOMAN is configured to.
FF_T_UINT8 *pCacheMem; ///< Pointer to a block of memory for the cache.
FF_T_UINT16 CacheSize; ///< Size of the cache in number of Sectors.
FF_T_UINT8 MemAllocation; ///< Bit-Mask identifying allocated pointers.
FF_T_UINT8 Locks; ///< Lock Flag for FAT & DIR Locking etc (This must be accessed via a semaphore).
void *pSemaphore; ///< Pointer to a Semaphore object. (For buffer description modifications only!).
void *FirstFile; ///< Pointer to the first File object.
FF_T_UINT8 *pCacheMem; ///< Pointer to a block of memory for the cache.
FF_T_UINT32 LastReplaced; ///< Marks which sector was last replaced in the cache.
FF_T_UINT16 BlkSize; ///< The Block size that IOMAN is configured to.
FF_T_UINT16 CacheSize; ///< Size of the cache in number of Sectors.
FF_T_UINT8 PreventFlush; ///< Flushing to disk only allowed when 0
FF_T_UINT8 MemAllocation; ///< Bit-Mask identifying allocated pointers.
FF_T_UINT8 Locks; ///< Lock Flag for FAT & DIR Locking etc (This must be accessed via a semaphore).
} FF_IOMAN;
// Bit-Masks for Memory Allocation testing.

View file

@ -41,19 +41,119 @@
#include "ff_config.h"
#include "ff_types.h"
/*
HT changed type of aOffset to u32
*/
//---------- PROTOTYPES
FF_T_UINT8 FF_getChar (FF_T_UINT8 *pBuffer, FF_T_UINT16 offset);
FF_T_UINT16 FF_getShort (FF_T_UINT8 *pBuffer, FF_T_UINT16 offset);
FF_T_UINT32 FF_getLong (FF_T_UINT8 *pBuffer, FF_T_UINT16 offset);
#if defined(FF_LITTLE_ENDIAN)
void FF_putChar (FF_T_UINT8 *pBuffer, FF_T_UINT16 offset, FF_T_UINT8 Value);
void FF_putShort (FF_T_UINT8 *pBuffer, FF_T_UINT16 offset, FF_T_UINT16 Value);
void FF_putLong (FF_T_UINT8 *pBuffer, FF_T_UINT16 offset, FF_T_UINT32 Value);
typedef struct {
FF_T_UINT8 u8_0;
FF_T_UINT8 u8_1;
} FF_T_SHORT;
void *FF_Malloc(FF_T_UINT32 allocSize);
void FF_Free(void *pBuffer);
typedef struct {
FF_T_UINT8 u8_0;
FF_T_UINT8 u8_1;
FF_T_UINT8 u8_2;
FF_T_UINT8 u8_3;
} FF_T_LONG;
#elif defined(FF_BIG_ENDIAN)
typedef struct {
FF_T_UINT8 u8_1;
FF_T_UINT8 u8_0;
} FF_T_SHORT;
typedef struct {
FF_T_UINT8 u8_3;
FF_T_UINT8 u8_2;
FF_T_UINT8 u8_1;
FF_T_UINT8 u8_0;
} FF_T_LONG;
#else
#error Little or Big Endian?
#endif
//! 16-bit union.
typedef union {
FF_T_UINT16 u16;
FF_T_SHORT bytes;
} FF_T_UN16;
//! 32-bit union.
typedef union {
FF_T_UINT32 u32;
FF_T_LONG bytes;
} FF_T_UN32;
/* HT inlined these functions:
*/
#ifdef FF_INLINE_MEMORY_ACCESS
FF_INLINE FF_T_UINT8 FF_getChar(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset)
{
return (FF_T_UINT8) (pBuffer[aOffset]);
}
FF_INLINE FF_T_UINT16 FF_getShort(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset)
{
FF_T_UN16 u16;
pBuffer += aOffset;
u16.bytes.u8_1 = pBuffer[1];
u16.bytes.u8_0 = pBuffer[0];
return u16.u16;
}
FF_INLINE FF_T_UINT32 FF_getLong(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset) {
FF_T_UN32 u32;
pBuffer += aOffset;
u32.bytes.u8_3 = pBuffer[3];
u32.bytes.u8_2 = pBuffer[2];
u32.bytes.u8_1 = pBuffer[1];
u32.bytes.u8_0 = pBuffer[0];
return u32.u32;
}
FF_INLINE void FF_putChar(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset, FF_T_UINT8 Value) {
pBuffer[aOffset] = Value;
}
FF_INLINE void FF_putShort(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset, FF_T_UINT16 Value) {
FF_T_UN16 u16;
u16.u16 = Value;
pBuffer += aOffset;
pBuffer[0] = u16.bytes.u8_0;
pBuffer[1] = u16.bytes.u8_1;
}
FF_INLINE void FF_putLong(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset, FF_T_UINT32 Value) {
FF_T_UN32 u32;
u32.u32 = Value;
pBuffer += aOffset;
pBuffer[0] = u32.bytes.u8_0;
pBuffer[1] = u32.bytes.u8_1;
pBuffer[2] = u32.bytes.u8_2;
pBuffer[3] = u32.bytes.u8_3;
}
#else
FF_T_UINT8 FF_getChar(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset);
FF_T_UINT16 FF_getShort(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset);
FF_T_UINT32 FF_getLong(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset);
void FF_putChar(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset, FF_T_UINT8 Value);
void FF_putShort(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset, FF_T_UINT16 Value);
void FF_putLong(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset, FF_T_UINT32 Value);
#endif
#endif

View file

@ -32,6 +32,10 @@
#ifndef _FULLFAT_H_
#define _FULLFAT_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "ff_config.h"
#include "ff_ioman.h"
#include "ff_fat.h"
@ -41,6 +45,10 @@
#include "ff_crc.h"
#include "ff_hash.h"
#include "ff_string.h"
//#include "ff_format.h"
#ifdef __cplusplus
} // extern "C"
#endif
#endif

View file

@ -1769,4 +1769,3 @@ void FF_RmLFNs(FF_IOMAN *pIoman, FF_T_UINT32 DirCluster, FF_T_UINT16 DirEntry) {
}while(FF_getChar(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_ATTRIB)) == FF_FAT_ATTR_LFN);
}

View file

@ -43,7 +43,7 @@
#include "ff_ioman.h"
#include "ff_blk.h"
#include "ff_fat.h"
#include "fat.h"
#include "ff_fatdef.h"
#include "ff_memory.h"
#include "ff_time.h"
#include "ff_hash.h"

View file

@ -136,13 +136,13 @@ FF_T_SINT32 FF_getFatEntry(FF_IOMAN *pIoman, FF_T_UINT32 nCluster) {
FatSectorEntry = FatOffset % pIoman->pPartition->BlkSize;
LBAadjust = (FF_T_UINT8) (FatSectorEntry / pIoman->BlkSize);
relClusterEntry = (FF_T_UINT16) (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 == (pIoman->BlkSize - 1)) {
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);
@ -333,7 +333,7 @@ FF_T_SINT8 FF_putFatEntry(FF_IOMAN *pIoman, FF_T_UINT32 nCluster, FF_T_UINT32 Va
FF_T_UINT32 FatSectorEntry;
FF_T_UINT32 FatEntry;
FF_T_UINT8 LBAadjust;
FF_T_UINT16 relClusterEntry;
FF_T_UINT32 relClusterEntry;
#ifdef FF_FAT12_SUPPORT
FF_T_UINT8 F12short[2]; // For FAT12 FAT Table Across sector boundary traversal.
#endif
@ -350,13 +350,13 @@ FF_T_SINT8 FF_putFatEntry(FF_IOMAN *pIoman, FF_T_UINT32 nCluster, FF_T_UINT32 Va
FatSectorEntry = FatOffset % pIoman->pPartition->BlkSize;
LBAadjust = (FF_T_UINT8) (FatSectorEntry / pIoman->BlkSize);
relClusterEntry = (FF_T_UINT16)(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_UINT16) (pIoman->BlkSize - 1)) {
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);
@ -497,6 +497,11 @@ FF_T_UINT32 FF_FindFreeCluster(FF_IOMAN *pIoman) {
for(i = FatSector; i < pIoman->pPartition->SectorsPerFAT; i++) {
pBuffer = FF_GetBuffer(pIoman, pIoman->pPartition->FatBeginLBA + i, FF_MODE_READ);
{
// HT addition: don't use non-existing clusters
if (nCluster >= pIoman->pPartition->NumClusters) {
FF_ReleaseBuffer(pIoman, pBuffer);
return 0;
}
for(x = nCluster % EntriesPerSector; x < EntriesPerSector; x++) {
if(pIoman->pPartition->Type == FF_T_FAT32) {
FatOffset = x * 4;
@ -612,6 +617,7 @@ FF_T_SINT8 FF_UnlinkClusterChain(FF_IOMAN *pIoman, FF_T_UINT32 StartCluster, FF_
FF_T_UINT32 fatEntry;
FF_T_UINT32 currentCluster, chainLength = 0;
FF_T_UINT32 iLen = 0;
FF_T_UINT32 lastFree = StartCluster; /* HT addition : reset LastFreeCluster */
fatEntry = StartCluster;
@ -622,9 +628,15 @@ FF_T_SINT8 FF_UnlinkClusterChain(FF_IOMAN *pIoman, FF_T_UINT32 StartCluster, FF_
do {
fatEntry = FF_getFatEntry(pIoman, fatEntry);
FF_putFatEntry(pIoman, currentCluster, 0x00000000);
if (lastFree > currentCluster) {
lastFree = currentCluster;
}
currentCluster = fatEntry;
iLen ++;
}while(!FF_isEndOfChain(pIoman, fatEntry));
if (pIoman->pPartition->LastFreeCluster > lastFree) {
pIoman->pPartition->LastFreeCluster = lastFree;
}
FF_IncreaseFreeClusters(pIoman, iLen);
} else {
// Truncation - This is quite hard, because we can only do it backwards.
@ -694,7 +706,7 @@ FF_T_UINT32 FF_CountFreeClusters(FF_IOMAN *pIoman) {
} else {
FatOffset = x * 2;
FatSectorEntry = FatOffset % pIoman->pPartition->BlkSize;
FatEntry = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, (FF_T_UINT16)FatSectorEntry);
FatEntry = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, FatSectorEntry);
}
if(FatEntry == 0x00000000) {
FreeClusters += 1;
@ -706,7 +718,7 @@ FF_T_UINT32 FF_CountFreeClusters(FF_IOMAN *pIoman) {
FF_ReleaseBuffer(pIoman, pBuffer);
}
return FreeClusters;
return FreeClusters <= pIoman->pPartition->NumClusters ? FreeClusters : pIoman->pPartition->NumClusters;
}
#ifdef FF_64_NUM_SUPPORT
@ -747,4 +759,4 @@ FF_T_UINT32 FF_GetFreeSize(FF_IOMAN *pIoman) {
}
return 0;
}
#endif
#endif

View file

@ -163,7 +163,7 @@ FF_FILE *FF_Open(FF_IOMAN *pIoman, const FF_T_INT8 *path, FF_T_UINT8 Mode, FF_ER
}
return (FF_FILE *)NULL;
}
pFile = FF_Malloc(sizeof(FF_FILE));
pFile = FF_MALLOC(sizeof(FF_FILE));
if(!pFile) {
if(pError) {
*pError = FF_ERR_NOT_ENOUGH_MEMORY;
@ -222,7 +222,7 @@ FF_FILE *FF_Open(FF_IOMAN *pIoman, const FF_T_INT8 *path, FF_T_UINT8 Mode, FF_ER
if(Object.Attrib == FF_FAT_ATTR_DIR) {
if(!(pFile->Mode & FF_MODE_DIR)) {
// Not the object, File Not Found!
FF_Free(pFile);
FF_FREE(pFile);
if(pError) {
*pError = FF_ERR_FILE_OBJECT_IS_A_DIR;
}
@ -233,7 +233,7 @@ FF_FILE *FF_Open(FF_IOMAN *pIoman, const FF_T_INT8 *path, FF_T_UINT8 Mode, FF_ER
//---------- Ensure Read-Only files don't get opened for Writing.
if((pFile->Mode & FF_MODE_WRITE) || (pFile->Mode & FF_MODE_APPEND)) {
if((Object.Attrib & FF_FAT_ATTR_READONLY)) {
FF_Free(pFile);
FF_FREE(pFile);
if(pError) {
*pError = FF_ERR_FILE_IS_READ_ONLY;
}
@ -276,7 +276,7 @@ FF_FILE *FF_Open(FF_IOMAN *pIoman, const FF_T_INT8 *path, FF_T_UINT8 Mode, FF_ER
if(pFileChain->ObjectCluster == pFile->ObjectCluster) {
// File is already open! DON'T ALLOW IT!
FF_ReleaseSemaphore(pIoman->pSemaphore);
FF_Free(pFile);
FF_FREE(pFile);
if(pError) {
*pError = FF_ERR_FILE_ALREADY_OPEN;
}
@ -294,7 +294,7 @@ FF_FILE *FF_Open(FF_IOMAN *pIoman, const FF_T_INT8 *path, FF_T_UINT8 Mode, FF_ER
return pFile;
}else {
FF_Free(pFile);
FF_FREE(pFile);
if(pError) {
*pError = FF_ERR_FILE_NOT_FOUND;
}
@ -305,7 +305,7 @@ FF_FILE *FF_Open(FF_IOMAN *pIoman, const FF_T_INT8 *path, FF_T_UINT8 Mode, FF_ER
*pError = FF_ERR_FILE_INVALID_PATH;
}
FF_Free(pFile);
FF_FREE(pFile);
return (FF_FILE *)NULL;
}
@ -600,7 +600,14 @@ static FF_T_SINT32 FF_ReadClusters(FF_FILE *pFile, FF_T_UINT32 Count, FF_T_UINT8
do {
if(pFile->pIoman->pBlkDevice->fnReadBlocks) {
#ifdef FF_BLKDEV_USES_SEM
FF_PendSemaphore(pFile->pIoman->pSemaphore);
#endif
// Called from FF_Read, sem not claimed
RetVal = pFile->pIoman->pBlkDevice->fnReadBlocks(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);
@ -703,7 +710,14 @@ static FF_T_SINT32 FF_WriteClusters(FF_FILE *pFile, FF_T_UINT32 Count, FF_T_UINT
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);
@ -832,7 +846,13 @@ FF_T_SINT32 FF_Read(FF_FILE *pFile, FF_T_UINT32 ElementSize, FF_T_UINT32 Count,
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();
@ -887,7 +907,13 @@ FF_T_SINT32 FF_Read(FF_FILE *pFile, FF_T_UINT32 ElementSize, FF_T_UINT32 Count,
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();
@ -1116,7 +1142,13 @@ FF_T_SINT32 FF_Write(FF_FILE *pFile, FF_T_UINT32 ElementSize, FF_T_UINT32 Count,
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();
@ -1174,7 +1206,13 @@ FF_T_SINT32 FF_Write(FF_FILE *pFile, FF_T_UINT32 ElementSize, FF_T_UINT32 Count,
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();
@ -1405,7 +1443,7 @@ FF_ERROR FF_Close(FF_FILE *pFile) {
FF_ReleaseSemaphore(pFile->pIoman->pSemaphore);
// If file written, flush to disk
FF_Free(pFile);
FF_FREE(pFile);
// Simply free the pointer!
return FF_ERR_NONE;
}

View file

@ -53,7 +53,7 @@ struct _FF_HASH_TABLE {
*
**/
FF_HASH_TABLE FF_CreateHashTable() {
FF_HASH_TABLE pHash = (FF_HASH_TABLE) FF_Malloc(sizeof(struct _FF_HASH_TABLE));
FF_HASH_TABLE pHash = (FF_HASH_TABLE) FF_MALLOC(sizeof(struct _FF_HASH_TABLE));
if(pHash) {
FF_ClearHashTable(pHash);
@ -110,7 +110,7 @@ FF_T_BOOL FF_isHashSet(FF_HASH_TABLE pHash, FF_T_UINT32 nHash) {
FF_ERROR FF_DestroyHashTable(FF_HASH_TABLE pHash) {
if(pHash) {
free(pHash);
FF_FREE(pHash);
return FF_ERR_NONE;
}
return FF_ERR_NULL_POINTER;

View file

@ -42,8 +42,10 @@
* Destroying a FullFAT IO object.
**/
#include <string.h>
#include "ff_ioman.h" // Includes ff_types.h, ff_safety.h, <stdio.h>
#include "fat.h"
#include "ff_fatdef.h"
extern FF_T_UINT32 FF_FindFreeCluster (FF_IOMAN *pIoman);
extern FF_T_UINT32 FF_CountFreeClusters (FF_IOMAN *pIoman);
@ -89,7 +91,7 @@ FF_IOMAN *FF_CreateIOMAN(FF_T_UINT8 *pCacheMem, FF_T_UINT32 Size, FF_T_UINT16 Bl
return NULL; // Memory Size not a multiple of BlkSize > 0
}
pIoman = (FF_IOMAN *) FF_Malloc(sizeof(FF_IOMAN));
pIoman = (FF_IOMAN *) FF_MALLOC(sizeof(FF_IOMAN));
if(!pIoman) { // Ensure malloc() succeeded.
if(pError) {
@ -98,62 +100,68 @@ FF_IOMAN *FF_CreateIOMAN(FF_T_UINT8 *pCacheMem, FF_T_UINT32 Size, FF_T_UINT16 Bl
return NULL;
}
memset (pIoman, '\0', sizeof(FF_IOMAN));
// This is just a bit-mask, to use a byte to keep track of memory.
// pIoman->MemAllocation = 0x00; // Unset all allocation identifiers.
pIoman->pBlkDevice = NULL;
pIoman->pBuffers = NULL;
pIoman->pCacheMem = NULL;
pIoman->pPartition = NULL;
pIoman->pSemaphore = NULL;
pIoman->pPartition = (FF_PARTITION *) FF_Malloc(sizeof(FF_PARTITION));
if(pIoman->pPartition) { // If succeeded, flag that allocation.
pIoman->MemAllocation |= FF_IOMAN_ALLOC_PART;
pIoman->pPartition->LastFreeCluster = 0;
pIoman->pPartition->PartitionMounted = FF_FALSE; // This should be checked by FF_Open();
#ifdef FF_PATH_CACHE
pIoman->pPartition->PCIndex = 0;
for(i = 0; i < FF_PATH_CACHE_DEPTH; i++) {
pIoman->pPartition->PathCache[i].DirCluster = 0;
pIoman->pPartition->PathCache[i].Path[0] = '\0';
#ifdef FF_HASH_TABLE_SUPPORT
pIoman->pPartition->PathCache[i].pHashTable = FF_CreateHashTable();
pIoman->pPartition->PathCache[i].bHashed = FF_FALSE;
#endif
pIoman->pPartition = (FF_PARTITION *) FF_MALLOC(sizeof(FF_PARTITION));
if(!pIoman->pPartition) {
if(pError) {
*pError = FF_ERR_NOT_ENOUGH_MEMORY;
}
FF_DestroyIOMAN(pIoman);
return NULL;
}
memset (pIoman->pPartition, '\0', sizeof(FF_PARTITION));
pIoman->MemAllocation |= FF_IOMAN_ALLOC_PART; // If succeeded, flag that allocation.
pIoman->pPartition->LastFreeCluster = 0;
pIoman->pPartition->PartitionMounted = FF_FALSE; // This should be checked by FF_Open();
#ifdef FF_PATH_CACHE
pIoman->pPartition->PCIndex = 0;
for(i = 0; i < FF_PATH_CACHE_DEPTH; i++) {
pIoman->pPartition->PathCache[i].DirCluster = 0;
pIoman->pPartition->PathCache[i].Path[0] = '\0';
#ifdef FF_HASH_TABLE_SUPPORT
pIoman->pPartition->PathCache[i].pHashTable = FF_CreateHashTable();
pIoman->pPartition->PathCache[i].bHashed = FF_FALSE;
#endif
} else {
}
#endif
pIoman->pBlkDevice = (FF_BLK_DEVICE *) FF_MALLOC(sizeof(FF_BLK_DEVICE));
if(!pIoman->pBlkDevice) { // If succeeded, flag that allocation.
if(pError) {
*pError = FF_ERR_NOT_ENOUGH_MEMORY;
}
FF_DestroyIOMAN(pIoman);
return NULL;
}
memset (pIoman->pBlkDevice, '\0', sizeof(FF_BLK_DEVICE));
pIoman->MemAllocation |= FF_IOMAN_ALLOC_BLKDEV;
pIoman->pBlkDevice = (FF_BLK_DEVICE *) FF_Malloc(sizeof(FF_BLK_DEVICE));
if(pIoman->pBlkDevice) { // If succeeded, flag that allocation.
pIoman->MemAllocation |= FF_IOMAN_ALLOC_BLKDEV;
// Make sure all pointers are NULL
pIoman->pBlkDevice->fnReadBlocks = NULL;
pIoman->pBlkDevice->fnWriteBlocks = NULL;
pIoman->pBlkDevice->pParam = NULL;
} else {
FF_DestroyIOMAN(pIoman);
return NULL;
}
// Make sure all pointers are NULL
pIoman->pBlkDevice->fnReadBlocks = NULL;
pIoman->pBlkDevice->fnWriteBlocks = NULL;
pIoman->pBlkDevice->pParam = NULL;
// Organise the memory provided, or create our own!
if(pCacheMem) {
pIoman->pCacheMem = pCacheMem;
}else { // No-Cache buffer provided (malloc)
pLong = (FF_T_UINT32 *) FF_Malloc(Size);
pLong = (FF_T_UINT32 *) FF_MALLOC(Size);
pIoman->pCacheMem = (FF_T_UINT8 *) pLong;
if(!pIoman->pCacheMem) {
pIoman->MemAllocation |= FF_IOMAN_ALLOC_BUFFERS;
if(pError) {
*pError = FF_ERR_NOT_ENOUGH_MEMORY;
}
FF_DestroyIOMAN(pIoman);
return NULL;
}
pIoman->MemAllocation |= FF_IOMAN_ALLOC_BUFFERS;
}
memset (pIoman->pCacheMem, '\0', Size);
pIoman->BlkSize = BlkSize;
pIoman->CacheSize = (FF_T_UINT16) (Size / BlkSize);
@ -163,14 +171,19 @@ FF_IOMAN *FF_CreateIOMAN(FF_T_UINT8 *pCacheMem, FF_T_UINT32 Size, FF_T_UINT16 Bl
/* Malloc() memory for buffer objects. (FullFAT never refers to a buffer directly
but uses buffer objects instead. Allows us to provide thread safety.
*/
pIoman->pBuffers = (FF_BUFFER *) FF_Malloc(sizeof(FF_BUFFER) * pIoman->CacheSize);
pIoman->pBuffers = (FF_BUFFER *) FF_MALLOC(sizeof(FF_BUFFER) * pIoman->CacheSize);
if(pIoman->pBuffers) {
pIoman->MemAllocation |= FF_IOMAN_ALLOC_BUFDESCR;
FF_IOMAN_InitBufferDescriptors(pIoman);
} else {
if(!pIoman->pBuffers) {
if(pError) {
*pError = FF_ERR_NOT_ENOUGH_MEMORY;
}
FF_DestroyIOMAN(pIoman);
return NULL; // HT added
}
memset (pIoman->pBuffers, '\0', sizeof(FF_BUFFER) * pIoman->CacheSize);
pIoman->MemAllocation |= FF_IOMAN_ALLOC_BUFDESCR;
FF_IOMAN_InitBufferDescriptors(pIoman);
// Finally create a Semaphore for Buffer Description modifications.
pIoman->pSemaphore = FF_CreateSemaphore();
@ -196,22 +209,22 @@ FF_ERROR FF_DestroyIOMAN(FF_IOMAN *pIoman) {
// Ensure pPartition pointer was allocated.
if((pIoman->MemAllocation & FF_IOMAN_ALLOC_PART)) {
FF_Free(pIoman->pPartition);
FF_FREE(pIoman->pPartition);
}
// Ensure pBlkDevice pointer was allocated.
if((pIoman->MemAllocation & FF_IOMAN_ALLOC_BLKDEV)) {
FF_Free(pIoman->pBlkDevice);
FF_FREE(pIoman->pBlkDevice);
}
// Ensure pBuffers pointer was allocated.
if((pIoman->MemAllocation & FF_IOMAN_ALLOC_BUFDESCR)) {
FF_Free(pIoman->pBuffers);
FF_FREE(pIoman->pBuffers);
}
// Ensure pCacheMem pointer was allocated.
if((pIoman->MemAllocation & FF_IOMAN_ALLOC_BUFFERS)) {
FF_Free(pIoman->pCacheMem);
FF_FREE(pIoman->pCacheMem);
}
// Destroy any Semaphore that was created.
@ -220,7 +233,7 @@ FF_ERROR FF_DestroyIOMAN(FF_IOMAN *pIoman) {
}
// Finally free the FF_IOMAN object.
FF_Free(pIoman);
FF_FREE(pIoman);
return FF_ERR_NONE;
}
@ -236,15 +249,9 @@ static void FF_IOMAN_InitBufferDescriptors(FF_IOMAN *pIoman) {
FF_T_UINT16 i;
FF_BUFFER *pBuffer = pIoman->pBuffers;
pIoman->LastReplaced = 0;
// HT : it is assmued that pBuffer was cleared by memset ()
for(i = 0; i < pIoman->CacheSize; i++) {
pBuffer->Mode = 0;
pBuffer->NumHandles = 0;
pBuffer->Persistance = 0;
pBuffer->LRU = 0;
pBuffer->Sector = 0;
pBuffer->pBuffer = (FF_T_UINT8 *)((pIoman->pCacheMem) + (pIoman->BlkSize * i));
pBuffer->Modified = FF_FALSE;
pBuffer->Valid = FF_FALSE;
pBuffer++;
}
}
@ -273,12 +280,15 @@ static void FF_IOMAN_InitBufferDescriptors(FF_IOMAN *pIoman) {
* @param Sector LBA address of the sector to fetch.
* @param pBuffer Pointer to a byte-wise buffer to store the fetched data.
*
* HT Note: will be called while semaphore claimed (by FF_GetBuffer)
*
* @return FF_TRUE when valid, else FF_FALSE.
**/
static FF_ERROR FF_IOMAN_FillBuffer(FF_IOMAN *pIoman, FF_T_UINT32 Sector, FF_T_UINT8 *pBuffer) {
FF_T_SINT32 retVal = 0;
if(pIoman->pBlkDevice->fnReadBlocks) { // Make sure we don't execute a NULL.
do{
// Called from FF_GetBuffer with semaphore claimed
retVal = pIoman->pBlkDevice->fnReadBlocks(pBuffer, Sector, 1, pIoman->pBlkDevice->pParam);
if(retVal == FF_ERR_DRIVER_BUSY) {
FF_Sleep(FF_DRIVER_BUSY_SLEEP);
@ -306,9 +316,13 @@ static FF_ERROR FF_IOMAN_FillBuffer(FF_IOMAN *pIoman, FF_T_UINT32 Sector, FF_T_U
* @param Sector LBA address of the sector to fetch.
* @param pBuffer Pointer to a byte-wise buffer to store the fetched data.
*
*
* HT made it a globally accesible function to be used by new module ff_format.c
* Note that this function is called when semaphore is already locked
*
* @return FF_TRUE when valid, else FF_FALSE.
**/
static FF_ERROR FF_IOMAN_FlushBuffer(FF_IOMAN *pIoman, FF_T_UINT32 Sector, FF_T_UINT8 *pBuffer) {
/* static */ FF_ERROR FF_IOMAN_FlushBuffer(FF_IOMAN *pIoman, FF_T_UINT32 Sector, FF_T_UINT8 *pBuffer) {
FF_T_SINT32 retVal = 0;
if(pIoman->pBlkDevice->fnWriteBlocks) { // Make sure we don't execute a NULL.
do{
@ -481,7 +495,7 @@ FF_BUFFER *FF_GetBuffer(FF_IOMAN *pIoman, FF_T_UINT32 Sector, FF_T_UINT8 Mode) {
}
}
FF_ReleaseSemaphore(pIoman->pSemaphore);
FF_Yield();
FF_Yield(); // Better to go asleep to give low-priority task a chance to release buffer(s)
}
return pBufMatch; // Return the Matched Buffer!
@ -500,7 +514,11 @@ void FF_ReleaseBuffer(FF_IOMAN *pIoman, FF_BUFFER *pBuffer) {
// Protect description changes with a semaphore.
FF_PendSemaphore(pIoman->pSemaphore);
{
pBuffer->NumHandles--;
if (pBuffer->NumHandles) {
pBuffer->NumHandles--;
} else {
//printf ("FF_ReleaseBuffer: buffer not claimed\n");
}
}
FF_ReleaseSemaphore(pIoman->pSemaphore);
}
@ -630,6 +648,34 @@ static FF_ERROR FF_DetermineFatType(FF_IOMAN *pIoman) {
return FF_ERR_IOMAN_NOT_FAT_FORMATTED;
}
static FF_T_SINT8 FF_PartitionCount (FF_T_UINT8 *pBuffer)
{
FF_T_SINT8 count = 0;
FF_T_SINT8 part;
// Check PBR or MBR signature
if (FF_getChar(pBuffer, FF_FAT_MBR_SIGNATURE) != 0x55 &&
FF_getChar(pBuffer, FF_FAT_MBR_SIGNATURE) != 0xAA ) {
// No MBR, but is it a PBR ?
if (FF_getChar(pBuffer, 0) == 0xEB && // PBR Byte 0
FF_getChar(pBuffer, 2) == 0x90 && // PBR Byte 2
(FF_getChar(pBuffer, 21) & 0xF0) == 0xF0) {// PBR Byte 21 : Media byte
return 1; // No MBR but PBR exist then only one partition
}
return 0; // No MBR and no PBR then no partition found
}
for (part = 0; part < 4; part++) {
FF_T_UINT8 active = FF_getChar(pBuffer, FF_FAT_PTBL + FF_FAT_PTBL_ACTIVE + (16 * part));
FF_T_UINT8 part_id = FF_getChar(pBuffer, FF_FAT_PTBL + FF_FAT_PTBL_ID + (16 * part));
// The first sector must be a MBR, then check the partition entry in the MBR
if (active != 0x80 && (active != 0 || part_id == 0)) {
break;
}
count++;
}
return count;
}
/**
* @public
* @brief Mounts the Specified partition, the volume specified by the FF_IOMAN object provided.
@ -651,6 +697,7 @@ static FF_ERROR FF_DetermineFatType(FF_IOMAN *pIoman) {
FF_ERROR FF_MountPartition(FF_IOMAN *pIoman, FF_T_UINT8 PartitionNumber) {
FF_PARTITION *pPart;
FF_BUFFER *pBuffer = 0;
int partCount;
if(!pIoman) {
return FF_ERR_NULL_POINTER;
@ -662,18 +709,27 @@ FF_ERROR FF_MountPartition(FF_IOMAN *pIoman, FF_T_UINT8 PartitionNumber) {
pPart = pIoman->pPartition;
memset (pIoman->pBuffers, '\0', sizeof(FF_BUFFER) * pIoman->CacheSize);
memset (pIoman->pCacheMem, '\0', pIoman->BlkSize * pIoman->CacheSize);
FF_IOMAN_InitBufferDescriptors(pIoman);
pIoman->FirstFile = 0;
pBuffer = FF_GetBuffer(pIoman, 0, FF_MODE_READ);
if(!pBuffer) {
return FF_ERR_DEVICE_DRIVER_FAILED;
}
partCount = FF_PartitionCount (pBuffer->pBuffer);
pPart->BlkSize = FF_getShort(pBuffer->pBuffer, FF_FAT_BYTES_PER_SECTOR);
if((pPart->BlkSize % 512) == 0 && pPart->BlkSize > 0) {
if (partCount == 0) { //(pPart->BlkSize % 512) == 0 && pPart->BlkSize > 0) {
// Volume is not partitioned (MBR Found)
pPart->BeginLBA = 0;
} else {
// Primary Partitions to deal with!
pPart->BeginLBA = FF_getLong(pBuffer->pBuffer, (FF_T_UINT16)(FF_FAT_PTBL + FF_FAT_PTBL_LBA + (16 * PartitionNumber)));
pPart->BeginLBA = FF_getLong(pBuffer->pBuffer, FF_FAT_PTBL + FF_FAT_PTBL_LBA + (16 * PartitionNumber));
FF_ReleaseBuffer(pIoman, pBuffer);
if(!pPart->BeginLBA) {
@ -690,6 +746,7 @@ FF_ERROR FF_MountPartition(FF_IOMAN *pIoman, FF_T_UINT8 PartitionNumber) {
return FF_ERR_IOMAN_INVALID_FORMAT;
}
}
// Assume FAT16, then we'll adjust if its FAT32
pPart->ReservedSectors = FF_getShort(pBuffer->pBuffer, FF_FAT_RESERVED_SECTORS);
pPart->FatBeginLBA = pPart->BeginLBA + pPart->ReservedSectors;
@ -709,6 +766,7 @@ FF_ERROR FF_MountPartition(FF_IOMAN *pIoman, FF_T_UINT8 PartitionNumber) {
if(pPart->TotalSectors == 0) {
pPart->TotalSectors = FF_getLong(pBuffer->pBuffer, FF_FAT_32_TOTAL_SECTORS);
}
memcpy (pPart->VolLabel, pBuffer->pBuffer + FF_FAT_32_VOL_LABEL, sizeof pPart->VolLabel);
} else { // FAT16
pPart->ClusterBeginLBA = pPart->BeginLBA + pPart->ReservedSectors + (pPart->NumFATS * pPart->SectorsPerFAT);
pPart->TotalSectors = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, FF_FAT_16_TOTAL_SECTORS);
@ -716,6 +774,7 @@ FF_ERROR FF_MountPartition(FF_IOMAN *pIoman, FF_T_UINT8 PartitionNumber) {
if(pPart->TotalSectors == 0) {
pPart->TotalSectors = FF_getLong(pBuffer->pBuffer, FF_FAT_32_TOTAL_SECTORS);
}
memcpy (pPart->VolLabel, pBuffer->pBuffer + FF_FAT_16_VOL_LABEL, sizeof pPart->VolLabel);
}
FF_ReleaseBuffer(pIoman, pBuffer); // Release the buffer finally!

View file

@ -48,87 +48,55 @@
#include "ff_memory.h"
#include "ff_config.h"
#ifdef FF_LITTLE_ENDIAN
/**
* @public
* @brief 8 bit memory access routines.
**/
/*
These functions swap the byte-orders of shorts and longs. A getChar function is provided
incase there is a system that doesn't have byte-wise access to all memory.
* HT inlined these functions
*
* Not much left for the C-module
*/
These functions can be replaced with your own platform specific byte-order swapping routines
for more efficiency.
The provided functions should work on almost all platforms.
*/
FF_T_UINT8 FF_getChar(FF_T_UINT8 *pBuffer, FF_T_UINT16 offset) {
return (FF_T_UINT8) (pBuffer[offset]);
#ifndef FF_INLINE_MEMORY_ACCESS
FF_T_UINT8 FF_getChar(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset) {
return (FF_T_UINT8) (pBuffer[aOffset]);
}
FF_T_UINT16 FF_getShort(FF_T_UINT8 *pBuffer, FF_T_UINT16 offset) {
return (FF_T_UINT16) (pBuffer[offset] & 0x00FF) | ((FF_T_UINT16) (pBuffer[offset+1] << 8) & 0xFF00);
FF_T_UINT16 FF_getShort(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset) {
FF_T_UN16 u16;
pBuffer += aOffset;
u16.bytes.u8_1 = pBuffer[1];
u16.bytes.u8_0 = pBuffer[0];
return u16.u16;
}
FF_T_UINT32 FF_getLong(FF_T_UINT8 *pBuffer, FF_T_UINT16 offset) {
return (FF_T_UINT32) (pBuffer[offset] & 0x000000FF) | ((FF_T_UINT32) (pBuffer[offset+1] << 8) & 0x0000FF00) | ((FF_T_UINT32) (pBuffer[offset+2] << 16) & 0x00FF0000) | ((FF_T_UINT32) (pBuffer[offset+3] << 24) & 0xFF000000);
FF_T_UINT32 FF_getLong(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset) {
FF_T_UN32 u32;
pBuffer += aOffset;
u32.bytes.u8_3 = pBuffer[3];
u32.bytes.u8_2 = pBuffer[2];
u32.bytes.u8_1 = pBuffer[1];
u32.bytes.u8_0 = pBuffer[0];
return u32.u32;
}
void FF_putChar(FF_T_UINT8 *pBuffer, FF_T_UINT16 offset, FF_T_UINT8 Value) {
pBuffer[offset] = Value;
void FF_putChar(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset, FF_T_UINT8 Value) {
pBuffer[aOffset] = Value;
}
void FF_putShort(FF_T_UINT8 *pBuffer, FF_T_UINT16 offset, FF_T_UINT16 Value) {
FF_T_UINT8 *Val = (FF_T_UINT8 *) &Value;
pBuffer[offset] = Val[0];
pBuffer[offset + 1] = Val[1];
void FF_putShort(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset, FF_T_UINT16 Value) {
FF_T_UN16 u16;
u16.u16 = Value;
pBuffer += aOffset;
pBuffer[0] = u16.bytes.u8_0;
pBuffer[1] = u16.bytes.u8_1;
}
void FF_putLong(FF_T_UINT8 *pBuffer, FF_T_UINT16 offset, FF_T_UINT32 Value) {
FF_T_UINT8 *Val = (FF_T_UINT8 *) &Value;
pBuffer[offset] = Val[0];
pBuffer[offset + 1] = Val[1];
pBuffer[offset + 2] = Val[2];
pBuffer[offset + 3] = Val[3];
}
#endif
#ifdef FF_BIG_ENDIAN
/*
These haven't been tested or checked. They should work in theory :)
Please contact james@worm.me.uk if they don't work, and also any fix.
*/
FF_T_UINT8 FF_getChar(FF_T_UINT8 *pBuffer, FF_T_UINT16 offset) {
return (FF_T_UINT8) (pBuffer[offset]);
}
FF_T_UINT16 FF_getShort(FF_T_UINT8 *pBuffer, FF_T_UINT16 offset) {
return (FF_T_UINT16) ((pBuffer[offset] & 0xFF00) << 8) | ((FF_T_UINT16) (pBuffer[offset+1]) & 0x00FF);
}
FF_T_UINT32 FF_getLong(FF_T_UINT8 *pBuffer, FF_T_UINT16 offset) {
return (FF_T_UINT32) ((pBuffer[offset] << 24) & 0xFF0000) | ((FF_T_UINT32) (pBuffer[offset+1] << 16) & 0x00FF0000) | ((FF_T_UINT32) (pBuffer[offset+2] << 8) & 0x0000FF00) | ((FF_T_UINT32) (pBuffer[offset+3]) & 0x000000FF);
}
void FF_putChar(FF_T_UINT8 *pBuffer, FF_T_UINT16 offset, FF_T_UINT8 Value) {
pBuffer[offset] = Value;
}
void FF_putShort(FF_T_UINT8 *pBuffer, FF_T_UINT16 offset, FF_T_UINT16 Value) {
FF_T_UINT8 *Val = (FF_T_UINT8 *) &Value;
pBuffer[offset] = Val[1];
pBuffer[offset + 1] = Val[0];
}
void FF_putLong(FF_T_UINT8 *pBuffer, FF_T_UINT16 offset, FF_T_UINT32 Value) {
FF_T_UINT8 *Val = (FF_T_UINT8 *) &Value;
pBuffer[offset] = Val[3];
pBuffer[offset + 1] = Val[2];
pBuffer[offset + 2] = Val[1];
pBuffer[offset + 3] = Val[0];
void FF_putLong(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset, FF_T_UINT32 Value) {
FF_T_UN32 u32;
u32.u32 = Value;
pBuffer += aOffset;
pBuffer[0] = u32.bytes.u8_0;
pBuffer[1] = u32.bytes.u8_1;
pBuffer[2] = u32.bytes.u8_2;
pBuffer[3] = u32.bytes.u8_3;
}
#endif