5bb8177aa1
* Add initial support for USB MSC * Add Firmware Upload/Download With MSC Current running firmware is available as file inside the MSC Disk. To update the firmware on the ESP, just copy a regular firmware bin into the drive * Support overwriting of the firmware file Overwriting a file is done totally differently on MacOS, Windows and Linux. This change supports it on all of them. * Allow CDC, FirmwareMSC and DFU to be enabled on boot * Add example ESP32-S2 USB-ONLY board * Various device code optimizations Added `end()` methods to MSC classes Made begin() methods safe to be called multiple times Optimized CDC class * Fix CDC Connect/Disconnect detection in Arduino IDE on Windows * Rework cdc_write * Update ESP32-S2 board configs
142 lines
5.5 KiB
C
142 lines
5.5 KiB
C
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define FAT_U8(v) ((v) & 0xFF)
|
|
#define FAT_U16(v) FAT_U8(v), FAT_U8((v) >> 8)
|
|
#define FAT_U32(v) FAT_U8(v), FAT_U8((v) >> 8), FAT_U8((v) >> 16), FAT_U8((v) >> 24)
|
|
|
|
#define FAT12_TBL2B(l,h) FAT_U8(l), FAT_U8(((l >> 8) & 0xF) | ((h << 4) & 0xF0)), FAT_U8(h >> 4)
|
|
|
|
#define FAT_MS2B(s,ms) FAT_U8(((((s) & 0x1) * 1000) + (ms)) / 10)
|
|
#define FAT_HMS2B(h,m,s) FAT_U8(((s) >> 1)|(((m) & 0x7) << 5)), FAT_U8((((m) >> 3) & 0x7)|((h) << 3))
|
|
#define FAT_YMD2B(y,m,d) FAT_U8(((d) & 0x1F)|(((m) & 0x7) << 5)), FAT_U8((((m) >> 3) & 0x1)|((((y) - 1980) & 0x7F) << 1))
|
|
|
|
#define FAT_MS2V(s,ms) FAT_U8(((((s) & 0x1) * 1000) + (ms)) / 10)
|
|
#define FAT_HMS2V(h,m,s) (FAT_U8(((s) >> 1)|(((m) & 0x7) << 5)) | (FAT_U8((((m) >> 3) & 0x7)|((h) << 3)) << 8))
|
|
#define FAT_YMD2V(y,m,d) (FAT_U8(((d) & 0x1F)|(((m) & 0x7) << 5)) | (FAT_U8((((m) >> 3) & 0x1)|((((y) - 1980) & 0x7F) << 1)) << 8))
|
|
|
|
#define FAT_B2HMS(hms) ((hms >> 11) & 0x1F), ((hms >> 5) & 0x3F), ((hms & 0x1F) << 1)
|
|
#define FAT_B2YMD(ymd) (((ymd >> 9) & 0x7F) + 1980), ((ymd >> 5) & 0x0F), (ymd & 0x1F)
|
|
|
|
#define FAT_FILE_ATTR_READ_ONLY 0x01
|
|
#define FAT_FILE_ATTR_HIDDEN 0x02
|
|
#define FAT_FILE_ATTR_SYSTEM 0x04
|
|
#define FAT_FILE_ATTR_VOLUME_LABEL 0x08
|
|
#define FAT_FILE_ATTR_SUBDIRECTORY 0x10
|
|
#define FAT_FILE_ATTR_ARCHIVE 0x20
|
|
#define FAT_FILE_ATTR_DEVICE 0x40
|
|
|
|
static const uint16_t DISK_SECTOR_SIZE = 512;
|
|
|
|
#define FAT_SIZE_TO_SECTORS(bytes) ((bytes) / DISK_SECTOR_SIZE) + (((bytes) % DISK_SECTOR_SIZE)?1:0)
|
|
|
|
typedef struct __attribute__ ((packed)) {
|
|
uint8_t jump_instruction[3];
|
|
char oem_name[8];//padded with spaces (0x20)
|
|
uint16_t bytes_per_sector;//DISK_SECTOR_SIZE usually 512
|
|
uint8_t sectors_per_cluster;//Allowed values are 1, 2, 4, 8, 16, 32, 64, and 128
|
|
uint16_t reserved_sectors_count;//At least 1 for this sector, usually 32 for FAT32
|
|
uint8_t file_alloc_tables_num;//Almost always 2; RAM disks might use 1
|
|
uint16_t max_root_dir_entries;//FAT12 and FAT16
|
|
uint16_t fat12_sector_num;//DISK_SECTOR_NUM FAT12 and FAT16
|
|
uint8_t media_descriptor;
|
|
uint16_t sectors_per_alloc_table;//FAT12 and FAT16
|
|
uint16_t sectors_per_track;//A value of 0 may indicate LBA-only access
|
|
uint16_t num_heads;
|
|
uint32_t hidden_sectors_count;
|
|
uint32_t total_sectors_32;
|
|
uint8_t physical_drive_number;//0x00 for (first) removable media, 0x80 for (first) fixed disk
|
|
uint8_t reserved0;
|
|
uint8_t extended_boot_signature;//should be 0x29
|
|
uint32_t serial_number;//0x1234 => 1234
|
|
char volume_label[11];//padded with spaces (0x20)
|
|
char file_system_type[8];//padded with spaces (0x20)
|
|
uint8_t reserved[448];
|
|
uint16_t signature;//should be 0xAA55
|
|
} fat_boot_sector_t;
|
|
|
|
typedef struct __attribute__ ((packed)) {
|
|
union {
|
|
struct {
|
|
char file_name[8];//padded with spaces (0x20)
|
|
char file_extension[3];//padded with spaces (0x20)
|
|
};
|
|
struct {
|
|
uint8_t file_magic;// 0xE5:deleted, 0x05:will_be_deleted, 0x00:end_marker, 0x2E:dot_marker(. or ..)
|
|
char file_magic_data[10];
|
|
};
|
|
char volume_label[11];//padded with spaces (0x20)
|
|
};
|
|
uint8_t file_attr;//mask of FAT_FILE_ATTR_*
|
|
uint8_t reserved;//always 0
|
|
uint8_t creation_time_ms;//ms * 10; max 1990 (1s 990ms)
|
|
uint16_t creation_time_hms; // [5:6:5] => h:m:(s/2)
|
|
uint16_t creation_time_ymd; // [7:4:5] => (y+1980):m:d
|
|
uint16_t last_access_ymd;
|
|
uint16_t extended_attr;
|
|
uint16_t last_modified_hms;
|
|
uint16_t last_modified_ymd;
|
|
uint16_t data_start_sector;
|
|
uint32_t file_size;
|
|
} fat_dir_entry_t;
|
|
|
|
typedef struct __attribute__ ((packed)) {
|
|
union {
|
|
struct {
|
|
uint8_t number:5;
|
|
uint8_t reserved0:1;
|
|
uint8_t llfp:1;
|
|
uint8_t reserved1:1;
|
|
} seq;
|
|
uint8_t seq_num; //0xE5: Deleted Entry
|
|
};
|
|
uint16_t name0[5];
|
|
uint8_t attr; //ALWAYS 0x0F
|
|
uint8_t type; //ALWAYS 0x00
|
|
uint8_t dos_checksum;
|
|
uint16_t name1[6];
|
|
uint16_t first_cluster; //ALWAYS 0x0000
|
|
uint16_t name2[2];
|
|
} fat_lfn_entry_t;
|
|
|
|
typedef union {
|
|
fat_dir_entry_t dir;
|
|
fat_lfn_entry_t lfn;
|
|
} fat_entry_t;
|
|
|
|
const char * fat_file_system_type(bool fat16);
|
|
uint16_t fat_sectors_per_alloc_table(uint32_t sector_num, bool fat16);
|
|
uint8_t * fat_add_table(uint8_t * dst, fat_boot_sector_t * boot, bool fat16);
|
|
void fat_set_table_index(uint8_t * table, uint16_t index, uint16_t value, bool fat16);
|
|
fat_boot_sector_t * fat_add_boot_sector(uint8_t * dst, uint16_t sector_num, uint16_t table_sectors, const char * file_system_type, const char * volume_label, uint32_t serial_number);
|
|
fat_dir_entry_t * fat_add_label(uint8_t * dst, const char * volume_label);
|
|
fat_dir_entry_t * fat_add_root_file(uint8_t * dst, uint8_t index, const char * file_name, const char * file_extension, size_t file_size, uint16_t data_start_sector, bool is_fat16);
|
|
uint8_t fat_lfn_checksum(const uint8_t *short_filename);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|