diff --git a/extmod/fsusermount.c b/extmod/fsusermount.c index 74525ef743670c8d9dd26603aeeef8e23e992241..441711ae2e1323a03b57273c170021072d2d1858 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 c141ecb99af26634542c8e9df33db9cf9c6c078d..53442a36890bd1bf9eb5f2db2939112c1b83bf4f 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 bf774e036b6bd189d70a0069af5caff42fd1d011..0a2cc2c8e6adbefccecc896f82ad33d8296d212a 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 3e53cdaa50107407fef382e5a6d789d0e3fbad2d..14eb9e297ecb51264f7d4194a0b1e5ddf2d1612f 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;