diff --git a/extmod/vfs.h b/extmod/vfs.h index f577d3e337c87..f05bda3c77d2c 100644 --- a/extmod/vfs.h +++ b/extmod/vfs.h @@ -51,6 +51,7 @@ #define MP_BLOCKDEV_IOCTL_BLOCK_COUNT (4) #define MP_BLOCKDEV_IOCTL_BLOCK_SIZE (5) #define MP_BLOCKDEV_IOCTL_BLOCK_ERASE (6) +#define MP_BLOCKDEV_IOCTL_STATUS (7) // At the moment the VFS protocol just has import_stat, but could be extended to other methods typedef struct _mp_vfs_proto_t { diff --git a/extmod/vfs_fat_diskio.c b/extmod/vfs_fat_diskio.c index 1bcd471f2162e..3df20ec6664ef 100644 --- a/extmod/vfs_fat_diskio.c +++ b/extmod/vfs_fat_diskio.c @@ -114,6 +114,7 @@ DRESULT disk_ioctl( [GET_SECTOR_COUNT] = MP_BLOCKDEV_IOCTL_BLOCK_COUNT, [GET_SECTOR_SIZE] = MP_BLOCKDEV_IOCTL_BLOCK_SIZE, [IOCTL_INIT] = MP_BLOCKDEV_IOCTL_INIT, + [IOCTL_STATUS] = MP_BLOCKDEV_IOCTL_STATUS, }; uint8_t bp_op = op_map[cmd & 7]; mp_obj_t ret = mp_const_none; @@ -147,16 +148,29 @@ DRESULT disk_ioctl( *((DWORD *)buff) = 1; // erase block size in units of sector size return RES_OK; - case IOCTL_INIT: - case IOCTL_STATUS: { - DSTATUS stat; + case IOCTL_INIT: { + DSTATUS stat = 0; if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) { // error initialising stat = STA_NOINIT; - } else if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) { - stat = STA_PROTECT; } else { - stat = 0; + // IOCTL_INIT only returns non 0 for all errors/flags. To return + // a more accurate disk state, IOCTL_STATUS is called again here. + ret = mp_vfs_blockdev_ioctl(&vfs->blockdev, MP_BLOCKDEV_IOCTL_STATUS, 0); + if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL || + (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0)) { + stat = STA_PROTECT; + } + } + *((DSTATUS *)buff) = stat; + return RES_OK; + } + + case IOCTL_STATUS: { + DSTATUS stat = 0; + if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL || + (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0)) { + stat = STA_PROTECT; } *((DSTATUS *)buff) = stat; return RES_OK; diff --git a/ports/rp2/main.c b/ports/rp2/main.c index da21e0b394793..1dadbd73f9e01 100644 --- a/ports/rp2/main.c +++ b/ports/rp2/main.c @@ -82,7 +82,6 @@ int main(int argc, char **argv) { #if MICROPY_HW_ENABLE_USBDEV bi_decl(bi_program_feature("USB REPL")) - tusb_init(); #endif #if MICROPY_PY_THREAD @@ -147,6 +146,12 @@ int main(int argc, char **argv) { pyexec_frozen_module("_boot.py"); #endif + #if MICROPY_HW_ENABLE_USBDEV + if (!tusb_inited()) { + tusb_init(); + } + #endif + // Execute user scripts. int ret = pyexec_file_if_exists("boot.py"); if (ret & PYEXEC_FORCED_EXIT) { diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 62388c6bcecd3..bff8a7c8f6636 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -116,6 +116,7 @@ #if MICROPY_HW_USB_MSC #define MICROPY_FATFS_USE_LABEL (1) #define MICROPY_FATFS_MULTI_PARTITION (1) +#define MICROPY_HW_USB_MSC_EXCLUSIVE_ACCESS (1) // Set FatFS block size to flash sector size to avoid caching // the flash sector in memory to support smaller block sizes. #define MICROPY_FATFS_MAX_SS (FLASH_SECTOR_SIZE) diff --git a/ports/rp2/msc_disk.c b/ports/rp2/msc_disk.c index 24bd51cec3f33..12c7372f469aa 100644 --- a/ports/rp2/msc_disk.c +++ b/ports/rp2/msc_disk.c @@ -39,7 +39,8 @@ #define FLASH_BASE_ADDR (PICO_FLASH_SIZE_BYTES - MICROPY_HW_FLASH_STORAGE_BYTES) #define FLASH_MMAP_ADDR (XIP_BASE + FLASH_BASE_ADDR) -static bool ejected = false; +bool tud_msc_ejected = true; +extern void tud_msc_remount(void); // Invoked when received SCSI_CMD_INQUIRY // 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 strncpy((char *)vendor_id, vid, 8); strncpy((char *)product_id, pid, 16); strncpy((char *)product_rev, rev, 4); + tud_msc_ejected = false; } // Invoked when received Test Unit Ready command. // return true allowing host to read/write this LUN e.g SD card inserted bool tud_msc_test_unit_ready_cb(uint8_t lun) { - if (ejected) { + if (tud_msc_ejected) { tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00); return false; } @@ -77,10 +79,13 @@ bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, boo if (load_eject) { if (start) { // load disk storage - ejected = false; + tud_msc_ejected = false; } else { // unload disk storage - ejected = true; + tud_msc_ejected = true; + #if MICROPY_HW_USB_MSC_EXCLUSIVE_ACCESS + tud_msc_remount(); + #endif } } return true; diff --git a/ports/rp2/rp2_flash.c b/ports/rp2/rp2_flash.c index 80bc1dc1df121..900794bb689fa 100644 --- a/ports/rp2/rp2_flash.c +++ b/ports/rp2/rp2_flash.c @@ -42,6 +42,8 @@ #define MICROPY_HW_FLASH_STORAGE_BASE (PICO_FLASH_SIZE_BYTES - MICROPY_HW_FLASH_STORAGE_BYTES) #endif +extern bool tud_msc_ejected; + static_assert(MICROPY_HW_FLASH_STORAGE_BYTES <= PICO_FLASH_SIZE_BYTES, "MICROPY_HW_FLASH_STORAGE_BYTES too big"); static_assert(MICROPY_HW_FLASH_STORAGE_BASE + MICROPY_HW_FLASH_STORAGE_BYTES <= PICO_FLASH_SIZE_BYTES, "MICROPY_HW_FLASH_STORAGE_BYTES too big"); @@ -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_ // TODO check return value return MP_OBJ_NEW_SMALL_INT(0); } + case MP_BLOCKDEV_IOCTL_STATUS: + #if MICROPY_HW_USB_MSC + return MP_OBJ_NEW_SMALL_INT(!tud_msc_ejected); + #else + return MP_OBJ_NEW_SMALL_INT(false); + #endif default: return mp_const_none; } diff --git a/shared/runtime/tinyusb_helpers.c b/shared/runtime/tinyusb_helpers.c index 00b72e74b7768..c465aa685a942 100644 --- a/shared/runtime/tinyusb_helpers.c +++ b/shared/runtime/tinyusb_helpers.c @@ -52,3 +52,29 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { } #endif + +#if MICROPY_HW_USB_MSC_EXCLUSIVE_ACCESS +#include "tusb.h" +#include "extmod/vfs.h" +static mp_sched_node_t mp_remount_sched_node; + +STATIC void tud_msc_remount_task(mp_sched_node_t *node) { + mp_vfs_mount_t *vfs = NULL; + for (vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) { + if (vfs->len == 1) { + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_vfs_umount(vfs->obj); + nlr_pop(); + } + mp_obj_t path = mp_obj_new_str(vfs->str, strlen(vfs->str)); + mp_vfs_mount_and_chdir_protected(vfs->obj, path); + break; + } + } +} + +void tud_msc_remount(void) { + mp_sched_schedule_node(&mp_remount_sched_node, tud_msc_remount_task); +} +#endif 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