Skip to content

Commit 3ab4efd

Browse files
committed
rp2: MSC exclusive access support.
1 parent e22b7fb commit 3ab4efd

File tree

6 files changed

+65
-10
lines changed

6 files changed

+65
-10
lines changed

extmod/vfs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#define MP_BLOCKDEV_IOCTL_BLOCK_COUNT (4)
5252
#define MP_BLOCKDEV_IOCTL_BLOCK_SIZE (5)
5353
#define MP_BLOCKDEV_IOCTL_BLOCK_ERASE (6)
54+
#define MP_BLOCKDEV_IOCTL_STATUS (7)
5455

5556
// At the moment the VFS protocol just has import_stat, but could be extended to other methods
5657
typedef struct _mp_vfs_proto_t {

extmod/vfs_fat_diskio.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ DRESULT disk_ioctl(
114114
[GET_SECTOR_COUNT] = MP_BLOCKDEV_IOCTL_BLOCK_COUNT,
115115
[GET_SECTOR_SIZE] = MP_BLOCKDEV_IOCTL_BLOCK_SIZE,
116116
[IOCTL_INIT] = MP_BLOCKDEV_IOCTL_INIT,
117+
[IOCTL_STATUS] = MP_BLOCKDEV_IOCTL_STATUS,
117118
};
118119
uint8_t bp_op = op_map[cmd & 7];
119120
mp_obj_t ret = mp_const_none;
@@ -147,16 +148,29 @@ DRESULT disk_ioctl(
147148
*((DWORD *)buff) = 1; // erase block size in units of sector size
148149
return RES_OK;
149150

150-
case IOCTL_INIT:
151-
case IOCTL_STATUS: {
152-
DSTATUS stat;
151+
case IOCTL_INIT: {
152+
DSTATUS stat = 0;
153153
if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) {
154154
// error initialising
155155
stat = STA_NOINIT;
156-
} else if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) {
157-
stat = STA_PROTECT;
158156
} else {
159-
stat = 0;
157+
// IOCTL_INIT only returns non 0 for all errors/flags. To return
158+
// a more accurate disk state, IOCTL_STATUS is called again here.
159+
ret = mp_vfs_blockdev_ioctl(&vfs->blockdev, MP_BLOCKDEV_IOCTL_STATUS, 0);
160+
if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL ||
161+
(ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0)) {
162+
stat = STA_PROTECT;
163+
}
164+
}
165+
*((DSTATUS *)buff) = stat;
166+
return RES_OK;
167+
}
168+
169+
case IOCTL_STATUS: {
170+
DSTATUS stat = 0;
171+
if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL ||
172+
(ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0)) {
173+
stat = STA_PROTECT;
160174
}
161175
*((DSTATUS *)buff) = stat;
162176
return RES_OK;

ports/rp2/mpconfigport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
#if MICROPY_HW_USB_MSC
117117
#define MICROPY_FATFS_USE_LABEL (1)
118118
#define MICROPY_FATFS_MULTI_PARTITION (1)
119+
#define MICROPY_HW_USB_MSC_EXCLUSIVE_ACCESS (1)
119120
// Set FatFS block size to flash sector size to avoid caching
120121
// the flash sector in memory to support smaller block sizes.
121122
#define MICROPY_FATFS_MAX_SS (FLASH_SECTOR_SIZE)

ports/rp2/msc_disk.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
#define FLASH_BASE_ADDR (PICO_FLASH_SIZE_BYTES - MICROPY_HW_FLASH_STORAGE_BYTES)
4040
#define FLASH_MMAP_ADDR (XIP_BASE + FLASH_BASE_ADDR)
4141

42-
static bool ejected = false;
42+
bool tud_msc_ejected = true;
43+
extern void tud_msc_remount(void);
4344

4445
// Invoked when received SCSI_CMD_INQUIRY
4546
// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
@@ -51,12 +52,13 @@ void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16
5152
strncpy((char *)vendor_id, vid, 8);
5253
strncpy((char *)product_id, pid, 16);
5354
strncpy((char *)product_rev, rev, 4);
55+
tud_msc_ejected = false;
5456
}
5557

5658
// Invoked when received Test Unit Ready command.
5759
// return true allowing host to read/write this LUN e.g SD card inserted
5860
bool tud_msc_test_unit_ready_cb(uint8_t lun) {
59-
if (ejected) {
61+
if (tud_msc_ejected) {
6062
tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
6163
return false;
6264
}
@@ -77,10 +79,13 @@ bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, boo
7779
if (load_eject) {
7880
if (start) {
7981
// load disk storage
80-
ejected = false;
82+
tud_msc_ejected = false;
8183
} else {
8284
// unload disk storage
83-
ejected = true;
85+
tud_msc_ejected = true;
86+
#if MICROPY_HW_USB_MSC_EXCLUSIVE_ACCESS
87+
tud_msc_remount();
88+
#endif
8489
}
8590
}
8691
return true;

ports/rp2/rp2_flash.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
#define MICROPY_HW_FLASH_STORAGE_BASE (PICO_FLASH_SIZE_BYTES - MICROPY_HW_FLASH_STORAGE_BYTES)
4343
#endif
4444

45+
extern bool tud_msc_ejected;
46+
4547
static_assert(MICROPY_HW_FLASH_STORAGE_BYTES <= PICO_FLASH_SIZE_BYTES, "MICROPY_HW_FLASH_STORAGE_BYTES too big");
4648
static_assert(MICROPY_HW_FLASH_STORAGE_BASE + MICROPY_HW_FLASH_STORAGE_BYTES <= PICO_FLASH_SIZE_BYTES, "MICROPY_HW_FLASH_STORAGE_BYTES too big");
4749

@@ -137,6 +139,12 @@ STATIC mp_obj_t rp2_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_
137139
// TODO check return value
138140
return MP_OBJ_NEW_SMALL_INT(0);
139141
}
142+
case MP_BLOCKDEV_IOCTL_STATUS:
143+
#if MICROPY_HW_USB_MSC
144+
return MP_OBJ_NEW_SMALL_INT(!tud_msc_ejected);
145+
#else
146+
return MP_OBJ_NEW_SMALL_INT(false);
147+
#endif
140148
default:
141149
return mp_const_none;
142150
}

shared/runtime/tinyusb_helpers.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,29 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
5252
}
5353

5454
#endif
55+
56+
#if MICROPY_HW_USB_MSC_EXCLUSIVE_ACCESS
57+
#include "tusb.h"
58+
#include "extmod/vfs.h"
59+
static mp_sched_node_t mp_remount_sched_node;
60+
61+
STATIC void tud_msc_remount_task(mp_sched_node_t *node) {
62+
mp_vfs_mount_t *vfs = NULL;
63+
for (vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) {
64+
if (vfs->len == 1) {
65+
nlr_buf_t nlr;
66+
if (nlr_push(&nlr) == 0) {
67+
mp_vfs_umount(vfs->obj);
68+
nlr_pop();
69+
}
70+
mp_obj_t path = mp_obj_new_str(vfs->str, strlen(vfs->str));
71+
mp_vfs_mount_and_chdir_protected(vfs->obj, path);
72+
break;
73+
}
74+
}
75+
}
76+
77+
void tud_msc_remount(void) {
78+
mp_sched_schedule_node(&mp_remount_sched_node, tud_msc_remount_task);
79+
}
80+
#endif

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy