From 786fb0adb285cf613799cb3d7d207ac2ae017c89 Mon Sep 17 00:00:00 2001 From: KalbeAbbas Date: Mon, 10 Aug 2020 18:41:21 +0500 Subject: [PATCH] Secure wifi throug SD card --- FATDirHandle.cpp | 51 +++++++ FATDirHandle.h | 23 +++ FATFileHandle.cpp | 74 +++++++++ FATFileHandle.h | 24 +++ FATFileSystem.cpp | 121 +++++++++++++++ FATFileSystem.h | 34 +++++ MemFileSystem.h | 80 ++++++++++ SDFileSystem.cpp | 380 ++++++++++++++++++++++++++++++++++++++++++++++ SDFileSystem.h | 39 +++++ ccsbcs.cpp | 84 ++++++++++ diskio.cpp | 80 ++++++++++ diskio.h | 32 ++++ ff.cpp | 119 +++++++++++++++ ff.h | 146 ++++++++++++++++++ ffconf.h | 10 ++ im01.cpp | 56 +++++++ integer.h | 11 ++ main.ts | 32 +++- pxt.json | 49 +++++- 19 files changed, 1438 insertions(+), 7 deletions(-) create mode 100644 FATDirHandle.cpp create mode 100644 FATDirHandle.h create mode 100644 FATFileHandle.cpp create mode 100644 FATFileHandle.h create mode 100644 FATFileSystem.cpp create mode 100644 FATFileSystem.h create mode 100644 MemFileSystem.h create mode 100644 SDFileSystem.cpp create mode 100644 SDFileSystem.h create mode 100644 ccsbcs.cpp create mode 100644 diskio.cpp create mode 100644 diskio.h create mode 100644 ff.cpp create mode 100644 ff.h create mode 100644 ffconf.h create mode 100644 im01.cpp create mode 100644 integer.h diff --git a/FATDirHandle.cpp b/FATDirHandle.cpp new file mode 100644 index 0000000..7f87209 --- /dev/null +++ b/FATDirHandle.cpp @@ -0,0 +1,51 @@ +#include +#include "ff.h" +#include "FATDirHandle.h" + +using namespace mbed; + +FATDirHandle::FATDirHandle(const FATFS_DIR &the_dir) +{ + dir = the_dir; +} + +int FATDirHandle::closedir() +{ + int retval = f_closedir(&dir); + delete this; + return retval; +} + +struct dirent *FATDirHandle::readdir() +{ + FILINFO finfo; + +#if _USE_LFN + finfo.lfname = cur_entry.d_name; + finfo.lfsize = sizeof(cur_entry.d_name); +#endif + + FRESULT res = f_readdir(&dir, &finfo); + +#if _USE_LFN + if (res != 0 || finfo.fname[0] == 0) + { + return NULL; + } + else + { + if (cur_entry.d_name[0] == 0) + { + memcpy(cur_entry.d_name, finfo.fname, sizeof(finfo.fname)); + } + return &cur_entry; + } +#else + +#endif +} + +void FATDirHandle::rewinddir() +{ + dir.index = 0; +} diff --git a/FATDirHandle.h b/FATDirHandle.h new file mode 100644 index 0000000..18891d7 --- /dev/null +++ b/FATDirHandle.h @@ -0,0 +1,23 @@ + #ifndef MBED_FATDIRHANDLE_H + #define MBED_FATDIRHANDLE_H + + #include "ff.h" + #include "DirHandle.h" + + using namespace mbed; + + class FATDirHandle : public DirHandle + { + + public: + FATDirHandle(const FATFS_DIR &the_dir); + virtual int closedir(); + virtual struct dirent *readdir(); + virtual void rewinddir(); + + private: + FATFS_DIR dir; + struct dirent cur_entry; + }; + + #endif diff --git a/FATFileHandle.cpp b/FATFileHandle.cpp new file mode 100644 index 0000000..1b7f954 --- /dev/null +++ b/FATFileHandle.cpp @@ -0,0 +1,74 @@ +#include "ff.h" +#include "ffconf.h" + +#include "FATFileHandle.h" + +FATFileHandle::FATFileHandle(FIL fh) +{ + _fh = fh; +} + +int FATFileHandle::close() +{ + int retval = f_close(&_fh); + delete this; + return retval; +} + +ssize_t FATFileHandle::write(const void *buffer, size_t length) +{ + UI n; + FRESULT res = f_write(&_fh, buffer, length, &n); + if (res) + { + return -1; + } + return n; +} + +ssize_t FATFileHandle::read(void *buffer, size_t length) +{ + UI n; + FRESULT res = f_read(&_fh, buffer, length, &n); + if (res) + { + return -1; + } + return n; +} + +int FATFileHandle::isatty() +{ + return 0; +} + +off_t FATFileHandle::lseek(off_t position, int whence) +{ + if (whence == SEEK_END) + { + position += _fh.fsize; + } + else if (whence == SEEK_CUR) + { + position += _fh.fptr; + } + FRESULT res = f_lseek(&_fh, position); + if (res) + { + return -1; + } + else + { + return _fh.fptr; + } +} + +int FATFileHandle::fsync() +{ + FRESULT res = f_sync(&_fh); + if (res) + { + return -1; + } + return 0; +} diff --git a/FATFileHandle.h b/FATFileHandle.h new file mode 100644 index 0000000..991d567 --- /dev/null +++ b/FATFileHandle.h @@ -0,0 +1,24 @@ +#ifndef MBED_FATFILEHANDLE_H +#define MBED_FATFILEHANDLE_H + +#include "ff.h" +#include "FileHandle.h" + +using namespace mbed; + +class FATFileHandle : public FileHandle +{ +public: + FATFileHandle(FIL fh); + virtual int close(); + virtual ssize_t write(const void *buffer, size_t length); + virtual ssize_t read(void *buffer, size_t length); + virtual int isatty(); + virtual off_t lseek(off_t position, int whence); + virtual int fsync(); + +protected: + FIL _fh; +}; + +#endif diff --git a/FATFileSystem.cpp b/FATFileSystem.cpp new file mode 100644 index 0000000..c24ef5e --- /dev/null +++ b/FATFileSystem.cpp @@ -0,0 +1,121 @@ +#include "mbed.h" + +#include "ffconf.h" + +#include "FATFileSystem.h" +#include "FATFileHandle.h" +#include "FATDirHandle.h" + +DW get_fattime(void) +{ + time_t rawtime; + time(&rawtime); + struct tm *ptm = localtime(&rawtime); + return (DW)(ptm->tm_year - 80) << 25 | (DW)(ptm->tm_mon + 1) << 21 | (DW)(ptm->tm_mday) << 16 | (DW)(ptm->tm_hour) << 11 | (DW)(ptm->tm_min) << 5 | (DW)(ptm->tm_sec / 2); +} + +FATFileSystem *FATFileSystem::_ffs[_VOLUMES] = {0}; + +FATFileSystem::FATFileSystem(const char *n) : FileSystemLike(n) +{ + for (int i = 0; i < _VOLUMES; i++) + { + if (_ffs[i] == 0) + { + _ffs[i] = this; + _fsid[0] = '0' + i; + _fsid[1] = '\0'; + f_mount(&_fs, _fsid, 0); + return; + } + } +} + +FATFileSystem::~FATFileSystem() +{ + for (int i = 0; i < _VOLUMES; i++) + { + if (_ffs[i] == this) + { + _ffs[i] = 0; + f_mount(NULL, _fsid, 0); + } + } +} + +FileHandle *FATFileSystem::open(const char *name, int flags) +{ + char n[64]; + sprintf(n, "%s:/%s", _fsid, name); + + + B openmode; + if (flags & O_RDWR) + { + openmode = FA_READ | FA_WRITE; + } + else if (flags & O_WRONLY) + { + openmode = FA_WRITE; + } + else + { + openmode = FA_READ; + } + if (flags & O_CREAT) + { + if (flags & O_TRUNC) + { + openmode |= FA_CREATE_ALWAYS; + } + else + { + openmode |= FA_OPEN_ALWAYS; + } + } + + FIL fh; + FRESULT res = f_open(&fh, n, openmode); + if (res) + { + return NULL; + } + if (flags & O_APPEND) + { + f_lseek(&fh, fh.fsize); + } + return new FATFileHandle(fh); +} + +int FATFileSystem::remove(const char *filename) +{ + FRESULT res = f_unlink(filename); + if (res) + { + return -1; + } + return 0; +} + +DirHandle *FATFileSystem::opendir(const char *name) +{ + FATFS_DIR dir; + FRESULT res = f_opendir(&dir, name); + if (res != 0) + { + return NULL; + } + return new FATDirHandle(dir); +} + +int FATFileSystem::mkdir(const char *name, mode_t mode) +{ + FRESULT res = f_mkdir(name); + return res == 0 ? 0 : -1; +} + +int FATFileSystem::mount() +{ + FRESULT res = f_mount(&_fs, _fsid, 1); + return res == 0 ? 0 : -1; +} diff --git a/FATFileSystem.h b/FATFileSystem.h new file mode 100644 index 0000000..846f8b8 --- /dev/null +++ b/FATFileSystem.h @@ -0,0 +1,34 @@ +#ifndef MBED_FATFILESYSTEM_H +#define MBED_FATFILESYSTEM_H + +#include "FileSystemLike.h" +#include "FileHandle.h" +#include "ff.h" +#include + +using namespace mbed; + +class FATFileSystem : public FileSystemLike +{ +public: + FATFileSystem(const char *n); + virtual ~FATFileSystem(); + + static FATFileSystem *_ffs[_VOLUMES]; + FATFS _fs; + char _fsid[2]; + + virtual FileHandle *open(const char *name, int flags); + virtual int remove(const char *filename); + virtual DirHandle *opendir(const char *name); + virtual int mkdir(const char *name, mode_t mode); + virtual int mount(); + virtual int disk_initialize() { return 0; } + virtual int disk_status() { return 0; } + virtual int disk_read(uint8_t *buffer, uint32_t sector, uint32_t count) = 0; + virtual int disk_write(const uint8_t *buffer, uint32_t sector, uint32_t count) = 0; + virtual int disk_sync() { return 0; } + virtual uint32_t disk_sectors() = 0; +}; + +#endif diff --git a/MemFileSystem.h b/MemFileSystem.h new file mode 100644 index 0000000..c766f4c --- /dev/null +++ b/MemFileSystem.h @@ -0,0 +1,80 @@ +#ifndef MBED_MEMFILESYSTEM_H +#define MBED_MEMFILESYSTEM_H + +#include "FATFileSystem.h" + +namespace mbed +{ + +class MemFileSystem : public FATFileSystem +{ +public: + char *sectors[2000]; + + MemFileSystem(const char *name) : FATFileSystem(name) + { + memset(sectors, 0, sizeof(sectors)); + } + + virtual ~MemFileSystem() + { + for (int i = 0; i < 2000; i++) + { + if (sectors[i]) + { + free(sectors[i]); + } + } + } + + virtual int disk_read(char *buffer, int sector) + { + if (sectors[sector] == 0) + { + + memset(buffer, 0, 512); + } + else + { + memcpy(buffer, sectors[sector], 512); + } + return 0; + } + + virtual int disk_write(const char *buffer, int sector) + { + + char zero[512]; + memset(zero, 0, 512); + if (memcmp(zero, buffer, 512) == 0) + { + if (sectors[sector] != 0) + { + free(sectors[sector]); + sectors[sector] = 0; + } + return 0; + } + + if (sectors[sector] == 0) + { + char *sec = (char *)malloc(512); + if (sec == 0) + { + return 1; + } + sectors[sector] = sec; + } + memcpy(sectors[sector], buffer, 512); + return 0; + } + + virtual int disk_sectors() + { + return sizeof(sectors) / sizeof(sectors[0]); + } +}; + +} + +#endif \ No newline at end of file diff --git a/SDFileSystem.cpp b/SDFileSystem.cpp new file mode 100644 index 0000000..72d937f --- /dev/null +++ b/SDFileSystem.cpp @@ -0,0 +1,380 @@ +#include "SDFileSystem.h" + +#define SD_COMMAND_TIMEOUT 5000 + +#define SD_DBG 0 + +SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char *name) : FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs), _is_initialized(0) +{ + _cs = 1; + _init_sck = 100000; + _transfer_sck = 1000000; +} + +#define R1_IDLE_STATE (1 << 0) +#define R1_ILLEGAL_COMMAND (1 << 2) + +#define SDCARD_FAIL 0 +#define SDCARD_V1 1 +#define SDCARD_V2 2 + +int SDFileSystem::initialise_card() +{ + + _spi.frequency(_init_sck); + _cs = 1; + for (int i = 0; i < 16; i++) + { + _spi.write(0xFF); + } + + if (_cmd(0, 0) != R1_IDLE_STATE) + { + return SDCARD_FAIL; + } + + int r = _cmd8(); + if (r == R1_IDLE_STATE) + { + return initialise_card_v2(); + } + else if (r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) + { + return initialise_card_v1(); + } + else + { + return SDCARD_FAIL; + } +} + +int SDFileSystem::initialise_card_v1() +{ + for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) + { + _cmd(55, 0); + if (_cmd(41, 0) == 0) + { + cdv = 512; + return SDCARD_V1; + } + } + + return SDCARD_FAIL; +} + +int SDFileSystem::initialise_card_v2() +{ + for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) + { + wait_ms(50); + _cmd58(); + _cmd(55, 0); + if (_cmd(41, 0x40000000) == 0) + { + _cmd58(); + cdv = 1; + return SDCARD_V2; + } + } + return SDCARD_FAIL; +} + +int SDFileSystem::disk_initialize() +{ + _is_initialized = initialise_card(); + if (_is_initialized == 0) + { + return 1; + } + _sectors = _sd_sectors(); + + if (_cmd(16, 512) != 0) + { + return 1; + } + + _spi.frequency(_transfer_sck); + return 0; +} + +int SDFileSystem::disk_write(const uint8_t *buffer, uint32_t block_number, uint32_t count) +{ + if (!_is_initialized) + { + return -1; + } + + for (uint32_t b = block_number; b < block_number + count; b++) + { + + if (_cmd(24, b * cdv) != 0) + { + return 1; + } + + _write(buffer, 512); + buffer += 512; + } + + return 0; +} + +int SDFileSystem::disk_read(uint8_t *buffer, uint32_t block_number, uint32_t count) +{ + if (!_is_initialized) + { + return -1; + } + + for (uint32_t b = block_number; b < block_number + count; b++) + { + + if (_cmd(17, b * cdv) != 0) + { + return 1; + } + + _read(buffer, 512); + buffer += 512; + } + + return 0; +} + +int SDFileSystem::disk_status() +{ + + if (_is_initialized) + { + return 0; + } + else + { + return 1; + } +} + +int SDFileSystem::disk_sync() { return 0; } +uint32_t SDFileSystem::disk_sectors() { return _sectors; } + +int SDFileSystem::_cmd(int cmd, int arg) +{ + _cs = 0; + + _spi.write(0x40 | cmd); + _spi.write(arg >> 24); + _spi.write(arg >> 16); + _spi.write(arg >> 8); + _spi.write(arg >> 0); + _spi.write(0x95); + + for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) + { + int response = _spi.write(0xFF); + if (!(response & 0x80)) + { + _cs = 1; + _spi.write(0xFF); + return response; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; +} +int SDFileSystem::_cmdx(int cmd, int arg) +{ + _cs = 0; + + _spi.write(0x40 | cmd); + _spi.write(arg >> 24); + _spi.write(arg >> 16); + _spi.write(arg >> 8); + _spi.write(arg >> 0); + _spi.write(0x95); + + for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) + { + int response = _spi.write(0xFF); + if (!(response & 0x80)) + { + return response; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; +} + +int SDFileSystem::_cmd58() +{ + _cs = 0; + int arg = 0; + + _spi.write(0x40 | 58); + _spi.write(arg >> 24); + _spi.write(arg >> 16); + _spi.write(arg >> 8); + _spi.write(arg >> 0); + _spi.write(0x95); + + for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) + { + int response = _spi.write(0xFF); + if (!(response & 0x80)) + { + int ocr = _spi.write(0xFF) << 24; + ocr |= _spi.write(0xFF) << 16; + ocr |= _spi.write(0xFF) << 8; + ocr |= _spi.write(0xFF) << 0; + _cs = 1; + _spi.write(0xFF); + return response; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; +} + +int SDFileSystem::_cmd8() +{ + _cs = 0; + + _spi.write(0x40 | 8); + _spi.write(0x00); + _spi.write(0x00); + _spi.write(0x01); + _spi.write(0xAA); + _spi.write(0x87); + + for (int i = 0; i < SD_COMMAND_TIMEOUT * 1000; i++) + { + char response[5]; + response[0] = _spi.write(0xFF); + if (!(response[0] & 0x80)) + { + for (int j = 1; j < 5; j++) + { + response[i] = _spi.write(0xFF); + } + _cs = 1; + _spi.write(0xFF); + return response[0]; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; +} + +int SDFileSystem::_read(uint8_t *buffer, uint32_t length) +{ + _cs = 0; + + while (_spi.write(0xFF) != 0xFE) + ; + + for (uint32_t i = 0; i < length; i++) + { + buffer[i] = _spi.write(0xFF); + } + _spi.write(0xFF); + _spi.write(0xFF); + + _cs = 1; + _spi.write(0xFF); + return 0; +} + +int SDFileSystem::_write(const uint8_t *buffer, uint32_t length) +{ + _cs = 0; + + _spi.write(0xFE); + + for (uint32_t i = 0; i < length; i++) + { + _spi.write(buffer[i]); + } + + _spi.write(0xFF); + _spi.write(0xFF); + + if ((_spi.write(0xFF) & 0x1F) != 0x05) + { + _cs = 1; + _spi.write(0xFF); + return 1; + } + + while (_spi.write(0xFF) == 0) + ; + + _cs = 1; + _spi.write(0xFF); + return 0; +} + +static uint32_t ext_bits(unsigned char *data, int msb, int lsb) +{ + uint32_t bits = 0; + uint32_t size = 1 + msb - lsb; + for (uint32_t i = 0; i < size; i++) + { + uint32_t position = lsb + i; + uint32_t byte = 15 - (position >> 3); + uint32_t bit = position & 0x7; + uint32_t value = (data[byte] >> bit) & 1; + bits |= value << i; + } + return bits; +} + +uint32_t SDFileSystem::_sd_sectors() +{ + uint32_t c_size, c_size_mult, read_bl_len; + uint32_t block_len, mult, blocknr, capacity; + uint32_t hc_c_size; + uint32_t blocks; + + if (_cmdx(9, 0) != 0) + { + return 0; + } + + uint8_t csd[16]; + if (_read(csd, 16) != 0) + { + return 0; + } + + int csd_structure = ext_bits(csd, 127, 126); + + switch (csd_structure) + { + case 0: + cdv = 512; + c_size = ext_bits(csd, 73, 62); + c_size_mult = ext_bits(csd, 49, 47); + read_bl_len = ext_bits(csd, 83, 80); + + block_len = 1 << read_bl_len; + mult = 1 << (c_size_mult + 2); + blocknr = (c_size + 1) * mult; + capacity = blocknr * block_len; + blocks = capacity / 512; + break; + + case 1: + cdv = 1; + hc_c_size = ext_bits(csd, 63, 48); + blocks = (hc_c_size + 1) * 1024; + break; + + default: + return 0; + }; + return blocks; +} \ No newline at end of file diff --git a/SDFileSystem.h b/SDFileSystem.h new file mode 100644 index 0000000..821fa27 --- /dev/null +++ b/SDFileSystem.h @@ -0,0 +1,39 @@ +#ifndef MBED_SDFILESYSTEM_H +#define MBED_SDFILESYSTEM_H +#include "mbed.h" +#include "FATFileSystem.h" +#include +class SDFileSystem : public FATFileSystem +{ +public: + SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char *name); + virtual int disk_initialize(); + virtual int disk_status(); + virtual int disk_read(uint8_t *buffer, uint32_t block_number, uint32_t count); + virtual int disk_write(const uint8_t *buffer, uint32_t block_number, uint32_t count); + virtual int disk_sync(); + virtual uint32_t disk_sectors(); + +protected: + int _cmd(int cmd, int arg); + int _cmdx(int cmd, int arg); + int _cmd8(); + int _cmd58(); + int initialise_card(); + int initialise_card_v1(); + int initialise_card_v2(); + + int _read(uint8_t *buffer, uint32_t length); + int _write(const uint8_t *buffer, uint32_t length); + uint32_t _sd_sectors(); + uint32_t _sectors; + uint32_t _init_sck; + uint32_t _transfer_sck; + + SPI _spi; + DigitalOut _cs; + int cdv; + int _is_initialized; +}; + +#endif \ No newline at end of file diff --git a/ccsbcs.cpp b/ccsbcs.cpp new file mode 100644 index 0000000..a7553f4 --- /dev/null +++ b/ccsbcs.cpp @@ -0,0 +1,84 @@ +#include "ff.h" +#define _TBLDEF 1 +static const WC Tbl[] = { + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0}; +WC ff_convert(WC chr, UI dir) +{ + WC c; + if (chr < 0x80) + { + c = chr; + } + else + { + if (dir) + { + c = (chr >= 0x100) ? 0 : Tbl[chr - 0x80]; + } + else + { + for (c = 0; c < 0x80; c++) + { + if (chr == Tbl[c]) + break; + } + c = (c + 0x80) & 0xFF; + } + } + return c; +} +WC ff_wtoupper(WC chr) +{ + static const WC lower[] = { + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, + 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, + 0x183, 0x185, 0x188, 0x18C, 0x192, 0x199, 0x1A1, 0x1A3, 0x1A8, 0x1AD, 0x1B0, 0x1B4, 0x1B6, 0x1B9, 0x1BD, 0x1C6, 0x1C9, 0x1CC, 0x1CE, 0x1D0, 0x1D2, 0x1D4, 0x1D6, 0x1D8, 0x1DA, 0x1DC, 0x1DD, 0x1DF, 0x1E1, 0x1E3, 0x1E5, 0x1E7, 0x1E9, 0x1EB, 0x1ED, 0x1EF, 0x1F3, 0x1F5, 0x1FB, 0x1FD, 0x1FF, 0x201, 0x203, 0x205, 0x207, 0x209, 0x20B, 0x20D, 0x20F, 0x211, 0x213, 0x215, 0x217, + 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x3CB, 0x3CC, 0x3CD, 0x3CE, 0x3E3, 0x3E5, 0x3E7, 0x3E9, 0x3EB, + 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x461, 0x463, 0x465, 0x467, 0x469, 0x46B, 0x46D, 0x46F, 0x471, 0x473, 0x475, 0x477, 0x479, 0x47B, 0x47D, 0x47F, 0x481, 0x491, 0x493, 0x495, 0x497, 0x499, 0x49B, 0x49D, 0x49F, 0x4A1, 0x4A3, 0x4A5, 0x4A7, 0x4A9, 0x4AB, 0x4AD, 0x4AF, 0x4B1, 0x4B3, 0x4B5, 0x4B7, 0x4B9, 0x4BB, 0x4BD, 0x4BF, 0x4C2, 0x4C4, 0x4C8, 0x4D1, 0x4D3, 0x4D5, 0x4D7, 0x4D9, 0x4DB, 0x4DD, 0x4DF, 0x4E1, 0x4E3, 0x4E5, 0x4E7, 0x4E9, 0x4EB, 0x4ED, 0x4EF, 0x4F1, 0x4F3, 0x4F5, 0x4F9, + 0x561, 0x562, 0x563, 0x564, 0x565, 0x566, 0x567, 0x568, 0x569, 0x56A, 0x56B, 0x56C, 0x56D, 0x56E, 0x56F, 0x570, 0x571, 0x572, 0x573, 0x574, 0x575, 0x576, 0x577, 0x578, 0x579, 0x57A, 0x57B, 0x57C, 0x57D, 0x57E, 0x57F, 0x580, 0x581, 0x582, 0x583, 0x584, 0x585, 0x586, + 0x1E01, 0x1E03, 0x1E05, 0x1E07, 0x1E09, 0x1E0B, 0x1E0D, 0x1E0F, 0x1E11, 0x1E13, 0x1E15, 0x1E17, 0x1E19, 0x1E1B, 0x1E1D, 0x1E1F, 0x1E21, 0x1E23, 0x1E25, 0x1E27, 0x1E29, 0x1E2B, 0x1E2D, 0x1E2F, 0x1E31, 0x1E33, 0x1E35, 0x1E37, 0x1E39, 0x1E3B, 0x1E3D, 0x1E3F, 0x1E41, 0x1E43, 0x1E45, 0x1E47, 0x1E49, 0x1E4B, 0x1E4D, 0x1E4F, 0x1E51, 0x1E53, 0x1E55, 0x1E57, 0x1E59, 0x1E5B, 0x1E5D, 0x1E5F, 0x1E61, 0x1E63, 0x1E65, 0x1E67, 0x1E69, 0x1E6B, 0x1E6D, 0x1E6F, 0x1E71, 0x1E73, 0x1E75, 0x1E77, 0x1E79, 0x1E7B, 0x1E7D, 0x1E7F, 0x1E81, 0x1E83, 0x1E85, 0x1E87, 0x1E89, 0x1E8B, 0x1E8D, 0x1E8F, 0x1E91, 0x1E93, 0x1E95, 0x1E97, 0x1E99, 0x1E9B, 0x1E9D, 0x1E9F, 0x1EA1, 0x1EA3, 0x1EA5, 0x1EA7, 0x1EA9, 0x1EAB, 0x1EAD, 0x1EAF, 0x1EB1, 0x1EB3, 0x1EB5, 0x1EB7, 0x1EB9, 0x1EBB, 0x1EBD, 0x1EBF, 0x1EC1, 0x1EC3, 0x1EC5, 0x1EC7, 0x1EC9, 0x1ECB, 0x1ECD, 0x1ECF, 0x1ED1, 0x1ED3, 0x1ED5, 0x1ED7, 0x1ED9, 0x1EDB, 0x1EDD, 0x1EDF, 0x1EE1, 0x1EE3, 0x1EE5, 0x1EE7, 0x1EE9, 0x1EEB, 0x1EED, 0x1EEF, 0x1EF1, 0x1EF3, 0x1EF5, 0x1EF7, 0x1EF9, + 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, + 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A}; + static const WC upper[] = { + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, + 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, + 0x182, 0x184, 0x187, 0x18B, 0x191, 0x198, 0x1A0, 0x1A2, 0x1A7, 0x1AC, 0x1AF, 0x1B3, 0x1B5, 0x1B8, 0x1BC, 0x1C4, 0x1C7, 0x1CA, 0x1CD, 0x1CF, 0x1D1, 0x1D3, 0x1D5, 0x1D7, 0x1D9, 0x1DB, 0x18E, 0x1DE, 0x1E0, 0x1E2, 0x1E4, 0x1E6, 0x1E8, 0x1EA, 0x1EC, 0x1EE, 0x1F1, 0x1F4, 0x1FA, 0x1FC, 0x1FE, 0x200, 0x202, 0x204, 0x206, 0x208, 0x20A, 0x20C, 0x20E, 0x210, 0x212, 0x214, 0x216, + 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x3AB, 0x38C, 0x38E, 0x38F, 0x3E2, 0x3E4, 0x3E6, 0x3E8, 0x3EA, + 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x460, 0x462, 0x464, 0x466, 0x468, 0x46A, 0x46C, 0x46E, 0x470, 0x472, 0x474, 0x476, 0x478, 0x47A, 0x47C, 0x47E, 0x480, 0x490, 0x492, 0x494, 0x496, 0x498, 0x49A, 0x49C, 0x49E, 0x4A0, 0x4A2, 0x4A4, 0x4A6, 0x4A8, 0x4AA, 0x4AC, 0x4AE, 0x4B0, 0x4B2, 0x4B4, 0x4B6, 0x4B8, 0x4BA, 0x4BC, 0x4BE, 0x4C1, 0x4C3, 0x5C7, 0x4D0, 0x4D2, 0x4D4, 0x4D6, 0x4D8, 0x4DA, 0x4DC, 0x4DE, 0x4E0, 0x4E2, 0x4E4, 0x4E6, 0x4E8, 0x4EA, 0x4EC, 0x4EE, 0x4F0, 0x4F2, 0x4F4, 0x4F8, + 0x531, 0x532, 0x533, 0x534, 0x535, 0x536, 0x537, 0x538, 0x539, 0x53A, 0x53B, 0x53C, 0x53D, 0x53E, 0x53F, 0x540, 0x541, 0x542, 0x543, 0x544, 0x545, 0x546, 0x547, 0x548, 0x549, 0x54A, 0x54B, 0x54C, 0x54D, 0x54E, 0x54F, 0x550, 0x551, 0x552, 0x553, 0x554, 0x555, 0x556, + 0x1E00, 0x1E02, 0x1E04, 0x1E06, 0x1E08, 0x1E0A, 0x1E0C, 0x1E0E, 0x1E10, 0x1E12, 0x1E14, 0x1E16, 0x1E18, 0x1E1A, 0x1E1C, 0x1E1E, 0x1E20, 0x1E22, 0x1E24, 0x1E26, 0x1E28, 0x1E2A, 0x1E2C, 0x1E2E, 0x1E30, 0x1E32, 0x1E34, 0x1E36, 0x1E38, 0x1E3A, 0x1E3C, 0x1E3E, 0x1E40, 0x1E42, 0x1E44, 0x1E46, 0x1E48, 0x1E4A, 0x1E4C, 0x1E4E, 0x1E50, 0x1E52, 0x1E54, 0x1E56, 0x1E58, 0x1E5A, 0x1E5C, 0x1E5E, 0x1E60, 0x1E62, 0x1E64, 0x1E66, 0x1E68, 0x1E6A, 0x1E6C, 0x1E6E, 0x1E70, 0x1E72, 0x1E74, 0x1E76, 0x1E78, 0x1E7A, 0x1E7C, 0x1E7E, 0x1E80, 0x1E82, 0x1E84, 0x1E86, 0x1E88, 0x1E8A, 0x1E8C, 0x1E8E, 0x1E90, 0x1E92, 0x1E94, 0x1E96, 0x1E98, 0x1E9A, 0x1E9C, 0x1E9E, 0x1EA0, 0x1EA2, 0x1EA4, 0x1EA6, 0x1EA8, 0x1EAA, 0x1EAC, 0x1EAE, 0x1EB0, 0x1EB2, 0x1EB4, 0x1EB6, 0x1EB8, 0x1EBA, 0x1EBC, 0x1EBE, 0x1EC0, 0x1EC2, 0x1EC4, 0x1EC6, 0x1EC8, 0x1ECA, 0x1ECC, 0x1ECE, 0x1ED0, 0x1ED2, 0x1ED4, 0x1ED6, 0x1ED8, 0x1EDA, 0x1EDC, 0x1EDE, 0x1EE0, 0x1EE2, 0x1EE4, 0x1EE6, 0x1EE8, 0x1EEA, 0x1EEC, 0x1EEE, 0x1EF0, 0x1EF2, 0x1EF4, 0x1EF6, 0x1EF8, + 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, + 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A}; + UI i, n, hi, li; + if (chr < 0x80) + { + if (chr >= 0x61 && chr <= 0x7A) + chr -= 0x20; + } + else + { + n = 12; + li = 0; + hi = sizeof lower / sizeof lower[0]; + do + { + i = li + (hi - li) / 2; + if (chr == lower[i]) + break; + if (chr > lower[i]) + li = i; + else + hi = i; + } while (--n); + if (n) + chr = upper[i]; + } + return chr; +} \ No newline at end of file diff --git a/diskio.cpp b/diskio.cpp new file mode 100644 index 0000000..a6507c4 --- /dev/null +++ b/diskio.cpp @@ -0,0 +1,80 @@ +#include "diskio.h" +#include "FATFileSystem.h" +using namespace mbed; +DSTATUS disk_status( + B pdrv) +{ + return (DSTATUS)FATFileSystem::_ffs[pdrv]->disk_status(); +} +DSTATUS disk_initialize( + B pdrv) +{ + return (DSTATUS)FATFileSystem::_ffs[pdrv]->disk_initialize(); +} +DRESULT disk_read( + B pdrv, + B *buff, + DW sector, + UI count) +{ + if (FATFileSystem::_ffs[pdrv]->disk_read((uint8_t *)buff, sector, count)) + return RES_PARERR; + else + return RES_OK; +} +#if _USE_WRITE +DRESULT disk_write( + B pdrv, + const B *buff, + DW sector, + UI count) +{ + if (FATFileSystem::_ffs[pdrv]->disk_write((uint8_t *)buff, sector, count)) + return RES_PARERR; + else + return RES_OK; +} +#endif +#if _USE_IOCTL +DRESULT disk_ioctl( + B pdrv, + B cmd, + void *buff) +{ + switch (cmd) + { + case CTRL_SYNC: + if (FATFileSystem::_ffs[pdrv] == NULL) + { + return RES_NOTRDY; + } + else if (FATFileSystem::_ffs[pdrv]->disk_sync()) + { + return RES_ERROR; + } + return RES_OK; + case GET_SECTOR_COUNT: + if (FATFileSystem::_ffs[pdrv] == NULL) + { + return RES_NOTRDY; + } + else + { + DW res = FATFileSystem::_ffs[pdrv]->disk_sectors(); + if (res > 0) + { + *((DW *)buff) = res; + return RES_OK; + } + else + { + return RES_ERROR; + } + } + case GET_BLOCK_SIZE: + *((DW *)buff) = 1; + return RES_OK; + } + return RES_PARERR; +} +#endif diff --git a/diskio.h b/diskio.h new file mode 100644 index 0000000..0d17a66 --- /dev/null +++ b/diskio.h @@ -0,0 +1,32 @@ +#ifndef _DISKIO_DEFINED +#define _DISKIO_DEFINED +#ifdef __cplusplus +extern "C" +{ +#endif +#define _USE_WRITE 1 +#define _USE_IOCTL 1 +#include "integer.h" + typedef B DSTATUS; + typedef enum + { + RES_OK = 0, + RES_ERROR, + RES_WRPRT, + RES_NOTRDY, + RES_PARERR + } DRESULT; + DSTATUS disk_initialize(B pdrv); + DSTATUS disk_status(B pdrv); + DRESULT disk_read(B pdrv, B *buff, DW sector, UI count); + DRESULT disk_write(B pdrv, const B *buff, DW sector, UI count); + DRESULT disk_ioctl(B pdrv, B cmd, void *buff); +#define STA_NOINIT 0x01 +#define STA_PROTECT 0x04 +#define CTRL_SYNC 0 +#define GET_SECTOR_COUNT 1 +#define GET_BLOCK_SIZE 3 +#ifdef __cplusplus +} +#endif +#endif diff --git a/ff.cpp b/ff.cpp new file mode 100644 index 0000000..003167a --- /dev/null +++ b/ff.cpp @@ -0,0 +1,119 @@ +#include "ff.h" +#include "diskio.h" +#define ENTER_FF(fs) +#define LEAVE_FF(fs, res) return res +#define ABORT(fs, res) { fp->err = (B)(res); LEAVE_FF(fs, res); } +#define SS(fs) ((UI)_MAX_SS) +#define GET_FATTIME() ((DW)(_NORTC_YEAR - 1980) << 25 | (DW)_NORTC_MON << 21 | (DW)_NORTC_MDAY << 16) +#define _DF1S 0 +#define _EXCVT {0x43,0x55,0x45,0x41,0x41,0x41,0x41,0x43,0x45,0x45,0x45,0x49,0x49,0x49,0x41,0x41, 0x45,0x92,0x92,0x4F,0x4F,0x4F,0x55,0x55,0x59,0x4F,0x55,0x4F,0x9C,0x4F,0x9E,0x9F, 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, 0xB0,0xB1,0xB2,0xB3,0xB4,0x41,0x41,0x41,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0x41,0x41,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, 0xD1,0xD1,0x45,0x45,0x45,0x49,0x49,0x49,0x49,0xD9,0xDA,0xDB,0xDC,0xDD,0x49,0xDF, 0x4F,0xE1,0x4F,0x4F,0x4F,0x4F,0xE6,0xE8,0xE8,0x55,0x55,0x55,0x59,0x59,0xEE,0xEF, 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define IsUpper(c) (((c)>='A')&&((c)<='Z')) +#define IsLower(c) (((c)>='a')&&((c)<='z')) +#define IsDigit(c) (((c)>='0')&&((c)<='9')) +#define IsDBCS1(c) 0 +#define IsDBCS2(c) 0 +#define NSFLAG 11 +#define NS_LOSS 0x01 +#define NS_LFN 0x02 +#define NS_LAST 0x04 +#define NS_BODY 0x08 +#define NS_EXT 0x10 +#define NS_DOT 0x20 +#define MIN_FAT16 4086U +#define MIN_FAT32 65526U +#define BPB_BytsPerSec 11 +#define BPB_SecPerClus 13 +#define BPB_RsvdSecCnt 14 +#define BPB_NumFATs 16 +#define BPB_RootEntCnt 17 +#define BPB_TotSec16 19 +#define BPB_FATSz16 22 +#define BPB_TotSec32 32 +#define BS_FilSysType 54 +#define BPB_FATSz32 36 +#define BPB_RootClus 44 +#define BPB_FSInfo 48 +#define BS_FilSysType32 82 +#define FSI_LeadSig 0 +#define FSI_StrucSig 484 +#define FSI_Free_Count 488 +#define FSI_Nxt_Free 492 +#define MBR_Table 446 +#define SZ_PTE 16 +#define BS_55AA 510 +#define DIR_Name 0 +#define DIR_Attr 11 +#define DIR_NTres 12 +#define DIR_CrtTime 14 +#define DIR_LstAccDate 18 +#define DIR_FstClusHI 20 +#define DIR_WrtTime 22 +#define DIR_WrtDate 24 +#define DIR_FstClusLO 26 +#define DIR_FileSize 28 +#define LDIR_Ord 0 +#define LDIR_Attr 11 +#define LDIR_Type 12 +#define LDIR_Chksum 13 +#define LDIR_FstClusLO 26 +#define SZ_DIRE 32 +#define LLEF 0x40 +#define DDEM 0xE5 +#define RDDEM 0x05 +static FATFS *FatFs[_VOLUMES]; +static W Fsid; +static WC LfnBuf[_MAX_LFN + 1]; +#define DEFINE_NAMEBUF B sfn[12] +#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } +#define FREE_BUF() +static const B ExCvt[] = _EXCVT; +static void mem_cpy (void* dst, const void* src, UI cnt) {B *d = (B*)dst; const B *s = (const B*)src; while (cnt--) *d++ = *s++; } +static void mem_set (void* dst, int val, UI cnt) {B *d = (B*)dst; while (cnt--) *d++ = (B)val; } +static int mem_cmp (const void* dst, const void* src, UI cnt) {const B *d = (const B *)dst, *s = (const B *)src; int r = 0; while (cnt-- && (r = *d++ - *s++) == 0) ; return r; } +static int chk_chr (const char* str, int chr) {while (*str && *str != chr) str++; return *str; } +static FRESULT sync_window (FATFS* fs) {DW wsect; UI nf;FRESULT res = FR_OK; if (fs->wflag) {wsect = fs->winsect; if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) {res = FR_DISK_ERR; } else {fs->wflag = 0; if (wsect - fs->fatbase < fs->fsize) { for (nf = fs->n_fats; nf >= 2; nf--) {wsect += fs->fsize; disk_write(fs->drv, fs->win, wsect, 1); } } } } return res; } +static FRESULT move_window (FATFS* fs, DW sector) {FRESULT res = FR_OK; if (sector != fs->winsect) {res = sync_window(fs); if (res == FR_OK) { if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) {sector = 0xFFFFFFFF; res = FR_DISK_ERR; } fs->winsect = sector; } } return res; } +static FRESULT sync_fs (FATFS* fs) {FRESULT res; res = sync_window(fs); if (res == FR_OK) {if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) {mem_set(fs->win, 0, SS(fs)); ST_WORD(fs->win + BS_55AA, 0xAA55); ST_DWORD(fs->win + FSI_LeadSig, 0x41615252); ST_DWORD(fs->win + FSI_StrucSig, 0x61417272); ST_DWORD(fs->win + FSI_Free_Count, fs->free_clust); ST_DWORD(fs->win + FSI_Nxt_Free, fs->last_clust); fs->winsect = fs->volbase + 1; disk_write(fs->drv, fs->win, fs->winsect, 1); fs->fsi_flag = 0; } if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR; } return res; } +DW clust2sect (FATFS* fs, DW clst) {clst -= 2; if (clst >= fs->n_fatent - 2) return 0; return clst * fs->csize + fs->database; } +DW get_fat (FATFS* fs, DW clst) {UI wc, bc; B *p; DW val; if (clst < 2 || clst >= fs->n_fatent) {val = 1; } else {val = 0xFFFFFFFF; switch (fs->fs_type) {case FS_FAT12 : bc = (UI)clst; bc += bc / 2; if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; wc = fs->win[bc++ % SS(fs)]; if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; wc |= fs->win[bc % SS(fs)] << 8; val = clst & 1 ? wc >> 4 : (wc & 0xFFF); break; case FS_FAT16 : if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break; p = &fs->win[clst * 2 % SS(fs)]; val = LD_WORD(p); break; case FS_FAT32 : if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; p = &fs->win[clst * 4 % SS(fs)]; val = LD_DWORD(p) & 0x0FFFFFFF; break; default: val = 1; } } return val; } +FRESULT put_fat (FATFS* fs, DW clst, DW val) {UI bc; B *p;FRESULT res; if (clst < 2 || clst >= fs->n_fatent) {res = FR_INT_ERR; } else {switch (fs->fs_type) {case FS_FAT12 : bc = (UI)clst; bc += bc / 2; res = move_window(fs, fs->fatbase + (bc / SS(fs))); if (res != FR_OK) break; p = &fs->win[bc++ % SS(fs)]; *p = (clst & 1) ? ((*p & 0x0F) | ((B)val << 4)) : (B)val; fs->wflag = 1; res = move_window(fs, fs->fatbase + (bc / SS(fs))); if (res != FR_OK) break; p = &fs->win[bc % SS(fs)]; *p = (clst & 1) ? (B)(val >> 4) : ((*p & 0xF0) | ((B)(val >> 8) & 0x0F)); fs->wflag = 1; break; case FS_FAT16 : res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); if (res != FR_OK) break; p = &fs->win[clst * 2 % SS(fs)]; ST_WORD(p, (W)val); fs->wflag = 1; break; case FS_FAT32 : res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); if (res != FR_OK) break; p = &fs->win[clst * 4 % SS(fs)]; val |= LD_DWORD(p) & 0xF0000000; ST_DWORD(p, val); fs->wflag = 1; break; default : res = FR_INT_ERR; } } return res; } +static FRESULT remove_chain (FATFS* fs, DW clst) {FRESULT res; DW nxt; if (clst < 2 || clst >= fs->n_fatent) {res = FR_INT_ERR; } else {res = FR_OK; while (clst < fs->n_fatent) { nxt = get_fat(fs, clst); if (nxt == 0) break; if (nxt == 1) { res = FR_INT_ERR; break; } if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } res = put_fat(fs, clst, 0); if (res != FR_OK) break; if (fs->free_clust != 0xFFFFFFFF) {fs->free_clust++; fs->fsi_flag |= 1; } clst = nxt; } } return res; } +static DW create_chain (FATFS* fs, DW clst) {DW cs, ncl, scl;FRESULT res; if (clst == 0) { scl = fs->last_clust; if (!scl || scl >= fs->n_fatent) scl = 1; } else { cs = get_fat(fs, clst); if (cs < 2) return 1; if (cs == 0xFFFFFFFF) return cs; if (cs < fs->n_fatent) return cs; scl = clst; } ncl = scl; for (;;) {ncl++; if (ncl >= fs->n_fatent) { ncl = 2; if (ncl > scl) return 0; } cs = get_fat(fs, ncl); if (cs == 0) break; if (cs == 0xFFFFFFFF || cs == 1) return cs; if (ncl == scl) return 0; } res = put_fat(fs, ncl, 0x0FFFFFFF); if (res == FR_OK && clst != 0) {res = put_fat(fs, clst, ncl); } if (res == FR_OK) {fs->last_clust = ncl; if (fs->free_clust != 0xFFFFFFFF) {fs->free_clust--; fs->fsi_flag |= 1; } } else {ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; } return ncl; } +static FRESULT dir_sdi (FATFS_DIR* dp, UI idx) {DW clst, sect; UI ic; dp->index = (W)idx; clst = dp->sclust; if (clst == 1 || clst >= dp->fs->n_fatent) return FR_INT_ERR; if (!clst && dp->fs->fs_type == FS_FAT32) clst = dp->fs->dirbase; if (clst == 0) {if (idx >= dp->fs->n_rootdir) return FR_INT_ERR; sect = dp->fs->dirbase; } else { ic = SS(dp->fs) / SZ_DIRE * dp->fs->csize; while (idx >= ic) {clst = get_fat(dp->fs, clst); if (clst == 0xFFFFFFFF) return FR_DISK_ERR; if (clst < 2 || clst >= dp->fs->n_fatent) return FR_INT_ERR; idx -= ic; } sect = clust2sect(dp->fs, clst); } dp->clust = clst; if (!sect) return FR_INT_ERR; dp->sect = sect + idx / (SS(dp->fs) / SZ_DIRE); dp->dir = dp->fs->win + (idx % (SS(dp->fs) / SZ_DIRE)) * SZ_DIRE; return FR_OK; } +static FRESULT dir_next (FATFS_DIR* dp, int stretch) {DW clst; UI i; UI c; i = dp->index + 1; if (!(i & 0xFFFF) || !dp->sect) return FR_NO_FILE; if (!(i % (SS(dp->fs) / SZ_DIRE))) {dp->sect++; if (!dp->clust) { if (i >= dp->fs->n_rootdir) return FR_NO_FILE; } else { if (((i / (SS(dp->fs) / SZ_DIRE)) & (dp->fs->csize - 1)) == 0) {clst = get_fat(dp->fs, dp->clust); if (clst <= 1) return FR_INT_ERR; if (clst == 0xFFFFFFFF) return FR_DISK_ERR; if (clst >= dp->fs->n_fatent) { if (!stretch) return FR_NO_FILE; clst = create_chain(dp->fs, dp->clust); if (clst == 0) return FR_DENIED; if (clst == 1) return FR_INT_ERR; if (clst == 0xFFFFFFFF) return FR_DISK_ERR; if (sync_window(dp->fs)) return FR_DISK_ERR; mem_set(dp->fs->win, 0, SS(dp->fs)); dp->fs->winsect = clust2sect(dp->fs, clst); for (c = 0; c < dp->fs->csize; c++) { dp->fs->wflag = 1; if (sync_window(dp->fs)) return FR_DISK_ERR; dp->fs->winsect++; } dp->fs->winsect -= c; } dp->clust = clst; dp->sect = clust2sect(dp->fs, clst); } } } dp->index = (W)i; dp->dir = dp->fs->win + (i % (SS(dp->fs) / SZ_DIRE)) * SZ_DIRE; return FR_OK; } +static FRESULT dir_alloc (FATFS_DIR* dp, UI nent) {FRESULT res; UI n; res = dir_sdi(dp, 0); if (res == FR_OK) {n = 0; do {res = move_window(dp->fs, dp->sect); if (res != FR_OK) break; if (dp->dir[0] == DDEM || dp->dir[0] == 0) {if (++n == nent) break; } else {n = 0; } res = dir_next(dp, 1); } while (res == FR_OK); } if (res == FR_NO_FILE) res = FR_DENIED; return res; } +static DW ld_clust (FATFS* fs, const B* dir) {DW cl; cl = LD_WORD(dir + DIR_FstClusLO); if (fs->fs_type == FS_FAT32) cl |= (DW)LD_WORD(dir + DIR_FstClusHI) << 16; return cl; } +static void st_clust (B* dir, DW cl) {ST_WORD(dir + DIR_FstClusLO, cl); ST_WORD(dir + DIR_FstClusHI, cl >> 16); } +static const B LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; +static int cmp_lfn (WC* lfnbuf, B* dir) {UI i, s; WC wc, uc; if (LD_WORD(dir + LDIR_FstClusLO) != 0) return 0; i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; for (wc = 1, s = 0; s < 13; s++) { uc = LD_WORD(dir + LfnOfs[s]); if (wc) {if (i >= _MAX_LFN || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) return 0; wc = uc; } else {if (uc != 0xFFFF) return 0; } } if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i]) return 0; return 1; } +static int pick_lfn (WC* lfnbuf, B* dir) {UI i, s; WC wc, uc; if (LD_WORD(dir + LDIR_FstClusLO) != 0) return 0; i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; for (wc = 1, s = 0; s < 13; s++) { uc = LD_WORD(dir + LfnOfs[s]); if (wc) {if (i >= _MAX_LFN) return 0; lfnbuf[i++] = wc = uc; } else {if (uc != 0xFFFF) return 0; } } if (dir[LDIR_Ord] & LLEF) { if (i >= _MAX_LFN) return 0; lfnbuf[i] = 0; } return 1; } +static void fit_lfn (const WC* lfnbuf, B* dir, B ord, B sum) {UI i, s; WC wc; dir[LDIR_Chksum] = sum; dir[LDIR_Attr] = AM_LFN; dir[LDIR_Type] = 0; ST_WORD(dir + LDIR_FstClusLO, 0); i = (ord - 1) * 13; s = wc = 0; do {if (wc != 0xFFFF) wc = lfnbuf[i++]; ST_WORD(dir+LfnOfs[s], wc); if (!wc) wc = 0xFFFF; } while (++s < 13); if (wc == 0xFFFF || !lfnbuf[i]) ord |= LLEF; dir[LDIR_Ord] = ord; } +static void gen_numname (B* dst, const B* src, const WC* lfn, UI seq) {B ns[8], c; UI i, j; WC wc;DW sr; mem_cpy(dst, src, 11); if (seq > 5) {sr = seq; while (*lfn) {wc = *lfn++; for (i = 0; i < 16; i++) {sr = (sr << 1) + (wc & 1); wc >>= 1; if (sr & 0x10000) sr ^= 0x11021; } } seq = (UI)sr; } i = 7; do {c = (seq % 16) + '0'; if (c > '9') c += 7; ns[i--] = c; seq /= 16; } while (seq); ns[i] = '~'; for (j = 0; j < i && dst[j] != ' '; j++) {if (IsDBCS1(dst[j])) {if (j == i - 1) break; j++; } } do {dst[j++] = (i < 8) ? ns[i++] : ' '; } while (j < 8); } +static B sum_sfn (const B* dir) {B sum = 0; UI n = 11; do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n); return sum; } +static FRESULT dir_find (FATFS_DIR* dp) {FRESULT res; B c, *dir; B a, ord, sum; res = dir_sdi(dp, 0); if (res != FR_OK) return res; ord = sum = 0xFF; dp->lfn_idx = 0xFFFF; do {res = move_window(dp->fs, dp->sect); if (res != FR_OK) break; dir = dp->dir; c = dir[DIR_Name]; if (c == 0) { res = FR_NO_FILE; break; } a = dir[DIR_Attr] & AM_MASK; if (c == DDEM || ((a & AM_VOL) && a != AM_LFN)) {ord = 0xFF; dp->lfn_idx = 0xFFFF; } else {if (a == AM_LFN) { if (dp->lfn) {if (c & LLEF) { sum = dir[LDIR_Chksum]; c &= ~LLEF; ord = c; dp->lfn_idx = dp->index; } ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dp->lfn, dir)) ? ord - 1 : 0xFF; } } else { if (!ord && sum == sum_sfn(dir)) break; if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dir, dp->fn, 11)) break; ord = 0xFF; dp->lfn_idx = 0xFFFF; } } res = dir_next(dp, 0); } while (res == FR_OK); return res; } +static FRESULT dir_read (FATFS_DIR* dp, int vol) {FRESULT res; B a, c, *dir; B ord = 0xFF, sum = 0xFF; res = FR_NO_FILE; while (dp->sect) {res = move_window(dp->fs, dp->sect); if (res != FR_OK) break; dir = dp->dir; c = dir[DIR_Name]; if (c == 0) { res = FR_NO_FILE; break; } a = dir[DIR_Attr] & AM_MASK; if (c == DDEM || (!_FS_RPATH && c == '.') || (int)((a & ~AM_ARC) == AM_VOL) != vol) {ord = 0xFF; } else {if (a == AM_LFN) { if (c & LLEF) { sum = dir[LDIR_Chksum]; c &= ~LLEF; ord = c; dp->lfn_idx = dp->index; } ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dp->lfn, dir)) ? ord - 1 : 0xFF; } else { if (ord || sum != sum_sfn(dir)) dp->lfn_idx = 0xFFFF; break; } } res = dir_next(dp, 0); if (res != FR_OK) break; } if (res != FR_OK) dp->sect = 0; return res; } +static FRESULT dir_register (FATFS_DIR* dp) {FRESULT res; UI n, nent; B sn[12], *fn, sum; WC *lfn; fn = dp->fn; lfn = dp->lfn; mem_cpy(sn, fn, 12); if (_FS_RPATH && (sn[NSFLAG] & NS_DOT)) return FR_INVALID_NAME; if (sn[NSFLAG] & NS_LOSS) { fn[NSFLAG] = 0; dp->lfn = 0; for (n = 1; n < 100; n++) {gen_numname(fn, sn, lfn, n); res = dir_find(dp); if (res != FR_OK) break; } if (n == 100) return FR_DENIED; if (res != FR_NO_FILE) return res; fn[NSFLAG] = sn[NSFLAG]; dp->lfn = lfn; } if (sn[NSFLAG] & NS_LFN) { for (n = 0; lfn[n]; n++) ; nent = (n + 25) / 13; } else { nent = 1; } res = dir_alloc(dp, nent); if (res == FR_OK && --nent) {res = dir_sdi(dp, dp->index - nent); if (res == FR_OK) {sum = sum_sfn(dp->fn); do { res = move_window(dp->fs, dp->sect); if (res != FR_OK) break; fit_lfn(dp->lfn, dp->dir, (B)nent, sum); dp->fs->wflag = 1; res = dir_next(dp, 0); } while (res == FR_OK && --nent); } } if (res == FR_OK) { res = move_window(dp->fs, dp->sect); if (res == FR_OK) {mem_set(dp->dir, 0, SZ_DIRE); mem_cpy(dp->dir, dp->fn, 11); dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT); dp->fs->wflag = 1; } } return res; } +static FRESULT dir_remove (FATFS_DIR* dp) {FRESULT res; UI i; i = dp->index; res = dir_sdi(dp, (dp->lfn_idx == 0xFFFF) ? i : dp->lfn_idx); if (res == FR_OK) {do {res = move_window(dp->fs, dp->sect); if (res != FR_OK) break; mem_set(dp->dir, 0, SZ_DIRE); *dp->dir = DDEM; dp->fs->wflag = 1; if (dp->index >= i) break; res = dir_next(dp, 0); } while (res == FR_OK); if (res == FR_NO_FILE) res = FR_INT_ERR; } return res; } +static void get_fileinfo (FATFS_DIR* dp, FILINFO* fno) {UI i; TCHAR *p, c; B *dir; WC w, *lfn; p = fno->fname; if (dp->sect) { dir = dp->dir; i = 0; while (i < 11) { c = (TCHAR)dir[i++]; if (c == ' ') continue; if (c == RDDEM) c = (TCHAR)DDEM; if (i == 9) *p++ = '.'; if (IsUpper(c) && (dir[DIR_NTres] & (i >= 9 ? NS_EXT : NS_BODY))) c += 0x20; *p++ = c; } fno->fattrib = dir[DIR_Attr]; fno->fsize = LD_DWORD(dir + DIR_FileSize); fno->fdate = LD_WORD(dir + DIR_WrtDate); fno->ftime = LD_WORD(dir + DIR_WrtTime); } *p = 0; if (fno->lfname) {i = 0; p = fno->lfname; if (dp->sect && fno->lfsize && dp->lfn_idx != 0xFFFF) {lfn = dp->lfn; while ((w = *lfn++) != 0) { if (i >= fno->lfsize - 1) { i = 0; break; } p[i++] = (TCHAR)w; } } p[i] = 0; } } +static FRESULT create_name (FATFS_DIR* dp, const TCHAR** path) {B b, cf; WC w, *lfn; UI i, ni, si, di; const TCHAR *p; for (p = *path; *p == '/' || *p == '\\'; p++) ; lfn = dp->lfn; si = di = 0; for (;;) {w = p[si++]; if (w < ' ' || w == '/' || w == '\\') break; if (di >= _MAX_LFN) return FR_INVALID_NAME; w &= 0xFF; if (IsDBCS1(w)) { b = (B)p[si++]; w = (w << 8) + b; if (!IsDBCS2(b)) return FR_INVALID_NAME; } w = ff_convert(w, 1); if (!w) return FR_INVALID_NAME; if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) return FR_INVALID_NAME; lfn[di++] = w; } *path = &p[si]; cf = (w < ' ') ? NS_LAST : 0; while (di) { w = lfn[di - 1]; if (w != ' ' && w != '.') break; di--; } if (!di) return FR_INVALID_NAME; lfn[di] = 0; mem_set(dp->fn, ' ', 11); for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; if (si) cf |= NS_LOSS | NS_LFN; while (di && lfn[di - 1] != '.') di--; b = i = 0; ni = 8; for (;;) {w = lfn[si++]; if (!w) break; if (w == ' ' || (w == '.' && si != di)) {cf |= NS_LOSS | NS_LFN; continue; } if (i >= ni || si == di) { if (ni == 11) { cf |= NS_LOSS | NS_LFN; break; } if (si != di) cf |= NS_LOSS | NS_LFN; if (si > di) break; si = di; i = 8; ni = 11; b <<= 2; continue; } if (w >= 0x80) { w = ff_convert(w, 0); if (w) w = ExCvt[w - 0x80]; cf |= NS_LFN; } if (_DF1S && w >= 0x100) { if (i >= ni - 1) {cf |= NS_LOSS | NS_LFN; i = ni; continue; } dp->fn[i++] = (B)(w >> 8); } else { if (!w || chk_chr("+,;=[]", w)) {w = '_'; cf |= NS_LOSS | NS_LFN; } else {if (IsUpper(w)) { b |= 2; } else {if (IsLower(w)) {b |= 1; w -= 0x20; } } } } dp->fn[i++] = (B)w; } if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM; if (ni == 8) b <<= 2; if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) cf |= NS_LFN; if (!(cf & NS_LFN)) { if ((b & 0x03) == 0x01) cf |= NS_EXT; if ((b & 0x0C) == 0x04) cf |= NS_BODY; } dp->fn[NSFLAG] = cf; return FR_OK; } +static FRESULT follow_path (FATFS_DIR* dp, const TCHAR* path) {FRESULT res; B *dir, ns; if (*path == '/' || *path == '\\') path++; dp->sclust = 0; if ((UI)*path < ' ') { res = dir_sdi(dp, 0); dp->dir = 0; } else { for (;;) {res = create_name(dp, &path); if (res != FR_OK) break; res = dir_find(dp); ns = dp->fn[NSFLAG]; if (res != FR_OK) { if (res == FR_NO_FILE) {if (_FS_RPATH && (ns & NS_DOT)) {dp->sclust = 0; dp->dir = 0; if (!(ns & NS_LAST)) continue; res = FR_OK; } else { if (!(ns & NS_LAST)) res = FR_NO_PATH; } } break; } if (ns & NS_LAST) break; dir = dp->dir; if (!(dir[DIR_Attr] & AM_DIR)) {res = FR_NO_PATH; break; } dp->sclust = ld_clust(dp->fs, dir); } } return res; } +static int get_ldnumber (const TCHAR** path) {const TCHAR *tp, *tt; UI i; int vol = -1; if (*path) {for (tt = *path; (UI)*tt >= (_USE_LFN ? ' ' : '!') && *tt != ':'; tt++) ; if (*tt == ':') {tp = *path; i = *tp++ - '0'; if (i < 10 && tp == tt) {if (i < _VOLUMES) {vol = (int)i; *path = ++tt; } } return vol; } vol = 0; } return vol; } +static B check_fs (FATFS* fs, DW sect) {fs->wflag = 0; fs->winsect = 0xFFFFFFFF; if (move_window(fs, sect) != FR_OK) return 3; if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) return 2; if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) return 0; if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146) return 0; return 1; } +static FRESULT find_volume (FATFS** rfs, const TCHAR** path, B wmode) {B fmt, *pt; int vol; DSTATUS stat;DW bsect, fasize, tsect, sysect, nclst, szbfat, br[4]; W nrsv; FATFS *fs; UI i; *rfs = 0; vol = get_ldnumber(path); if (vol < 0) return FR_INVALID_DRIVE; fs = FatFs[vol]; if (!fs) return FR_NOT_ENABLED; ENTER_FF(fs); *rfs = fs; if (fs->fs_type) { stat = disk_status(fs->drv); if (!(stat & STA_NOINIT)) { if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) return FR_WRITE_PROTECTED; return FR_OK; } } fs->fs_type = 0; fs->drv = LD2PD(vol); stat = disk_initialize(fs->drv); if (stat & STA_NOINIT) return FR_NOT_READY; if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) return FR_WRITE_PROTECTED; bsect = 0; fmt = check_fs(fs, bsect); if (fmt == 1 || (!fmt && (LD2PT(vol)))) {for (i = 0; i < 4; i++) { pt = fs->win + MBR_Table + i * SZ_PTE; br[i] = pt[4] ? LD_DWORD(&pt[8]) : 0; } i = LD2PT(vol); if (i) i--; do { bsect = br[i]; fmt = bsect ? check_fs(fs, bsect) : 2; } while (!LD2PT(vol) && fmt && ++i < 4); } if (fmt == 3) return FR_DISK_ERR; if (fmt) return FR_NO_FILESYSTEM; if (LD_WORD(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM; fasize = LD_WORD(fs->win + BPB_FATSz16); if (!fasize) fasize = LD_DWORD(fs->win + BPB_FATSz32); fs->fsize = fasize; fs->n_fats = fs->win[BPB_NumFATs]; if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM; fasize *= fs->n_fats; fs->csize = fs->win[BPB_SecPerClus]; if (!fs->csize || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM; fs->n_rootdir = LD_WORD(fs->win + BPB_RootEntCnt); if (fs->n_rootdir % (SS(fs) / SZ_DIRE)) return FR_NO_FILESYSTEM; tsect = LD_WORD(fs->win + BPB_TotSec16); if (!tsect) tsect = LD_DWORD(fs->win + BPB_TotSec32); nrsv = LD_WORD(fs->win + BPB_RsvdSecCnt); if (!nrsv) return FR_NO_FILESYSTEM; sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZ_DIRE); if (tsect < sysect) return FR_NO_FILESYSTEM; nclst = (tsect - sysect) / fs->csize; if (!nclst) return FR_NO_FILESYSTEM; fmt = FS_FAT12; if (nclst >= MIN_FAT16) fmt = FS_FAT16; if (nclst >= MIN_FAT32) fmt = FS_FAT32; fs->n_fatent = nclst + 2; fs->volbase = bsect; fs->fatbase = bsect + nrsv; fs->database = bsect + sysect; if (fmt == FS_FAT32) {if (fs->n_rootdir) return FR_NO_FILESYSTEM; fs->dirbase = LD_DWORD(fs->win + BPB_RootClus); szbfat = fs->n_fatent * 4; } else {if (!fs->n_rootdir) return FR_NO_FILESYSTEM; fs->dirbase = fs->fatbase + fasize; szbfat = (fmt == FS_FAT16) ? fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); } if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM; fs->last_clust = fs->free_clust = 0xFFFFFFFF; fs->fsi_flag = 0x80; if (fmt == FS_FAT32 && LD_WORD(fs->win + BPB_FSInfo) == 1&& move_window(fs, bsect + 1) == FR_OK) {fs->fsi_flag = 0; if (LD_WORD(fs->win + BS_55AA) == 0xAA55 && LD_DWORD(fs->win + FSI_LeadSig) == 0x41615252&& LD_DWORD(fs->win + FSI_StrucSig) == 0x61417272) {fs->free_clust = LD_DWORD(fs->win + FSI_Free_Count); fs->last_clust = LD_DWORD(fs->win + FSI_Nxt_Free); } } fs->fs_type = fmt; fs->id = ++Fsid; return FR_OK; } +static FRESULT validate (void* obj) {FIL *fil = (FIL*)obj; if (!fil || !fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id || (disk_status(fil->fs->drv) & STA_NOINIT)) return FR_INVALID_OBJECT; ENTER_FF(fil->fs); return FR_OK; } +FRESULT f_mount (FATFS* fs, const TCHAR* path, B opt) {FATFS *cfs; int vol;FRESULT res; const TCHAR *rp = path; vol = get_ldnumber(&rp); if (vol < 0) return FR_INVALID_DRIVE; cfs = FatFs[vol]; if (cfs) {cfs->fs_type = 0; } if (fs) {fs->fs_type = 0; } FatFs[vol] = fs; if (!fs || opt != 1) return FR_OK; res = find_volume(&fs, &path, 0); LEAVE_FF(fs, res); } +FRESULT f_open (FIL* fp, const TCHAR* path, B mode) {FRESULT res; FATFS_DIR dj; B *dir; DEFINE_NAMEBUF;DW dw, cl; if (!fp) return FR_INVALID_OBJECT; fp->fs = 0; mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; res = find_volume(&dj.fs, &path, (B)(mode & ~FA_READ)); if (res == FR_OK) {INIT_BUF(dj); res = follow_path(&dj, path); dir = dj.dir; if (res == FR_OK) {if (!dir) res = FR_INVALID_NAME; } if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {if (res != FR_OK) { if (res == FR_NO_FILE) res = dir_register(&dj); mode |= FA_CREATE_ALWAYS; dir = dj.dir; } else { if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) {res = FR_DENIED; } else {if (mode & FA_CREATE_NEW) res = FR_EXIST; } } if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) {dw = GET_FATTIME(); ST_DWORD(dir + DIR_CrtTime, dw); ST_DWORD(dir + DIR_WrtTime, dw); dir[DIR_Attr] = 0; ST_DWORD(dir + DIR_FileSize, 0); cl = ld_clust(dj.fs, dir); st_clust(dir, 0); dj.fs->wflag = 1; if (cl) { dw = dj.fs->winsect; res = remove_chain(dj.fs, cl); if (res == FR_OK) {dj.fs->last_clust = cl - 1; res = move_window(dj.fs, dw); } } } } else {if (res == FR_OK) { if (dir[DIR_Attr] & AM_DIR) {res = FR_NO_FILE; } else {if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) res = FR_DENIED; } } } if (res == FR_OK) {if (mode & FA_CREATE_ALWAYS) mode |= FA__WRITTEN; fp->dir_sect = dj.fs->winsect; fp->dir_ptr = dir; } FREE_BUF(); if (res == FR_OK) {fp->flag = mode; fp->err = 0; fp->sclust = ld_clust(dj.fs, dir); fp->fsize = LD_DWORD(dir + DIR_FileSize); fp->fptr = 0; fp->dsect = 0; fp->fs = dj.fs; fp->id = fp->fs->id; } } LEAVE_FF(dj.fs, res); } +FRESULT f_read (FIL* fp, void* buff, UI btr, UI* br) {FRESULT res;DW clst, sect, remain; UI rcnt, cc; B csect, *rbuff = (B*)buff; *br = 0; res = validate(fp); if (res != FR_OK) LEAVE_FF(fp->fs, res); if (fp->err) LEAVE_FF(fp->fs, (FRESULT)fp->err); if (!(fp->flag & FA_READ)) LEAVE_FF(fp->fs, FR_DENIED); remain = fp->fsize - fp->fptr; if (btr > remain) btr = (UI)remain; for (; btr; rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {if ((fp->fptr % SS(fp->fs)) == 0) { csect = (B)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); if (!csect) { if (fp->fptr == 0) { clst = fp->sclust; } else {clst = get_fat(fp->fs, fp->clust); } if (clst < 2) ABORT(fp->fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); fp->clust = clst; } sect = clust2sect(fp->fs, fp->clust); if (!sect) ABORT(fp->fs, FR_INT_ERR); sect += csect; cc = btr / SS(fp->fs); if (cc) { if (csect + cc > fp->fs->csize) cc = fp->fs->csize - csect; if (disk_read(fp->fs->drv, rbuff, sect, cc) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); if (fp->fs->wflag && fp->fs->winsect - sect < cc) mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs)); rcnt = SS(fp->fs) * cc; continue; } fp->dsect = sect; } rcnt = SS(fp->fs) - ((UI)fp->fptr % SS(fp->fs)); if (rcnt > btr) rcnt = btr; if (move_window(fp->fs, fp->dsect) != FR_OK) ABORT(fp->fs, FR_DISK_ERR); mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); } LEAVE_FF(fp->fs, FR_OK); } +FRESULT f_write (FIL* fp, const void *buff, UI btw, UI* bw) {FRESULT res;DW clst, sect; UI wcnt, cc; const B *wbuff = (const B*)buff; B csect; bool need_sync = false; *bw = 0; res = validate(fp); if (res != FR_OK) LEAVE_FF(fp->fs, res); if (fp->err) LEAVE_FF(fp->fs, (FRESULT)fp->err); if (!(fp->flag & FA_WRITE)) LEAVE_FF(fp->fs, FR_DENIED); if (fp->fptr + btw < fp->fptr) btw = 0; for (; btw; wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) {if ((fp->fptr % SS(fp->fs)) == 0) {csect = (B)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); if (!csect) { if (fp->fptr == 0) { clst = fp->sclust; if (clst == 0) clst = create_chain(fp->fs, 0); } else {clst = create_chain(fp->fs, fp->clust); } if (clst == 0) break; if (clst == 1) ABORT(fp->fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); fp->clust = clst; if (fp->sclust == 0) fp->sclust = clst; } if (fp->fs->winsect == fp->dsect && sync_window(fp->fs)) ABORT(fp->fs, FR_DISK_ERR); sect = clust2sect(fp->fs, fp->clust); if (!sect) ABORT(fp->fs, FR_INT_ERR); sect += csect; cc = btw / SS(fp->fs); if (cc) { if (csect + cc > fp->fs->csize) cc = fp->fs->csize - csect; if (disk_write(fp->fs->drv, wbuff, sect, cc) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); if (fp->fs->winsect - sect < cc) {mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs)); fp->fs->wflag = 0; } wcnt = SS(fp->fs) * cc; need_sync = true; continue; } if (fp->fptr >= fp->fsize) {if (sync_window(fp->fs)) ABORT(fp->fs, FR_DISK_ERR); fp->fs->winsect = sect; } fp->dsect = sect; } wcnt = SS(fp->fs) - ((UI)fp->fptr % SS(fp->fs)); if (wcnt > btw) wcnt = btw; if (move_window(fp->fs, fp->dsect) != FR_OK) ABORT(fp->fs, FR_DISK_ERR); mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); fp->fs->wflag = 1; } if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; fp->flag |= FA__WRITTEN; if (need_sync) {f_sync (fp); } LEAVE_FF(fp->fs, FR_OK); } +FRESULT f_sync (FIL* fp) {FRESULT res;DW tm; B *dir; res = validate(fp); if (res == FR_OK) {if (fp->flag & FA__WRITTEN) { res = move_window(fp->fs, fp->dir_sect); if (res == FR_OK) {dir = fp->dir_ptr; dir[DIR_Attr] |= AM_ARC; ST_DWORD(dir + DIR_FileSize, fp->fsize); st_clust(dir, fp->sclust); tm = GET_FATTIME(); ST_DWORD(dir + DIR_WrtTime, tm); ST_WORD(dir + DIR_LstAccDate, 0); fp->flag &= ~FA__WRITTEN; fp->fs->wflag = 1; res = sync_fs(fp->fs); } } } LEAVE_FF(fp->fs, res); } +FRESULT f_close (FIL *fp) {FRESULT res; res = f_sync(fp); if (res == FR_OK) {res = validate(fp); if (res == FR_OK) {fp->fs = 0; } } return res; } +FRESULT f_lseek (FIL* fp, DW ofs) {FRESULT res;DW clst, bcs, nsect, ifptr; res = validate(fp); if (res != FR_OK) LEAVE_FF(fp->fs, res); if (fp->err) LEAVE_FF(fp->fs, (FRESULT)fp->err); {if (ofs > fp->fsize && !(fp->flag & FA_WRITE) ) ofs = fp->fsize; ifptr = fp->fptr; fp->fptr = nsect = 0; if (ofs) {bcs = (DW)fp->fs->csize * SS(fp->fs); if (ifptr > 0 && (ofs - 1) / bcs >= (ifptr - 1) / bcs) {fp->fptr = (ifptr - 1) & ~(bcs - 1); ofs -= fp->fptr; clst = fp->clust; } else { clst = fp->sclust; if (clst == 0) { clst = create_chain(fp->fs, 0); if (clst == 1) ABORT(fp->fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); fp->sclust = clst; } fp->clust = clst; } if (clst != 0) {while (ofs > bcs) {if (fp->flag & FA_WRITE) { clst = create_chain(fp->fs, clst); if (clst == 0) { ofs = bcs; break; } } else clst = get_fat(fp->fs, clst); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR); fp->clust = clst; fp->fptr += bcs; ofs -= bcs; } fp->fptr += ofs; if (ofs % SS(fp->fs)) {nsect = clust2sect(fp->fs, clst); if (!nsect) ABORT(fp->fs, FR_INT_ERR); nsect += ofs / SS(fp->fs); } } } if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) {fp->dsect = nsect; } if (fp->fptr > fp->fsize) { fp->fsize = fp->fptr; fp->flag |= FA__WRITTEN; } } LEAVE_FF(fp->fs, res); } +FRESULT f_opendir (FATFS_DIR* dp, const TCHAR* path) {FRESULT res; FATFS* fs; DEFINE_NAMEBUF; if (!dp) return FR_INVALID_OBJECT; res = find_volume(&fs, &path, 0); if (res == FR_OK) {dp->fs = fs; INIT_BUF(*dp); res = follow_path(dp, path); FREE_BUF(); if (res == FR_OK) { if (dp->dir) { if (dp->dir[DIR_Attr] & AM_DIR) dp->sclust = ld_clust(fs, dp->dir); else res = FR_NO_PATH; } if (res == FR_OK) {dp->id = fs->id; res = dir_sdi(dp, 0); } } if (res == FR_NO_FILE) res = FR_NO_PATH; } if (res != FR_OK) dp->fs = 0; LEAVE_FF(fs, res); } +FRESULT f_closedir (FATFS_DIR *dp) {FRESULT res; res = validate(dp); if (res == FR_OK) {dp->fs = 0; } return res; } +FRESULT f_readdir (FATFS_DIR* dp, FILINFO* fno) {FRESULT res; DEFINE_NAMEBUF; res = validate(dp); if (res == FR_OK) {if (!fno) {res = dir_sdi(dp, 0); } else {INIT_BUF(*dp); res = dir_read(dp, 0); if (res == FR_NO_FILE) { dp->sect = 0; res = FR_OK; } if (res == FR_OK) { get_fileinfo(dp, fno); res = dir_next(dp, 0); if (res == FR_NO_FILE) {dp->sect = 0; res = FR_OK; } } FREE_BUF(); } } LEAVE_FF(dp->fs, res); } +FRESULT f_unlink (const TCHAR* path) {FRESULT res; FATFS_DIR dj, sdj; B *dir;DW dclst = 0; DEFINE_NAMEBUF; res = find_volume(&dj.fs, &path, 1); if (res == FR_OK) {INIT_BUF(dj); res = follow_path(&dj, path); if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) res = FR_INVALID_NAME; if (res == FR_OK) { dir = dj.dir; if (!dir) {res = FR_INVALID_NAME; } else {if (dir[DIR_Attr] & AM_RDO) res = FR_DENIED; } if (res == FR_OK) {dclst = ld_clust(dj.fs, dir); if (dclst && (dir[DIR_Attr] & AM_DIR)) {{ mem_cpy(&sdj, &dj, sizeof (FATFS_DIR)); sdj.sclust = dclst; res = dir_sdi(&sdj, 2); if (res == FR_OK) {res = dir_read(&sdj, 0); if (res == FR_OK) res = FR_DENIED; if (res == FR_NO_FILE) res = FR_OK; } } } } if (res == FR_OK) {res = dir_remove(&dj); if (res == FR_OK && dclst) res = remove_chain(dj.fs, dclst); if (res == FR_OK) res = sync_fs(dj.fs); } } FREE_BUF(); } LEAVE_FF(dj.fs, res); } +FRESULT f_mkdir (const TCHAR* path) {FRESULT res; FATFS_DIR dj; B *dir, n;DW dsc, dcl, pcl, tm = GET_FATTIME(); DEFINE_NAMEBUF; res = find_volume(&dj.fs, &path, 1); if (res == FR_OK) {INIT_BUF(dj); res = follow_path(&dj, path); if (res == FR_OK) res = FR_EXIST; if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) res = FR_INVALID_NAME; if (res == FR_NO_FILE) { dcl = create_chain(dj.fs, 0); res = FR_OK; if (dcl == 0) res = FR_DENIED; if (dcl == 1) res = FR_INT_ERR; if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; if (res == FR_OK) res = sync_window(dj.fs); if (res == FR_OK) { dsc = clust2sect(dj.fs, dcl); dir = dj.fs->win; mem_set(dir, 0, SS(dj.fs)); mem_set(dir + DIR_Name, ' ', 11); dir[DIR_Name] = '.'; dir[DIR_Attr] = AM_DIR; ST_DWORD(dir + DIR_WrtTime, tm); st_clust(dir, dcl); mem_cpy(dir + SZ_DIRE, dir, SZ_DIRE); dir[SZ_DIRE + 1] = '.'; pcl = dj.sclust; if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase) pcl = 0; st_clust(dir + SZ_DIRE, pcl); for (n = dj.fs->csize; n; n--) {dj.fs->winsect = dsc++; dj.fs->wflag = 1; res = sync_window(dj.fs); if (res != FR_OK) break; mem_set(dir, 0, SS(dj.fs)); } } if (res == FR_OK) res = dir_register(&dj); if (res != FR_OK) {remove_chain(dj.fs, dcl); } else {dir = dj.dir; dir[DIR_Attr] = AM_DIR; ST_DWORD(dir + DIR_WrtTime, tm); st_clust(dir, dcl); dj.fs->wflag = 1; res = sync_fs(dj.fs); } } FREE_BUF(); } LEAVE_FF(dj.fs, res); } +#include +typedef struct {FIL* fp; int idx, nchr; B buf[64]; } putbuff; +static void putc_bfd (putbuff* pb, TCHAR c) {UI bw; int i; if (_USE_STRFUNC == 2 && c == '\n') putc_bfd(pb, '\r'); i = pb->idx; if (i < 0) return; pb->buf[i++] = (B)c; if (i >= (int)(sizeof pb->buf) - 3) {f_write(pb->fp, pb->buf, (UI)i, &bw); i = (bw == (UI)i) ? 0 : -1; } pb->idx = i; pb->nchr++; } +int f_printf (FIL* fp, const TCHAR* fmt, ...) {va_list arp; B f, r; UI nw, i, j, w; DW v; TCHAR c, d, s[16], *p; putbuff pb; pb.fp = fp; pb.nchr = pb.idx = 0; va_start(arp, fmt); for (;;) {c = *fmt++; if (c == 0) break; if (c != '%') { putc_bfd(&pb, c); continue; } w = f = 0; c = *fmt++; if (c == '0') { f = 1; c = *fmt++; } else {if (c == '-') { f = 2; c = *fmt++; } } while (IsDigit(c)) { w = w * 10 + c - '0'; c = *fmt++; } if (c == 'l' || c == 'L') {f |= 4; c = *fmt++; } if (!c) break; d = c; if (IsLower(d)) d -= 0x20; switch (d) { case 'S' : p = va_arg(arp, TCHAR*); for (j = 0; p[j]; j++) ; if (!(f & 2)) {while (j++ < w) putc_bfd(&pb, ' '); } while (*p) putc_bfd(&pb, *p++); while (j++ < w) putc_bfd(&pb, ' '); continue; case 'C' : putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue; case 'B' : r = 2; break; case 'O' : r = 8; break; case 'D' : case 'U' : r = 10; break; case 'X' : r = 16; break; default: putc_bfd(&pb, c); continue; } v = (f & 4) ? (DW)va_arg(arp, long) : ((d == 'D') ? (DW)(long)va_arg(arp, int) : (DW)va_arg(arp, unsigned int)); if (d == 'D' && (v & 0x80000000)) {v = 0 - v; f |= 8; } i = 0; do {d = (TCHAR)(v % r); v /= r; if (d > 9) d += (c == 'x') ? 0x27 : 0x07; s[i++] = d + '0'; } while (v && i < sizeof s / sizeof s[0]); if (f & 8) s[i++] = '-'; j = i; d = (f & 1) ? '0' : ' '; while (!(f & 2) && j++ < w) putc_bfd(&pb, d); do putc_bfd(&pb, s[--i]); while (i); while (j++ < w) putc_bfd(&pb, d); } va_end(arp); if (pb.idx >= 0&& f_write(pb.fp, pb.buf, (UI)pb.idx, &nw) == FR_OK && (UI)pb.idx == nw) return pb.nchr; return EOF; } \ No newline at end of file diff --git a/ff.h b/ff.h new file mode 100644 index 0000000..02ff087 --- /dev/null +++ b/ff.h @@ -0,0 +1,146 @@ +#ifndef _FATFS +#define _FATFS 64180 +#ifdef __cplusplus +extern "C" +{ +#endif +#include "integer.h" +#include "ffconf.h" + +#define LD2PD(vol) (B)(vol) +#define LD2PT(vol) 0 + typedef char TCHAR; + typedef struct + { + B fs_type; + B drv; + B csize; + B n_fats; + B wflag; + B fsi_flag; + W id; + W n_rootdir; + DW last_clust; + DW free_clust; + DW n_fatent; + DW fsize; + DW volbase; + DW fatbase; + DW dirbase; + DW database; + DW winsect; + B win[_MAX_SS]; + } FATFS; + typedef struct + { + FATFS *fs; + W id; + B flag; + B err; + DW fptr; + DW fsize; + DW sclust; + DW clust; + DW dsect; + DW dir_sect; + B *dir_ptr; + } FIL; + typedef struct + { + FATFS *fs; + W id; + W index; + DW sclust; + DW clust; + DW sect; + B *dir; + B *fn; + WC *lfn; + W lfn_idx; + } FATFS_DIR; + typedef struct + { + DW fsize; + W fdate; + W ftime; + B fattrib; + char fname[13]; + char *lfname; + UI lfsize; + } FILINFO; + typedef enum + { + FR_OK = 0, + FR_DISK_ERR, + FR_INT_ERR, + FR_NOT_READY, + FR_NO_FILE, + FR_NO_PATH, + FR_INVALID_NAME, + FR_DENIED, + FR_EXIST, + FR_INVALID_OBJECT, + FR_WRITE_PROTECTED, + FR_INVALID_DRIVE, + FR_NOT_ENABLED, + FR_NO_FILESYSTEM, + FR_MKFS_ABORTED, + FR_TIMEOUT, + FR_LOCKED, + FR_NOT_ENOUGH_CORE, + FR_TOO_MANY_OPEN_FILES, + FR_INVALID_PARAMETER + } FRESULT; + FRESULT f_open(FIL *fp, const char *path, B mode); + FRESULT f_close(FIL *fp); + FRESULT f_read(FIL *fp, void *buff, UI btr, UI *br); + FRESULT f_write(FIL *fp, const void *buff, UI btw, UI *bw); + FRESULT f_lseek(FIL *fp, DW ofs); + FRESULT f_sync(FIL *fp); + FRESULT f_opendir(FATFS_DIR *dp, const char *path); + FRESULT f_closedir(FATFS_DIR *dp); + FRESULT f_readdir(FATFS_DIR *dp, FILINFO *fno); + FRESULT f_mkdir(const char *path); + FRESULT f_unlink(const char *path); + FRESULT f_utime(const char *path, const FILINFO *fno); + FRESULT f_mount(FATFS *fs, const char *path, B opt); + int f_printf(FIL *fp, const char *str, ...); + +#ifndef EOF +#define EOF (-1) +#endif +#if _USE_LFN + WC ff_convert(WC chr, UI dir); + WC ff_wtoupper(WC chr); +#endif +#define FA_READ 0x01 +#define FA_WRITE 0x02 +#define FA_CREATE_NEW 0x04 +#define FA_CREATE_ALWAYS 0x08 +#define FA_OPEN_ALWAYS 0x10 +#define FA__WRITTEN 0x20 +#define FS_FAT12 1 +#define FS_FAT16 2 +#define FS_FAT32 3 +#define AM_RDO 0x01 +#define AM_HID 0x02 +#define AM_SYS 0x04 +#define AM_VOL 0x08 +#define AM_LFN 0x0F +#define AM_DIR 0x10 +#define AM_ARC 0x20 +#define AM_MASK 0x3F +#define LD_WORD(ptr) (W)(((W) * ((B *)(ptr) + 1) << 8) | (W) * (B *)(ptr)) +#define LD_DWORD(ptr) (DW)(((DW) * ((B *)(ptr) + 3) << 24) | ((DW) * ((B *)(ptr) + 2) << 16) | ((W) * ((B *)(ptr) + 1) << 8) | *(B *)(ptr)) +#define ST_WORD(ptr, val) \ + *(B *)(ptr) = (B)(val); \ + *((B *)(ptr) + 1) = (B)((W)(val) >> 8) +#define ST_DWORD(ptr, val) \ + *(B *)(ptr) = (B)(val); \ + *((B *)(ptr) + 1) = (B)((W)(val) >> 8); \ + *((B *)(ptr) + 2) = (B)((DW)(val) >> 16); \ + *((B *)(ptr) + 3) = (B)((DW)(val) >> 24) +#ifdef __cplusplus +} +#endif +#endif diff --git a/ffconf.h b/ffconf.h new file mode 100644 index 0000000..55574fd --- /dev/null +++ b/ffconf.h @@ -0,0 +1,10 @@ +#define _FS_READONLY 0 +#define _USE_STRFUNC 1 +#define _USE_LFN 1 +#define _MAX_LFN 255 +#define _FS_RPATH 0 +#define _VOLUMES 1 +#define _MAX_SS 512 +#define _NORTC_MON 1 +#define _NORTC_MDAY 1 +#define _NORTC_YEAR 2015 \ No newline at end of file diff --git a/im01.cpp b/im01.cpp new file mode 100644 index 0000000..790f1b8 --- /dev/null +++ b/im01.cpp @@ -0,0 +1,56 @@ +#include "pxt.h" +#include "mbed.h" +#include "SDFileSystem.h" +#include "MicroBit.h" + +namespace im01 +{ +//% +void _mkdir(String s) +{ + SDFileSystem sd(P0_21, P0_22, P0_23, P0_16, "sd"); + microbit_create_heap(MICROBIT_SD_GATT_TABLE_START + MICROBIT_SD_GATT_TABLE_SIZE, MICROBIT_SD_LIMIT); + mkdir((const char *)s->getUTF8Data(), 0777); +} + + +//% +String _read(String s) +{ + char * _word; + char* error_no_file = "ERROR! NO FILE"; + char* cant_read_file = "ERROR! CANT READ FILE"; + //char* path = "/sd/im01/"; + long lSize; + size_t b_read; + + SDFileSystem sd(P0_21, P0_22, P0_23, P0_16, "sd"); + FILE *fp = fopen((const char *)s->getUTF8Data(), "rb"); + + if (fp == NULL) + { + return mkString(error_no_file, strlen(error_no_file)); + }else{ + + // obtain file size: + fseek (fp , 0 , SEEK_END); + lSize = ftell(fp); + rewind (fp); + + _word = (char*) malloc (sizeof(char)*(lSize)); + b_read = fread(_word, sizeof(char), lSize, fp); + + fclose(fp); + } + + if(b_read != (lSize)) + { + return mkString(cant_read_file, strlen(cant_read_file)); + } + + String str = mkString(_word, strlen(_word) - 1); + + free(_word); + return str; +} +} // namespace im01 \ No newline at end of file diff --git a/integer.h b/integer.h new file mode 100644 index 0000000..db6af89 --- /dev/null +++ b/integer.h @@ -0,0 +1,11 @@ +#ifndef _FF_INTEGER +#define _FF_INTEGER +typedef unsigned char B; +typedef short S; +typedef unsigned short W; +typedef unsigned short WC; +typedef int I; +typedef unsigned int UI; +typedef long L; +typedef unsigned long DW; +#endif diff --git a/main.ts b/main.ts index e5b2abd..6c1e6c6 100644 --- a/main.ts +++ b/main.ts @@ -7,7 +7,7 @@ enum USER { } -//% groups=["Common",ATT", "Ubidots", "Azure", "MQTT", "others"] +//% groups='["Common",ATT", "Ubidots", "Azure", "MQTT", "SD Card", "others"]' //% weight=6 color=#2699BF icon="\uf110" block="CW01" namespace cw01 { class cw01_int_var123 { @@ -110,6 +110,8 @@ namespace cw01 { this.sending_data = false } } + + let sdFlag=false let cw01_vars = new cw01_int_var123() let cw01_mqtt_vars = new cw01_mqtt() @@ -1320,6 +1322,24 @@ namespace cw01 { return parseInt(value) } + + //%block="IM01 read file %u" + //%u.defl="log.txt" + //%group="SD Card" + export function readFile(u: string): string { + if(sdFlag==false) { + createFolder("im01") + sdFlag=true + } + return file_read("/sd/im01/" + u) + } + + //%block="IM01 create folder %u" + function createFolder(u: string): void { + mkdir("/sd/" + u) + return; + } + function get_status(): boolean { @@ -1350,5 +1370,15 @@ namespace cw01 { } } } + + //%shim=im01::_read + function file_read(u: string): string { + return "" + } + + //%shim=im01::_mkdir + function mkdir(u: string): void { + return + } } diff --git a/pxt.json b/pxt.json index 7fc306a..027a495 100644 --- a/pxt.json +++ b/pxt.json @@ -1,21 +1,58 @@ { "name": "pxt-cw01", - "version": "0.1.3", + "version": "0.2.12", "description": "", "dependencies": { - "core": "*", - "radio": "*" + "core": "*" }, "files": [ "README.md", - "main.ts" + "main.ts", + "FATDirHandle.cpp", + "FATDirHandle.h", + "FATFileHandle.cpp", + "FATFileHandle.h", + "FATFileSystem.cpp", + "FATFileSystem.h", + "SDFileSystem.cpp", + "SDFileSystem.h", + "ccsbcs.cpp", + "diskio.cpp", + "diskio.h", + "ff.h", + "ffconf.h", + "ff.cpp", + "integer.h", + "im01.cpp" ], "testFiles": [ "test.ts" ], - "public": false, + "public": true, "supportedTargets": [ "microbit" ], - "preferredEditor": "tsprj" + "preferredEditor": "tsprj", + "yotta": { + "config": { + "microbit-dal": { + "bluetooth": { + "private_addressing": 0, + "advertising_timeout": 0, + "tx_power": 0, + "dfu_service": 0, + "event_service": 0, + "device_info_service": 0, + "eddystone_url": 0, + "eddystone_uid": 0, + "open": 0, + "pairing_mode": 0, + "whitelist": 1, + "security_level": "SECURITY_MODE_ENCRYPTION_NO_MITM", + "partial_flashing": 1, + "enabled": 0 + } + } + } + } }