From f7543e32200f29f2966673bf112e519a0e816ef7 Mon Sep 17 00:00:00 2001 From: Damjan Adamic Date: Sun, 15 Jan 2017 21:53:18 +0100 Subject: [PATCH] Projectkk2glider/simu tmp sd path (#4231) * Re #4224: Introduced settingsPath and use std::string for paths in simpgmspace. * Re #4224: Relevant parts of simpgmspace.cpp moved into simufatfs.cpp and simudisk.cpp * Removed "/" from "mask_monitor_logsw.png" * Re #4224: findTrueFileName() refactoring * Faster gtests (less waiting for eeprom operations to finish) * Re #4224: Radio settings and models directories now taken from alternate path (if set) [simu] * Fixes #3322: together with previous changes to the SD browser this prevents the simulator from browsing higher than SD card root path. * f_chdir() debug traces --- companion/src/simulation/simulatorinterface.h | 2 +- radio/src/gui/480x272/themes/default.cpp | 2 +- radio/src/simu.cpp | 6 +- radio/src/targets/simu/CMakeLists.txt | 2 + radio/src/targets/simu/opentxsimulator.cpp | 10 +- radio/src/targets/simu/opentxsimulator.h | 4 +- radio/src/targets/simu/simpgmspace.cpp | 695 +----------------- radio/src/targets/simu/simpgmspace.h | 19 +- radio/src/targets/simu/simudisk.cpp | 245 ++++++ radio/src/targets/simu/simueeprom.cpp | 4 + radio/src/targets/simu/simufatfs.cpp | 554 ++++++++++++++ radio/src/tests/CMakeLists.txt | 3 +- 12 files changed, 840 insertions(+), 706 deletions(-) create mode 100644 radio/src/targets/simu/simudisk.cpp create mode 100644 radio/src/targets/simu/simufatfs.cpp diff --git a/companion/src/simulation/simulatorinterface.h b/companion/src/simulation/simulatorinterface.h index e05515d34..289b306d6 100644 --- a/companion/src/simulation/simulatorinterface.h +++ b/companion/src/simulation/simulatorinterface.h @@ -64,7 +64,7 @@ class SimulatorInterface virtual ~SimulatorInterface() {}; - virtual void setSdPath(const QString &sdPath) { }; + virtual void setSdPath(const QString & sdPath = "", const QString & settingsPath = "") { }; virtual void setVolumeGain(int value) { }; diff --git a/radio/src/gui/480x272/themes/default.cpp b/radio/src/gui/480x272/themes/default.cpp index 768308896..fccf6ffcd 100644 --- a/radio/src/gui/480x272/themes/default.cpp +++ b/radio/src/gui/480x272/themes/default.cpp @@ -130,7 +130,7 @@ class DefaultTheme: public Theme loadMenuIcon(ICON_MONITOR_CHANNELS2, "mask_monitor_channels2.png"); loadMenuIcon(ICON_MONITOR_CHANNELS3, "mask_monitor_channels3.png"); loadMenuIcon(ICON_MONITOR_CHANNELS4, "mask_monitor_channels4.png"); - loadMenuIcon(ICON_MONITOR_LOGICAL_SWITCHES, "/mask_monitor_logsw.png"); + loadMenuIcon(ICON_MONITOR_LOGICAL_SWITCHES, "mask_monitor_logsw.png"); BitmapBuffer * background = BitmapBuffer::loadMask(getThemePath("mask_currentmenu_bg.png")); BitmapBuffer * shadow = BitmapBuffer::loadMask(getThemePath("mask_currentmenu_shadow.png")); diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index 826af36c5..b71983739 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -131,7 +131,9 @@ Open9xSim::~Open9xSim() { StopSimu(); StopAudioThread(); +#if defined(EEPROM) StopEepromThread(); +#endif delete bmp; delete sliders[0]; @@ -548,9 +550,11 @@ int main(int argc,char **argv) simuInit(); +#if defined(EEPROM) StartEepromThread(argc >= 2 ? argv[1] : "eeprom.bin"); +#endif StartAudioThread(); - StartSimu(); + StartSimu(false, argc >= 3 ? argv[2] : 0, argc >= 4 ? argv[3] : 0); return application.run(); } diff --git a/radio/src/targets/simu/CMakeLists.txt b/radio/src/targets/simu/CMakeLists.txt index 448e8c1b3..ac292a712 100644 --- a/radio/src/targets/simu/CMakeLists.txt +++ b/radio/src/targets/simu/CMakeLists.txt @@ -6,6 +6,8 @@ set(SIMU_SRC ${SIMU_SRC} simpgmspace.cpp simueeprom.cpp + simufatfs.cpp + simudisk.cpp ) add_definitions(-DSIMU) diff --git a/radio/src/targets/simu/opentxsimulator.cpp b/radio/src/targets/simu/opentxsimulator.cpp index 112a03b7c..f02981916 100644 --- a/radio/src/targets/simu/opentxsimulator.cpp +++ b/radio/src/targets/simu/opentxsimulator.cpp @@ -58,12 +58,10 @@ OpenTxSimulator::OpenTxSimulator() { } -void OpenTxSimulator::setSdPath(const QString &sdPath) +void OpenTxSimulator::setSdPath(const QString & sdPath, const QString & settingsPath) { -#if defined(SDCARD) - strncpy(simuSdDirectory, sdPath.toLatin1().constData(), sizeof(simuSdDirectory)-1); - simuSdDirectory[sizeof(simuSdDirectory)-1] = '\0'; -#endif + simuSdDirectory = sdPath; + simuSettingsDirectory = settingsPath; } void OpenTxSimulator::setVolumeGain(int value) @@ -106,7 +104,7 @@ void OpenTxSimulator::start(const char * filename, bool tests) StartEepromThread(filename); StartAudioThread(volumeGain); - StartSimu(tests); + StartSimu(tests, simuSdDirectory.toLatin1().constData(), simuSettingsDirectory.toLatin1().constData()); } void OpenTxSimulator::stop() diff --git a/radio/src/targets/simu/opentxsimulator.h b/radio/src/targets/simu/opentxsimulator.h index 98a9b4ea2..ab2ffbe31 100644 --- a/radio/src/targets/simu/opentxsimulator.h +++ b/radio/src/targets/simu/opentxsimulator.h @@ -29,12 +29,14 @@ class DLLEXPORT OpenTxSimulator : public SimulatorInterface { private: int volumeGain; + QString simuSdDirectory; + QString simuSettingsDirectory; public: OpenTxSimulator(); - virtual void setSdPath(const QString &sdPath); + virtual void setSdPath(const QString & sdPath = "", const QString & settingsPath = ""); virtual void setVolumeGain(int value); diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index 89b4d1841..02c3ce9d2 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -20,9 +20,8 @@ #include "opentx.h" #include -#include #include -#include +#include #if !defined _MSC_VER || defined __GNUC__ #include @@ -36,17 +35,6 @@ #include #endif -#if defined(TRACE_SIMPGMSPACE) - #undef TRACE_SIMPGMSPACE - #define TRACE_SIMPGMSPACE TRACE -#else - #define TRACE_SIMPGMSPACE(...) -#endif - -#if defined(SDCARD) && !defined(SKIP_FATFS_DECLARATION) && !defined(SIMU_DISKIO) - #define SIMU_USE_SDCARD -#endif - uint8_t MCUCSR, MCUSR, MCUCR; volatile uint8_t pina=0xff, pinb=0xff, pinc=0xff, pind, pine=0xff, pinf=0xff, ping=0xff, pinh=0xff, pinj=0, pinl=0; uint8_t portb, portc, porth=0, dummyport; @@ -77,10 +65,6 @@ Dacc dacc; Adc Adc0; #endif -#if defined(SIMU_USE_SDCARD) -char simuSdDirectory[1024] = ""; -#endif - void lcdInit() { } @@ -305,18 +289,14 @@ void simuSetSwitch(uint8_t swtch, int8_t state) } } -void StartSimu(bool tests) +void StartSimu(bool tests, const char * sdPath, const char * settingsPath) { s_current_protocol[0] = 255; menuLevel = 0; main_thread_running = (tests ? 1 : 2); // TODO rename to simu_run_mode with #define -#if defined(SIMU_USE_SDCARD) - if (strlen(simuSdDirectory) == 0) { - f_getcwd(simuSdDirectory, 1024); - } -#endif + simuFatfsSetPaths(sdPath, settingsPath); /* g_tmr10ms must be non-zero otherwise some SF functions (that use this timer as a marker when it was last executed) @@ -522,675 +502,6 @@ uint16_t stackAvailable() return 500; } -#if defined(SIMU_USE_SDCARD) -#if defined(_MSC_VER) || !defined(__GNUC__) - #include - #include - #include - #define mkdir(s, f) _mkdir(s) -#else - #include -#endif -#include "ff.h" -#include -#include - -namespace simu { -#include -#if !defined(_MSC_VER) - #include -#endif -} - -#if defined(CPUARM) -FATFS g_FATFS_Obj; -#endif - -char * convertSimuPath(const char *path) -{ - static char result[1024]; - if (((path[0] == '/') || (path[0] == '\\')) && (strcmp(simuSdDirectory, "/") != 0)) - sprintf(result, "%s%s", simuSdDirectory, path); - else - strcpy(result, path); - - return result; -} - -typedef std::map filemap_t; - -filemap_t fileMap; - -char *findTrueFileName(const char *path) -{ - // TRACE_SIMPGMSPACE("findTrueFileName(%s)", path); - static char result[1024]; - filemap_t::iterator i = fileMap.find(path); - if (i != fileMap.end()) { - strcpy(result, i->second.c_str()); - // TRACE_SIMPGMSPACE("\tfound in map: %s", result); - return result; - } - else { - //find file - //add to map -#if defined _MSC_VER || !defined __GNUC__ - char drive[_MAX_DRIVE]; - char dir[_MAX_DIR]; - char fname[_MAX_FNAME]; - char ext[_MAX_EXT]; - _splitpath(path, drive, dir, fname, ext); - std::string fileName = std::string(fname) + std::string(ext); - std::string dirName = std::string(drive) + std::string(dir); - std::string searchName = dirName + "*"; - // TRACE_SIMPGMSPACE("\tsearching for: %s", fileName.c_str()); - WIN32_FIND_DATA ffd; - HANDLE hFind = FindFirstFile(searchName.c_str(), &ffd); - if (INVALID_HANDLE_VALUE != hFind) { - do { - if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { - //TRACE_SIMPGMSPACE("comparing with: %s", ffd.cFileName); - if (!strcasecmp(fileName.c_str(), ffd.cFileName)) { - strcpy(result, dirName.c_str()); - strcat(result, ffd.cFileName); - TRACE_SIMPGMSPACE("\tfound: %s", ffd.cFileName); - fileMap.insert(filemap_t:: value_type(path, result)); - return result; - } - } - } - while (FindNextFile(hFind, &ffd) != 0); - } -#else - strcpy(result, path); - std::string fileName = simu::basename(result); - strcpy(result, path); - std::string dirName = simu::dirname(result); - simu::DIR * dir = simu::opendir(dirName.c_str()); - if (dir) { - // TRACE_SIMPGMSPACE("\tsearching for: %s", fileName.c_str()); - for (;;) { - struct simu::dirent * res = simu::readdir(dir); - if (res == 0) break; -#if defined(WIN32) || defined(__APPLE__) || defined(__FreeBSD__) - if ((res->d_type == DT_REG) || (res->d_type == DT_LNK)) { -#else - if ((res->d_type == simu::DT_REG) || (res->d_type == simu::DT_LNK)) { -#endif - // TRACE_SIMPGMSPACE("comparing with: %s", res->d_name); - if (!strcasecmp(fileName.c_str(), res->d_name)) { - strcpy(result, dirName.c_str()); - strcat(result, "/"); - strcat(result, res->d_name); - // TRACE_SIMPGMSPACE("\tfound: %s", res->d_name); - fileMap.insert(filemap_t:: value_type(path, result)); - simu::closedir(dir); - return result; - } - } - } - simu::closedir(dir); - } -#endif - } - // TRACE_SIMPGMSPACE("\tnot found"); - strcpy(result, path); - return result; -} - -FRESULT f_stat (const TCHAR * name, FILINFO *fno) -{ - char *path = convertSimuPath(name); - char * realPath = findTrueFileName(path); - struct stat tmp; - if (stat(realPath, &tmp)) { - TRACE_SIMPGMSPACE("f_stat(%s) = error %d (%s)", path, errno, strerror(errno)); - return FR_INVALID_NAME; - } - else { - TRACE_SIMPGMSPACE("f_stat(%s) = OK", path); - if (fno) { - fno->fattrib = (tmp.st_mode & S_IFDIR) ? AM_DIR : 0; - // convert to FatFs fdate/ftime - struct tm *ltime = localtime(&tmp.st_mtime); - fno->fdate = ((ltime->tm_year - 80) << 9) | ((ltime->tm_mon + 1) << 5) | ltime->tm_mday; - fno->ftime = (ltime->tm_hour << 11) | (ltime->tm_min << 5) | (ltime->tm_sec / 2); - fno->fsize = (DWORD)tmp.st_size; - } - return FR_OK; - } -} - -FRESULT f_mount (FATFS* ,const TCHAR*, BYTE opt) -{ - return FR_OK; -} - -FRESULT f_open (FIL * fil, const TCHAR *name, BYTE flag) -{ - char * path = convertSimuPath(name); - char * realPath = findTrueFileName(path); - fil->obj.fs = 0; - if (!(flag & FA_WRITE)) { - struct stat tmp; - if (stat(realPath, &tmp)) { - TRACE_SIMPGMSPACE("f_open(%s) = INVALID_NAME (FIL %p)", path, fil); - return FR_INVALID_NAME; - } - fil->obj.objsize = tmp.st_size; - fil->fptr = 0; - } - fil->obj.fs = (FATFS*)fopen(realPath, (flag & FA_WRITE) ? ((flag & FA_CREATE_ALWAYS) ? "wb+" : "ab+") : "rb+"); - fil->fptr = 0; - if (fil->obj.fs) { - TRACE_SIMPGMSPACE("f_open(%s, %x) = %p (FIL %p)", path, flag, fil->obj.fs, fil); - return FR_OK; - } - TRACE_SIMPGMSPACE("f_open(%s) = error %d (%s) (FIL %p)", path, errno, strerror(errno), fil); - return FR_INVALID_NAME; -} - -FRESULT f_read (FIL* fil, void* data, UINT size, UINT* read) -{ - if (fil && fil->obj.fs) { - *read = fread(data, 1, size, (FILE*)fil->obj.fs); - fil->fptr += *read; - // TRACE_SIMPGMSPACE("fread(%p) %u, %u", fil->obj.fs, size, *read); - } - return FR_OK; -} - -FRESULT f_write (FIL* fil, const void* data, UINT size, UINT* written) -{ - if (fil && fil->obj.fs) { - *written = fwrite(data, 1, size, (FILE*)fil->obj.fs); - fil->fptr += size; - // TRACE_SIMPGMSPACE("fwrite(%p) %u, %u", fil->obj.fs, size, *written); - } - return FR_OK; -} - -TCHAR * f_gets (TCHAR* buff, int len, FIL* fil) -{ - if (fil && fil->obj.fs) { - buff = fgets(buff, len, (FILE*)fil->obj.fs); - if (buff != NULL) { - fil->fptr = *buff; - } - // TRACE_SIMPGMSPACE("fgets(%p) %u, %s", fil->obj.fs, len, buff); - } - return buff; -} - -FRESULT f_lseek (FIL* fil, DWORD offset) -{ - if (fil && fil->obj.fs) fseek((FILE*)fil->obj.fs, offset, SEEK_SET); - fil->fptr = offset; - return FR_OK; -} - -UINT f_size(FIL* fil) -{ - if (fil && fil->obj.fs) { - long curr = ftell((FILE*)fil->obj.fs); - fseek((FILE*)fil->obj.fs, 0, SEEK_END); - long size = ftell((FILE*)fil->obj.fs); - fseek((FILE*)fil->obj.fs, curr, SEEK_SET); - TRACE_SIMPGMSPACE("f_size(%p) %u", fil->obj.fs, size); - return size; - } - return 0; -} - -FRESULT f_close (FIL * fil) -{ - TRACE_SIMPGMSPACE("f_close(%p) (FIL:%p)", fil->obj.fs, fil); - if (fil->obj.fs) { - fclose((FILE*)fil->obj.fs); - fil->obj.fs = NULL; - } - return FR_OK; -} - -FRESULT f_chdir (const TCHAR *name) -{ - chdir(convertSimuPath(name)); - return FR_OK; -} - -FRESULT f_opendir (DIR * rep, const TCHAR * name) -{ - char *path = convertSimuPath(name); - rep->obj.fs = (FATFS *)simu::opendir(path); - if ( rep->obj.fs ) { - TRACE_SIMPGMSPACE("f_opendir(%s) = OK", path); - return FR_OK; - } - TRACE_SIMPGMSPACE("f_opendir(%s) = error %d (%s)", path, errno, strerror(errno)); - return FR_NO_PATH; -} - -FRESULT f_closedir (DIR * rep) -{ - TRACE_SIMPGMSPACE("f_closedir(%p)", rep); - if (rep->obj.fs) simu::closedir((simu::DIR *)rep->obj.fs); - return FR_OK; -} - -FRESULT f_readdir (DIR * rep, FILINFO * fil) -{ - simu::dirent * ent; - if (!rep->obj.fs) return FR_NO_FILE; - for(;;) { - ent = simu::readdir((simu::DIR *)rep->obj.fs); - if (!ent) return FR_NO_FILE; - if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, "..") ) break; - } - -#if defined(WIN32) || !defined(__GNUC__) || defined(__APPLE__) || defined(__FreeBSD__) - fil->fattrib = (ent->d_type == DT_DIR ? AM_DIR : 0); -#else - if (ent->d_type == simu::DT_UNKNOWN || ent->d_type == simu::DT_LNK) { - fil->fattrib = 0; - struct stat buf; - if (stat(ent->d_name, &buf) == 0) { - fil->fattrib = (S_ISDIR(buf.st_mode) ? AM_DIR : 0); - } - } - else { - fil->fattrib = (ent->d_type == simu::DT_DIR ? AM_DIR : 0); - } -#endif - - memset(fil->fname, 0, SD_SCREEN_FILE_LENGTH); - strcpy(fil->fname, ent->d_name); - // TRACE_SIMPGMSPACE("f_readdir(): %s", fil->fname); - return FR_OK; -} - -FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len) -{ - TRACE_SIMPGMSPACE("Format SD..."); - return FR_OK; -} - -FRESULT f_mkdir (const TCHAR * name) -{ - char * path = convertSimuPath(name); -#if defined(WIN32) && defined(__GNUC__) - if (mkdir(path)) { -#else - if (mkdir(path, 0777)) { -#endif - TRACE_SIMPGMSPACE("mkdir(%s) = error %d (%s)", path, errno, strerror(errno)); - return FR_INVALID_NAME; - } - else { - TRACE_SIMPGMSPACE("mkdir(%s) = OK", path); - return FR_OK; - } - return FR_OK; -} - -FRESULT f_unlink (const TCHAR * name) -{ - char * path = convertSimuPath(name); - if (unlink(path)) { - TRACE_SIMPGMSPACE("f_unlink(%s) = error %d (%s)", path, errno, strerror(errno)); - return FR_INVALID_NAME; - } - else { - TRACE_SIMPGMSPACE("f_unlink(%s) = OK", path); - return FR_OK; - } -} - -FRESULT f_rename(const TCHAR *oldname, const TCHAR *newname) -{ - char old[1024]; - strcpy(old, convertSimuPath(oldname)); - char * path = convertSimuPath(newname); - - if (rename(old, path) < 0) { - TRACE_SIMPGMSPACE("f_rename(%s, %s) = error %d (%s)", old, path, errno, strerror(errno)); - return FR_INVALID_NAME; - } - TRACE_SIMPGMSPACE("f_rename(%s, %s) = OK", old, path); - return FR_OK; -} - -FRESULT f_utime(const TCHAR* path, const FILINFO* fno) -{ - if (fno == NULL) - return FR_INVALID_PARAMETER; - - char *simpath = convertSimuPath(path); - char *realPath = findTrueFileName(simpath); - struct utimbuf newTimes; - struct tm ltime; - - // convert from FatFs fdate/ftime - ltime.tm_year = ((fno->fdate >> 9) & 0x7F) + 80; - ltime.tm_mon = ((fno->fdate >> 5) & 0xF) - 1; - ltime.tm_mday = (fno->fdate & 0x1F); - ltime.tm_hour = ((fno->ftime >> 11) & 0x1F); - ltime.tm_min = ((fno->ftime >> 5) & 0x3F); - ltime.tm_sec = (fno->ftime & 0x1F) * 2; - ltime.tm_isdst = -1; // force mktime() to check dst - - newTimes.modtime = mktime(<ime); - newTimes.actime = newTimes.modtime; - - if (utime(realPath, &newTimes)) { - TRACE_SIMPGMSPACE("f_utime(%s) = error %d (%s)", simpath, errno, strerror(errno)); - return FR_DENIED; - } - else { - TRACE_SIMPGMSPACE("f_utime(%s) set mtime = %s", simpath, ctime(&newTimes.modtime)); - return FR_OK; - } -} - -int f_putc (TCHAR c, FIL * fil) -{ - if (fil && fil->obj.fs) fwrite(&c, 1, 1, (FILE*)fil->obj.fs); - return FR_OK; -} - -int f_puts (const TCHAR * str, FIL * fil) -{ - int n; - for (n = 0; *str; str++, n++) { - if (f_putc(*str, fil) == EOF) return EOF; - } - return n; -} - -int f_printf (FIL *fil, const TCHAR * format, ...) -{ - va_list arglist; - va_start(arglist, format); - if (fil && fil->obj.fs) vfprintf((FILE*)fil->obj.fs, format, arglist); - va_end(arglist); - return 0; -} - -FRESULT f_getcwd (TCHAR *path, UINT sz_path) -{ - char cwd[1024]; - size_t sdlen = strlen(simuSdDirectory); - if (!getcwd(cwd, 1024)) { - TRACE_SIMPGMSPACE("f_getcwd() = getcwd() error %d (%s)", errno, strerror(errno)); - strcpy(path, "."); - return FR_NO_PATH; - } - size_t cwdlen = strlen(cwd); - - if (cwdlen < sdlen) { - TRACE_SIMPGMSPACE("f_getcwd() = logic error strlen(cwd) < strlen(simuSdDirectory): cwd: \"%s\", simuSdDirectory: \"%s\"", cwd, simuSdDirectory); - strcpy(path, "."); - return FR_NO_PATH; - } - - if (sz_path < (cwdlen - sdlen)) { - //TRACE_SIMPGMSPACE("f_getcwd(): buffer too short"); - return FR_NOT_ENOUGH_CORE; - } - - // remove simuSdDirectory from the cwd - strcpy(path, cwd + sdlen); - - if (path[0] == '\0') { - strcpy(path, "/"); // fix for the root directory - } - - TRACE_SIMPGMSPACE("f_getcwd() = %s", path); - return FR_OK; -} - -FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs) -{ - // just fake that we always have some clusters free - *nclst = 10; - return FR_OK; -} - -#if defined(PCBSKY9X) -int32_t Card_state = SD_ST_MOUNTED; -uint32_t Card_CSD[4]; // TODO elsewhere -#endif - -#endif // #if defined(SIMU_USE_SDCARD) - - -#if defined(SIMU_DISKIO) -#include "FatFs/diskio.h" -#include -#include - -#if defined(CPUARM) -FATFS g_FATFS_Obj = { 0}; -#endif - -pthread_mutex_t ioMutex; - -int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj) /* Create a sync object */ -{ - pthread_mutex_init(&ioMutex, 0); - return 1; -} - -int ff_req_grant (_SYNC_t sobj) /* Lock sync object */ -{ - pthread_mutex_lock(&ioMutex); - return 1; -} - -void ff_rel_grant (_SYNC_t sobj) /* Unlock sync object */ -{ - pthread_mutex_unlock(&ioMutex); -} - -int ff_del_syncobj (_SYNC_t sobj) /* Delete a sync object */ -{ - pthread_mutex_destroy(&ioMutex); - return 1; -} - -DWORD get_fattime (void) -{ - time_t tim = time(0); - const struct tm * t = gmtime(&tim); - - /* Pack date and time into a DWORD variable */ - return ((DWORD)(t->tm_year - 80) << 25) - | ((uint32_t)(t->tm_mon+1) << 21) - | ((uint32_t)t->tm_mday << 16) - | ((uint32_t)t->tm_hour << 11) - | ((uint32_t)t->tm_min << 5) - | ((uint32_t)t->tm_sec >> 1); -} - -unsigned int noDiskStatus = 0; - -void traceDiskStatus() -{ - if (noDiskStatus > 0) { - TRACE_SIMPGMSPACE("disk_status() called %d times", noDiskStatus); - noDiskStatus = 0; - } -} - -DSTATUS disk_initialize (BYTE pdrv) -{ - traceDiskStatus(); - TRACE_SIMPGMSPACE("disk_initialize(%u)", pdrv); - diskImage = fopen("sdcard.image", "r+"); - return diskImage ? (DSTATUS)0 : (DSTATUS)STA_NODISK; -} - -DSTATUS disk_status (BYTE pdrv) -{ - ++noDiskStatus; - // TRACE_SIMPGMSPACE("disk_status(%u)", pdrv); - return (DSTATUS)0; -} - -DRESULT __disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count) -{ - if (diskImage == 0) return RES_NOTRDY; - traceDiskStatus(); - TRACE_SIMPGMSPACE("disk_read(%u, %p, %u, %u)", pdrv, buff, sector, count); - fseek(diskImage, sector*512, SEEK_SET); - fread(buff, count, 512, diskImage); - return RES_OK; -} - -DRESULT __disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) -{ - if (diskImage == 0) return RES_NOTRDY; - traceDiskStatus(); - TRACE_SIMPGMSPACE("disk_write(%u, %p, %u, %u)", pdrv, buff, sector, count); - fseek(diskImage, sector*512, SEEK_SET); - fwrite(buff, count, 512, diskImage); - return RES_OK; -} - -DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff) -{ - if (diskImage == 0) return RES_NOTRDY; - traceDiskStatus(); - TRACE_SIMPGMSPACE("disk_ioctl(%u, %u, %p)", pdrv, cmd, buff); - if (pdrv) return RES_PARERR; - - DRESULT res; - BYTE *ptr = (BYTE *)buff; - - if (cmd == CTRL_POWER) { - switch (*ptr) { - case 0: /* Sub control code == 0 (POWER_OFF) */ - res = RES_OK; - break; - case 1: /* Sub control code == 1 (POWER_ON) */ - res = RES_OK; - break; - case 2: /* Sub control code == 2 (POWER_GET) */ - *(ptr+1) = (BYTE)1; /* fake powered */ - res = RES_OK; - break; - default : - res = RES_PARERR; - } - return res; - } - - switch(cmd) { -/* Generic command (Used by FatFs) */ - case CTRL_SYNC : /* Complete pending write process (needed at _FS_READONLY == 0) */ - break; - - case GET_SECTOR_COUNT: /* Get media size (needed at _USE_MKFS == 1) */ - { - struct stat buf; - if (stat("sdcard.image", &buf) == 0) { - DWORD noSectors = buf.st_size / 512; - *(DWORD*)buff = noSectors; - TRACE_SIMPGMSPACE("disk_ioctl(GET_SECTOR_COUNT) = %u", noSectors); - return RES_OK; - } - return RES_ERROR; - } - - case GET_SECTOR_SIZE: /* Get sector size (needed at _MAX_SS != _MIN_SS) */ - TRACE_SIMPGMSPACE("disk_ioctl(GET_SECTOR_SIZE) = 512"); - *(WORD*)buff = 512; - res = RES_OK; - break; - - case GET_BLOCK_SIZE : /* Get erase block size (needed at _USE_MKFS == 1) */ - *(WORD*)buff = 512 * 4; - res = RES_OK; - break; - - case CTRL_TRIM : /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */ - break; - -/* Generic command (Not used by FatFs) */ - case CTRL_LOCK : /* Lock/Unlock media removal */ - case CTRL_EJECT: /* Eject media */ - case CTRL_FORMAT: /* Create physical format on the media */ - return RES_PARERR; - - -/* MMC/SDC specific ioctl command */ - // case MMC_GET_TYPE 10 /* Get card type */ - // case MMC_GET_CSD 11 /* Get CSD */ - // case MMC_GET_CID 12 /* Get CID */ - // case MMC_GET_OCR 13 /* Get OCR */ - // case MMC_GET_SDSTAT 14 /* Get SD status */ - -/* ATA/CF specific ioctl command */ - // case ATA_GET_REV 20 /* Get F/W revision */ - // case ATA_GET_MODEL 21 /* Get model name */ - // case ATA_GET_SN 22 /* Get serial number */ - default: - return RES_PARERR; - } - return RES_OK; -} - -void sdInit(void) -{ - // ioMutex = CoCreateMutex(); - // if (ioMutex >= CFG_MAX_MUTEX ) { - // // sd error - // return; - // } - - if (f_mount(&g_FATFS_Obj, "", 1) == FR_OK) { - // call sdGetFreeSectors() now because f_getfree() takes a long time first time it's called - sdGetFreeSectors(); - -#if defined(LOG_TELEMETRY) - f_open(&g_telemetryFile, LOGS_PATH "/telemetry.log", FA_OPEN_ALWAYS | FA_WRITE); - if (f_size(&g_telemetryFile) > 0) { - f_lseek(&g_telemetryFile, f_size(&g_telemetryFile)); // append - } -#endif - } - else { - TRACE_SIMPGMSPACE("f_mount() failed"); - } -} - -void sdDone() -{ - if (sdMounted()) { - audioQueue.stopSD(); -#if defined(LOG_TELEMETRY) - f_close(&g_telemetryFile); -#endif - f_mount(NULL, "", 0); // unmount SD - } -} - -uint32_t sdMounted() -{ - return g_FATFS_Obj.fs_type != 0; -} - -uint32_t sdIsHC() -{ - return sdGetSize() > 2000000; -} - -uint32_t sdGetSpeed() -{ - return 330000; -} - -#endif // #if defined(SIMU_DISKIO) - bool simuLcdRefresh = true; display_t simuLcdBuf[DISPLAY_BUFFER_SIZE]; diff --git a/radio/src/targets/simu/simpgmspace.h b/radio/src/targets/simu/simpgmspace.h index f4352c0c1..6dadb0fed 100644 --- a/radio/src/targets/simu/simpgmspace.h +++ b/radio/src/targets/simu/simpgmspace.h @@ -372,7 +372,7 @@ void simuSetKey(uint8_t key, bool state); void simuSetTrim(uint8_t trim, bool state); void simuSetSwitch(uint8_t swtch, int8_t state); -void StartSimu(bool tests=true); +void StartSimu(bool tests=true, const char * sdPath = 0, const char * settingsPath = 0); void StopSimu(); void StartEepromThread(const char *filename="eeprom.bin"); @@ -467,8 +467,8 @@ inline void NVIC_Init(NVIC_InitTypeDef *) { } inline void delay_01us(int dummy) { } #define configure_pins(...) -#if defined(SDCARD) -extern char simuSdDirectory[1024]; +#if defined(SDCARD) && !defined(SKIP_FATFS_DECLARATION) && !defined(SIMU_DISKIO) + #define SIMU_USE_SDCARD #endif #define sdMountPoll() @@ -478,4 +478,17 @@ extern char simuSdDirectory[1024]; #define sdMounted() (true) #endif +#if defined(SIMU_USE_SDCARD) + void simuFatfsSetPaths(const char * sdPath, const char * settingsPath); +#else + #define simuFatfsSetPaths(...) +#endif + +#if defined(TRACE_SIMPGMSPACE) + #undef TRACE_SIMPGMSPACE + #define TRACE_SIMPGMSPACE TRACE +#else + #define TRACE_SIMPGMSPACE(...) +#endif + #endif // _SIMPGMSPACE_H_ diff --git a/radio/src/targets/simu/simudisk.cpp b/radio/src/targets/simu/simudisk.cpp new file mode 100644 index 000000000..78e72b996 --- /dev/null +++ b/radio/src/targets/simu/simudisk.cpp @@ -0,0 +1,245 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#if defined(SIMU_DISKIO) +#include "FatFs/diskio.h" +#include +#include + +FATFS g_FATFS_Obj = {0}; + +pthread_mutex_t ioMutex; + +int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj) /* Create a sync object */ +{ + pthread_mutex_init(&ioMutex, 0); + return 1; +} + +int ff_req_grant (_SYNC_t sobj) /* Lock sync object */ +{ + pthread_mutex_lock(&ioMutex); + return 1; +} + +void ff_rel_grant (_SYNC_t sobj) /* Unlock sync object */ +{ + pthread_mutex_unlock(&ioMutex); +} + +int ff_del_syncobj (_SYNC_t sobj) /* Delete a sync object */ +{ + pthread_mutex_destroy(&ioMutex); + return 1; +} + +DWORD get_fattime (void) +{ + time_t tim = time(0); + const struct tm * t = gmtime(&tim); + + /* Pack date and time into a DWORD variable */ + return ((DWORD)(t->tm_year - 80) << 25) + | ((uint32_t)(t->tm_mon+1) << 21) + | ((uint32_t)t->tm_mday << 16) + | ((uint32_t)t->tm_hour << 11) + | ((uint32_t)t->tm_min << 5) + | ((uint32_t)t->tm_sec >> 1); +} + +unsigned int noDiskStatus = 0; + +void traceDiskStatus() +{ + if (noDiskStatus > 0) { + TRACE_SIMPGMSPACE("disk_status() called %d times", noDiskStatus); + noDiskStatus = 0; + } +} + +DSTATUS disk_initialize (BYTE pdrv) +{ + traceDiskStatus(); + TRACE_SIMPGMSPACE("disk_initialize(%u)", pdrv); + diskImage = fopen("sdcard.image", "r+"); + return diskImage ? (DSTATUS)0 : (DSTATUS)STA_NODISK; +} + +DSTATUS disk_status (BYTE pdrv) +{ + ++noDiskStatus; + // TRACE_SIMPGMSPACE("disk_status(%u)", pdrv); + return (DSTATUS)0; +} + +DRESULT __disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count) +{ + if (diskImage == 0) return RES_NOTRDY; + traceDiskStatus(); + TRACE_SIMPGMSPACE("disk_read(%u, %p, %u, %u)", pdrv, buff, sector, count); + fseek(diskImage, sector*512, SEEK_SET); + fread(buff, count, 512, diskImage); + return RES_OK; +} + +DRESULT __disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) +{ + if (diskImage == 0) return RES_NOTRDY; + traceDiskStatus(); + TRACE_SIMPGMSPACE("disk_write(%u, %p, %u, %u)", pdrv, buff, sector, count); + fseek(diskImage, sector*512, SEEK_SET); + fwrite(buff, count, 512, diskImage); + return RES_OK; +} + +DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff) +{ + if (diskImage == 0) return RES_NOTRDY; + traceDiskStatus(); + TRACE_SIMPGMSPACE("disk_ioctl(%u, %u, %p)", pdrv, cmd, buff); + if (pdrv) return RES_PARERR; + + DRESULT res; + BYTE *ptr = (BYTE *)buff; + + if (cmd == CTRL_POWER) { + switch (*ptr) { + case 0: /* Sub control code == 0 (POWER_OFF) */ + res = RES_OK; + break; + case 1: /* Sub control code == 1 (POWER_ON) */ + res = RES_OK; + break; + case 2: /* Sub control code == 2 (POWER_GET) */ + *(ptr+1) = (BYTE)1; /* fake powered */ + res = RES_OK; + break; + default : + res = RES_PARERR; + } + return res; + } + + switch(cmd) { +/* Generic command (Used by FatFs) */ + case CTRL_SYNC : /* Complete pending write process (needed at _FS_READONLY == 0) */ + break; + + case GET_SECTOR_COUNT: /* Get media size (needed at _USE_MKFS == 1) */ + { + struct stat buf; + if (stat("sdcard.image", &buf) == 0) { + DWORD noSectors = buf.st_size / 512; + *(DWORD*)buff = noSectors; + TRACE_SIMPGMSPACE("disk_ioctl(GET_SECTOR_COUNT) = %u", noSectors); + return RES_OK; + } + return RES_ERROR; + } + + case GET_SECTOR_SIZE: /* Get sector size (needed at _MAX_SS != _MIN_SS) */ + TRACE_SIMPGMSPACE("disk_ioctl(GET_SECTOR_SIZE) = 512"); + *(WORD*)buff = 512; + res = RES_OK; + break; + + case GET_BLOCK_SIZE : /* Get erase block size (needed at _USE_MKFS == 1) */ + *(WORD*)buff = 512 * 4; + res = RES_OK; + break; + + case CTRL_TRIM : /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */ + break; + +/* Generic command (Not used by FatFs) */ + case CTRL_LOCK : /* Lock/Unlock media removal */ + case CTRL_EJECT: /* Eject media */ + case CTRL_FORMAT: /* Create physical format on the media */ + return RES_PARERR; + + +/* MMC/SDC specific ioctl command */ + // case MMC_GET_TYPE 10 /* Get card type */ + // case MMC_GET_CSD 11 /* Get CSD */ + // case MMC_GET_CID 12 /* Get CID */ + // case MMC_GET_OCR 13 /* Get OCR */ + // case MMC_GET_SDSTAT 14 /* Get SD status */ + +/* ATA/CF specific ioctl command */ + // case ATA_GET_REV 20 /* Get F/W revision */ + // case ATA_GET_MODEL 21 /* Get model name */ + // case ATA_GET_SN 22 /* Get serial number */ + default: + return RES_PARERR; + } + return RES_OK; +} + +void sdInit(void) +{ + // ioMutex = CoCreateMutex(); + // if (ioMutex >= CFG_MAX_MUTEX ) { + // // sd error + // return; + // } + + if (f_mount(&g_FATFS_Obj, "", 1) == FR_OK) { + // call sdGetFreeSectors() now because f_getfree() takes a long time first time it's called + sdGetFreeSectors(); + +#if defined(LOG_TELEMETRY) + f_open(&g_telemetryFile, LOGS_PATH "/telemetry.log", FA_OPEN_ALWAYS | FA_WRITE); + if (f_size(&g_telemetryFile) > 0) { + f_lseek(&g_telemetryFile, f_size(&g_telemetryFile)); // append + } +#endif + } + else { + TRACE_SIMPGMSPACE("f_mount() failed"); + } +} + +void sdDone() +{ + if (sdMounted()) { + audioQueue.stopSD(); +#if defined(LOG_TELEMETRY) + f_close(&g_telemetryFile); +#endif + f_mount(NULL, "", 0); // unmount SD + } +} + +uint32_t sdMounted() +{ + return g_FATFS_Obj.fs_type != 0; +} + +uint32_t sdIsHC() +{ + return sdGetSize() > 2000000; +} + +uint32_t sdGetSpeed() +{ + return 330000; +} + +#endif // #if defined(SIMU_DISKIO) diff --git a/radio/src/targets/simu/simueeprom.cpp b/radio/src/targets/simu/simueeprom.cpp index bd6845fa0..be37e9541 100644 --- a/radio/src/targets/simu/simueeprom.cpp +++ b/radio/src/targets/simu/simueeprom.cpp @@ -134,7 +134,11 @@ void eepromWriteBlock(uint8_t * buffer, size_t address, size_t size) eepromStartWrite(buffer, address, size); while (!eepromIsTransferComplete()) { +#if defined(GTESTS) + sleep(0/*ms*/); +#else sleep(1/*ms*/); +#endif } } diff --git a/radio/src/targets/simu/simufatfs.cpp b/radio/src/targets/simu/simufatfs.cpp new file mode 100644 index 000000000..9c93a64d6 --- /dev/null +++ b/radio/src/targets/simu/simufatfs.cpp @@ -0,0 +1,554 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "opentx.h" + +#if defined _MSC_VER || !defined (__GNUC__) + #define WINDOWS_BUILD +#endif + +#if defined(SIMU_USE_SDCARD) +#if defined(WINDOWS_BUILD) + #include + #include + #include + #define mkdir(s, f) _mkdir(s) +#else + #include +#endif + +#include +#include +#include +#include +#include "ff.h" +#include +#include +#include + +namespace simu { +#include +#if !defined(_MSC_VER) + #include +#endif +} + +std::string simuSdDirectory; // path to the root of the SD card image +std::string simuSettingsDirectory; // path to the root of the models and settings (only for the radios that use SD for model storage) + +bool isPathDelimiter(char delimiter) +{ + return (delimiter == '/' || delimiter == '\\'); +} + +std::string removeTrailingPathDelimiter(const char * path) +{ + std::string result = path; + while (!result.empty() && isPathDelimiter(result.back())) { + result.pop_back(); + } + return result; +} + +void simuFatfsSetPaths(const char * sdPath, const char * settingsPath) +{ + if (sdPath) { + simuSdDirectory = removeTrailingPathDelimiter(sdPath); + } + else { + char buff[1024]; + f_getcwd(buff, sizeof(buff)-1); + simuSdDirectory = removeTrailingPathDelimiter(buff); + } + if (settingsPath) { + simuSettingsDirectory = removeTrailingPathDelimiter(settingsPath); + } +} + +bool startsWith(const char *path, const char * start) +{ + return strncasecmp(path, start, strlen(start)) == 0; +} + +std::string convertToSimuPath(const char *path) +{ + std::string result; + if (isPathDelimiter(path[0])) { + if (!simuSettingsDirectory.empty() && (startsWith(path, "/MODELS") || startsWith(path, "/RADIO"))) { + result = simuSettingsDirectory + std::string(path); + } + else { + result = simuSdDirectory + std::string(path); + } + } + else { + result = std::string(path); + } + TRACE("convertToSimuPath(): %s -> %s", path, result.c_str()); + return result; +} + +std::string convertFromSimuPath(const char *path) +{ + std::string result; + if (startsWith(path, simuSdDirectory.c_str())) { + result = std::string(path).substr(simuSdDirectory.length(), std::string::npos); + if (result.empty()) { + result = "/"; + } + } + else { + result = std::string(path); + if (!result.empty() && !isPathDelimiter(result[0])) { + result = "/" + result; + } + } + TRACE("convertFromSimuPath(): %s -> %s", path, result.c_str()); + return result; +} + +typedef std::map filemap_t; + +filemap_t fileMap; + +void splitPath(const std::string & path, std::string & dir, std::string & name) +{ +#if defined(WINDOWS_BUILD) + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + _splitpath(path.c_str(), drive, dir, fname, ext); + name = std::string(fname) + std::string(ext); + dir = std::string(drive) + std::string(dir); + std::string searchName = dirName + "*"; +#else + char * buff = new char[path.length()+1]; + strcpy(buff, path.c_str()); + name = simu::basename(buff); + strcpy(buff, path.c_str()); + dir = simu::dirname(buff); + delete[] buff; +#endif +} + + +bool isFile(const std::string & fullName, unsigned char d_type) +{ +#if defined(WIN32) || defined(__APPLE__) || defined(__FreeBSD__) + #define REGULAR_FILE DT_REG + #define SYMBOLIC_LINK DT_LNK +#else + #define REGULAR_FILE simu::DT_REG + #define SYMBOLIC_LINK simu::DT_LNK +#endif + + if (d_type == REGULAR_FILE) return true; + if (d_type == SYMBOLIC_LINK) { + struct stat tmp; + if (stat(fullName.c_str(), &tmp) == 0) { + // TRACE_SIMPGMSPACE("\tsymlik: %s is %s", fullName.c_str(), (tmp.st_mode & S_IFREG) ? "file" : "other"); + if (tmp.st_mode & S_IFREG) return true; + } + } + return false; +} + +std::vector listDirectoryFiles(const std::string & dirName) +{ + std::vector result; + +#if defined (WINDOWS_BUILD) + std::string searchName = dirName + "*"; + // TRACE_SIMPGMSPACE("\tsearching for: %s", fileName.c_str()); + WIN32_FIND_DATA ffd; + HANDLE hFind = FindFirstFile(searchName.c_str(), &ffd); + if (INVALID_HANDLE_VALUE != hFind) { + do { + if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + //TRACE_SIMPGMSPACE("comparing with: %s", ffd.cFileName); + if (!strcasecmp(fileName.c_str(), ffd.cFileName)) { + std::string fullName = dirName + std::string(ffd.cFileName); + // TRACE_SIMPGMSPACE("listDirectoryFiles(): %s", fullName.c_str()); + result.push_back(fullName); + } + } + } + while (FindNextFile(hFind, &ffd) != 0); + } +#else + simu::DIR * dir = simu::opendir(dirName.c_str()); + if (dir) { + struct simu::dirent * res; + while ((res = simu::readdir(dir)) != 0) { + std::string fullName = dirName + "/" + std::string(res->d_name); + if (isFile(fullName, res->d_type)) { + // TRACE_SIMPGMSPACE("listDirectoryFiles(): %s", fullName.c_str()); + result.push_back(fullName); + } + } + simu::closedir(dir); + } +#endif + return result; +} + +std::string findTrueFileName(const std::string & path) +{ + TRACE_SIMPGMSPACE("findTrueFileName(%s)", path.c_str()); + std::string result; + filemap_t::iterator i = fileMap.find(path); + if (i != fileMap.end()) { + result = i->second; + TRACE_SIMPGMSPACE("\tfound in map: %s", result.c_str()); + return result; + } + else { + //find file and add to map + std::string dirName; + std::string fileName; + splitPath(path, dirName, fileName); + std::vector files = listDirectoryFiles(dirName); + for(unsigned int i=0; ifattrib = (tmp.st_mode & S_IFDIR) ? AM_DIR : 0; + // convert to FatFs fdate/ftime + struct tm *ltime = localtime(&tmp.st_mtime); + fno->fdate = ((ltime->tm_year - 80) << 9) | ((ltime->tm_mon + 1) << 5) | ltime->tm_mday; + fno->ftime = (ltime->tm_hour << 11) | (ltime->tm_min << 5) | (ltime->tm_sec / 2); + fno->fsize = (DWORD)tmp.st_size; + } + return FR_OK; + } +} + +FRESULT f_mount (FATFS* ,const TCHAR*, BYTE opt) +{ + return FR_OK; +} + +FRESULT f_open (FIL * fil, const TCHAR *name, BYTE flag) +{ + std::string path = convertToSimuPath(name); + std::string realPath = findTrueFileName(path); + fil->obj.fs = 0; + if (!(flag & FA_WRITE)) { + struct stat tmp; + if (stat(realPath.c_str(), &tmp)) { + TRACE_SIMPGMSPACE("f_open(%s) = INVALID_NAME (FIL %p)", path.c_str(), fil); + return FR_INVALID_NAME; + } + fil->obj.objsize = tmp.st_size; + fil->fptr = 0; + } + fil->obj.fs = (FATFS*)fopen(realPath.c_str(), (flag & FA_WRITE) ? ((flag & FA_CREATE_ALWAYS) ? "wb+" : "ab+") : "rb+"); + fil->fptr = 0; + if (fil->obj.fs) { + TRACE_SIMPGMSPACE("f_open(%s, %x) = %p (FIL %p)", path.c_str(), flag, fil->obj.fs, fil); + return FR_OK; + } + TRACE_SIMPGMSPACE("f_open(%s) = error %d (%s) (FIL %p)", path.c_str(), errno, strerror(errno), fil); + return FR_INVALID_NAME; +} + +FRESULT f_read (FIL* fil, void* data, UINT size, UINT* read) +{ + if (fil && fil->obj.fs) { + *read = fread(data, 1, size, (FILE*)fil->obj.fs); + fil->fptr += *read; + // TRACE_SIMPGMSPACE("fread(%p) %u, %u", fil->obj.fs, size, *read); + } + return FR_OK; +} + +FRESULT f_write (FIL* fil, const void* data, UINT size, UINT* written) +{ + if (fil && fil->obj.fs) { + *written = fwrite(data, 1, size, (FILE*)fil->obj.fs); + fil->fptr += size; + // TRACE_SIMPGMSPACE("fwrite(%p) %u, %u", fil->obj.fs, size, *written); + } + return FR_OK; +} + +TCHAR * f_gets (TCHAR* buff, int len, FIL* fil) +{ + if (fil && fil->obj.fs) { + buff = fgets(buff, len, (FILE*)fil->obj.fs); + if (buff != NULL) { + fil->fptr = *buff; + } + // TRACE_SIMPGMSPACE("fgets(%p) %u, %s", fil->obj.fs, len, buff); + } + return buff; +} + +FRESULT f_lseek (FIL* fil, DWORD offset) +{ + if (fil && fil->obj.fs) fseek((FILE*)fil->obj.fs, offset, SEEK_SET); + fil->fptr = offset; + return FR_OK; +} + +UINT f_size(FIL* fil) +{ + if (fil && fil->obj.fs) { + long curr = ftell((FILE*)fil->obj.fs); + fseek((FILE*)fil->obj.fs, 0, SEEK_END); + long size = ftell((FILE*)fil->obj.fs); + fseek((FILE*)fil->obj.fs, curr, SEEK_SET); + TRACE_SIMPGMSPACE("f_size(%p) %u", fil->obj.fs, size); + return size; + } + return 0; +} + +FRESULT f_close (FIL * fil) +{ + TRACE_SIMPGMSPACE("f_close(%p) (FIL:%p)", fil->obj.fs, fil); + if (fil->obj.fs) { + fclose((FILE*)fil->obj.fs); + fil->obj.fs = NULL; + } + return FR_OK; +} + +FRESULT f_chdir (const TCHAR *name) +{ + std::string path = convertToSimuPath(name); + if (chdir(path.c_str())) { + TRACE_SIMPGMSPACE("f_chdir(%s) = error %d (%s)", path.c_str(), errno, strerror(errno)); + return FR_NO_PATH; + } + TRACE_SIMPGMSPACE("f_chdir(%s)", path.c_str()); + return FR_OK; +} + +FRESULT f_opendir (DIR * rep, const TCHAR * name) +{ + std::string path = convertToSimuPath(name); + rep->obj.fs = (FATFS *)simu::opendir(path.c_str()); + if (rep->obj.fs) { + TRACE_SIMPGMSPACE("f_opendir(%s) = OK", path.c_str()); + return FR_OK; + } + TRACE_SIMPGMSPACE("f_opendir(%s) = error %d (%s)", path.c_str(), errno, strerror(errno)); + return FR_NO_PATH; +} + +FRESULT f_closedir (DIR * rep) +{ + TRACE_SIMPGMSPACE("f_closedir(%p)", rep); + if (rep->obj.fs) simu::closedir((simu::DIR *)rep->obj.fs); + return FR_OK; +} + +FRESULT f_readdir (DIR * rep, FILINFO * fil) +{ + simu::dirent * ent; + if (!rep->obj.fs) return FR_NO_FILE; + for(;;) { + ent = simu::readdir((simu::DIR *)rep->obj.fs); + if (!ent) return FR_NO_FILE; + if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, "..") ) break; + } + +#if defined(WIN32) || !defined(__GNUC__) || defined(__APPLE__) || defined(__FreeBSD__) + fil->fattrib = (ent->d_type == DT_DIR ? AM_DIR : 0); +#else + if (ent->d_type == simu::DT_UNKNOWN || ent->d_type == simu::DT_LNK) { + fil->fattrib = 0; + struct stat buf; + if (stat(ent->d_name, &buf) == 0) { + fil->fattrib = (S_ISDIR(buf.st_mode) ? AM_DIR : 0); + } + } + else { + fil->fattrib = (ent->d_type == simu::DT_DIR ? AM_DIR : 0); + } +#endif + + memset(fil->fname, 0, SD_SCREEN_FILE_LENGTH); + strcpy(fil->fname, ent->d_name); + // TRACE_SIMPGMSPACE("f_readdir(): %s", fil->fname); + return FR_OK; +} + +FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len) +{ + TRACE_SIMPGMSPACE("Format SD..."); + return FR_OK; +} + +FRESULT f_mkdir (const TCHAR * name) +{ + std::string path = convertToSimuPath(name); +#if defined(WIN32) && defined(__GNUC__) + if (mkdir(path.c_str())) { +#else + if (mkdir(path.c_str(), 0777)) { +#endif + TRACE_SIMPGMSPACE("mkdir(%s) = error %d (%s)", path.c_str(), errno, strerror(errno)); + return FR_INVALID_NAME; + } + else { + TRACE_SIMPGMSPACE("mkdir(%s) = OK", path.c_str()); + return FR_OK; + } + return FR_OK; +} + +FRESULT f_unlink (const TCHAR * name) +{ + std::string path = convertToSimuPath(name); + if (unlink(path.c_str())) { + TRACE_SIMPGMSPACE("f_unlink(%s) = error %d (%s)", path.c_str(), errno, strerror(errno)); + return FR_INVALID_NAME; + } + else { + TRACE_SIMPGMSPACE("f_unlink(%s) = OK", path.c_str()); + return FR_OK; + } +} + +FRESULT f_rename(const TCHAR *oldname, const TCHAR *newname) +{ + std::string old = convertToSimuPath(oldname); + std::string path = convertToSimuPath(newname); + + if (rename(old.c_str(), path.c_str()) < 0) { + TRACE_SIMPGMSPACE("f_rename(%s, %s) = error %d (%s)", old.c_str(), path.c_str(), errno, strerror(errno)); + return FR_INVALID_NAME; + } + TRACE_SIMPGMSPACE("f_rename(%s, %s) = OK", old.c_str(), path.c_str()); + return FR_OK; +} + +FRESULT f_utime(const TCHAR* path, const FILINFO* fno) +{ + if (fno == NULL) + return FR_INVALID_PARAMETER; + + std::string simpath = convertToSimuPath(path); + std::string realPath = findTrueFileName(simpath); + struct utimbuf newTimes; + struct tm ltime; + + // convert from FatFs fdate/ftime + ltime.tm_year = ((fno->fdate >> 9) & 0x7F) + 80; + ltime.tm_mon = ((fno->fdate >> 5) & 0xF) - 1; + ltime.tm_mday = (fno->fdate & 0x1F); + ltime.tm_hour = ((fno->ftime >> 11) & 0x1F); + ltime.tm_min = ((fno->ftime >> 5) & 0x3F); + ltime.tm_sec = (fno->ftime & 0x1F) * 2; + ltime.tm_isdst = -1; // force mktime() to check dst + + newTimes.modtime = mktime(<ime); + newTimes.actime = newTimes.modtime; + + if (utime(realPath.c_str(), &newTimes)) { + TRACE_SIMPGMSPACE("f_utime(%s) = error %d (%s)", simpath.c_str(), errno, strerror(errno)); + return FR_DENIED; + } + else { + TRACE_SIMPGMSPACE("f_utime(%s) set mtime = %s", simpath.c_str(), ctime(&newTimes.modtime)); + return FR_OK; + } +} + +int f_putc (TCHAR c, FIL * fil) +{ + if (fil && fil->obj.fs) fwrite(&c, 1, 1, (FILE*)fil->obj.fs); + return FR_OK; +} + +int f_puts (const TCHAR * str, FIL * fil) +{ + int n; + for (n = 0; *str; str++, n++) { + if (f_putc(*str, fil) == EOF) return EOF; + } + return n; +} + +int f_printf (FIL *fil, const TCHAR * format, ...) +{ + va_list arglist; + va_start(arglist, format); + if (fil && fil->obj.fs) vfprintf((FILE*)fil->obj.fs, format, arglist); + va_end(arglist); + return 0; +} + +FRESULT f_getcwd (TCHAR *path, UINT sz_path) +{ + char cwd[1024]; + if (!getcwd(cwd, 1024)) { + TRACE_SIMPGMSPACE("f_getcwd() = getcwd() error %d (%s)", errno, strerror(errno)); + strcpy(path, "."); + return FR_NO_PATH; + } + + std::string result = convertFromSimuPath(cwd); + if (result.length() > sz_path) { + //TRACE_SIMPGMSPACE("f_getcwd(): buffer too short"); + return FR_NOT_ENOUGH_CORE; + } + + strcpy(path, result.c_str()); + TRACE_SIMPGMSPACE("f_getcwd() = %s", path); + return FR_OK; +} + +FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs) +{ + // just fake that we always have some clusters free + *nclst = 10; + return FR_OK; +} + +#if defined(PCBSKY9X) +int32_t Card_state = SD_ST_MOUNTED; +uint32_t Card_CSD[4]; // TODO elsewhere +#endif + +#endif // #if defined(SIMU_USE_SDCARD) diff --git a/radio/src/tests/CMakeLists.txt b/radio/src/tests/CMakeLists.txt index 395b54b20..a8b0941e2 100644 --- a/radio/src/tests/CMakeLists.txt +++ b/radio/src/tests/CMakeLists.txt @@ -7,6 +7,7 @@ if(GTEST_INCDIR AND GTEST_SRCDIR AND Qt5Widgets_FOUND) add_library(gtests-lib STATIC EXCLUDE_FROM_ALL ${GTEST_SRCDIR}/src/gtest-all.cc ) target_include_directories(gtests-lib PUBLIC ${GTEST_INCDIR} ${GTEST_INCDIR}/gtest ${GTEST_SRCDIR}) add_definitions(-DSIMU) + add_definitions(-DGTESTS) set(TESTS_PATH ${RADIO_SRC_DIRECTORY}) configure_file(${RADIO_SRC_DIRECTORY}/tests/location.h.in ${CMAKE_CURRENT_BINARY_DIR}/location.h @ONLY) include_directories(${CMAKE_CURRENT_BINARY_DIR}) @@ -36,7 +37,7 @@ if(GTEST_INCDIR AND GTEST_SRCDIR AND Qt5Widgets_FOUND) use_cxx11() # ensure gnu++11 in CXX_FLAGS with CMake < 3.1 - add_executable(gtests EXCLUDE_FROM_ALL ${TEST_SRC_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/location.h ${RADIO_SRC} ../targets/simu/simpgmspace.cpp ../targets/simu/simueeprom.cpp) + add_executable(gtests EXCLUDE_FROM_ALL ${TEST_SRC_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/location.h ${RADIO_SRC} ../targets/simu/simpgmspace.cpp ../targets/simu/simueeprom.cpp ../targets/simu/simufatfs.cpp) qt5_use_modules(gtests Core Widgets) add_dependencies(gtests ${FIRMWARE_DEPENDENCIES} gtests-lib) target_link_libraries(gtests gtests-lib pthread)