Update Studio Integration DLL, to include package logging.
[pub/USBasp.git] / Bootloaders / MassStorage / Lib / VirtualFAT.c
index 5b94ed3..63d4ea0 100644 (file)
@@ -1,13 +1,13 @@
 /*
              LUFA Library
 /*
              LUFA Library
-     Copyright (C) Dean Camera, 2013.
+     Copyright (C) Dean Camera, 2015.
 
   dean [at] fourwalledcubicle [dot] com
            www.lufa-lib.org
 */
 
 /*
 
   dean [at] fourwalledcubicle [dot] com
            www.lufa-lib.org
 */
 
 /*
-  Copyright 2013  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+  Copyright 2015  Dean Camera (dean [at] fourwalledcubicle [dot] com)
 
   Permission to use, copy, modify, distribute, and sell this
   software and its documentation for any purpose is hereby granted
 
   Permission to use, copy, modify, distribute, and sell this
   software and its documentation for any purpose is hereby granted
@@ -78,6 +78,7 @@ static FATDirectoryEntry_t FirmwareFileEntries[] =
                 * Extension fields (concatenated) with a special attribute flag - other
                 * fields are ignored. Should be the same as the label in the boot block.
                 */
                 * Extension fields (concatenated) with a special attribute flag - other
                 * fields are ignored. Should be the same as the label in the boot block.
                 */
+               [DISK_FILE_ENTRY_VolumeID] =
                {
                        .MSDOS_Directory =
                                {
                {
                        .MSDOS_Directory =
                                {
@@ -92,54 +93,147 @@ static FATDirectoryEntry_t FirmwareFileEntries[] =
                },
 
                /* VFAT Long File Name entry for the virtual firmware file; required to
                },
 
                /* VFAT Long File Name entry for the virtual firmware file; required to
-                * prevent corruption of systems that are unable to detect the device
-                * as being a legacy MSDOS style FAT12 volume to prevent corruption. */
+                * prevent corruption from systems that are unable to detect the device
+                * as being a legacy MSDOS style FAT12 volume. */
+               [DISK_FILE_ENTRY_FLASH_LFN] =
                {
                        .VFAT_LongFileName =
                                {
                {
                        .VFAT_LongFileName =
                                {
-                                       .Ordinal         = FAT_ORDINAL_LAST_ENTRY | 1,
+                                       .Ordinal         = 1 | FAT_ORDINAL_LAST_ENTRY,
                                        .Attribute       = FAT_FLAG_LONG_FILE_NAME,
                                        .Reserved1       = 0,
                                        .Reserved2       = 0,
 
                                        .Attribute       = FAT_FLAG_LONG_FILE_NAME,
                                        .Reserved1       = 0,
                                        .Reserved2       = 0,
 
-                                       .Checksum        = 0x57,
+                                       .Checksum        = FAT_CHECKSUM('F','L','A','S','H',' ',' ',' ','B','I','N'),
 
                                        .Unicode1        = 'F',
 
                                        .Unicode1        = 'F',
-                                       .Unicode2        = 'I',
-                                       .Unicode3        = 'R',
-                                       .Unicode4        = 'M',
-                                       .Unicode5        = 'W',
-                                       .Unicode6        = 'A',
-                                       .Unicode7        = 'R',
-                                       .Unicode8        = 'E',
-                                       .Unicode9        = '.',
-                                       .Unicode10       = 'B',
-                                       .Unicode11       = 'I',
-                                       .Unicode12       = 'N',
+                                       .Unicode2        = 'L',
+                                       .Unicode3        = 'A',
+                                       .Unicode4        = 'S',
+                                       .Unicode5        = 'H',
+                                       .Unicode6        = '.',
+                                       .Unicode7        = 'B',
+                                       .Unicode8        = 'I',
+                                       .Unicode9        = 'N',
+                                       .Unicode10       = 0,
+                                       .Unicode11       = 0,
+                                       .Unicode12       = 0,
                                        .Unicode13       = 0,
                                }
                },
 
                /* MSDOS file entry for the virtual Firmware image. */
                                        .Unicode13       = 0,
                                }
                },
 
                /* MSDOS file entry for the virtual Firmware image. */
+               [DISK_FILE_ENTRY_FLASH_MSDOS] =
                {
                        .MSDOS_File =
                                {
                {
                        .MSDOS_File =
                                {
-                                       .Filename        = "FIRMWARE",
+                                       .Filename        = "FLASH   ",
                                        .Extension       = "BIN",
                                        .Attributes      = 0,
                                        .Reserved        = {0},
                                        .CreationTime    = FAT_TIME(1, 1, 0),
                                        .CreationDate    = FAT_DATE(14, 2, 1989),
                                        .StartingCluster = 2,
                                        .Extension       = "BIN",
                                        .Attributes      = 0,
                                        .Reserved        = {0},
                                        .CreationTime    = FAT_TIME(1, 1, 0),
                                        .CreationDate    = FAT_DATE(14, 2, 1989),
                                        .StartingCluster = 2,
-                                       .FileSizeBytes   = FIRMWARE_FILE_SIZE_BYTES,
+                                       .FileSizeBytes   = FLASH_FILE_SIZE_BYTES,
+                               }
+               },
+
+               [DISK_FILE_ENTRY_EEPROM_LFN] =
+               {
+                       .VFAT_LongFileName =
+                               {
+                                       .Ordinal         = 1 | FAT_ORDINAL_LAST_ENTRY,
+                                       .Attribute       = FAT_FLAG_LONG_FILE_NAME,
+                                       .Reserved1       = 0,
+                                       .Reserved2       = 0,
+
+                                       .Checksum        = FAT_CHECKSUM('E','E','P','R','O','M',' ',' ','B','I','N'),
+
+                                       .Unicode1        = 'E',
+                                       .Unicode2        = 'E',
+                                       .Unicode3        = 'P',
+                                       .Unicode4        = 'R',
+                                       .Unicode5        = 'O',
+                                       .Unicode6        = 'M',
+                                       .Unicode7        = '.',
+                                       .Unicode8        = 'B',
+                                       .Unicode9        = 'I',
+                                       .Unicode10       = 'N',
+                                       .Unicode11       = 0,
+                                       .Unicode12       = 0,
+                                       .Unicode13       = 0,
+                               }
+               },
+
+               [DISK_FILE_ENTRY_EEPROM_MSDOS] =
+               {
+                       .MSDOS_File =
+                               {
+                                       .Filename        = "EEPROM  ",
+                                       .Extension       = "BIN",
+                                       .Attributes      = 0,
+                                       .Reserved        = {0},
+                                       .CreationTime    = FAT_TIME(1, 1, 0),
+                                       .CreationDate    = FAT_DATE(14, 2, 1989),
+                                       .StartingCluster = 2 + FILE_CLUSTERS(FLASH_FILE_SIZE_BYTES),
+                                       .FileSizeBytes   = EEPROM_FILE_SIZE_BYTES,
                                }
                },
        };
 
                                }
                },
        };
 
+/** Starting cluster of the virtual FLASH.BIN file on disk, tracked so that the
+ *  offset from the start of the data sector can be determined. On Windows
+ *  systems files are usually replaced using the original file's disk clusters,
+ *  while Linux appears to overwrite with an offset which must be compensated for.
+ */
+static const uint16_t* FLASHFileStartCluster  = &FirmwareFileEntries[DISK_FILE_ENTRY_FLASH_MSDOS].MSDOS_File.StartingCluster;
+
+/** Starting cluster of the virtual EEPROM.BIN file on disk, tracked so that the
+ *  offset from the start of the data sector can be determined. On Windows
+ *  systems files are usually replaced using the original file's disk clusters,
+ *  while Linux appears to overwrite with an offset which must be compensated for.
+ */
+static const uint16_t* EEPROMFileStartCluster = &FirmwareFileEntries[DISK_FILE_ENTRY_EEPROM_MSDOS].MSDOS_File.StartingCluster;
+
+/** Reads a byte of EEPROM out from the EEPROM memory space.
+ *
+ *  \note This function is required as the avr-libc EEPROM functions do not cope
+ *        with linker relaxations, and a jump longer than 4K of FLASH on the
+ *        larger USB AVRs will break the linker. This function is marked as
+ *        never inlinable and placed into the normal text segment so that the
+ *        call to the EEPROM function will be short even if the AUX boot section
+ *        is used.
+ *
+ *  \param[in]  Address   Address of the EEPROM location to read from
+ *
+ *  \return Read byte of EEPROM data.
+ */
+static uint8_t ReadEEPROMByte(const uint8_t* const Address)
+{
+       return eeprom_read_byte(Address);
+}
+
+/** Writes a byte of EEPROM out to the EEPROM memory space.
+ *
+ *  \note This function is required as the avr-libc EEPROM functions do not cope
+ *        with linker relaxations, and a jump longer than 4K of FLASH on the
+ *        larger USB AVRs will break the linker. This function is marked as
+ *        never inlinable and placed into the normal text segment so that the
+ *        call to the EEPROM function will be short even if the AUX boot section
+ *        is used.
+ *
+ *  \param[in]  Address   Address of the EEPROM location to write to
+ *  \param[in]  Data      New data to write to the EEPROM location
+ */
+static void WriteEEPROMByte(uint8_t* const Address,
+                            const uint8_t Data)
+{
+        eeprom_update_byte(Address, Data);
+}
 
 /** Updates a FAT12 cluster entry in the FAT file table with the specified next
  *  chain index. If the cluster is the last in the file chain, the magic value
 
 /** Updates a FAT12 cluster entry in the FAT file table with the specified next
  *  chain index. If the cluster is the last in the file chain, the magic value
- *  0xFFF is used.
+ *  \c 0xFFF should be used.
  *
  *  \note FAT data cluster indexes are offset by 2, so that cluster 2 is the
  *        first file data cluster on the disk. See the FAT specification.
  *
  *  \note FAT data cluster indexes are offset by 2, so that cluster 2 is the
  *        first file data cluster on the disk. See the FAT specification.
@@ -170,103 +264,214 @@ static void UpdateFAT12ClusterEntry(uint8_t* const FATTable,
        }
 }
 
        }
 }
 
-/** Writes a block of data to the virtual FAT filesystem, from the USB Mass
- *  Storage interface.
+/** Updates a FAT12 cluster chain in the FAT file table with a linear chain of
+ *  the specified length.
  *
  *
- *  \param[in]  BlockNumber  Index of the block to write.
+ *  \note FAT data cluster indexes are offset by 2, so that cluster 2 is the
+ *        first file data cluster on the disk. See the FAT specification.
+ *
+ *  \param[out]  FATTable     Pointer to the FAT12 allocation table
+ *  \param[in]   Index        Index of the start of the cluster chain to update
+ *  \param[in]   ChainLength  Length of the chain to write, in clusters
  */
  */
-static void WriteVirtualBlock(const uint16_t BlockNumber)
+static void UpdateFAT12ClusterChain(uint8_t* const FATTable,
+                                    const uint16_t Index,
+                                    const uint8_t ChainLength)
 {
 {
-       uint8_t BlockBuffer[SECTOR_SIZE_BYTES];
+       for (uint8_t i = 0; i < ChainLength; i++)
+       {
+               uint16_t CurrentCluster = Index + i;
+               uint16_t NextCluster    = CurrentCluster + 1;
 
 
-       /* Buffer the entire block to be written from the host */
-       Endpoint_Read_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
-       Endpoint_ClearOUT();
+               /* Mark last cluster as end of file */
+               if (i == (ChainLength - 1))
+                 NextCluster = 0xFFF;
 
 
-       if ((BlockNumber >= 4) && (BlockNumber < (4 + FILE_SECTORS(FIRMWARE_FILE_SIZE_BYTES))))
-       {
-               #if (FLASHEND > 0xFFFF)
-               uint32_t WriteFlashAddress = (uint32_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES;
-               #else
-               uint16_t WriteFlashAddress = (uint16_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES;
-               #endif
+               UpdateFAT12ClusterEntry(FATTable, CurrentCluster, NextCluster);
+       }
+}
 
 
+/** Reads or writes a block of data from/to the physical device FLASH using a
+ *  block buffer stored in RAM, if the requested block is within the virtual
+ *  firmware file's sector ranges in the emulated FAT file system.
+ *
+ *  \param[in]      BlockNumber  Physical disk block to read from/write to
+ *  \param[in,out]  BlockBuffer  Pointer to the start of the block buffer in RAM
+ *  \param[in]      Read         If \c true, the requested block is read, if
+ *                               \c false, the requested block is written
+ */
+static void ReadWriteFLASHFileBlock(const uint16_t BlockNumber,
+                                    uint8_t* BlockBuffer,
+                                    const bool Read)
+{
+       uint16_t FileStartBlock = DISK_BLOCK_DataStartBlock + (*FLASHFileStartCluster - 2) * SECTOR_PER_CLUSTER;
+       uint16_t FileEndBlock   = FileStartBlock + (FILE_SECTORS(FLASH_FILE_SIZE_BYTES) - 1);
+
+       /* Range check the write request - abort if requested block is not within the
+        * virtual firmware file sector range */
+       if (!((BlockNumber >= FileStartBlock) && (BlockNumber <= FileEndBlock)))
+         return;
+
+       #if (FLASHEND > 0xFFFF)
+       uint32_t FlashAddress = (uint32_t)(BlockNumber - FileStartBlock) * SECTOR_SIZE_BYTES;
+       #else
+       uint16_t FlashAddress = (uint16_t)(BlockNumber - FileStartBlock) * SECTOR_SIZE_BYTES;
+       #endif
+
+       if (Read)
+       {
+               /* Read out the mapped block of data from the device's FLASH */
+               for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
+               {
+                       #if (FLASHEND > 0xFFFF)
+                         BlockBuffer[i] = pgm_read_byte_far(FlashAddress++);
+                       #else
+                         BlockBuffer[i] = pgm_read_byte(FlashAddress++);
+                       #endif
+               }
+       }
+       else
+       {
+               /* Write out the mapped block of data to the device's FLASH */
                for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i += 2)
                {
                for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i += 2)
                {
-                       if ((WriteFlashAddress % SPM_PAGESIZE) == 0)
+                       if ((FlashAddress % SPM_PAGESIZE) == 0)
                        {
                                /* Erase the given FLASH page, ready to be programmed */
                        {
                                /* Erase the given FLASH page, ready to be programmed */
-                               BootloaderAPI_ErasePage(WriteFlashAddress);
+                               BootloaderAPI_ErasePage(FlashAddress);
                        }
 
                        /* Write the next data word to the FLASH page */
                        }
 
                        /* Write the next data word to the FLASH page */
-                       BootloaderAPI_FillWord(WriteFlashAddress, (BlockBuffer[i + 1] << 8) | BlockBuffer[i]);
-                       WriteFlashAddress += 2;
+                       BootloaderAPI_FillWord(FlashAddress, (BlockBuffer[i + 1] << 8) | BlockBuffer[i]);
+                       FlashAddress += 2;
 
 
-                       if ((WriteFlashAddress % SPM_PAGESIZE) == 0)
+                       if ((FlashAddress % SPM_PAGESIZE) == 0)
                        {
                                /* Write the filled FLASH page to memory */
                        {
                                /* Write the filled FLASH page to memory */
-                               BootloaderAPI_WritePage(WriteFlashAddress - SPM_PAGESIZE);
+                               BootloaderAPI_WritePage(FlashAddress - SPM_PAGESIZE);
                        }
                }
        }
 }
 
                        }
                }
        }
 }
 
+/** Reads or writes a block of data from/to the physical device EEPROM using a
+ *  block buffer stored in RAM, if the requested block is within the virtual
+ *  firmware file's sector ranges in the emulated FAT file system.
+ *
+ *  \param[in]      BlockNumber  Physical disk block to read from/write to
+ *  \param[in,out]  BlockBuffer  Pointer to the start of the block buffer in RAM
+ *  \param[in]      Read         If \c true, the requested block is read, if
+ *                               \c false, the requested block is written
+ */
+static void ReadWriteEEPROMFileBlock(const uint16_t BlockNumber,
+                                     uint8_t* BlockBuffer,
+                                     const bool Read)
+{
+       uint16_t FileStartBlock = DISK_BLOCK_DataStartBlock + (*EEPROMFileStartCluster - 2) * SECTOR_PER_CLUSTER;
+       uint16_t FileEndBlock   = FileStartBlock + (FILE_SECTORS(EEPROM_FILE_SIZE_BYTES) - 1);
+
+       /* Range check the write request - abort if requested block is not within the
+        * virtual firmware file sector range */
+       if (!((BlockNumber >= FileStartBlock) && (BlockNumber <= FileEndBlock)))
+         return;
+
+       uint16_t EEPROMAddress = (uint16_t)(BlockNumber - FileStartBlock) * SECTOR_SIZE_BYTES;
+
+       if (Read)
+       {
+               /* Read out the mapped block of data from the device's EEPROM */
+               for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
+                 BlockBuffer[i] = ReadEEPROMByte((uint8_t*)EEPROMAddress++);
+       }
+       else
+       {
+               /* Write out the mapped block of data to the device's EEPROM */
+               for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
+                 WriteEEPROMByte((uint8_t*)EEPROMAddress++, BlockBuffer[i]);
+       }
+}
+
+/** Writes a block of data to the virtual FAT filesystem, from the USB Mass
+ *  Storage interface.
+ *
+ *  \param[in]  BlockNumber  Index of the block to write.
+ */
+void VirtualFAT_WriteBlock(const uint16_t BlockNumber)
+{
+       uint8_t BlockBuffer[SECTOR_SIZE_BYTES];
+
+       /* Buffer the entire block to be written from the host */
+       Endpoint_Read_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
+       Endpoint_ClearOUT();
+
+       switch (BlockNumber)
+       {
+               case DISK_BLOCK_BootBlock:
+               case DISK_BLOCK_FATBlock1:
+               case DISK_BLOCK_FATBlock2:
+                       /* Ignore writes to the boot and FAT blocks */
+
+                       break;
+
+               case DISK_BLOCK_RootFilesBlock:
+                       /* Copy over the updated directory entries */
+                       memcpy(FirmwareFileEntries, BlockBuffer, sizeof(FirmwareFileEntries));
+
+                       break;
+
+               default:
+                       ReadWriteFLASHFileBlock(BlockNumber, BlockBuffer, false);
+                       ReadWriteEEPROMFileBlock(BlockNumber, BlockBuffer, false);
+
+                       break;
+       }
+}
+
 /** Reads a block of data from the virtual FAT filesystem, and sends it to the
  *  host via the USB Mass Storage interface.
  *
  *  \param[in]  BlockNumber  Index of the block to read.
  */
 /** Reads a block of data from the virtual FAT filesystem, and sends it to the
  *  host via the USB Mass Storage interface.
  *
  *  \param[in]  BlockNumber  Index of the block to read.
  */
-static void ReadVirtualBlock(const uint16_t BlockNumber)
+void VirtualFAT_ReadBlock(const uint16_t BlockNumber)
 {
        uint8_t BlockBuffer[SECTOR_SIZE_BYTES];
        memset(BlockBuffer, 0x00, sizeof(BlockBuffer));
 
        switch (BlockNumber)
        {
 {
        uint8_t BlockBuffer[SECTOR_SIZE_BYTES];
        memset(BlockBuffer, 0x00, sizeof(BlockBuffer));
 
        switch (BlockNumber)
        {
-               case 0: /* Block 0: Boot block sector */
+               case DISK_BLOCK_BootBlock:
                        memcpy(BlockBuffer, &BootBlock, sizeof(FATBootBlock_t));
 
                        /* Add the magic signature to the end of the block */
                        BlockBuffer[SECTOR_SIZE_BYTES - 2] = 0x55;
                        BlockBuffer[SECTOR_SIZE_BYTES - 1] = 0xAA;
                        memcpy(BlockBuffer, &BootBlock, sizeof(FATBootBlock_t));
 
                        /* Add the magic signature to the end of the block */
                        BlockBuffer[SECTOR_SIZE_BYTES - 2] = 0x55;
                        BlockBuffer[SECTOR_SIZE_BYTES - 1] = 0xAA;
+
                        break;
 
                        break;
 
-               case 1: /* Block 1: First FAT12 cluster chain copy */
-               case 2: /* Block 2: Second FAT12 cluster chain copy */
+               case DISK_BLOCK_FATBlock1:
+               case DISK_BLOCK_FATBlock2:
                        /* Cluster 0: Media type/Reserved */
                        UpdateFAT12ClusterEntry(BlockBuffer, 0, 0xF00 | BootBlock.MediaDescriptor);
 
                        /* Cluster 1: Reserved */
                        UpdateFAT12ClusterEntry(BlockBuffer, 1, 0xFFF);
 
                        /* Cluster 0: Media type/Reserved */
                        UpdateFAT12ClusterEntry(BlockBuffer, 0, 0xF00 | BootBlock.MediaDescriptor);
 
                        /* Cluster 1: Reserved */
                        UpdateFAT12ClusterEntry(BlockBuffer, 1, 0xFFF);
 
-                       /* Cluster 2 onwards: Cluster chain of FIRMWARE.BIN */
-                       for (uint16_t i = 0; i < FILE_CLUSTERS(FIRMWARE_FILE_SIZE_BYTES); i++)
-                         UpdateFAT12ClusterEntry(BlockBuffer, i+2, i+3);
+                       /* Cluster 2 onwards: Cluster chain of FLASH.BIN */
+                       UpdateFAT12ClusterChain(BlockBuffer, *FLASHFileStartCluster, FILE_CLUSTERS(FLASH_FILE_SIZE_BYTES));
 
 
-                       /* Mark last cluster as end of file */
-                       UpdateFAT12ClusterEntry(BlockBuffer, FILE_CLUSTERS(FIRMWARE_FILE_SIZE_BYTES) + 1, 0xFFF);
-                       break;
+                       /* Cluster 2+n onwards: Cluster chain of EEPROM.BIN */
+                       UpdateFAT12ClusterChain(BlockBuffer, *EEPROMFileStartCluster, FILE_CLUSTERS(EEPROM_FILE_SIZE_BYTES));
 
 
-               case 3: /* Block 3: Root file entries */
-                       memcpy(BlockBuffer, FirmwareFileEntries, sizeof(FirmwareFileEntries));
                        break;
 
                        break;
 
-               default: /* Blocks 4 onwards: Data allocation section */
-                       if ((BlockNumber >= 4) && (BlockNumber < (4 + FILE_SECTORS(FIRMWARE_FILE_SIZE_BYTES))))
-                       {
-                               #if (FLASHEND > 0xFFFF)
-                               uint32_t ReadFlashAddress = (uint32_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES;
+               case DISK_BLOCK_RootFilesBlock:
+                       memcpy(BlockBuffer, FirmwareFileEntries, sizeof(FirmwareFileEntries));
 
 
-                               for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
-                                 BlockBuffer[i] = pgm_read_byte_far(ReadFlashAddress++);
-                               #else
-                               uint16_t ReadFlashAddress = (uint16_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES;
+                       break;
 
 
-                               for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
-                                 BlockBuffer[i] = pgm_read_byte(ReadFlashAddress++);
-                               #endif
-                       }
+               default:
+                       ReadWriteFLASHFileBlock(BlockNumber, BlockBuffer, true);
+                       ReadWriteEEPROMFileBlock(BlockNumber, BlockBuffer, true);
 
                        break;
        }
 
                        break;
        }
@@ -275,38 +480,3 @@ static void ReadVirtualBlock(const uint16_t BlockNumber)
        Endpoint_Write_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
        Endpoint_ClearIN();
 }
        Endpoint_Write_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
        Endpoint_ClearIN();
 }
-
-/** Writes a number of blocks to the virtual FAT file system, from the host
- *  PC via the USB Mass Storage interface.
- *
- *  \param[in] BlockAddress     Data block starting address for the write sequence
- *  \param[in] TotalBlocks      Number of blocks of data to write
- */
-void VirtualFAT_WriteBlocks(const uint16_t BlockAddress,
-                            uint16_t TotalBlocks)
-{
-       uint16_t CurrentBlock = (uint16_t)BlockAddress;
-
-       /* Emulated FAT is performed per-block, pass each requested block index
-        * to the emulated FAT block write function */
-       while (TotalBlocks--)
-         WriteVirtualBlock(CurrentBlock++);
-}
-
-/** Reads a number of blocks from the virtual FAT file system, and sends them
- *  to the host PC via the USB Mass Storage interface.
- *
- *  \param[in] BlockAddress     Data block starting address for the read sequence
- *  \param[in] TotalBlocks      Number of blocks of data to read
- */
-void VirtualFAT_ReadBlocks(const uint16_t BlockAddress,
-                           uint16_t TotalBlocks)
-{
-       uint16_t CurrentBlock = (uint16_t)BlockAddress;
-
-       /* Emulated FAT is performed per-block, pass each requested block index
-        * to the emulated FAT block read function */
-       while (TotalBlocks--)
-         ReadVirtualBlock(CurrentBlock++);
-}
-