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

📄 fat.c

📁 看到最近大家都关心 usbhost 的实现, 论坛上能找到的代码仅是一些简单的 demo , 完整的源码级的协议层是找不到的 我就贡献一把, 将我前一段时间移植成功的 USBHost 代码奉上 注
💻 C
📖 第 1 页 / 共 5 页
字号:
    filesysBytePerSec = BYTE_PER_READ;  // Sector size is redefined to be 512 bytes
    filesysSecPerClus = bootSec->sectorsPerCluster * bootSec->bytesPerSector / BYTE_PER_READ;
    filesysBytePerClus = filesysBytePerSec * filesysSecPerClus;
    filesysFAT = bootSector + bootSec->reservedSectors;
  
    filesysRootDir = filesysFAT + (bootSec->numFATs * filesysSecPerFAT);
    filesysData = filesysRootDir + ((bootSec->rootEntries * sizeof(DIR_ENT)) / filesysBytePerSec);
  
    filesysTotalSize = (filesysNumSec - filesysData) * filesysBytePerSec;
  
    // Store info about FAT
    fatLastCluster = (filesysNumSec - filesysData) / bootSec->sectorsPerCluster;
    fatFirstFree = CLUSTER_FIRST;
    fatBufferCurSector = 0;
    disc_ReadSector(fatBufferCurSector, fatBuffer);
  
    if (fatLastCluster < 4085)
    {
      filesysType = FS_FAT12;  // FAT12 volume - unsupported
    }
    else if (fatLastCluster < 65525)
    {
      filesysType = FS_FAT16;  // FAT16 volume
    }
    else
    {
      filesysType = FS_FAT32;  // FAT32 volume
    }
  
    if (filesysType != FS_FAT32)
    {
      filesysRootDirClus = FAT16_ROOT_DIR_CLUSTER;
    }
    else  // Set up for the FAT32 way
    {
      filesysRootDirClus = bootSec->extBlock.fat32.rootClus;
      // Check if FAT mirroring is enabled
      if (!(bootSec->extBlock.fat32.extFlags & 0x80))
      {
        // Use the active FAT
        filesysFAT = filesysFAT + ( filesysSecPerFAT * (bootSec->extBlock.fat32.extFlags & 0x0F));
      }
    }
  
    // Set current directory to the root
    curWorkDirCluster = filesysRootDirClus;
    wrkDirCluster = filesysRootDirClus;
    wrkDirSector = 0;
    wrkDirOffset = 0;
  
    // Set all files to free
    for (i=0; i < MAX_FILES_OPEN; i++)
    {
      openFiles[i].inUse = false;
    }
  
    // No long filenames so far
    lfnExists = false;
    for (i = 0; i < MAX_FILENAME_LENGTH; i++)
    {
      lfnName[i] = '\0';
    }
  
    return (true);
}

/*-----------------------------------------------------------------
FAT_FreeFiles
Closes all open files then resets the CF card.
Call this before exiting back to the GBAMP
char return OUT: true if successful.
-----------------------------------------------------------------*/
char FAT_FreeFiles (void)
{
  int i;

  // Close all open files
  for (i=0; i < MAX_FILES_OPEN; i++)
  {
    if (openFiles[i].inUse == true)
    {
      FAT_fclose(&openFiles[i]);
    }
  }

  // Flush any sectors in disc cache
  disc_CacheFlush();

  // Clear card status
  disc_ClearStatus();

  // Return status of card
  return disc_IsInserted();
}


/*-----------------------------------------------------------------
FAT_GetDirEntry
Return the file info structure of the next valid file entry
unsigned int dirCluster: IN cluster of subdirectory table
int entry: IN the desired file entry
int origin IN: relative position of the entry
DIR_ENT return OUT: desired dirEntry. First char will be FILE_FREE if 
  the entry does not exist.
-----------------------------------------------------------------*/
DIR_ENT FAT_GetDirEntry ( unsigned int dirCluster, int entry, int origin)
{
  DIR_ENT dir;
  DIR_ENT_LFN lfn;
  int firstSector = 0;
  char notFound = false;
  char found = false;
  //int maxSectors;
  int lfnPos, aliasPos;
  unsigned char lfnChkSum, chkSum;

  int i;

  dir.name[0] = FILE_FREE; // default to no file found
  dir.attrib = 0x00;

  // Check if fat has been initialised
  if (filesysBytePerSec == 0)
  {
    return (dir);
  }
  
  switch (origin) 
  {
  case SEEK_SET:
    wrkDirCluster = dirCluster;
    wrkDirSector = 0;
    wrkDirOffset = -1;
    break;
  case SEEK_CUR:  // Don't change anything
    break;
  case SEEK_END:  // Find entry signifying end of directory
    // Subtraction will never reach 0, so it keeps going 
    // until reaches end of directory
    wrkDirCluster = dirCluster;
    wrkDirSector = 0;
    wrkDirOffset = -1;
    entry = -1;
    break;
  default:
    return dir;
  }

  lfnChkSum = 0;
  //maxSectors = (wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? (filesysData - filesysRootDir) : filesysSecPerClus);

  // Scan Dir for correct entry
  firstSector = (wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster));
  disc_ReadSector (firstSector + wrkDirSector, globalBuffer);
  found = false;
  notFound = false;
  do {
    wrkDirOffset++;
    if (wrkDirOffset == BYTE_PER_READ / sizeof (DIR_ENT))
    {
      wrkDirOffset = 0;
      wrkDirSector++;
      if ((wrkDirSector == filesysSecPerClus) && (wrkDirCluster != FAT16_ROOT_DIR_CLUSTER))
      {
        wrkDirSector = 0;
        wrkDirCluster = FAT_NextCluster(wrkDirCluster);
        if (wrkDirCluster == CLUSTER_EOF)
        {
          notFound = true;
        }
        firstSector = FAT_ClustToSect(wrkDirCluster);    
      }
      else if ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER) && (wrkDirSector == (filesysData - filesysRootDir)))
      {
        notFound = true;  // Got to end of root dir
      }
      disc_ReadSector (firstSector + wrkDirSector, globalBuffer);
    }
    dir = ((DIR_ENT*) globalBuffer)[wrkDirOffset];
    if ((dir.name[0] != FILE_FREE) && (dir.name[0] > 0x20) && ((dir.attrib & ATTRIB_VOL) != ATTRIB_VOL))
    {
      entry--;
      if (lfnExists)
      {
        // Calculate file checksum
        chkSum = 0;
        for (aliasPos=0; aliasPos < 11; aliasPos++)
        {
          // NOTE: The operation is an unsigned char rotate right
          chkSum = ((chkSum & 1) ? 0x80 : 0) + (chkSum >> 1) + (aliasPos < 8 ? dir.name[aliasPos] : dir.ext[aliasPos - 8]);
        }
        if (chkSum != lfnChkSum)
        {
          lfnExists = false;
          lfnName[0] = '\0';
        }
      }
      if (entry == 0) 
      {
        if (!lfnExists)
        {
          FAT_GetFilename (dir, lfnName);
        }
        found = true;
      }
    }
    else if (dir.name[0] == FILE_LAST)
    {
      if (origin == SEEK_END)
      {
        found = true;
      }
      else
      {
        notFound = true;
      }
    }
    else if (dir.attrib == ATTRIB_LFN)
    {
      lfn = ((DIR_ENT_LFN*) globalBuffer)[wrkDirOffset];
      if (lfn.ordinal & LFN_DEL)
      {
        lfnExists = false;
      }
      else if (lfn.ordinal & LFN_END)  // Last part of LFN, make sure it isn't deleted (Thanks MoonLight)
      {
        lfnExists = true;
        lfnName[(lfn.ordinal & ~LFN_END) * 13] = '\0';  // Set end of lfn to null character
        lfnChkSum = lfn.checkSum;
      }
      if (lfnChkSum != lfn.checkSum)
      {
        lfnExists = false;
      }
      if (lfnExists)
      {
        lfnPos = ((lfn.ordinal & ~LFN_END) - 1) * 13;
        for (i = 0; i < 13; i++) {
          lfnName[lfnPos + i] = ((unsigned char*)&lfn)[(int)(lfn_offset_table[i])] /* | ((unsigned char*)&lfn)[(int)(lfn_offset_table[i]) + 1]  include this for unicode support*/;
        }
      }
    }
  } while (!found && !notFound);
  
  // If no file is found, return FILE_FREE
  if (notFound)
  {
    dir.name[0] = FILE_FREE;
  }

  return (dir);
}


/*-----------------------------------------------------------------
FAT_GetLongFilename
Get the long name of the last file or directory retrived with 
  GetDirEntry. Also works for FindFirstFile and FindNextFile.
  If a long name doesn't exist, it returns the short name
  instead.
char* filename: OUT will be filled with the filename, should be at
  least 256 bytes long
char return OUT: return true if successful
-----------------------------------------------------------------*/
char FAT_GetLongFilename (char* filename)
{
  if (filename == NULL)
    return false;

  strncpy (filename, lfnName, MAX_FILENAME_LENGTH - 1);
  filename[MAX_FILENAME_LENGTH - 1] = '\0';
  
  return true;
}


/*-----------------------------------------------------------------
FAT_GetFilename
Get the alias (short name) of the file or directory stored in 
  dirEntry
DIR_ENT dirEntry: IN a valid directory table entry
char* alias OUT: will be filled with the alias (short filename),
  should be at least 13 bytes long
char return OUT: return true if successful
-----------------------------------------------------------------*/
char FAT_GetFilename (DIR_ENT dirEntry, char* alias)
{
  int i=0;
  int j=0;

  alias[0] = '\0';
  if (dirEntry.name[0] != FILE_FREE)
  {
    if (dirEntry.name[0] == '.')
    {
      alias[0] = '.';
      if (dirEntry.name[1] == '.')
      {
        alias[1] = '.';
        alias[2] = '\0';
      }
      else
      {
        alias[1] = '\0';
      }
    }
    else
    {    
      // Copy the filename from the dirEntry to the string
      for (i = 0; (i < 8) && (dirEntry.name[i] != ' '); i++)
      {
        alias[i] = dirEntry.name[i];
      }
      // Copy the extension from the dirEntry to the string
      if (dirEntry.ext[0] != ' ')
      {
        alias[i++] = '.';
        for ( j = 0; (j < 3) && (dirEntry.ext[j] != ' '); j++)
        {
          alias[i++] = dirEntry.ext[j];
        }
      }
      alias[i] = '\0';
    }
  }

  return (alias[0] != '\0');
}

/*-----------------------------------------------------------------
FAT_GetAlias
Get the alias (short name) of the last file or directory entry read
  using GetDirEntry. Works for FindFirstFile and FindNextFile
char* alias OUT: will be filled with the alias (short filename),
  should be at least 13 bytes long
char return OUT: return true if successful
-----------------------------------------------------------------*/
char FAT_GetAlias (char* alias)
{
  if (alias == NULL)
  {
    return false;
  }
  // Read in the last accessed directory entry
  disc_ReadSector ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector, globalBuffer);
  
  return   FAT_GetFilename (((DIR_ENT*)globalBuffer)[wrkDirOffset], alias);
}

/*-----------------------------------------------------------------
FAT_GetFileSize
Get the file size of the last file found or openned.
This idea is based on a modification by MoonLight
unsigned int return OUT: the file size
-----------------------------------------------------------------*/
unsigned int FAT_GetFileSize (void)
{
  // Read in the last accessed directory entry
  disc_ReadSector ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector, globalBuffer);
  
  return   ((DIR_ENT*)globalBuffer)[wrkDirOffset].fileSize;
}

/*-----------------------------------------------------------------
FAT_GetFileCluster
Get the first cluster of the last file found or openned.
unsigned int return OUT: the file start cluster
-----------------------------------------------------------------*/
unsigned int FAT_GetFileCluster (void)
{
  // Read in the last accessed directory entry
  disc_ReadSector ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector, globalBuffer);
  
  return   (((DIR_ENT*)globalBuffer)[wrkDirOffset].startCluster) | (((DIR_ENT*)globalBuffer)[wrkDirOffset].startClusterHigh << 16);
}

/*-----------------------------------------------------------------
FAT_GetFileAttributes
Get the attributes of the last file found or openned.
unsigned char return OUT: the file's attributes
-----------------------------------------------------------------*/
unsigned char FAT_GetFileAttributes (void)
{
  // Read in the last accessed directory entry
  disc_ReadSector ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector, globalBuffer);
  
  return   ((DIR_ENT*)globalBuffer)[wrkDirOffset].attrib;
}

#ifdef CAN_WRITE_TO_DISC
/*-----------------------------------------------------------------
FAT_SetFileAttributes
Set the attributes of a file.
const char* filename IN: The name and path of the file to modify
unsigned char attributes IN: The attribute values to assign
unsigned char mask IN: Detemines which attributes are changed
unsigned char return OUT: the file's new attributes
-----------------------------------------------------------------*/
unsigned char FAT_SetFileAttributes (const char* filename, unsigned char attributes, unsigned char mask)
{
  // Get the file
  if (!FAT_FileExists(filename)) {
    return 0xff;
  }

  // Read in the last accessed directory entry
  disc_ReadSector ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector, globalBuffer);

  ((DIR_ENT*)globalBuffer)[wrkDirOffset].attrib = (((DIR_ENT*)globalBuffer)[wrkDirOffset].attrib & ~(mask & 0x27)) | (attributes & 0x27);  // 0x27 is he settable attributes
  
  disc_WriteSector ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? filesysRootDir : FAT_ClustToSect(wrkDirCluster)) + wrkDirSector, globalBuffer);

  return   ((DIR_ENT*)globalBuffer)[wrkDirOffset].attrib;
}
#endif

#ifdef FILE_TIME_SUPPORT
time_t FAT_FileTimeToCTime (unsigned short fileTime, unsigned short fileDate)
{
  struct tm timeInfo;
  
  timeInfo.tm_year = (fileDate >> 9) + 80;    // years since midnight January 1970
  timeInfo.tm_mon = ((fileDate >> 5) & 0xf) - 1;  // Months since january
  timeInfo.tm_mday = fileDate & 0x1f;        // Day of the month

  timeInfo.tm_hour = fileTime >> 11;        // hours past midnight
  timeInfo.tm_min = (fileTime >> 5) & 0x3f;    // minutes past the hour
  timeInfo.tm_sec = (fileTime & 0x1f) * 2;    // seconds past the minute

  return mktime(&timeInfo);
}

⌨️ 快捷键说明

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