diff --git a/MiSTer.vcxproj b/MiSTer.vcxproj index 3738def..61f4136 100644 --- a/MiSTer.vcxproj +++ b/MiSTer.vcxproj @@ -30,7 +30,7 @@ MiSTer git.lnk ./clean.sh __arm__;__GNUC__;__USE_GNU ;_GNU_SOURCE;VDATE="000000";_FILE_OFFSET_BITS=64;_LARGEFILE64_SOURCE;$(NMakePreprocessorDefinitions) - c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\libc\usr\include;c:\Work\Git\opt\gcc54\lib\gcc\arm-linux-gnueabihf\5.4.1\include;c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\include\c++\5.4.1;$(NMakeIncludeSearchPath);lib\libco;lib\miniz;lib\lodepng + c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\libc\usr\include;c:\Work\Git\opt\gcc54\lib\gcc\arm-linux-gnueabihf\5.4.1\include;c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\include\c++\5.4.1;c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\include\c++\5.4.1\arm-linux-gnueabihf;$(NMakeIncludeSearchPath);lib\libco;lib\miniz;lib\lodepng $(TEMP) $(TEMP) @@ -86,6 +86,7 @@ + @@ -142,11 +143,13 @@ + + diff --git a/MiSTer.vcxproj.filters b/MiSTer.vcxproj.filters index c3abb9b..dc907d1 100644 --- a/MiSTer.vcxproj.filters +++ b/MiSTer.vcxproj.filters @@ -196,6 +196,9 @@ Source Files + + Source Files\support + @@ -369,5 +372,11 @@ Header Files + + Header Files\support + + + Header Files\support + \ No newline at end of file diff --git a/support.h b/support.h index 884a2f9..ba004f1 100644 --- a/support.h +++ b/support.h @@ -3,6 +3,7 @@ #include "support/minimig/minimig_boot.h" #include "support/minimig/minimig_fdd.h" #include "support/minimig/minimig_hdd.h" +#include "support/minimig/minimig_share.h" // SharpMz support #include "support/sharpmz/sharpmz.h" diff --git a/support/minimig/miminig_fs_messages.h b/support/minimig/miminig_fs_messages.h new file mode 100644 index 0000000..d65f906 --- /dev/null +++ b/support/minimig/miminig_fs_messages.h @@ -0,0 +1,378 @@ +#define ACTION_NIL 0 +#define ACTION_GET_BLOCK 2 +#define ACTION_SET_MAP 4 +#define ACTION_DIE 5 +#define ACTION_EVENT 6 +#define ACTION_CURRENT_VOLUME 7 +#define ACTION_LOCATE_OBJECT 8 +#define ACTION_RENAME_DISK 9 +#define ACTION_WRITE 'W' +#define ACTION_READ 'R' +#define ACTION_FREE_LOCK 15 +#define ACTION_DELETE_OBJECT 16 +#define ACTION_RENAME_OBJECT 17 +#define ACTION_MORE_CACHE 18 +#define ACTION_COPY_LOCK 19 +#define ACTION_WAIT_CHAR 20 +#define ACTION_SET_PROTECT 21 +#define ACTION_CREATE_DIR 22 +#define ACTION_EXAMINE_OBJECT 23 +#define ACTION_EXAMINE_NEXT 24 +#define ACTION_DISK_INFO 25 +#define ACTION_INFO 26 +#define ACTION_FLUSH 27 +#define ACTION_SET_COMMENT 28 +#define ACTION_PARENT 29 +#define ACTION_TIMER 30 +#define ACTION_INHIBIT 31 +#define ACTION_DISK_TYPE 32 +#define ACTION_DISK_CHANGE 33 +#define ACTION_SET_DATE 34 +#define ACTION_SCREEN_MODE 994 +#define ACTION_READ_RETURN 1001 +#define ACTION_WRITE_RETURN 1002 +#define ACTION_FINDUPDATE 1004 +#define ACTION_FINDINPUT 1005 +#define ACTION_FINDOUTPUT 1006 +#define ACTION_END 1007 +#define ACTION_SEEK 1008 +#define ACTION_TRUNCATE 1022 +#define ACTION_WRITE_PROTECT 1023 + +#define ERROR_NO_FREE_STORE 103 +#define ERROR_TASK_TABLE_FULL 105 +#define ERROR_LINE_TOO_LONG 120 +#define ERROR_FILE_NOT_OBJECT 121 +#define ERROR_INVALID_RESIDENT_LIBRARY 122 +#define ERROR_NO_DEFAULT_DIR 201 +#define ERROR_OBJECT_IN_USE 202 +#define ERROR_OBJECT_EXISTS 203 +#define ERROR_DIR_NOT_FOUND 204 +#define ERROR_OBJECT_NOT_FOUND 205 +#define ERROR_BAD_STREAM_NAME 206 +#define ERROR_OBJECT_TOO_LARGE 207 +#define ERROR_ACTION_NOT_KNOWN 209 +#define ERROR_INVALID_COMPONENT_NAME 210 +#define ERROR_INVALID_LOCK 211 +#define ERROR_OBJECT_WRONG_TYPE 212 +#define ERROR_DISK_NOT_VALIDATED 213 +#define ERROR_DISK_WRITE_PROTECTED 214 +#define ERROR_RENAME_ACROSS_DEVICES 215 +#define ERROR_DIRECTORY_NOT_EMPTY 216 +#define ERROR_TOO_MANY_LEVELS 217 +#define ERROR_DEVICE_NOT_MOUNTED 218 +#define ERROR_SEEK_ERROR 219 +#define ERROR_COMMENT_TOO_BIG 220 +#define ERROR_DISK_FULL 221 +#define ERROR_DELETE_PROTECTED 222 +#define ERROR_WRITE_PROTECTED 223 +#define ERROR_READ_PROTECTED 224 +#define ERROR_NOT_A_DOS_DISK 225 +#define ERROR_NO_DISK 226 +#define ERROR_NO_MORE_ENTRIES 232 + +#define SHARED_LOCK -2 +#define EXCLUSIVE_LOCK -1 + +#define MODE_OLDFILE 1005 +#define MODE_NEWFILE 1006 +#define MODE_READWRITE 1004 + +#define OFFSET_BEGINNING -1 +#define OFFSET_CURRENT 0 +#define OFFSET_END 1 + +#define ST_ROOT 1 +#define ST_USERDIR 2 +#define ST_SOFTLINK 3 +#define ST_LINKDIR 4 +#define ST_FILE -3 +#define ST_LINKFILE -4 +#define ST_PIPEFILE -5 + +#pragma pack(push, 1) + +struct GenericRequestResponse +{ + long sz; + union + { + struct + { + long type; + long key; + }; + + struct + { + long success; + long error_code; + }; + }; +}; + +struct LocateObjectRequest +{ + long sz; + long type; + long key; + long mode; + char name[1]; +}; + +struct LocateObjectResponse +{ + long sz; + long success; + long error_code; + long key; +}; + +struct FreeLockRequest +{ + long sz; + long type; + long key; +}; + +struct FreeLockResponse +{ + long sz; + long success; + long error_code; +}; + +struct CopyDirRequest +{ + long sz; + long type; + long key; +}; + +struct CopyDirResponse +{ + long sz; + long success; + long error_code; + long key; +}; + +struct ParentRequest +{ + long sz; + long type; + long key; +}; + +struct ParentResponse +{ + long sz; + long success; + long error_code; + long key; +}; + +struct ExamineObjectRequest +{ + long sz; + long type; + long key; + long disk_key; +}; + +struct ExamineObjectResponse +{ + long sz; + long success; + long error_code; + + long disk_key; + long entry_type; + int size; + int protection; + int date[3]; + char file_name[1]; +}; + +struct FindXxxRequest +{ + long sz; + long type; + long key; + char name[1]; +}; + +struct FindXxxResponse +{ + long sz; + long success; + long error_code; + long arg1; +}; + +struct ReadRequest +{ + long sz; + long type; + long arg1; + int address; + int length; +}; + +struct ReadResponse +{ + long sz; + long success; + long error_code; + int actual; +}; + +struct WriteRequest +{ + long sz; + long type; + long arg1; + int address; + int length; +}; + +struct WriteResponse +{ + long sz; + long success; + long error_code; + int actual; +}; + +struct SeekRequest +{ + long sz; + long type; + long arg1; + int new_pos; + int mode; +}; + +struct SeekResponse +{ + long sz; + long success; + long error_code; + int old_pos; +}; + +struct EndRequest +{ + long sz; + long type; + long arg1; +}; + +struct EndResponse +{ + long sz; + long success; + long error_code; +}; + +struct DeleteObjectRequest +{ + long sz; + long type; + long key; + char name[1]; +}; + +struct DeleteObjectResponse +{ + long sz; + long success; + long error_code; +}; + +struct RenameObjectRequest +{ + long sz; + long type; + long key; + long target_dir; + unsigned char name_len; + unsigned char new_name_len; + char name[1]; +}; + +struct RenameObjectResponse +{ + long sz; + long success; + long error_code; +}; + +struct CreateDirRequest +{ + long sz; + long type; + long key; + char name[1]; +}; + +struct CreateDirResponse +{ + long sz; + long success; + long error_code; + long key; +}; + +struct SetProtectRequest +{ + long sz; + long type; + long key; + long mask; + char name[1]; +}; + +struct SetProtectResponse +{ + long sz; + long success; + long error_code; +}; + +struct SetCommentRequest +{ + long sz; + long type; + long key; + unsigned char name_len; + unsigned char comment_len; +}; + +struct SetCommentResponse +{ + long sz; + long success; + long error_code; +}; + +struct DiskInfoRequest +{ + long sz; + long type; + long key; + long dummy1; + long dummy2; +}; + +struct DiskInfoResponse +{ + long sz; + long success; + long error_code; + unsigned long total; + unsigned long used; + long update; +}; + +#pragma pack(pop) diff --git a/support/minimig/minimig_config.cpp b/support/minimig/minimig_config.cpp index 37176ea..1278e9b 100644 --- a/support/minimig/minimig_config.cpp +++ b/support/minimig/minimig_config.cpp @@ -15,6 +15,7 @@ #include "minimig_fdd.h" #include "minimig_hdd.h" #include "minimig_config.h" +#include "minimig_share.h" const char *config_memory_chip_msg[] = { "512K", "1M", "1.5M", "2M" }; const char *config_memory_slow_msg[] = { "none", "512K", "1M", "1.5M" }; @@ -502,6 +503,7 @@ void minimig_reset() { ApplyConfiguration(0); user_io_rtc_reset(); + minimig_share_reset(); } void minimig_set_kickstart(char *name) diff --git a/support/minimig/minimig_share.cpp b/support/minimig/minimig_share.cpp new file mode 100644 index 0000000..86ea73f --- /dev/null +++ b/support/minimig/minimig_share.cpp @@ -0,0 +1,751 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "../../hardware.h" +#include "../../file_io.h" +#include "../../user_io.h" +#include "../../spi.h" +#include "miminig_fs_messages.h" + +#define SHMEM_ADDR 0x27FF4000 +#define SHMEM_SIZE 0x2000 +static uint8_t *shmem = 0; + +#define REQUEST_FLG 0 // 4B +#define REQUEST_BUFFER 4 // ~512B +#define DATA_BUFFER 0x1000 // 4KB + +//#define DEBUG + +#ifdef DEBUG + #define dbg_print printf + #define dbg_hexdump hexdump +#else + #define dbg_print(x,...) void() + #define dbg_hexdump(x,...) void() +#endif + +#define SWAP_INT(a) ((((a)&0x000000ff)<<24)|(((a)&0x0000ff00)<<8)|(((a)&0x00ff0000)>>8)|(((a)&0xff000000)>>24)) + +static char basepath[1024] = {}; +static int baselen = 0; + +struct lock +{ + uint16_t mode; + std::string path; + std::vector dir_items; +}; + +static std::map locks; +static uint32_t next_key = 1; + +static uint32_t get_key() +{ + uint32_t key; + + do + { + key = next_key; + if (next_key == INT32_MAX) next_key = 1; else next_key++; + + } while (locks.find(key) != locks.end()); + + return key; +} + +static uint32_t add_lock(uint16_t mode, const char* path) +{ + uint32_t key = get_key(); + locks[key] = { mode, path, {} }; + + dbg_print("+ add lock: %d, %s\n", key, path); + return key; +} + +static int has_locks(const char* path) +{ + int has = 0; + for (const auto &pair : locks) + { + if (pair.second.path == path) + { + if (!has) + { + dbg_print("! path %s has locks:", path); + } + + has = 1; + dbg_print(" %d", pair.first); + } + } + + if (has) + { + dbg_print("\n"); + } + return has; +} + +static std::map open_file_handles; +static uint32_t next_fp = 1; + +static uint32_t get_fp() +{ + uint32_t fp; + + do + { + fp = next_fp; + if (next_fp == INT32_MAX) next_fp = 1; else next_fp++; + + } while (open_file_handles.find(fp) != open_file_handles.end()); + + return fp; +} + +static char* find_path(uint32_t key, const char *name) +{ + dbg_print("find_path(%d, %s)\n", key, name); + + static char str[1024] = {}; + const char* p = strchr(name, ':'); + if (p) + { + key = 0; + name = p + 1; + } + + strcpy(str, basepath); + if (key) + { + auto it = locks.find(key); + if (it != locks.end()) strcpy(str, it->second.path.c_str()); + } + + if (PathIsDir(str)) + { + if (strlen(name)) + { + strcat(str, "/"); + strcat(str, name); + + dbg_print("check path: %s\n", str); + char *p = strrchr(str, '/'); + if (!p) str[0] = 0; + else + { + *p = 0; + if (!PathIsDir(str)) str[0] = 0; + else *p = '/'; + } + } + } + else + { + str[0] = 0; + } + + dbg_print("returned path: %s\n", str); + return str; +} + +static int process_request(void *reqres_buffer) +{ + static char buf[1024]; + GenericRequestResponse *reqres = ( GenericRequestResponse *)reqres_buffer; + + int rtype = SWAP_INT(reqres->type); + int ret = ERROR_ACTION_NOT_KNOWN; + + int sz = SWAP_INT(reqres->sz); + ((uint8_t*)reqres_buffer)[sz] = 0; + + int sz_res = sizeof(GenericRequestResponse); + + dbg_print("request type: %d, struct size: %d\n", rtype, sz); + dbg_hexdump(reqres_buffer, sz, 0); + + if (!baselen) + { + strcpy(basepath, HomeDir()); + strcat(basepath, "/shared"); + baselen = strlen(basepath); + FileCreatePath(basepath); + } + + switch (rtype) + { + case ACTION_LOCATE_OBJECT: + { + dbg_print("> ACTION_LOCATE_OBJECT\n"); + LocateObjectRequest *req = (LocateObjectRequest*)reqres_buffer; + LocateObjectResponse *res = (LocateObjectResponse*)reqres_buffer; + sz_res = sizeof(LocateObjectResponse); + + char *str = find_path(SWAP_INT(req->key), req->name + 1); + if (!str[0]) + { + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + if (!FileExists(str) && !PathIsDir(str)) + { + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + uint32_t key = add_lock(req->mode, str); + res->key = SWAP_INT(key); + ret = 0; + } + break; + + case ACTION_FREE_LOCK: + { + dbg_print("> ACTION_FREE_LOCK\n"); + FreeLockRequest *req = (FreeLockRequest*)reqres_buffer; + + uint32_t key = SWAP_INT(req->key); + locks.erase(key); + dbg_print(" lock: %d\n", key); + + ret = 0; + } + break; + + case ACTION_COPY_LOCK: + { + dbg_print("> ACTION_COPY_LOCK\n"); + CopyDirRequest *req = (CopyDirRequest*)reqres_buffer; + CopyDirResponse *res = (CopyDirResponse*)reqres_buffer; + sz_res = sizeof(CopyDirResponse); + + uint32_t key = SWAP_INT(req->key); + if (locks.find(key) == locks.end()) + { + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + uint32_t new_key = add_lock(locks[key].mode, locks[key].path.c_str()); + dbg_print("CopyDir: %s: %d -> %d\n", locks[new_key].path.c_str(), key, new_key); + + res->key = SWAP_INT(new_key); + ret = 0; + } + break; + + case ACTION_PARENT: + { + dbg_print("> ACTION_PARENT\n"); + ParentRequest *req = (ParentRequest*)reqres_buffer; + ParentResponse *res = (ParentResponse*)reqres_buffer; + sz_res = sizeof(ParentResponse); + + uint32_t key = SWAP_INT(req->key); + dbg_print(" current key: %d\n", key); + + if (locks.find(key) == locks.end()) + { + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + ret = 0; + res->key = 0; + + char *name = buf; + strcpy(name, locks[key].path.c_str()); + dbg_print(" current path: %s\n", name); + + if (!strncasecmp(basepath, name, baselen)) name += baselen; + + if (strlen(name)) + { + char* p = strrchr(name, '/'); + if (p) + { + *p = 0; + uint32_t key = add_lock(SHARED_LOCK, buf); + res->key = SWAP_INT(key); + dbg_print(" parent path: %s\n", buf); + dbg_print(" parent path: %s\n", buf); + } + } + } + break; + + case ACTION_EXAMINE_NEXT: + case ACTION_EXAMINE_OBJECT: + { + dbg_print("> ACTION_EXAMINE\n"); + ExamineObjectRequest *req = (ExamineObjectRequest*)reqres_buffer; + ExamineObjectResponse *res = (ExamineObjectResponse*)reqres_buffer; + sz_res = sizeof(ExamineObjectResponse); + + uint32_t key = SWAP_INT(req->key); + dbg_print(" key: %d\n", key); + + char *name = buf; + name[0] = 0; + if (locks.find(key) != locks.end()) strcpy(name, locks[key].path.c_str()); + if (!strlen(name)) strcpy(name, basepath); + + int disk_key = 666; + static char fn[256]; + if (rtype == ACTION_EXAMINE_OBJECT) + { + dbg_print(" examine first\n"); + + if (!strlen(name + baselen)) strcpy(fn, "MiSTer"); + else + { + const char *p = strrchr(name, '/'); + strcpy(fn, p ? p + 1 : name); + } + + locks[key].dir_items.clear(); + if (PathIsDir(name)) + { + const char* full_path = getFullPath(name); + DIR *d = opendir(full_path); + if (!d) + { + printf("Couldn't open dir: %s\n", full_path); + ret = ERROR_OBJECT_WRONG_TYPE; + break; + } + + struct dirent64 *de; + while ((de = readdir64(d))) + { + if (!strcmp(de->d_name, "..") || !strcmp(de->d_name, ".")) continue; + locks[key].dir_items.push_back(*de); + } + closedir(d); + } + } + else + { + dbg_print(" examine next\n"); + + disk_key = SWAP_INT(req->disk_key); + + uint32_t listed = disk_key - 666; + disk_key++; + + if (listed >= locks[key].dir_items.size()) + { + locks[key].dir_items.clear(); + ret = ERROR_NO_MORE_ENTRIES; + break; + } + + strcat(name, "/"); + strcat(name, locks[key].dir_items[listed].d_name); + memcpy(fn, locks[key].dir_items[listed].d_name, sizeof(fn)); + ret = 0; + } + + dbg_print(" name: %s\n", name); + dbg_print(" fn: %s\n", fn); + + int type = 0; + if (FileExists(name)) type = ST_FILE; + else if (PathIsDir(name)) type = ST_USERDIR; + else + { + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + time_t time = 0; + uint32_t size = 0; + + struct stat64 *st = getPathStat(name); + if (st) + { + time = st->st_mtime; + if (type == ST_FILE) + { + if (st->st_size > UINT32_MAX) size = UINT32_MAX; + else size = (uint32_t)st->st_size; + } + } + + time_t days = time / 86400; + time_t left = time - (days * 86400); + time_t mins = left / 60; + time_t secs = left - (mins * 60); + time_t ticks = secs * 50; + days -= 2922; // Days between 1970 - 01 - 01 and 1978 - 01 - 01 + if (days < 0) days = 0; + + res->disk_key = SWAP_INT(disk_key); + res->entry_type = SWAP_INT(type); + res->size = SWAP_INT(size); + res->protection = 0; + res->date[0] = SWAP_INT(days); + res->date[1] = SWAP_INT(mins); + res->date[2] = SWAP_INT(ticks); + + res->file_name[0] = strlen(fn); + strcpy(res->file_name + 1, fn); + + sz_res = sizeof(ExamineObjectResponse) + strlen(fn); + ret = 0; + } + break; + + case ACTION_FINDINPUT: // MODE_OLDFILE + case ACTION_FINDOUTPUT: // MODE_NEWFILE + case ACTION_FINDUPDATE: // MODE_READWRITE + { + dbg_print("> ACTION_FIND\n"); + FindXxxRequest *req = (FindXxxRequest*)reqres_buffer; + FindXxxResponse *res = (FindXxxResponse*)reqres_buffer; + sz_res = sizeof(FindXxxResponse); + + char *name = find_path(SWAP_INT(req->key), req->name + 1); + + if (!name[0]) + { + ret = ERROR_DIR_NOT_FOUND; + break; + } + + if (PathIsDir(name)) + { + ret = ERROR_OBJECT_WRONG_TYPE; + break; + } + + uint32_t key = get_fp(); + open_file_handles[key] = {}; + + int mode = O_RDWR; + + if (rtype == MODE_NEWFILE) mode = O_RDWR | O_CREAT | O_TRUNC; + if (rtype == MODE_READWRITE) mode = O_RDWR | O_CREAT; + + ret = FileOpenEx(&open_file_handles[key], name, mode); + if (!ret) + { + open_file_handles.erase(key); + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + res->arg1 = SWAP_INT(key); + ret = 0; + } + break; + + case ACTION_READ: + { + dbg_print("> ACTION_READ\n"); + ReadRequest *req = (ReadRequest*)reqres_buffer; + ReadResponse *res = (ReadResponse*)reqres_buffer; + sz_res = sizeof(ReadResponse); + + uint32_t key = SWAP_INT(req->arg1); + if (open_file_handles.find(key) == open_file_handles.end()) + { + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + uint32_t length = SWAP_INT(req->length); + length = FileReadAdv(&open_file_handles[key], shmem + DATA_BUFFER, length); + + res->actual = SWAP_INT(length); + ret = 0; + } + break; + + case ACTION_WRITE: + { + dbg_print("> ACTION_WRITE\n"); + WriteRequest *req = (WriteRequest*)reqres_buffer; + WriteResponse *res = (WriteResponse*)reqres_buffer; + sz_res = sizeof(WriteResponse); + + uint32_t key = SWAP_INT(req->arg1); + if (open_file_handles.find(key) == open_file_handles.end()) + { + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + uint32_t length = SWAP_INT(req->length); + length = FileWriteAdv(&open_file_handles[key], shmem + DATA_BUFFER, length); + + res->actual = SWAP_INT(length); + ret = 0; + } + break; + + case ACTION_SEEK: + { + dbg_print("> ACTION_SEEK\n"); + SeekRequest *req = (SeekRequest*)reqres_buffer; + SeekResponse *res = (SeekResponse*)reqres_buffer; + sz_res = sizeof(SeekResponse); + + uint32_t key = SWAP_INT(req->arg1); + if (open_file_handles.find(key) == open_file_handles.end()) + { + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + uint32_t old_pos = open_file_handles[key].offset; + + uint32_t new_pos = SWAP_INT(req->new_pos); + uint32_t mode = SWAP_INT(req->mode); + + int origin = SEEK_SET; + if (mode == OFFSET_CURRENT) origin = SEEK_CUR; + if (mode == OFFSET_END) origin = SEEK_END; + + ret = FileSeek(&open_file_handles[key], new_pos, origin); + + dbg_print(" mode: %d\n", mode); + dbg_print(" old_pos: %d\n", old_pos); + dbg_print(" new_pos: %d\n", new_pos); + + if (!ret) + { + ret = ERROR_SEEK_ERROR; + break; + } + + res->old_pos = SWAP_INT(old_pos); + ret = 0; + } + break; + + case ACTION_END: + { + dbg_print("> ACTION_END\n"); + EndRequest *req = (EndRequest*)reqres_buffer; + uint32_t key = SWAP_INT(req->arg1); + + if (open_file_handles.find(key) != open_file_handles.end()) + { + FileClose(&open_file_handles[key]); + open_file_handles.erase(key); + } + + ret = 0; + } + break; + + case ACTION_DELETE_OBJECT: + { + dbg_print("> ACTION_DELETE_OBJECT\n"); + DeleteObjectRequest *req = (DeleteObjectRequest*)reqres_buffer; + + char *name = find_path(SWAP_INT(req->key), req->name + 1); + if (name[0]) + { + if (has_locks(name)) + { + ret = ERROR_OBJECT_IN_USE; + break; + } + + if (PathIsDir(name)) + { + ret = DirDelete(name) ? 0 : ERROR_DIRECTORY_NOT_EMPTY; + break; + } + + if (FileExists(name)) + { + ret = FileDelete(name) ? 0 : ERROR_OBJECT_NOT_FOUND; + break; + } + } + + ret = ERROR_OBJECT_NOT_FOUND; + } + break; + + case ACTION_RENAME_OBJECT: + { + dbg_print("> ACTION_RENAME_OBJECT\n"); + RenameObjectRequest *req = (RenameObjectRequest*)reqres_buffer; + + strncpy(buf, req->name, req->name_len); + buf[req->name_len] = 0; + + uint32_t key = SWAP_INT(req->key); + char *cp1 = find_path(key, buf); + if (!cp1[0]) + { + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + if (!FileExists(cp1) && !PathIsDir(cp1)) + { + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + strcpy(buf, cp1); + key = SWAP_INT(req->target_dir); + char *cp2 = find_path(key, req->name + req->name_len); + if (!cp2[0]) + { + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + if (FileExists(cp2) || PathIsDir(cp2)) + { + ret = ERROR_OBJECT_EXISTS; + break; + } + + strcpy(buf, getFullPath(buf)); + if (rename(buf, getFullPath(cp2))) + { + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + ret = 0; + } + break; + + case ACTION_CREATE_DIR: + { + dbg_print("> ACTION_CREATE_DIR\n"); + CreateDirRequest *req = (CreateDirRequest*)reqres_buffer; + CreateDirResponse *res = (CreateDirResponse*)reqres_buffer; + sz_res = sizeof(CreateDirResponse); + + char *name = find_path(SWAP_INT(req->key), req->name + 1); + if (!FileCreatePath(name)) + { + ret = ERROR_OBJECT_NOT_FOUND; + break; + } + + uint32_t key = add_lock(SHARED_LOCK, name); + res->key = SWAP_INT(key); + + ret = 0; + } + break; + + case ACTION_DISK_INFO: + case ACTION_INFO: + { + dbg_print("> ACTION_INFO\n"); + DiskInfoResponse *res = (DiskInfoResponse*)reqres_buffer; + sz_res = sizeof(DiskInfoResponse); + + uint32_t total = 10; + uint32_t used = 1; + + struct statvfs st; + if (!statvfs(getFullPath(basepath), &st)) + { + uint64_t sz = st.f_bsize * st.f_blocks; + uint64_t avail = st.f_bsize * st.f_bavail; + + total = sz / 512; + used = (sz - avail) / 512; + } + + res->total = SWAP_INT(total); + res->used = SWAP_INT(used); + ret = 0; + } + break; + + case ACTION_SET_PROTECT: + { + dbg_print("> ACTION_SET_PROTECT unimplemented\n"); + ret = 0; + } + break; + + case ACTION_SET_COMMENT: + { + dbg_print("> ACTION_SET_COMMENT unimplemented\n"); + ret = 0; + } + break; + } + + int success = ret ? 0 : 1; + reqres->success = SWAP_INT(success); + reqres->error_code = SWAP_INT(ret); + + dbg_print("error: %d\n", ret); + dbg_hexdump(shmem + REQUEST_BUFFER, sz_res, 0); + dbg_print("\n"); + + return sz_res; +} + +static void share_init() +{ + int fd; + if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) return; + + shmem = (uint8_t*)mmap(0, SHMEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, SHMEM_ADDR); + close(fd); + + if (shmem == (uint8_t *)-1) printf("minimig_setup_shmem: Unable to mmap(/dev/mem)\n"); + return; +} + +void minimig_share_poll() +{ + if (!shmem) + { + share_init(); + } + else if(shmem != (uint8_t *)-1) + { + static uint32_t old_req_id = 0; + uint32_t req_id = *(uint32_t*)(shmem + REQUEST_FLG); + + if ((uint16_t)old_req_id != (uint16_t)req_id) + { + dbg_print("new req: %08X\n", req_id); + old_req_id = req_id; + if (((req_id>>16) & 0xFFFF) == 0x5AA5 && ((req_id - 77) & 0xFF) == ((req_id >> 8) & 0xFF)) + { + process_request(shmem + REQUEST_BUFFER); + *(uint16_t*)(shmem + REQUEST_FLG + 2) = (uint16_t)req_id; + } + } + } +} + +void minimig_share_reset() +{ + open_file_handles.clear(); + locks.clear(); + next_fp = 1; + next_key = 1; +} diff --git a/support/minimig/minimig_share.h b/support/minimig/minimig_share.h new file mode 100644 index 0000000..b28d55a --- /dev/null +++ b/support/minimig/minimig_share.h @@ -0,0 +1,10 @@ + +#ifndef __MINIMIG_SHARE_H__ +#define __MINIMIG_SHARE_H__ + +#include + +void minimig_share_poll(); +void minimig_share_reset(); + +#endif diff --git a/user_io.cpp b/user_io.cpp index 020022f..4da7430 100644 --- a/user_io.cpp +++ b/user_io.cpp @@ -2165,13 +2165,14 @@ void user_io_poll() } } - if (!rtc_timer || CheckTimer(rtc_timer)) { // Update once per minute should be enough rtc_timer = GetTimer(60000); send_rtc(1); } + + minimig_share_poll(); } if (core_type == CORE_TYPE_8BIT && !is_menu())