Automount SD cards
And make them available over USB MSC. They can be remount to make them writable (slowly) from the host PC. Fixes #9954. Fixes #8678. Fixes #3477
This commit is contained in:
parent
ca0eec3f1a
commit
d0c840094a
13 changed files with 257 additions and 62 deletions
23
extmod/vfs.c
23
extmod/vfs.c
|
|
@ -47,6 +47,11 @@
|
|||
#include "extmod/vfs_posix.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if CIRCUITPY_SDCARDIO
|
||||
#include "shared-module/sdcardio/__init__.h"
|
||||
#endif
|
||||
|
||||
// For mp_vfs_proxy_call, the maximum number of additional args that can be passed.
|
||||
// A fixed maximum size is used to avoid the need for a costly variable array.
|
||||
#define PROXY_MAX_ARGS (2)
|
||||
|
|
@ -67,6 +72,10 @@ mp_vfs_mount_t *mp_vfs_lookup_path(const char *path, const char **path_out) {
|
|||
// path is "" or "/" so return virtual root
|
||||
return MP_VFS_ROOT;
|
||||
}
|
||||
// CIRCUITPY-CHANGE: Try and automount the SD card.
|
||||
#if CIRCUITPY_SDCARDIO
|
||||
automount_sd_card();
|
||||
#endif
|
||||
for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) {
|
||||
size_t len = vfs->len - 1;
|
||||
if (len == 0) {
|
||||
|
|
@ -367,8 +376,18 @@ mp_obj_t mp_vfs_getcwd(void) {
|
|||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_vfs_getcwd_obj, mp_vfs_getcwd);
|
||||
|
||||
// CIRCUITPY-CHANGE: accessible from shared-module/os/__init__.c
|
||||
mp_obj_t mp_vfs_ilistdir_it_iternext(mp_obj_t self_in) {
|
||||
typedef struct _mp_vfs_ilistdir_it_t {
|
||||
mp_obj_base_t base;
|
||||
mp_fun_1_t iternext;
|
||||
union {
|
||||
mp_vfs_mount_t *vfs;
|
||||
mp_obj_t iter;
|
||||
} cur;
|
||||
bool is_str;
|
||||
bool is_iter;
|
||||
} mp_vfs_ilistdir_it_t;
|
||||
|
||||
static mp_obj_t mp_vfs_ilistdir_it_iternext(mp_obj_t self_in) {
|
||||
mp_vfs_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (self->is_iter) {
|
||||
// continue delegating to root dir
|
||||
|
|
|
|||
13
extmod/vfs.h
13
extmod/vfs.h
|
|
@ -94,19 +94,6 @@ typedef struct _mp_vfs_mount_t {
|
|||
struct _mp_vfs_mount_t *next;
|
||||
} mp_vfs_mount_t;
|
||||
|
||||
// CIRCUITPY-CHANGE: allow outside use of ilistdir_it_iternext
|
||||
typedef struct _mp_vfs_ilistdir_it_t {
|
||||
mp_obj_base_t base;
|
||||
mp_fun_1_t iternext;
|
||||
union {
|
||||
mp_vfs_mount_t *vfs;
|
||||
mp_obj_t iter;
|
||||
} cur;
|
||||
bool is_str;
|
||||
bool is_iter;
|
||||
} mp_vfs_ilistdir_it_t;
|
||||
|
||||
mp_obj_t mp_vfs_ilistdir_it_iternext(mp_obj_t self_in);
|
||||
void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev);
|
||||
int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf);
|
||||
int mp_vfs_blockdev_read_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, uint8_t *buf);
|
||||
|
|
|
|||
|
|
@ -789,7 +789,7 @@ msgid "Cannot record to a file"
|
|||
msgstr ""
|
||||
|
||||
#: shared-module/storage/__init__.c
|
||||
msgid "Cannot remount '/' when visible via USB."
|
||||
msgid "Cannot remount path when visible via USB."
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/digitalio/DigitalInOut.c
|
||||
|
|
@ -1975,6 +1975,7 @@ msgstr ""
|
|||
#: shared-bindings/displayio/TileGrid.c
|
||||
#: shared-bindings/memorymonitor/AllocationSize.c
|
||||
#: shared-bindings/pulseio/PulseIn.c
|
||||
#: shared-bindings/tilepalettemapper/TilePaletteMapper.c
|
||||
msgid "Slices not supported"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -2042,7 +2043,9 @@ msgstr ""
|
|||
msgid "Tile height must exactly divide bitmap height"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c
|
||||
#: shared-bindings/displayio/TileGrid.c
|
||||
#: shared-bindings/tilepalettemapper/TilePaletteMapper.c
|
||||
#: shared-module/displayio/TileGrid.c
|
||||
msgid "Tile index out of bounds"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -4277,7 +4280,9 @@ msgstr ""
|
|||
msgid "unreadable attribute"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c
|
||||
#: shared-bindings/displayio/TileGrid.c
|
||||
#: shared-bindings/tilepalettemapper/TilePaletteMapper.c
|
||||
#: shared-bindings/vectorio/VectorShape.c
|
||||
msgid "unsupported %q type"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,13 @@
|
|||
#define DEFAULT_DVI_BUS_BLUE_DN (&pin_GPIO18)
|
||||
#define DEFAULT_DVI_BUS_BLUE_DP (&pin_GPIO19)
|
||||
|
||||
#define DEFAULT_SD_SCK (&pin_GPIO34)
|
||||
#define DEFAULT_SD_MOSI (&pin_GPIO35)
|
||||
#define DEFAULT_SD_MISO (&pin_GPIO36)
|
||||
#define DEFAULT_SD_CS (&pin_GPIO39)
|
||||
#define DEFAULT_SD_CARD_DETECT (&pin_GPIO33)
|
||||
#define DEFAULT_SD_CARD_INSERTED true
|
||||
|
||||
#define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO47)
|
||||
|
||||
// #define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO44)
|
||||
|
|
|
|||
|
|
@ -90,20 +90,18 @@ mp_obj_t common_hal_os_getcwd(void) {
|
|||
mp_obj_t common_hal_os_listdir(const char *path) {
|
||||
mp_obj_t path_out;
|
||||
mp_vfs_mount_t *vfs = lookup_dir_path(path, &path_out);
|
||||
|
||||
mp_vfs_ilistdir_it_t iter;
|
||||
mp_obj_t iter_obj = MP_OBJ_FROM_PTR(&iter);
|
||||
|
||||
if (vfs == MP_VFS_ROOT) {
|
||||
// list the root directory
|
||||
iter.base.type = &mp_type_polymorph_iter;
|
||||
iter.iternext = mp_vfs_ilistdir_it_iternext;
|
||||
iter.cur.vfs = MP_STATE_VM(vfs_mount_table);
|
||||
iter.is_str = true;
|
||||
iter.is_iter = false;
|
||||
} else {
|
||||
iter_obj = mp_vfs_proxy_call(vfs, MP_QSTR_ilistdir, 1, &path_out);
|
||||
vfs = MP_STATE_VM(vfs_mount_table);
|
||||
while (vfs != NULL) {
|
||||
if (vfs->len == 1) {
|
||||
break;
|
||||
}
|
||||
vfs = vfs->next;
|
||||
}
|
||||
path_out = MP_OBJ_NEW_QSTR(MP_QSTR__slash_);
|
||||
}
|
||||
|
||||
mp_obj_t iter_obj = mp_vfs_proxy_call(vfs, MP_QSTR_ilistdir, 1, &path_out);
|
||||
|
||||
mp_obj_t dir_list = mp_obj_new_list(0, NULL);
|
||||
mp_obj_t next;
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ static mp_rom_error_text_t init_card(sdcardio_sdcard_obj_t *self) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate) {
|
||||
mp_rom_error_text_t sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate) {
|
||||
self->bus = bus;
|
||||
common_hal_digitalio_digitalinout_construct(&self->cs, cs);
|
||||
common_hal_digitalio_digitalinout_switch_to_output(&self->cs, true, DRIVE_MODE_PUSH_PULL);
|
||||
|
|
@ -309,10 +309,19 @@ void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi
|
|||
|
||||
if (result != NULL) {
|
||||
common_hal_digitalio_digitalinout_deinit(&self->cs);
|
||||
mp_raise_OSError_msg(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
self->baudrate = baudrate;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate) {
|
||||
mp_rom_error_text_t result = sdcardio_sdcard_construct(self, bus, cs, baudrate);
|
||||
if (result != NULL) {
|
||||
mp_raise_OSError_msg(result);
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self) {
|
||||
|
|
|
|||
|
|
@ -24,3 +24,5 @@ typedef struct {
|
|||
uint32_t next_block;
|
||||
bool in_cmd25;
|
||||
} sdcardio_sdcard_obj_t;
|
||||
|
||||
mp_rom_error_text_t sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate);
|
||||
|
|
|
|||
|
|
@ -3,3 +3,118 @@
|
|||
// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "shared-module/sdcardio/__init__.h"
|
||||
|
||||
#include "extmod/vfs_fat.h"
|
||||
|
||||
#include "shared-bindings/busio/SPI.h"
|
||||
#include "shared-bindings/digitalio/DigitalInOut.h"
|
||||
#include "shared-bindings/sdcardio/SDCard.h"
|
||||
|
||||
#include "supervisor/filesystem.h"
|
||||
|
||||
#ifdef DEFAULT_SD_CARD_DETECT
|
||||
static digitalio_digitalinout_obj_t sd_card_detect_pin;
|
||||
static sdcardio_sdcard_obj_t sdcard;
|
||||
|
||||
static mp_vfs_mount_t _sdcard_vfs;
|
||||
fs_user_mount_t _sdcard_usermount;
|
||||
|
||||
static bool _init_error = false;
|
||||
static bool _mounted = false;
|
||||
|
||||
#ifdef DEFAULT_SD_MOSI
|
||||
static busio_spi_obj_t busio_spi_obj;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void sdcardio_init(void) {
|
||||
#ifdef DEFAULT_SD_CARD_DETECT
|
||||
sd_card_detect_pin.base.type = &digitalio_digitalinout_type;
|
||||
common_hal_digitalio_digitalinout_construct(&sd_card_detect_pin, DEFAULT_SD_CARD_DETECT);
|
||||
common_hal_digitalio_digitalinout_switch_to_input(&sd_card_detect_pin, PULL_UP);
|
||||
common_hal_digitalio_digitalinout_never_reset(&sd_card_detect_pin);
|
||||
#endif
|
||||
}
|
||||
|
||||
void automount_sd_card(void) {
|
||||
#ifdef DEFAULT_SD_CARD_DETECT
|
||||
if (common_hal_digitalio_digitalinout_get_value(&sd_card_detect_pin) != DEFAULT_SD_CARD_INSERTED) {
|
||||
// No card.
|
||||
_init_error = false;
|
||||
if (_mounted) {
|
||||
// Unmount the card.
|
||||
mp_vfs_mount_t *cur = MP_STATE_VM(vfs_mount_table);
|
||||
if (cur == &_sdcard_vfs) {
|
||||
MP_STATE_VM(vfs_mount_table) = cur->next;
|
||||
} else {
|
||||
while (cur->next != &_sdcard_vfs && cur != NULL) {
|
||||
cur = cur->next;
|
||||
}
|
||||
if (cur != NULL) {
|
||||
cur->next = _sdcard_vfs.next;
|
||||
}
|
||||
}
|
||||
_sdcard_vfs.next = NULL;
|
||||
|
||||
#ifdef DEFAULT_SD_MOSI
|
||||
common_hal_busio_spi_deinit(&busio_spi_obj);
|
||||
#endif
|
||||
_mounted = false;
|
||||
}
|
||||
return;
|
||||
} else if (_init_error || _mounted) {
|
||||
// We've already tried and failed to init the card. Don't try again.
|
||||
return;
|
||||
}
|
||||
|
||||
busio_spi_obj_t *spi_obj;
|
||||
#ifndef DEFAULT_SD_MOSI
|
||||
spi_obj = MP_OBJ_TO_PTR(common_hal_board_create_spi(0));
|
||||
#else
|
||||
spi_obj = &busio_spi_obj;
|
||||
spi_obj->base.type = &busio_spi_type;
|
||||
common_hal_busio_spi_construct(spi_obj, DEFAULT_SD_SCK, DEFAULT_SD_MOSI, DEFAULT_SD_MISO, false);
|
||||
common_hal_busio_spi_never_reset(spi_obj);
|
||||
#endif
|
||||
sdcard.base.type = &sdcardio_SDCard_type;
|
||||
mp_rom_error_text_t error = sdcardio_sdcard_construct(&sdcard, spi_obj, DEFAULT_SD_CS, 25000000);
|
||||
if (error != NULL) {
|
||||
// Failed to communicate with the card.
|
||||
_init_error = true;
|
||||
}
|
||||
common_hal_digitalio_digitalinout_never_reset(&sdcard.cs);
|
||||
|
||||
fs_user_mount_t *vfs = &_sdcard_usermount;
|
||||
vfs->base.type = &mp_fat_vfs_type;
|
||||
vfs->fatfs.drv = vfs;
|
||||
|
||||
// Initialise underlying block device
|
||||
vfs->blockdev.block_size = FF_MIN_SS; // default, will be populated by call to MP_BLOCKDEV_IOCTL_BLOCK_SIZE
|
||||
mp_vfs_blockdev_init(&vfs->blockdev, &sdcard);
|
||||
|
||||
// mount the block device so the VFS methods can be used
|
||||
FRESULT res = f_mount(&vfs->fatfs);
|
||||
if (res != FR_OK) {
|
||||
_mounted = false;
|
||||
_init_error = true;
|
||||
common_hal_sdcardio_sdcard_deinit(&sdcard);
|
||||
#ifdef DEFAULT_SD_MOSI
|
||||
common_hal_busio_spi_deinit(spi_obj);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
filesystem_set_concurrent_write_protection(vfs, true);
|
||||
filesystem_set_writable_by_usb(vfs, false);
|
||||
|
||||
mp_vfs_mount_t *sdcard_vfs = &_sdcard_vfs;
|
||||
sdcard_vfs->str = "/sd";
|
||||
sdcard_vfs->len = 3;
|
||||
sdcard_vfs->obj = MP_OBJ_FROM_PTR(&_sdcard_usermount);
|
||||
sdcard_vfs->next = MP_STATE_VM(vfs_mount_table);
|
||||
MP_STATE_VM(vfs_mount_table) = sdcard_vfs;
|
||||
_mounted = true;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,3 +5,6 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
void sdcardio_init(void);
|
||||
void automount_sd_card(void);
|
||||
|
|
|
|||
|
|
@ -174,18 +174,23 @@ mp_obj_t common_hal_storage_getmount(const char *mount_path) {
|
|||
}
|
||||
|
||||
void common_hal_storage_remount(const char *mount_path, bool readonly, bool disable_concurrent_write_protection) {
|
||||
if (strcmp(mount_path, "/") != 0) {
|
||||
const char *path_under_mount;
|
||||
fs_user_mount_t *fs_usermount = filesystem_for_path(mount_path, &path_under_mount);
|
||||
if (path_under_mount[0] != 0 && strcmp(mount_path, "/") != 0) {
|
||||
mp_raise_OSError(MP_EINVAL);
|
||||
}
|
||||
|
||||
#if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_MSC
|
||||
if (!usb_msc_ejected() && storage_usb_is_enabled) {
|
||||
mp_raise_RuntimeError(MP_ERROR_TEXT("Cannot remount '/' when visible via USB."));
|
||||
if (!blockdev_lock(fs_usermount)) {
|
||||
mp_raise_RuntimeError(MP_ERROR_TEXT("Cannot remount path when visible via USB."));
|
||||
}
|
||||
#endif
|
||||
|
||||
filesystem_set_internal_writable_by_usb(readonly);
|
||||
filesystem_set_internal_concurrent_write_protection(!disable_concurrent_write_protection);
|
||||
filesystem_set_writable_by_usb(fs_usermount, readonly);
|
||||
filesystem_set_concurrent_write_protection(fs_usermount, !disable_concurrent_write_protection);
|
||||
blockdev_unlock(fs_usermount);
|
||||
|
||||
usb_msc_remount(fs_usermount);
|
||||
}
|
||||
|
||||
void common_hal_storage_erase_filesystem(bool extended) {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@
|
|||
#include "supervisor/flash.h"
|
||||
#include "supervisor/linker.h"
|
||||
|
||||
#if CIRCUITPY_SDCARDIO
|
||||
#include "shared-module/sdcardio/__init__.h"
|
||||
#endif
|
||||
|
||||
static mp_vfs_mount_t _circuitpy_vfs;
|
||||
static fs_user_mount_t _circuitpy_usermount;
|
||||
|
||||
|
|
@ -214,6 +218,10 @@ bool filesystem_init(bool create_allowed, bool force_create) {
|
|||
supervisor_flash_update_extended();
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_SDCARDIO
|
||||
sdcardio_init();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -288,7 +296,7 @@ fs_user_mount_t *filesystem_for_path(const char *path_in, const char **path_unde
|
|||
// because otherwise the path will be adjusted by os.getcwd() when it's looked up.
|
||||
if (strlen(vfs->str) != 1) {
|
||||
// Remove the mount point directory name, such as "/sd".
|
||||
path_under_mount += strlen(vfs->str);
|
||||
*path_under_mount += strlen(vfs->str);
|
||||
}
|
||||
}
|
||||
return fs_mount;
|
||||
|
|
|
|||
|
|
@ -21,12 +21,25 @@
|
|||
#define MSC_FLASH_BLOCK_SIZE 512
|
||||
|
||||
#if CIRCUITPY_SAVES_PARTITION_SIZE > 0
|
||||
#define LUN_COUNT 2
|
||||
#define SAVES_COUNT 1
|
||||
#define SAVES_LUN (1)
|
||||
#else
|
||||
#define LUN_COUNT 1
|
||||
#define SAVES_COUNT 0
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_SDCARDIO
|
||||
#include "shared-module/sdcardio/__init__.h"
|
||||
|
||||
#define SDCARD_COUNT 1
|
||||
#define SDCARD_LUN (1 + SAVES_COUNT)
|
||||
#else
|
||||
#define SDCARD_COUNT 0
|
||||
#endif
|
||||
|
||||
#define LUN_COUNT (1 + SAVES_COUNT + SDCARD_COUNT)
|
||||
|
||||
static bool ejected[LUN_COUNT];
|
||||
static bool eject_once[LUN_COUNT];
|
||||
static bool locked[LUN_COUNT];
|
||||
|
||||
#include "tusb.h"
|
||||
|
|
@ -103,25 +116,37 @@ size_t usb_msc_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *desc
|
|||
return sizeof(usb_msc_descriptor_template);
|
||||
}
|
||||
|
||||
// The root FS is always at the end of the list.
|
||||
// We hardcode LUN -> mount mapping so that it doesn't changes with saves and
|
||||
// SD card appearing and disappearing.
|
||||
static fs_user_mount_t *get_vfs(int lun) {
|
||||
// Keep a history of the mounts we pass so we can search back.
|
||||
mp_vfs_mount_t *mounts[LUN_COUNT];
|
||||
mp_vfs_mount_t *current_mount = MP_STATE_VM(vfs_mount_table);
|
||||
if (current_mount == NULL) {
|
||||
fs_user_mount_t *root = filesystem_circuitpy();
|
||||
if (lun == 0) {
|
||||
return root;
|
||||
}
|
||||
#ifdef SAVES_LUN
|
||||
if (lun == SAVES_LUN) {
|
||||
const char *path_under_mount;
|
||||
fs_user_mount_t *saves = filesystem_for_path("/saves", &path_under_mount);
|
||||
if (saves != root) {
|
||||
return saves;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef SDCARD_LUN
|
||||
if (lun == SDCARD_LUN) {
|
||||
const char *path_under_mount;
|
||||
fs_user_mount_t *sdcard = filesystem_for_path("/sd", &path_under_mount);
|
||||
if (sdcard != root) {
|
||||
return sdcard;
|
||||
} else {
|
||||
// Clear any ejected state so that a re-insert causes it to reappear.
|
||||
ejected[SDCARD_LUN] = false;
|
||||
locked[SDCARD_LUN] = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
// i is the last entry filled
|
||||
size_t i = 0;
|
||||
mounts[i] = current_mount;
|
||||
while (current_mount->next != NULL) {
|
||||
current_mount = current_mount->next;
|
||||
i = (i + 1) % LUN_COUNT;
|
||||
mounts[i] = current_mount;
|
||||
}
|
||||
fs_user_mount_t *vfs = mounts[(i - lun) % LUN_COUNT]->obj;
|
||||
return vfs;
|
||||
}
|
||||
|
||||
static void _usb_msc_uneject(void) {
|
||||
for (uint8_t i = 0; i < LUN_COUNT; i++) {
|
||||
|
|
@ -136,7 +161,7 @@ void usb_msc_mount(void) {
|
|||
|
||||
void usb_msc_umount(void) {
|
||||
for (uint8_t i = 0; i < LUN_COUNT; i++) {
|
||||
fs_user_mount_t *vfs = get_vfs(i + 1);
|
||||
fs_user_mount_t *vfs = get_vfs(i);
|
||||
if (vfs == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -145,12 +170,15 @@ void usb_msc_umount(void) {
|
|||
}
|
||||
}
|
||||
|
||||
bool usb_msc_ejected(void) {
|
||||
bool all_ejected = true;
|
||||
void usb_msc_remount(fs_user_mount_t *fs_mount) {
|
||||
for (uint8_t i = 0; i < LUN_COUNT; i++) {
|
||||
all_ejected &= ejected[i];
|
||||
fs_user_mount_t *vfs = get_vfs(i);
|
||||
if (vfs == NULL || vfs != fs_mount) {
|
||||
continue;
|
||||
}
|
||||
ejected[i] = false;
|
||||
eject_once[i] = true;
|
||||
}
|
||||
return all_ejected;
|
||||
}
|
||||
|
||||
uint8_t tud_msc_get_maxlun_cb(void) {
|
||||
|
|
@ -295,11 +323,18 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#if CIRCUITPY_SDCARDIO
|
||||
if (lun == SDCARD_LUN) {
|
||||
automount_sd_card();
|
||||
}
|
||||
#endif
|
||||
|
||||
fs_user_mount_t *current_mount = get_vfs(lun);
|
||||
if (current_mount == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (ejected[lun]) {
|
||||
if (ejected[lun] || eject_once[lun]) {
|
||||
eject_once[lun] = false;
|
||||
// Set 0x3a for media not present.
|
||||
tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00);
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -65,7 +65,9 @@ size_t usb_msc_descriptor_length(void);
|
|||
size_t usb_msc_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string);
|
||||
void usb_msc_mount(void);
|
||||
void usb_msc_umount(void);
|
||||
bool usb_msc_ejected(void);
|
||||
|
||||
#include "extmod/vfs_fat.h"
|
||||
void usb_msc_remount(fs_user_mount_t *fs_mount);
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_USB_KEYBOARD_WORKFLOW
|
||||
|
|
|
|||
Loading…
Reference in a new issue