+/** 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;
+ }
+}
+