⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat.c

📁 看到最近大家都关心 usbhost 的实现, 论坛上能找到的代码仅是一些简单的 demo , 完整的源码级的协议层是找不到的 我就贡献一把, 将我前一段时间移植成功的 USBHost 代码奉上 注
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
  gba_nds_fat.c
  By chishm (Michael Chisholm)

  Routines for reading a compact flash card
  using the GBA Movie Player or M3.

  Some FAT routines are based on those in fat.c, which
  is part of avrlib by Pascal Stang.

  This software is completely free. No warranty is provided.
  If you use it, please give me credit and email me about your
  project at chishm@hotmail.com

  See gba_nds_fat.txt for help and license details.
*/

//---------------------------------------------------------------
// Includes

#include "fat.h"
#include <string.h>
#include "..\main\sys.h"
#include "..\hardware\hardware.h"
//----------------------------------------------------------------
// Data  types
#ifndef  NULL
 #define  NULL  0
#endif

//----------------------------------------------------------------
// NDS memory access control register
#ifdef NDS
 #ifndef WAIT_CR
  #define WAIT_CR (*(vunsigned short*)0x04000204)
 #endif
#endif

//---------------------------------------------------------------
// Appropriate placement of CF functions and data
#ifdef NDS
 #define _VARS_IN_RAM 
#else
 #define _VARS_IN_RAM __attribute__ ((section (".sbss")))
#endif


//-----------------------------------------------------------------
// FAT constants
#define CLUSTER_EOF_16  0xFFFF
#define CLUSTER_EOF     0x0FFFFFFF
#define CLUSTER_FREE    0x0000
#define CLUSTER_FIRST   0x0002

#define FILE_LAST       0x00
#define FILE_FREE       0xE5

#define FAT16_ROOT_DIR_CLUSTER 0x00


//-----------------------------------------------------------------
// long file name constants
#define LFN_END         0x40
#define LFN_DEL         0x80

//-----------------------------------------------------------------
// Data Structures

// Take care of packing for GCC - it doesn't obey pragma pack()
// properly for ARM targets.

#define BYTE_PER_READ 512

int usbhost_read(unsigned long rblk,unsigned long rcnt,void* rbuffer);
int usbhost_write(unsigned long rblk,unsigned long rcnt,void* rbuffer);

#define disc_ReadSectors(sector, numSecs, buffer) usbhost_read(sector,numSecs,buffer)
#define disc_WriteSectors(sector,numSecs, buffer) usbhost_write(sector,numSecs,buffer)

#define disc_ReadSector(sector,buffer)  usbhost_read(sector,1,buffer)
#define disc_WriteSector(sector,buffer) usbhost_write(sector,1,buffer)
#define disc_Init() 1
#define disc_CacheFlush()
#define disc_ClearStatus()
#define disc_IsInserted() 1

// Boot Sector - must be packed
__packed typedef struct
{
    unsigned char  jmpBoot[3];
    unsigned char  OEMName[8];
    // BIOS Parameter Block
    unsigned short bytesPerSector;
    unsigned char  sectorsPerCluster;
    unsigned short reservedSectors;
    unsigned char  numFATs;
    unsigned short rootEntries;
    unsigned short numSectorsSmall;
    unsigned char  mediaDesc;
    unsigned short sectorsPerFAT;
    unsigned short sectorsPerTrk;
    unsigned short numHeads;
    unsigned int   numHiddenSectors;
    unsigned int   numSectors;
    __packed union  // Different types of extended BIOS Parameter Block for FAT16 and FAT32
    {
      __packed struct  
      {
        // Ext BIOS Parameter Block for FAT16
        unsigned char driveNumber;
        unsigned char reserved1;
        unsigned char extBootSig;
        unsigned int  volumeID;
        unsigned char volumeLabel[11];
        unsigned char fileSysType[8];
        // Bootcode
        unsigned char bootCode[448];
      }  fat16;
      __packed struct  
      {
        // FAT32 extended block
        unsigned int   sectorsPerFAT32;
        unsigned short extFlags;
        unsigned short fsVer;
        unsigned int   rootClus;
        unsigned short fsInfo;
        unsigned short bkBootSec;
        unsigned char  reserved[12];
        // Ext BIOS Parameter Block for FAT16
        unsigned char  driveNumber;
        unsigned char  reserved1;
        unsigned char  extBootSig;
        unsigned int   volumeID;
        unsigned char  volumeLabel[11];
        unsigned char  fileSysType[8];
        // Bootcode
        unsigned char  bootCode[420];
      }  fat32;
    }  extBlock;

  unsigned short  bootSig;

}  BOOT_SEC;

// Directory entry - must be packed
__packed typedef struct
{
    unsigned char   name[8];
    unsigned char   ext[3];
    unsigned char   attrib;
    unsigned char   reserved;
    unsigned char   cTime_ms;
    unsigned short  cTime;
    unsigned short  cDate;
    unsigned short  aDate;
    unsigned short  startClusterHigh;
    unsigned short  mTime;
    unsigned short  mDate;
    unsigned short  startCluster;
    unsigned int    fileSize;
}  DIR_ENT;

// Long file name directory entry - must be packed
__packed typedef struct
{
    unsigned char  ordinal;  // Position within LFN
    unsigned short char0;  
    unsigned short char1;
    unsigned short char2;
    unsigned short char3;
    unsigned short char4;
    unsigned char  flag;  // Should be equal to ATTRIB_LFN
    unsigned char  reserved1;  // Always 0x00
    unsigned char  checkSum;  // Checksum of short file name (alias)
    unsigned short char5;
    unsigned short char6;
    unsigned short char7;
    unsigned short char8;
    unsigned short char9;
    unsigned short char10;
    unsigned short reserved2;  // Always 0x0000
    unsigned short char11;
    unsigned short char12;
}  DIR_ENT_LFN;

static const char lfn_offset_table[13]={0x01,0x03,0x05,0x07,0x09,0x0E,0x10,0x12,0x14,0x16,0x18,0x1C,0x1E}; 

//-----------------------------------------------------------------
// Global Variables

// _VARS_IN_RAM variables are stored in the largest section of WRAM 
// available: IWRAM on NDS ARM7, EWRAM on NDS ARM9 and GBA

// Files
static _VARS_IN_RAM FAT_FILE openFiles[MAX_FILES_OPEN];

// Long File names
static _VARS_IN_RAM char lfnName[MAX_FILENAME_LENGTH];
static char lfnExists;

// Locations on card
static int filesysRootDir;
static int filesysRootDirClus;
static int filesysFAT;
static int filesysSecPerFAT;
static int filesysNumSec;
static int filesysData;
static int filesysBytePerSec;
static int filesysSecPerClus;
static int filesysBytePerClus;

static FS_TYPE filesysType = FS_UNKNOWN;
static unsigned int filesysTotalSize;

// Info about FAT
static unsigned int fatLastCluster;
static unsigned int fatFirstFree;

// fatBuffer used to reduce wear on the CF card from multiple writes
_VARS_IN_RAM char fatBuffer[BYTE_PER_READ];
static unsigned int fatBufferCurSector;

// Current working directory
static unsigned int curWorkDirCluster;

// Position of the directory entry last retreived with FAT_GetDirEntry
static unsigned int wrkDirCluster;
static int wrkDirSector;
static int wrkDirOffset;

// Global sector buffer to save on stack space
static _VARS_IN_RAM unsigned char globalBuffer[BYTE_PER_READ];

//-----------------------------------------------------------------
// 本文件的函数表
        char  ucase (char character);
unsigned short getRTCtoFileTime (void);
unsigned short getRTCtoFileDate (void);

        char  FAT_AddDirEntry (const char* path, DIR_ENT newDirEntry);
        char  FAT_ClearLinks (unsigned int cluster);
     DIR_ENT  FAT_DirEntFromPath (const char* path);
unsigned int  FAT_FirstFreeCluster(void);
     DIR_ENT  FAT_GetDirEntry ( unsigned int dirCluster, int entry, int origin);
unsigned int  FAT_LinkFreeCluster(unsigned int cluster);
unsigned int  FAT_NextCluster(unsigned int cluster);
        char  FAT_WriteFatEntry (unsigned int cluster, unsigned int value);
        char  FAT_GetFilename (DIR_ENT dirEntry, char* alias);
        char  FAT_InitFiles (void);
        char  FAT_FreeFiles (void);
         int  FAT_remove (const char* path);
        char  FAT_chdir (const char* path);
   FILE_TYPE  FAT_FindFirstFile (char* filename);
   FILE_TYPE  FAT_FindNextFile (char* filename);
   FILE_TYPE  FAT_FileExists (const char* filename);
        char  FAT_GetAlias (char* alias);
        char  FAT_GetLongFilename (char* filename);
unsigned int  FAT_GetFileSize (void);
unsigned int  FAT_GetFileCluster (void);

   FAT_FILE*  FAT_fopen(const char* path, const char* mode);
        char  FAT_fclose (FAT_FILE* file);
        char  FAT_feof(FAT_FILE* file);
         int  FAT_fseek(FAT_FILE* file, int offset, int origin);
         int  FAT_ftell (FAT_FILE* file);
unsigned int  FAT_fread (void* buffer, unsigned int size, unsigned int count, FAT_FILE* file);
unsigned int  FAT_fwrite (const void* buffer, unsigned int size, unsigned int count, FAT_FILE* file);
        char  FAT_fgetc (FAT_FILE* file);
        char  FAT_fputc (char c, FAT_FILE* file);

/*-----------------------------------------------------------------
ucase
Returns the uppercase version of the given char
char IN: a character
char return OUT: uppercase version of character
-----------------------------------------------------------------*/
char ucase (char character)
{
  if((character > 0x60) && (character < 0x7B))
  { character = character - 0x20; }
  
  return (character);
}


/*-----------------------------------------------------------------
getRTCtoFileTime and getRTCtoFileDate
Returns the time / date in Dir Entry styled format
unsigned short return OUT: time / date in Dir Entry styled format
-----------------------------------------------------------------*/
unsigned short getRTCtoFileTime (void)
{
  return (
        ( ( (ctime.hour > 11 ? ctime.hour - 40 : ctime.hour) & 0x1F) << 11) |
        ( (ctime.min & 0x3F) << 5) |
        ( (ctime.sec >> 1) & 0x1F) );
}

unsigned short getRTCtoFileDate (void)
{
  return ( 
        ( ((ctime.year + 20) & 0x7F) <<9) |
        ( (ctime.month & 0xF) << 5) |
        (ctime.day & 0x1F) );
}


/*-----------------------------------------------------------------
Disc level FAT routines
-----------------------------------------------------------------*/
#define FAT_ClustToSect(m) \
  (((m-2) * filesysSecPerClus) + filesysData)

/*-----------------------------------------------------------------
FAT_NextCluster
Internal function - gets the cluster linked from input cluster
-----------------------------------------------------------------*/
unsigned int FAT_NextCluster(unsigned int cluster)
{
  unsigned int nextCluster = CLUSTER_FREE;
  unsigned int sector;
  int offset;
  
  switch (filesysType) 
  {
    case FS_UNKNOWN:
      nextCluster = CLUSTER_FREE;
      break;
      
    case FS_FAT12:
      sector = filesysFAT + (((cluster * 3) / 2) / BYTE_PER_READ);
      offset = ((cluster * 3) / 2) % BYTE_PER_READ;

      // If FAT buffer contains wrong sector
      if (sector != fatBufferCurSector)
      {
        // Load correct sector to buffer
        fatBufferCurSector = sector;
        disc_ReadSector(fatBufferCurSector, fatBuffer);
      }

      nextCluster = ((unsigned char*)fatBuffer)[offset];
      offset++;
      
      if (offset >= BYTE_PER_READ) {
        offset = 0;
        fatBufferCurSector++;
        disc_ReadSector(fatBufferCurSector, fatBuffer);
      }
      
      nextCluster |= (((unsigned char*)fatBuffer)[offset]) << 8;
      
      if (cluster & 0x01) {
        nextCluster = nextCluster >> 4;
      } else   {
        nextCluster &= 0x0FFF;
      }
      
      if (nextCluster >= 0x0FF7)
      {
        nextCluster = CLUSTER_EOF;
      }

      break;
      
    case FS_FAT16:
      sector = filesysFAT + ((cluster << 1) / BYTE_PER_READ);
      offset = cluster % (BYTE_PER_READ >> 1);
      
      // If FAT buffer contains wrong sector
      if (sector != fatBufferCurSector)
      {
        // Load correct sector to buffer
        fatBufferCurSector = sector;
        disc_ReadSector(fatBufferCurSector, fatBuffer);
      }

      // read the nextCluster value
      nextCluster = ((unsigned short*)fatBuffer)[offset];
      
      if (nextCluster >= 0xFFF7)
      {
        nextCluster = CLUSTER_EOF;
      }
      break;
      
    case FS_FAT32:
      sector = filesysFAT + ((cluster << 2) / BYTE_PER_READ);
      offset = cluster % (BYTE_PER_READ >> 2);
      
      // If FAT buffer contains wrong sector
      if (sector != fatBufferCurSector)
      {
        // Load correct sector to buffer
        fatBufferCurSector = sector;
        disc_ReadSector(fatBufferCurSector, fatBuffer);
      }

      // read the nextCluster value
      nextCluster = (((unsigned int*)fatBuffer)[offset]) & 0x0FFFFFFF;
      
      if (nextCluster >= 0x0FFFFFF7)
      {
        nextCluster = CLUSTER_EOF;
      }
      break;
      
    default:
      nextCluster = CLUSTER_FREE;
      break;
  }
  
  return nextCluster;
}

#ifdef CAN_WRITE_TO_DISC
/*-----------------------------------------------------------------
FAT_WriteFatEntry
Internal function - writes FAT information about a cluster
-----------------------------------------------------------------*/
char FAT_WriteFatEntry (unsigned int cluster, unsigned int value)
{
  unsigned int sector;
  int offset;

  if ((cluster < 0x0002) || (cluster > fatLastCluster))
  {
    return false;
  }
  
  switch (filesysType) 
  {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -