summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--extmod/fsusermount.c11
-rw-r--r--extmod/fsusermount.h11
-rw-r--r--py/qstrdefs.h1
-rw-r--r--stmhal/diskio.c62
4 files changed, 67 insertions, 18 deletions
diff --git a/extmod/fsusermount.c b/extmod/fsusermount.c
index 74525ef743..441711ae2e 100644
--- a/extmod/fsusermount.c
+++ b/extmod/fsusermount.c
@@ -76,8 +76,15 @@ STATIC mp_obj_t fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp_
// load block protocol methods
mp_load_method(device, MP_QSTR_readblocks, vfs->readblocks);
mp_load_method_maybe(device, MP_QSTR_writeblocks, vfs->writeblocks);
- mp_load_method_maybe(device, MP_QSTR_sync, vfs->sync);
- mp_load_method(device, MP_QSTR_count, vfs->count);
+ mp_load_method_maybe(device, MP_QSTR_ioctl, vfs->u.ioctl);
+ if (vfs->u.ioctl[0] != MP_OBJ_NULL) {
+ // device supports new block protocol, so indicate it
+ vfs->u.old.count[1] = MP_OBJ_SENTINEL;
+ } else {
+ // no ioctl method, so assume the device uses the old block protocol
+ mp_load_method_maybe(device, MP_QSTR_sync, vfs->u.old.sync);
+ mp_load_method(device, MP_QSTR_count, vfs->u.old.count);
+ }
// Read-only device indicated by writeblocks[0] == MP_OBJ_NULL.
// User can specify read-only device by:
diff --git a/extmod/fsusermount.h b/extmod/fsusermount.h
index c141ecb99a..53442a3689 100644
--- a/extmod/fsusermount.h
+++ b/extmod/fsusermount.h
@@ -29,8 +29,15 @@ typedef struct _fs_user_mount_t {
mp_uint_t len;
mp_obj_t readblocks[4];
mp_obj_t writeblocks[4];
- mp_obj_t sync[2];
- mp_obj_t count[2];
+ // new protocol uses just ioctl, old uses sync (optional) and count
+ // if ioctl[3]=count[1]=MP_OBJ_SENTINEL then we have the new protocol, else old
+ union {
+ mp_obj_t ioctl[4];
+ struct {
+ mp_obj_t sync[2];
+ mp_obj_t count[2];
+ } old;
+ } u;
FATFS fatfs;
} fs_user_mount_t;
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index bf774e036b..0a2cc2c8e6 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -675,6 +675,7 @@ Q(readonly)
Q(mkfs)
Q(readblocks)
Q(writeblocks)
+Q(ioctl)
Q(sync)
Q(count)
#endif
diff --git a/stmhal/diskio.c b/stmhal/diskio.c
index 3e53cdaa50..14eb9e297e 100644
--- a/stmhal/diskio.c
+++ b/stmhal/diskio.c
@@ -39,6 +39,12 @@
#include "sdcard.h"
#include "extmod/fsusermount.h"
+// constants for block protocol ioctl
+//#define BP_IOCTL_INIT (1) // unused
+//#define BP_IOCTL_DEINIT (2) // unused
+#define BP_IOCTL_SYNC (3)
+#define BP_IOCTL_SEC_COUNT (4)
+
/*-----------------------------------------------------------------------*/
/* Initialize a Drive */
/*-----------------------------------------------------------------------*/
@@ -242,29 +248,57 @@ DRESULT disk_ioctl (
break;
#endif
- case PD_USER:
- if (MP_STATE_PORT(fs_user_mount) == NULL) {
+ case PD_USER: {
+ fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount);
+ if (vfs == NULL) {
// nothing mounted
return RES_ERROR;
}
- switch (cmd) {
- case CTRL_SYNC:
- if (MP_STATE_PORT(fs_user_mount)->sync[0] != MP_OBJ_NULL) {
- mp_call_method_n_kw(0, 0, MP_STATE_PORT(fs_user_mount)->sync);
+ if (vfs->u.old.count[1] == MP_OBJ_SENTINEL) {
+ // new protocol with ioctl
+ switch (cmd) {
+ case CTRL_SYNC:
+ vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(BP_IOCTL_SYNC);
+ vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused
+ mp_call_method_n_kw(2, 0, vfs->u.ioctl);
+ vfs->u.ioctl[3] = MP_OBJ_SENTINEL; // indicate new protocol
+ return RES_OK;
+
+ case GET_SECTOR_COUNT: {
+ vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(BP_IOCTL_SEC_COUNT);
+ vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused
+ mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl);
+ *((DWORD*)buff) = mp_obj_get_int(ret);
+ vfs->u.ioctl[3] = MP_OBJ_SENTINEL; // indicate new protocol
+ return RES_OK;
}
- return RES_OK;
- case GET_BLOCK_SIZE:
- *((DWORD*)buff) = 1; // high-level sector erase size in units of the small (512) bl
- return RES_OK;
+ case GET_BLOCK_SIZE:
+ *((DWORD*)buff) = 1; // erase block size in units of sector size
+ return RES_OK;
+ }
+ } else {
+ // old protocol with sync and count
+ switch (cmd) {
+ case CTRL_SYNC:
+ if (vfs->u.old.sync[0] != MP_OBJ_NULL) {
+ mp_call_method_n_kw(0, 0, vfs->u.old.sync);
+ }
+ return RES_OK;
+
+ case GET_SECTOR_COUNT: {
+ mp_obj_t ret = mp_call_method_n_kw(0, 0, vfs->u.old.count);
+ *((DWORD*)buff) = mp_obj_get_int(ret);
+ return RES_OK;
+ }
- case GET_SECTOR_COUNT: {
- mp_obj_t ret = mp_call_method_n_kw(0, 0, MP_STATE_PORT(fs_user_mount)->count);
- *((DWORD*)buff) = mp_obj_get_int(ret);
- return RES_OK;
+ case GET_BLOCK_SIZE:
+ *((DWORD*)buff) = 1; // erase block size in units of sector size
+ return RES_OK;
}
}
break;
+ }
}
return RES_PARERR;