mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-18 10:53:17 +00:00
Access to the "/data" partition via USB Mass Storage (#405)
This commit is contained in:
parent
e2ec39304c
commit
ab2aa2c4d4
@ -5,7 +5,14 @@ namespace tt::hal::usb {
|
||||
enum class Mode {
|
||||
Default, // Default state of USB stack
|
||||
None, // State after TinyUSB was used and (partially) deinitialized
|
||||
MassStorageSdmmc
|
||||
MassStorageSdmmc,
|
||||
MassStorageFlash // For internal flash /data partition
|
||||
};
|
||||
|
||||
enum class BootMode {
|
||||
None,
|
||||
Sdmmc,
|
||||
Flash
|
||||
};
|
||||
|
||||
bool startMassStorageWithSdmmc();
|
||||
@ -18,4 +25,11 @@ void rebootIntoMassStorageSdmmc();
|
||||
bool isUsbBootMode();
|
||||
void resetUsbBootMode();
|
||||
|
||||
BootMode getUsbBootMode();
|
||||
|
||||
// Flash-based mass storage
|
||||
bool startMassStorageWithFlash();
|
||||
bool canRebootIntoMassStorageFlash();
|
||||
void rebootIntoMassStorageFlash();
|
||||
|
||||
}
|
||||
@ -3,10 +3,12 @@
|
||||
#ifdef ESP_PLATFORM
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_vfs_fat.h"
|
||||
|
||||
namespace tt {
|
||||
|
||||
esp_err_t initPartitionsEsp();
|
||||
wl_handle_t getDataPartitionWlHandle();
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
@ -2,4 +2,6 @@
|
||||
|
||||
bool tusbIsSupported();
|
||||
bool tusbStartMassStorageWithSdmmc();
|
||||
bool tusbStartMassStorageWithFlash();
|
||||
void tusbStop();
|
||||
bool tusbCanStartMassStorageWithFlash();
|
||||
@ -22,6 +22,10 @@ static esp_err_t initNvsFlashSafely() {
|
||||
|
||||
static wl_handle_t data_wl_handle = WL_INVALID_HANDLE;
|
||||
|
||||
wl_handle_t getDataPartitionWlHandle() {
|
||||
return data_wl_handle;
|
||||
}
|
||||
|
||||
size_t getSectorSize() {
|
||||
#if defined(CONFIG_FATFS_SECTOR_512)
|
||||
return 512;
|
||||
|
||||
@ -71,8 +71,19 @@ class BootApp : public App {
|
||||
}
|
||||
|
||||
TT_LOG_I(TAG, "Rebooting into mass storage device mode");
|
||||
auto mode = hal::usb::getUsbBootMode(); // Get mode before reset
|
||||
hal::usb::resetUsbBootMode();
|
||||
hal::usb::startMassStorageWithSdmmc();
|
||||
if (mode == hal::usb::BootMode::Flash) {
|
||||
if (!hal::usb::startMassStorageWithFlash()) {
|
||||
TT_LOG_E(TAG, "Unable to start flash mass storage");
|
||||
return false;
|
||||
}
|
||||
} else if (mode == hal::usb::BootMode::Sdmmc) {
|
||||
if (!hal::usb::startMassStorageWithSdmmc()) {
|
||||
TT_LOG_E(TAG, "Unable to start SD mass storage");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -11,32 +11,50 @@
|
||||
|
||||
namespace tt::app::usbsettings {
|
||||
|
||||
static void onRebootMassStorage(TT_UNUSED lv_event_t* event) {
|
||||
static void onRebootMassStorageSdmmc(TT_UNUSED lv_event_t* event) {
|
||||
hal::usb::rebootIntoMassStorageSdmmc();
|
||||
}
|
||||
|
||||
// Flash reboot handler
|
||||
static void onRebootMassStorageFlash(TT_UNUSED lv_event_t* event) {
|
||||
hal::usb::rebootIntoMassStorageFlash();
|
||||
}
|
||||
|
||||
class UsbSettingsApp : public App {
|
||||
|
||||
void onShow(AppContext& app, lv_obj_t* parent) override {
|
||||
auto* toolbar = lvgl::toolbar_create(parent, app);
|
||||
lv_obj_align(toolbar, LV_ALIGN_TOP_MID, 0, 0);
|
||||
|
||||
if (hal::usb::canRebootIntoMassStorageSdmmc()) {
|
||||
auto* button = lv_button_create(parent);
|
||||
auto* label = lv_label_create(button);
|
||||
lv_label_set_text(label, "Reboot as USB storage");
|
||||
lv_obj_align(button, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_add_event_cb(button, onRebootMassStorage, LV_EVENT_SHORT_CLICKED, nullptr);
|
||||
} else {
|
||||
// Create a wrapper container for buttons
|
||||
auto* wrapper = lv_obj_create(parent);
|
||||
lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_align(wrapper, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_set_size(wrapper, lv_pct(100), LV_SIZE_CONTENT);
|
||||
lv_obj_align(wrapper, LV_ALIGN_CENTER, 0, 0);
|
||||
|
||||
bool hasSd = hal::usb::canRebootIntoMassStorageSdmmc();
|
||||
bool hasFlash = hal::usb::canRebootIntoMassStorageFlash();
|
||||
|
||||
if (hasSd) {
|
||||
auto* button_sd = lv_button_create(wrapper);
|
||||
auto* label_sd = lv_label_create(button_sd);
|
||||
lv_label_set_text(label_sd, "Reboot as USB storage (SD)");
|
||||
lv_obj_add_event_cb(button_sd, onRebootMassStorageSdmmc, LV_EVENT_SHORT_CLICKED, nullptr);
|
||||
}
|
||||
|
||||
if (hasFlash) {
|
||||
auto* button_flash = lv_button_create(wrapper);
|
||||
auto* label_flash = lv_label_create(button_flash);
|
||||
lv_label_set_text(label_flash, "Reboot as USB storage (Flash)");
|
||||
lv_obj_add_event_cb(button_flash, onRebootMassStorageFlash, LV_EVENT_SHORT_CLICKED, nullptr);
|
||||
}
|
||||
|
||||
if (!hasSd && !hasFlash) {
|
||||
bool supported = hal::usb::isSupported();
|
||||
const char* first = supported ? "USB storage not available:" : "USB driver not supported";
|
||||
const char* second = supported ? "SD card not mounted" : "on this hardware";
|
||||
auto* label_a = lv_label_create(parent);
|
||||
lv_label_set_text(label_a, first);
|
||||
lv_obj_align(label_a, LV_ALIGN_CENTER, 0, 0);
|
||||
auto* label_b = lv_label_create(parent);
|
||||
lv_label_set_text(label_b, second);
|
||||
lv_obj_align_to(label_b, label_a, LV_ALIGN_OUT_BOTTOM_MID, 0, 4);
|
||||
const char* message = supported ? "USB storage not available" : "USB driver not supported";
|
||||
auto* label = lv_label_create(wrapper);
|
||||
lv_label_set_text(label, message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -9,14 +9,15 @@
|
||||
namespace tt::hal::usb {
|
||||
|
||||
constexpr auto* TAG = "usb";
|
||||
constexpr auto BOOT_FLAG = 42;
|
||||
constexpr auto BOOT_FLAG_SDMMC = 42; // Existing
|
||||
constexpr auto BOOT_FLAG_FLASH = 43; // For flash mode
|
||||
|
||||
struct BootMode {
|
||||
struct BootModeData {
|
||||
uint32_t flag = 0;
|
||||
};
|
||||
|
||||
static Mode currentMode = Mode::Default;
|
||||
static RTC_NOINIT_ATTR BootMode bootMode;
|
||||
static RTC_NOINIT_ATTR BootModeData bootModeData;
|
||||
|
||||
sdmmc_card_t* _Nullable getCard() {
|
||||
auto sdcards = findDevices<sdcard::SpiSdCardDevice>(Device::Type::SdCard);
|
||||
@ -87,17 +88,55 @@ bool canRebootIntoMassStorageSdmmc() {
|
||||
|
||||
void rebootIntoMassStorageSdmmc() {
|
||||
if (tusbIsSupported()) {
|
||||
bootMode.flag = BOOT_FLAG;
|
||||
bootModeData.flag = BOOT_FLAG_SDMMC;
|
||||
esp_restart();
|
||||
}
|
||||
}
|
||||
|
||||
// NEW: Flash mass storage functions
|
||||
bool startMassStorageWithFlash() {
|
||||
if (!canStartNewMode()) {
|
||||
TT_LOG_E(TAG, "Can't start flash mass storage");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tusbStartMassStorageWithFlash()) {
|
||||
currentMode = Mode::MassStorageFlash;
|
||||
return true;
|
||||
} else {
|
||||
TT_LOG_E(TAG, "Failed to init flash mass storage");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool canRebootIntoMassStorageFlash() {
|
||||
return tusbCanStartMassStorageWithFlash();
|
||||
}
|
||||
|
||||
void rebootIntoMassStorageFlash() {
|
||||
if (tusbCanStartMassStorageWithFlash()) {
|
||||
bootModeData.flag = BOOT_FLAG_FLASH;
|
||||
esp_restart();
|
||||
}
|
||||
}
|
||||
|
||||
bool isUsbBootMode() {
|
||||
return bootMode.flag == BOOT_FLAG;
|
||||
return bootModeData.flag == BOOT_FLAG_SDMMC || bootModeData.flag == BOOT_FLAG_FLASH; // Support both
|
||||
}
|
||||
|
||||
BootMode getUsbBootMode() {
|
||||
switch (bootModeData.flag) {
|
||||
case BOOT_FLAG_SDMMC:
|
||||
return BootMode::Sdmmc;
|
||||
case BOOT_FLAG_FLASH:
|
||||
return BootMode::Flash;
|
||||
default:
|
||||
return BootMode::None;
|
||||
}
|
||||
}
|
||||
|
||||
void resetUsbBootMode() {
|
||||
bootMode.flag = 0;
|
||||
bootModeData.flag = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -9,10 +9,14 @@ namespace tt::hal::usb {
|
||||
bool startMassStorageWithSdmmc() { return false; }
|
||||
void stop() {}
|
||||
Mode getMode() { return Mode::Default; }
|
||||
BootMode getUsbBootMode() { return BootMode::None; }
|
||||
bool isSupported() { return false; }
|
||||
|
||||
bool canRebootIntoMassStorageSdmmc() { return false; }
|
||||
void rebootIntoMassStorageSdmmc() {}
|
||||
bool startMassStorageWithFlash() { return false; }
|
||||
bool canRebootIntoMassStorageFlash() { return false; }
|
||||
void rebootIntoMassStorageFlash() {}
|
||||
bool isUsbBootMode() { return false; }
|
||||
void resetUsbBootMode() {}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#ifdef ESP_PLATFORM
|
||||
|
||||
#include "Tactility/hal/usb/UsbTusb.h"
|
||||
#include <Tactility/PartitionsEsp.h>
|
||||
|
||||
#include <sdkconfig.h>
|
||||
|
||||
@ -9,10 +10,12 @@
|
||||
#include <Tactility/Log.h>
|
||||
#include <tinyusb.h>
|
||||
#include <tusb_msc_storage.h>
|
||||
#include <wear_levelling.h>
|
||||
|
||||
#define TAG "usb"
|
||||
#define EPNUM_MSC 1
|
||||
#define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_MSC_DESC_LEN)
|
||||
#define SECTOR_SIZE 512
|
||||
|
||||
namespace tt::hal::usb {
|
||||
extern sdmmc_card_t* _Nullable getCard();
|
||||
@ -90,9 +93,9 @@ static uint8_t const msc_hs_configuration_desc[] = {
|
||||
|
||||
static void storage_mount_changed_cb(tinyusb_msc_event_t* event) {
|
||||
if (event->mount_changed_data.is_mounted) {
|
||||
TT_LOG_I(TAG, "Mounted");
|
||||
TT_LOG_I(TAG, "MSC Mounted");
|
||||
} else {
|
||||
TT_LOG_I(TAG, "Unmounted");
|
||||
TT_LOG_I(TAG, "MSC Unmounted");
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,22 +155,62 @@ bool tusbStartMassStorageWithSdmmc() {
|
||||
|
||||
auto result = tinyusb_msc_storage_init_sdmmc(&config_sdmmc);
|
||||
if (result != ESP_OK) {
|
||||
TT_LOG_E(TAG, "TinyUSB init failed: %s", esp_err_to_name(result));
|
||||
TT_LOG_E(TAG, "TinyUSB SDMMC init failed: %s", esp_err_to_name(result));
|
||||
} else {
|
||||
TT_LOG_I(TAG, "TinyUSB SDMMC init success");
|
||||
}
|
||||
|
||||
return result == ESP_OK;
|
||||
}
|
||||
|
||||
bool tusbStartMassStorageWithFlash() {
|
||||
TT_LOG_I(TAG, "Starting flash MSC");
|
||||
ensureDriverInstalled();
|
||||
|
||||
wl_handle_t handle = tt::getDataPartitionWlHandle();
|
||||
if (handle == WL_INVALID_HANDLE) {
|
||||
TT_LOG_E(TAG, "WL not mounted for /data");
|
||||
return false;
|
||||
}
|
||||
|
||||
const tinyusb_msc_spiflash_config_t config_flash = {
|
||||
.wl_handle = handle,
|
||||
.callback_mount_changed = storage_mount_changed_cb,
|
||||
.callback_premount_changed = nullptr,
|
||||
.mount_config = {
|
||||
.format_if_mount_failed = false,
|
||||
.max_files = 5,
|
||||
.allocation_unit_size = 0,
|
||||
.disk_status_check_enable = false,
|
||||
.use_one_fat = false
|
||||
}
|
||||
};
|
||||
|
||||
esp_err_t result = tinyusb_msc_storage_init_spiflash(&config_flash);
|
||||
if (result != ESP_OK) {
|
||||
TT_LOG_E(TAG, "TinyUSB flash init failed: %s", esp_err_to_name(result));
|
||||
} else {
|
||||
TT_LOG_I(TAG, "TinyUSB flash init success");
|
||||
}
|
||||
return result == ESP_OK;
|
||||
}
|
||||
|
||||
void tusbStop() {
|
||||
tinyusb_msc_storage_deinit();
|
||||
}
|
||||
|
||||
bool tusbCanStartMassStorageWithFlash() {
|
||||
return tusbIsSupported() && (tt::getDataPartitionWlHandle() != WL_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool tusbIsSupported() { return false; }
|
||||
bool tusbStartMassStorageWithSdmmc() { return false; }
|
||||
bool tusbStartMassStorageWithFlash() { return false; }
|
||||
void tusbStop() {}
|
||||
bool tusbCanStartMassStorageWithFlash() { return false; }
|
||||
|
||||
#endif // TinyUSB enabled
|
||||
#endif // CONFIG_TINYUSB_MSC_ENABLED
|
||||
|
||||
#endif // ESP_PLATFORM
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user