mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
esp/vfs: VFS semihosting interface support
This commit is contained in:
parent
b0fa5c7c2d
commit
f6248ebf0d
@ -31,27 +31,27 @@ extern "C" {
|
||||
* these are not supported in ESP-IDF yet.
|
||||
*/
|
||||
|
||||
#define SEMIHOSTING_SYS_CLOCK 0x10
|
||||
#define SEMIHOSTING_SYS_CLOSE 0x02
|
||||
#define SEMIHOSTING_SYS_ERRNO 0x13
|
||||
#define SEMIHOSTING_SYS_EXIT 0x18
|
||||
#define SEMIHOSTING_SYS_EXIT_EXTENDED 0x20
|
||||
#define SEMIHOSTING_SYS_FLEN 0x0C
|
||||
#define SEMIHOSTING_SYS_GET_CMDLINE 0x15
|
||||
#define SEMIHOSTING_SYS_HEAPINFO 0x16
|
||||
#define SEMIHOSTING_SYS_ISERROR 0x08
|
||||
#define SEMIHOSTING_SYS_ISTTY 0x09
|
||||
#define SEMIHOSTING_SYS_OPEN 0x01
|
||||
#define SEMIHOSTING_SYS_READ 0x06
|
||||
#define SEMIHOSTING_SYS_READC 0x07
|
||||
#define SEMIHOSTING_SYS_REMOVE 0x0E
|
||||
#define SEMIHOSTING_SYS_RENAME 0x0F
|
||||
#define SEMIHOSTING_SYS_SEEK 0x0A
|
||||
#define SEMIHOSTING_SYS_SYSTEM 0x12
|
||||
#define SEMIHOSTING_SYS_TIME 0x11
|
||||
#define SEMIHOSTING_SYS_WRITE 0x05
|
||||
#define SEMIHOSTING_SYS_WRITEC 0x03
|
||||
#define SEMIHOSTING_SYS_WRITE0 0x04
|
||||
#define SEMIHOSTING_SYS_OPEN 0x01
|
||||
#define SEMIHOSTING_SYS_CLOSE 0x02
|
||||
#define SEMIHOSTING_SYS_WRITEC 0x03
|
||||
#define SEMIHOSTING_SYS_WRITE0 0x04
|
||||
#define SEMIHOSTING_SYS_WRITE 0x05
|
||||
#define SEMIHOSTING_SYS_READ 0x06
|
||||
#define SEMIHOSTING_SYS_READC 0x07
|
||||
#define SEMIHOSTING_SYS_ISERROR 0x08
|
||||
#define SEMIHOSTING_SYS_ISTTY 0x09
|
||||
#define SEMIHOSTING_SYS_SEEK 0x0A
|
||||
#define SEMIHOSTING_SYS_FLEN 0x0C
|
||||
#define SEMIHOSTING_SYS_REMOVE 0x0E
|
||||
#define SEMIHOSTING_SYS_RENAME 0x0F
|
||||
#define SEMIHOSTING_SYS_CLOCK 0x10
|
||||
#define SEMIHOSTING_SYS_TIME 0x11
|
||||
#define SEMIHOSTING_SYS_SYSTEM 0x12
|
||||
#define SEMIHOSTING_SYS_ERRNO 0x13
|
||||
#define SEMIHOSTING_SYS_GET_CMDLINE 0x15
|
||||
#define SEMIHOSTING_SYS_HEAPINFO 0x16
|
||||
#define SEMIHOSTING_SYS_EXIT 0x18
|
||||
#define SEMIHOSTING_SYS_EXIT_EXTENDED 0x20
|
||||
|
||||
/* This call is an Espressif OpenOCD extension to send the version
|
||||
* information to the host. This lets the host support different IDF versions,
|
||||
@ -114,7 +114,7 @@ static inline long semihosting_call(long id, long *data, int *out_errno)
|
||||
long ret = semihosting_call_noerrno(id, data);
|
||||
if (ret < 0) {
|
||||
const int semihosting_sys_errno = SEMIHOSTING_SYS_ERRNO;
|
||||
*out_errno = (int) semihosting_call_noerrno(semihosting_sys_errno, NULL);
|
||||
*out_errno = (int)semihosting_call_noerrno(semihosting_sys_errno, NULL);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -124,7 +124,7 @@ static inline int semihosting_open(const char *path, int open_mode, int mode)
|
||||
int host_errno = 0;
|
||||
long args[] = {(long) path, open_mode, strlen(path), 0};
|
||||
(void) mode; // unused in OpenOCD
|
||||
int result = (int) semihosting_call(SEMIHOSTING_SYS_OPEN, args, &host_errno);
|
||||
int result = (int)semihosting_call(SEMIHOSTING_SYS_OPEN, args, &host_errno);
|
||||
if (result < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
@ -135,7 +135,7 @@ static inline ssize_t semihosting_write(int fd, const void *data, size_t size)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {fd, (long) data, size, 0};
|
||||
ssize_t ret = (ssize_t) semihosting_call(SEMIHOSTING_SYS_WRITE, args, &host_errno);
|
||||
ssize_t ret = (ssize_t)semihosting_call(SEMIHOSTING_SYS_WRITE, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
return ret;
|
||||
@ -150,7 +150,7 @@ static inline ssize_t semihosting_read(int fd, void *data, size_t size)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {fd, (long) data, size, 0};
|
||||
ssize_t ret = (ssize_t) semihosting_call(SEMIHOSTING_SYS_READ, args, &host_errno);
|
||||
ssize_t ret = (ssize_t)semihosting_call(SEMIHOSTING_SYS_READ, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
return ret;
|
||||
@ -165,7 +165,7 @@ static inline int semihosting_close(int fd)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {fd, 0, 0, 0};
|
||||
int ret = (int) semihosting_call(SEMIHOSTING_SYS_CLOSE, args, &host_errno);
|
||||
int ret = (int)semihosting_call(SEMIHOSTING_SYS_CLOSE, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
@ -176,7 +176,7 @@ static inline off_t semihosting_seek(int fd, off_t offset, int mode)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {fd, offset, mode, 0};
|
||||
off_t ret = (off_t) semihosting_call(ESP_SEMIHOSTING_SYS_SEEK, args, &host_errno);
|
||||
off_t ret = (off_t)semihosting_call(ESP_SEMIHOSTING_SYS_SEEK, args, &host_errno);
|
||||
if (ret == -1) {
|
||||
errno = host_errno;
|
||||
}
|
||||
@ -190,11 +190,188 @@ static inline int semihosting_ver_info(void)
|
||||
int version;
|
||||
} ver_info = { SEMIHOSTING_DRV_VERSION };
|
||||
long args[] = {(long) &ver_info, sizeof(ver_info), 0, 0};
|
||||
int ret = (int) semihosting_call(ESP_SEMIHOSTING_SYS_DRV_INFO, args, &host_errno);
|
||||
int ret = (int)semihosting_call(ESP_SEMIHOSTING_SYS_DRV_INFO, args, &host_errno);
|
||||
(void) host_errno; /* errno not set by this call */
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int semihosting_fstat(int fd, struct stat *restrict statbuf)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {fd, (int)statbuf, 0, 0};
|
||||
int ret = (int)semihosting_call(ESP_SEMIHOSTING_SYS_FSTAT, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int semihosting_fsync(int fd)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {fd, 0, 0, 0};
|
||||
int ret = (int)semihosting_call(ESP_SEMIHOSTING_SYS_FSYNC, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||
static inline int semihosting_mkdir(const char *host_path, mode_t mode)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {(long)host_path, mode, strlen(host_path), 0};
|
||||
int ret = (int)semihosting_call(ESP_SEMIHOSTING_SYS_MKDIR, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int semihosting_rmdir(const char *host_path)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {(long)host_path, strlen(host_path), 0, 0};
|
||||
int ret = (int)semihosting_call(ESP_SEMIHOSTING_SYS_RMDIR, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int semihosting_access(const char *host_path, int mode)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {(long)host_path, strlen(host_path), mode, 0};
|
||||
int ret = (int)semihosting_call(ESP_SEMIHOSTING_SYS_ACCESS, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int semihosting_truncate(const char *host_path, off_t truncate_length)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {(long)host_path, strlen(host_path), truncate_length, 0};
|
||||
int ret = (int)semihosting_call(ESP_SEMIHOSTING_SYS_TRUNCATE, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int semihosting_utime(const char *host_path, const struct utimbuf *times)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {(long)host_path, strlen(host_path), times->actime, times->modtime};
|
||||
int ret = (int)semihosting_call(ESP_SEMIHOSTING_SYS_UTIME, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int semihosting_stat(const char *host_path, struct stat *restrict statbuf)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {(long)host_path, strlen(host_path), (int)statbuf, 0};
|
||||
int ret = (int)semihosting_call(ESP_SEMIHOSTING_SYS_STAT, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int semihosting_rename(const char *old_path, const char *new_path)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {(long)old_path, strlen(old_path), (long)new_path, strlen(new_path)};
|
||||
int ret = (int)semihosting_call(SEMIHOSTING_SYS_RENAME, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int semihosting_link(const char *path1, const char *path2)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {(long)path1, strlen(path1), (long)path2, strlen(path2)};
|
||||
int ret = (int)semihosting_call(ESP_SEMIHOSTING_SYS_LINK, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int semihosting_unlink(const char *path)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {(long)path, strlen(path), 0, 0};
|
||||
int ret = (int)semihosting_call(ESP_SEMIHOSTING_SYS_UNLINK, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int semihosting_opendir(const char *path, long offset)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {(long)path, strlen(path), offset, 0};
|
||||
int ret = (int)semihosting_call(ESP_SEMIHOSTING_SYS_OPENDIR, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int semihosting_readdir(int struct_dirent_ptr, long offset)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {struct_dirent_ptr, offset, 0, 0};
|
||||
int ret = (int)semihosting_call(ESP_SEMIHOSTING_SYS_READDIR, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int semihosting_closedir(long id)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {id, 0, 0, 0};
|
||||
int ret = (int)semihosting_call(ESP_SEMIHOSTING_SYS_CLOSEDIR, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline long semihosting_telldir(long id)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {id, 0, 0, 0};
|
||||
long ret = semihosting_call(ESP_SEMIHOSTING_SYS_TELLDIR, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static inline int semihosting_seekdir(long id, long offset)
|
||||
{
|
||||
int host_errno = 0;
|
||||
long args[] = {id, offset, 0, 0};
|
||||
int ret = (int)semihosting_call(ESP_SEMIHOSTING_SYS_SEEKDIR, args, &host_errno);
|
||||
if (ret < 0) {
|
||||
errno = host_errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -19,8 +19,17 @@
|
||||
#define CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS 1
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
const static char *TAG = "esp_semihost";
|
||||
|
||||
typedef struct {
|
||||
char path[256]; /*!< VFS DIR stream path */
|
||||
struct dirent e; /*!< Last open dirent */
|
||||
long id; /*!< DIR* unique id */
|
||||
} vfs_semihost_dir_t;
|
||||
|
||||
/* Additional open flags */
|
||||
|
||||
@ -98,24 +107,20 @@ static esp_err_t vfs_semihost_drvinfo(vfs_semihost_ctx_t *ctx)
|
||||
|
||||
static int vfs_semihost_open(void* ctx, const char* path, int flags, int mode)
|
||||
{
|
||||
int ret_fd = -1;
|
||||
|
||||
FAIL_IF_NO_DEBUGGER();
|
||||
|
||||
if (path == NULL) {
|
||||
errno = ENOENT;
|
||||
return ret_fd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s: '%s 0x%x 0x%x'", __func__, path, flags, mode);
|
||||
|
||||
int o_mode = get_o_mode(flags);
|
||||
if (o_mode == -1) { /* if wrong flags - error */
|
||||
errno = EINVAL;
|
||||
} else {
|
||||
ret_fd = semihosting_open(path, o_mode, mode);
|
||||
return -1;
|
||||
}
|
||||
return ret_fd;
|
||||
return semihosting_open(path, o_mode, mode);
|
||||
}
|
||||
|
||||
static ssize_t vfs_semihost_write(void* ctx, int fd, const void * data, size_t size)
|
||||
@ -159,6 +164,261 @@ static off_t vfs_semihost_lseek(void* ctx, int fd, off_t offset, int mode)
|
||||
return semihosting_seek(fd, offset, mode);
|
||||
}
|
||||
|
||||
static int vfs_semihost_fstat(void* ctx, int fd, struct stat *restrict statbuf)
|
||||
{
|
||||
FAIL_IF_NO_DEBUGGER();
|
||||
|
||||
if (statbuf == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s: '0x%x'", __func__, fd);
|
||||
return semihosting_fstat(fd, statbuf);
|
||||
}
|
||||
|
||||
static int vfs_semihost_fsync(void* ctx, int fd)
|
||||
{
|
||||
FAIL_IF_NO_DEBUGGER();
|
||||
|
||||
ESP_LOGV(TAG, "%s: '0x%x'", __func__, fd);
|
||||
return semihosting_fsync(fd);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||
static int vfs_semihost_mkdir(void* ctx, const char* path, mode_t mode)
|
||||
{
|
||||
FAIL_IF_NO_DEBUGGER();
|
||||
|
||||
if (path == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s: '%s 0x%x'", __func__, path, mode);
|
||||
return semihosting_mkdir(path, mode);
|
||||
}
|
||||
|
||||
static int vfs_semihost_rmdir(void* ctx, const char* path)
|
||||
{
|
||||
FAIL_IF_NO_DEBUGGER();
|
||||
|
||||
if (path == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s: '%s'", __func__, path);
|
||||
return semihosting_rmdir(path);
|
||||
}
|
||||
|
||||
static int vfs_semihost_access(void* ctx, const char* path, int mode)
|
||||
{
|
||||
FAIL_IF_NO_DEBUGGER();
|
||||
|
||||
if (path == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s: '%s 0x%x'", __func__, path, mode);
|
||||
return semihosting_access(path, mode);
|
||||
}
|
||||
|
||||
static int vfs_semihost_truncate(void* ctx, const char* path, off_t length)
|
||||
{
|
||||
FAIL_IF_NO_DEBUGGER();
|
||||
|
||||
if (length < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (path == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s: '%s after %ld bytes'", __func__, path, length);
|
||||
return semihosting_truncate(path, length);
|
||||
}
|
||||
|
||||
static int vfs_semihost_utime(void* ctx, const char* path, const struct utimbuf *times)
|
||||
{
|
||||
FAIL_IF_NO_DEBUGGER();
|
||||
|
||||
if (path == NULL || times == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s: '%s'", __func__, path);
|
||||
return semihosting_utime(path, times);
|
||||
}
|
||||
|
||||
static int vfs_semihost_stat(void* ctx, const char *restrict path, struct stat *restrict statbuf)
|
||||
{
|
||||
FAIL_IF_NO_DEBUGGER();
|
||||
|
||||
if (statbuf == NULL || path == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s: '%s'", __func__, path);
|
||||
return semihosting_stat(path, statbuf);
|
||||
}
|
||||
|
||||
static int vfs_semihost_rename(void* ctx, const char *restrict old_name, const char *restrict new_name)
|
||||
{
|
||||
FAIL_IF_NO_DEBUGGER();
|
||||
|
||||
if (old_name == NULL || new_name == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s: '%s -> %s'", __func__, old_name, new_name);
|
||||
return semihosting_rename(old_name, new_name);
|
||||
}
|
||||
|
||||
static int vfs_semihost_link(void* ctx, const char *restrict path1, const char *restrict path2)
|
||||
{
|
||||
FAIL_IF_NO_DEBUGGER();
|
||||
|
||||
if (path1 == NULL || path2 == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s: '%s <-> %s'", __func__, path1, path2);
|
||||
return semihosting_link(path1, path2);
|
||||
}
|
||||
|
||||
static int vfs_semihost_unlink(void* ctx, const char *restrict path)
|
||||
{
|
||||
FAIL_IF_NO_DEBUGGER();
|
||||
|
||||
if (path == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s: '%s'", __func__, path);
|
||||
return semihosting_unlink(path);
|
||||
}
|
||||
|
||||
static DIR* vfs_semihost_opendir(void* ctx, const char *restrict path)
|
||||
{
|
||||
if (!cpu_hal_is_debugger_attached()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (path == NULL) {
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vfs_semihost_dir_t *semihost_dirp = (vfs_semihost_dir_t*)calloc(1, sizeof(vfs_semihost_dir_t));
|
||||
if (semihost_dirp == NULL) {
|
||||
ESP_LOGE("Error", "Error on vfs_semihost_dir_t creation");
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy(semihost_dirp->path, path, MIN(strlen(path), sizeof(semihost_dirp->path) - 1));
|
||||
ESP_LOGV(TAG, "%s: '%s'", __func__, path);
|
||||
int ret_fd = semihosting_opendir(path, (int)&semihost_dirp->id);
|
||||
if (ret_fd < 0) {
|
||||
free(semihost_dirp);
|
||||
return NULL;
|
||||
}
|
||||
return (DIR *)semihost_dirp;
|
||||
}
|
||||
|
||||
static int vfs_semihost_closedir(void* ctx, DIR* dirp)
|
||||
{
|
||||
FAIL_IF_NO_DEBUGGER();
|
||||
|
||||
vfs_semihost_dir_t *semihost_dirp = (vfs_semihost_dir_t*)dirp;
|
||||
if (semihost_dirp == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s: %s %ld", __func__, semihost_dirp->path, semihost_dirp->id);
|
||||
int ret_fd = semihosting_closedir(semihost_dirp->id);
|
||||
free(semihost_dirp);
|
||||
return ret_fd;
|
||||
}
|
||||
|
||||
static long vfs_semihost_telldir(void* ctx, DIR* dirp)
|
||||
{
|
||||
FAIL_IF_NO_DEBUGGER();
|
||||
|
||||
vfs_semihost_dir_t *semihost_dirp = (vfs_semihost_dir_t*)dirp;
|
||||
if (semihost_dirp == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s: %s %ld", __func__, semihost_dirp->path, semihost_dirp->id);
|
||||
return semihosting_telldir(semihost_dirp->id);
|
||||
}
|
||||
|
||||
static int vfs_semihost_readdir_r(void* ctx, DIR* dirp, struct dirent* entry, struct dirent** out_dirent)
|
||||
{
|
||||
FAIL_IF_NO_DEBUGGER();
|
||||
|
||||
vfs_semihost_dir_t *semihost_dirp = (vfs_semihost_dir_t *)dirp;
|
||||
if (semihost_dirp == NULL || entry == NULL || out_dirent == NULL) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s: %s %ld", __func__, semihost_dirp->path, semihost_dirp->id);
|
||||
int ret_fd = semihosting_readdir((int)entry, semihost_dirp->id);
|
||||
if (ret_fd < 0) {
|
||||
if (errno == 0) { /* end of directory */
|
||||
*out_dirent = NULL;
|
||||
return 0;
|
||||
}
|
||||
return errno;
|
||||
}
|
||||
*out_dirent = entry;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dirent* vfs_semihost_readdir(void* ctx, DIR* dirp)
|
||||
{
|
||||
if (!cpu_hal_is_debugger_attached()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vfs_semihost_dir_t *semihost_dirp = (vfs_semihost_dir_t *)dirp;
|
||||
struct dirent *dir_ptr;
|
||||
ESP_LOGV(TAG, "%s: %s %ld", __func__, semihost_dirp->path, semihost_dirp->id);
|
||||
int ret = vfs_semihost_readdir_r(ctx, (DIR*)semihost_dirp, &semihost_dirp->e, &dir_ptr);
|
||||
if (ret != 0) {
|
||||
errno = ret;
|
||||
return NULL;
|
||||
}
|
||||
return dir_ptr;
|
||||
}
|
||||
|
||||
static void vfs_semihost_seekdir(void* ctx, DIR* pdir, long offset)
|
||||
{
|
||||
if (!cpu_hal_is_debugger_attached()) {
|
||||
return;
|
||||
}
|
||||
|
||||
vfs_semihost_dir_t *semihost_dirp = (vfs_semihost_dir_t *) pdir;
|
||||
if (semihost_dirp != NULL) {
|
||||
ESP_LOGV(TAG, "%s: %s %ld '%ld' bytes", __func__, semihost_dirp->path, semihost_dirp->id, offset);
|
||||
semihosting_seekdir(semihost_dirp->id, offset);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
esp_err_t esp_vfs_semihost_register(const char* base_path)
|
||||
{
|
||||
assert(base_path);
|
||||
@ -170,6 +430,25 @@ esp_err_t esp_vfs_semihost_register(const char* base_path)
|
||||
.close_p = &vfs_semihost_close,
|
||||
.read_p = &vfs_semihost_read,
|
||||
.lseek_p = &vfs_semihost_lseek,
|
||||
.fsync_p = &vfs_semihost_fsync,
|
||||
.fstat_p = &vfs_semihost_fstat,
|
||||
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||
.mkdir_p = &vfs_semihost_mkdir,
|
||||
.rmdir_p = &vfs_semihost_rmdir,
|
||||
.access_p = &vfs_semihost_access,
|
||||
.truncate_p = &vfs_semihost_truncate,
|
||||
.utime_p = &vfs_semihost_utime,
|
||||
.stat_p = &vfs_semihost_stat,
|
||||
.rename_p = &vfs_semihost_rename,
|
||||
.link_p = &vfs_semihost_link,
|
||||
.unlink_p = &vfs_semihost_unlink,
|
||||
.opendir_p = &vfs_semihost_opendir,
|
||||
.closedir_p = &vfs_semihost_closedir,
|
||||
.telldir_p = &vfs_semihost_telldir,
|
||||
.readdir_p = &vfs_semihost_readdir,
|
||||
.readdir_r_p = &vfs_semihost_readdir_r,
|
||||
.seekdir_p = &vfs_semihost_seekdir,
|
||||
#endif
|
||||
};
|
||||
ESP_LOGD(TAG, "Register semihosting driver '%s'", base_path);
|
||||
if (!cpu_hal_is_debugger_attached()) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user