Skip to content

Commit c33ad60

Browse files
committed
extmod/fsusermount: Change block protocol to support ioctl method.
The new block protocol is: - readblocks(self, n, buf) - writeblocks(self, n, buf) - ioctl(self, cmd, arg) The new ioctl method handles the old sync and count methods, as well as a new "get sector size" method. The old protocol is still supported, and used if the device doesn't have the ioctl method.
1 parent 3846fd5 commit c33ad60

4 files changed

Lines changed: 67 additions & 18 deletions

File tree

extmod/fsusermount.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,15 @@ STATIC mp_obj_t fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp_
7676
// load block protocol methods
7777
mp_load_method(device, MP_QSTR_readblocks, vfs->readblocks);
7878
mp_load_method_maybe(device, MP_QSTR_writeblocks, vfs->writeblocks);
79-
mp_load_method_maybe(device, MP_QSTR_sync, vfs->sync);
80-
mp_load_method(device, MP_QSTR_count, vfs->count);
79+
mp_load_method_maybe(device, MP_QSTR_ioctl, vfs->u.ioctl);
80+
if (vfs->u.ioctl[0] != MP_OBJ_NULL) {
81+
// device supports new block protocol, so indicate it
82+
vfs->u.old.count[1] = MP_OBJ_SENTINEL;
83+
} else {
84+
// no ioctl method, so assume the device uses the old block protocol
85+
mp_load_method_maybe(device, MP_QSTR_sync, vfs->u.old.sync);
86+
mp_load_method(device, MP_QSTR_count, vfs->u.old.count);
87+
}
8188

8289
// Read-only device indicated by writeblocks[0] == MP_OBJ_NULL.
8390
// User can specify read-only device by:

extmod/fsusermount.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,15 @@ typedef struct _fs_user_mount_t {
2929
mp_uint_t len;
3030
mp_obj_t readblocks[4];
3131
mp_obj_t writeblocks[4];
32-
mp_obj_t sync[2];
33-
mp_obj_t count[2];
32+
// new protocol uses just ioctl, old uses sync (optional) and count
33+
// if ioctl[3]=count[1]=MP_OBJ_SENTINEL then we have the new protocol, else old
34+
union {
35+
mp_obj_t ioctl[4];
36+
struct {
37+
mp_obj_t sync[2];
38+
mp_obj_t count[2];
39+
} old;
40+
} u;
3441
FATFS fatfs;
3542
} fs_user_mount_t;
3643

py/qstrdefs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,7 @@ Q(readonly)
675675
Q(mkfs)
676676
Q(readblocks)
677677
Q(writeblocks)
678+
Q(ioctl)
678679
Q(sync)
679680
Q(count)
680681
#endif

stmhal/diskio.c

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@
3939
#include "sdcard.h"
4040
#include "extmod/fsusermount.h"
4141

42+
// constants for block protocol ioctl
43+
//#define BP_IOCTL_INIT (1) // unused
44+
//#define BP_IOCTL_DEINIT (2) // unused
45+
#define BP_IOCTL_SYNC (3)
46+
#define BP_IOCTL_SEC_COUNT (4)
47+
4248
/*-----------------------------------------------------------------------*/
4349
/* Initialize a Drive */
4450
/*-----------------------------------------------------------------------*/
@@ -242,29 +248,57 @@ DRESULT disk_ioctl (
242248
break;
243249
#endif
244250

245-
case PD_USER:
246-
if (MP_STATE_PORT(fs_user_mount) == NULL) {
251+
case PD_USER: {
252+
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount);
253+
if (vfs == NULL) {
247254
// nothing mounted
248255
return RES_ERROR;
249256
}
250-
switch (cmd) {
251-
case CTRL_SYNC:
252-
if (MP_STATE_PORT(fs_user_mount)->sync[0] != MP_OBJ_NULL) {
253-
mp_call_method_n_kw(0, 0, MP_STATE_PORT(fs_user_mount)->sync);
257+
if (vfs->u.old.count[1] == MP_OBJ_SENTINEL) {
258+
// new protocol with ioctl
259+
switch (cmd) {
260+
case CTRL_SYNC:
261+
vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(BP_IOCTL_SYNC);
262+
vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused
263+
mp_call_method_n_kw(2, 0, vfs->u.ioctl);
264+
vfs->u.ioctl[3] = MP_OBJ_SENTINEL; // indicate new protocol
265+
return RES_OK;
266+
267+
case GET_SECTOR_COUNT: {
268+
vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(BP_IOCTL_SEC_COUNT);
269+
vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused
270+
mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl);
271+
*((DWORD*)buff) = mp_obj_get_int(ret);
272+
vfs->u.ioctl[3] = MP_OBJ_SENTINEL; // indicate new protocol
273+
return RES_OK;
254274
}
255-
return RES_OK;
256275

257-
case GET_BLOCK_SIZE:
258-
*((DWORD*)buff) = 1; // high-level sector erase size in units of the small (512) bl
259-
return RES_OK;
276+
case GET_BLOCK_SIZE:
277+
*((DWORD*)buff) = 1; // erase block size in units of sector size
278+
return RES_OK;
279+
}
280+
} else {
281+
// old protocol with sync and count
282+
switch (cmd) {
283+
case CTRL_SYNC:
284+
if (vfs->u.old.sync[0] != MP_OBJ_NULL) {
285+
mp_call_method_n_kw(0, 0, vfs->u.old.sync);
286+
}
287+
return RES_OK;
288+
289+
case GET_SECTOR_COUNT: {
290+
mp_obj_t ret = mp_call_method_n_kw(0, 0, vfs->u.old.count);
291+
*((DWORD*)buff) = mp_obj_get_int(ret);
292+
return RES_OK;
293+
}
260294

261-
case GET_SECTOR_COUNT: {
262-
mp_obj_t ret = mp_call_method_n_kw(0, 0, MP_STATE_PORT(fs_user_mount)->count);
263-
*((DWORD*)buff) = mp_obj_get_int(ret);
264-
return RES_OK;
295+
case GET_BLOCK_SIZE:
296+
*((DWORD*)buff) = 1; // erase block size in units of sector size
297+
return RES_OK;
265298
}
266299
}
267300
break;
301+
}
268302
}
269303

270304
return RES_PARERR;

0 commit comments

Comments
 (0)