diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h index 4456a0bbf455ade1e3f72ca16f7f28e0daef8d80..e7638d94bea9193bdb7153e1aa23273611e40f78 100644 --- a/epicardium/epicardium.h +++ b/epicardium/epicardium.h @@ -56,6 +56,7 @@ typedef unsigned int size_t; #define API_FILE_FLUSH 0x35 #define API_FILE_SEEK 0x36 //NYI #define API_FILE_TELL 0x37 //NYI +#define API_FILE_STAT 0x38 /* clang-format on */ typedef uint32_t api_int_id_t; @@ -463,4 +464,29 @@ API(API_FILE_READ, int32_t epic_read(int32_t fd, void* buf, uint32_t nbytes)); API(API_FILE_WRITE, int32_t epic_write(int32_t fd, const void* buf, uint32_t nbytes)); API(API_FILE_FLUSH, int32_t epic_flush(int32_t fd)); +enum epic_stat_type { + EPICSTAT_FILE, + EPICSTAT_DIR, +}; + +typedef struct epic_stat_t { + enum epic_stat_type type; +} epic_stat_t; + +/** + * stat path + * + * This does not follow posix convention, but rather takes + * a path as parameter. This aligns more with libff's API and + * also this has been implemented for python import support, which + * passes the filename as well. + * + * :param const char* filename: path to stat + * :param epic_stat_t* stat: pointer to result + * + * :return: `0` on success, negative on error + * if an error occured. + */ +API(API_FILE_STAT, int32_t epic_stat(const char* path, epic_stat_t* stat)); + #endif /* _EPICARDIUM_H */ diff --git a/epicardium/modules/fatfs.c b/epicardium/modules/fatfs.c index 84622d264287b872b793ca432b6c8e63a2f94755..254f9a0a4fb459bd858ecec8c0cee51935919671 100644 --- a/epicardium/modules/fatfs.c +++ b/epicardium/modules/fatfs.c @@ -14,6 +14,7 @@ #include <semphr.h> #include "modules.h" +#include "epicardium.h" #ifndef EPIC_FAT_STATIC_SEMAPHORE #define EPIC_FAT_STATIC_SEMAPHORE 0 @@ -326,3 +327,21 @@ int32_t epic_flush(int32_t fd) { return 0; } +int32_t epic_stat(const char* filename, epic_stat_t* stat) { + + int res; + FILINFO finfo; + res = f_stat(filename, &finfo); + if (res != FR_OK) { + return -fresult_to_errno_table[res]; + } + + if(finfo.fattrib & AM_DIR) { + stat->type = EPICSTAT_DIR; + } else { + stat->type = EPICSTAT_FILE; + } + + return 0; +} + diff --git a/pycardium/meson.build b/pycardium/meson.build index 453fc752e9c4bbe403b117c65d1c4cf992faded1..42fa849d1da7d63cae02f260495f61dd9875eec3 100644 --- a/pycardium/meson.build +++ b/pycardium/meson.build @@ -6,8 +6,9 @@ modsrc = files( 'modules/sys_display.c', 'modules/utime.c', 'modules/vibra.c', - 'modules/light_sensor.c' + 'modules/light_sensor.c', 'modules/fat_file.c', + 'modules/fat_reader_import.c', ) ################################# diff --git a/pycardium/modules/fat_file.c b/pycardium/modules/fat_file.c index 711217b4dfd0ace444d08ab6a6f03d5676fcc5d5..70f019950915a24e84ae2b19092be1a057e9abf6 100644 --- a/pycardium/modules/fat_file.c +++ b/pycardium/modules/fat_file.c @@ -31,6 +31,7 @@ #include "py/builtin.h" #include "py/stream.h" #include "py/mperrno.h" + #include "epicardium.h" extern const mp_obj_type_t mp_type_fat_textio; @@ -271,3 +272,4 @@ mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) return file_open(&mp_type_fat_textio, arg_vals); } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); + diff --git a/pycardium/modules/fat_reader_import.c b/pycardium/modules/fat_reader_import.c new file mode 100644 index 0000000000000000000000000000000000000000..a035754e761f8ff29e8db19baf2fa1cd9e1769a9 --- /dev/null +++ b/pycardium/modules/fat_reader_import.c @@ -0,0 +1,79 @@ +#include "epicardium.h" + +#include <py/runtime.h> +#include <py/reader.h> +#include <py/lexer.h> + +/** ported from picropython's posic implementation */ + +typedef struct _mp_reader_epicfat_t { + bool close_fd; + int fd; + size_t len; + size_t pos; + byte buf[20]; +} mp_reader_epicfat_t; + +STATIC mp_uint_t mp_reader_epicfat_readbyte(void *data) { + mp_reader_epicfat_t *reader = (mp_reader_epicfat_t*)data; + if (reader->pos >= reader->len) { + if (reader->len == 0) { + return MP_READER_EOF; + } else { + int n = epic_read(reader->fd, reader->buf, sizeof(reader->buf)); + if (n <= 0) { + reader->len = 0; + return MP_READER_EOF; + } + reader->len = n; + reader->pos = 0; + } + } + return reader->buf[reader->pos++]; +} + +STATIC void mp_reader_epicfat_close(void *data) { + mp_reader_epicfat_t *reader = (mp_reader_epicfat_t*)data; + epic_close(reader->fd); + m_del_obj(mp_reader_epicfat_t, reader); +} + +void mp_reader_new_file(mp_reader_t* reader, const char *filename) +{ + int fd = epic_open(filename, "r"); + if (fd < 0) { + mp_raise_OSError(-fd); + } + mp_reader_epicfat_t *rp = m_new_obj(mp_reader_epicfat_t); + rp->fd = fd; + int n = epic_read(rp->fd, rp->buf, sizeof(rp->buf)); + if (n < 0) { + epic_close(fd); + } + rp->len = n; + rp->pos = 0; + reader->data = rp; + reader->readbyte = mp_reader_epicfat_readbyte; + reader->close = mp_reader_epicfat_close; +} + +mp_lexer_t *mp_lexer_new_from_file(const char *filename) +{ + mp_reader_t reader; + mp_reader_new_file(&reader, filename); + return mp_lexer_new(qstr_from_str(filename), reader); +} + +mp_import_stat_t mp_import_stat(const char *path) +{ + struct epic_stat_t stat; + + if(epic_stat(path, &stat) == 0) { + if (stat.type == EPICSTAT_FILE) { + return MP_IMPORT_STAT_FILE; + } else { + return MP_IMPORT_STAT_DIR; + } + } + return MP_IMPORT_STAT_NO_EXIST; +} diff --git a/pycardium/mphalport.c b/pycardium/mphalport.c index 7c14df44e3ef09bbc6972b1a442cae8240fe7b36..29784be54638f22eeac9215697eb11f7fd19dd93 100644 --- a/pycardium/mphalport.c +++ b/pycardium/mphalport.c @@ -121,14 +121,3 @@ void NORETURN nlr_jump_fail(void *val) * Stubs */ -mp_lexer_t *mp_lexer_new_from_file(const char *filename) -{ - /* TODO: Do we need an implementation for this? */ - mp_raise_OSError(MP_ENOENT); -} - -mp_import_stat_t mp_import_stat(const char *path) -{ - return MP_IMPORT_STAT_NO_EXIST; -} -