mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-10-17 02:45:05 +00:00
Update esp_tinyusb to v2.2.1
+ add error screen for usb mount failure at boot
This commit is contained in:
parent
8556103eb1
commit
3d71ba5407
@ -9,7 +9,7 @@
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <tinyusb.h>
|
||||
#include <tusb_cdc_acm.h>
|
||||
#include <tinyusb_cdc_acm.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
#include <cstdarg>
|
||||
@ -112,15 +112,14 @@ static error_t cdc_device_build_contribution(struct Device* device, struct Devic
|
||||
static error_t cdc_device_start_console(struct Device* device) {
|
||||
(void)device;
|
||||
const tinyusb_config_cdcacm_t acm_cfg = {
|
||||
.usb_dev = TINYUSB_USBDEV_0,
|
||||
.cdc_port = TINYUSB_CDC_ACM_0,
|
||||
.callback_rx = nullptr,
|
||||
.callback_rx_wanted_char = nullptr,
|
||||
.callback_line_state_changed = nullptr,
|
||||
.callback_line_coding_changed = nullptr,
|
||||
};
|
||||
if (tusb_cdc_acm_init(&acm_cfg) != ESP_OK) {
|
||||
LOG_E(TAG, "tusb_cdc_acm_init failed - CDC console unavailable");
|
||||
if (tinyusb_cdcacm_init(&acm_cfg) != ESP_OK) {
|
||||
LOG_E(TAG, "tinyusb_cdcacm_init failed - CDC console unavailable");
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
previous_vprintf = esp_log_set_vprintf(cdc_mirroring_vprintf);
|
||||
@ -135,7 +134,7 @@ static error_t cdc_device_stop_console(struct Device* device) {
|
||||
}
|
||||
esp_log_set_vprintf(previous_vprintf ? previous_vprintf : vprintf);
|
||||
previous_vprintf = nullptr;
|
||||
tusb_cdc_acm_deinit(TINYUSB_CDC_ACM_0);
|
||||
tinyusb_cdcacm_deinit(TINYUSB_CDC_ACM_0);
|
||||
cdc_console_installed = false;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
@ -12,8 +12,10 @@
|
||||
#include <freertos/task.h>
|
||||
|
||||
#include <tinyusb.h>
|
||||
#include <tinyusb_default_config.h>
|
||||
#include <tusb.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
@ -33,6 +35,15 @@ static constexpr size_t COMPOSITE_CONFIG_DESCRIPTOR_MAX = TUD_CONFIG_DESC_LEN +
|
||||
// Worst case: primary's own table (lang/mfr/product/serial/interface = 5) + CDC's own interface string.
|
||||
static constexpr size_t COMPOSITE_STRING_DESCRIPTOR_MAX = 6;
|
||||
|
||||
// Detail for the most recent claim() failure - the console can be unreachable by the time this
|
||||
// fails (route_phy_for_device_mode() already reassigned the PHY away from it), so callers read
|
||||
// this instead of relying on the LOG_E above having been visible.
|
||||
static char last_claim_error[48] = "";
|
||||
|
||||
extern "C" const char* usb_device_controller_get_last_error() {
|
||||
return last_claim_error;
|
||||
}
|
||||
|
||||
// ---- Controller state ----
|
||||
// One TinyUSB device-mode slot, shared by every USB device class (each a separate child device
|
||||
// under usbdevice0 in the devicetree; \see esp32_usb_hid_device.cpp, esp32_usb_device_msc.cpp,
|
||||
@ -256,13 +267,14 @@ static error_t claim(struct Device* device, enum UsbDeviceClass usb_class, const
|
||||
}
|
||||
|
||||
ctx->composite_tusb_cfg = {};
|
||||
ctx->composite_tusb_cfg.device_descriptor = &ctx->composite_device_descriptor;
|
||||
ctx->composite_tusb_cfg.string_descriptor = ctx->composite_string_descriptor;
|
||||
ctx->composite_tusb_cfg.string_descriptor_count = string_count;
|
||||
ctx->composite_tusb_cfg.external_phy = false;
|
||||
ctx->composite_tusb_cfg.descriptor.device = &ctx->composite_device_descriptor;
|
||||
ctx->composite_tusb_cfg.descriptor.string = ctx->composite_string_descriptor;
|
||||
ctx->composite_tusb_cfg.descriptor.string_count = (int)string_count;
|
||||
ctx->composite_tusb_cfg.phy.skip_setup = false;
|
||||
ctx->composite_tusb_cfg.task = TINYUSB_TASK_DEFAULT(); // task.size/priority can't be left 0 - rejected by tinyusb_task_check_config()
|
||||
#if (TUD_OPT_HIGH_SPEED)
|
||||
ctx->composite_tusb_cfg.fs_configuration_descriptor = ctx->composite_fs_config_descriptor;
|
||||
ctx->composite_tusb_cfg.hs_configuration_descriptor = ctx->composite_hs_config_descriptor;
|
||||
ctx->composite_tusb_cfg.descriptor.full_speed_config = ctx->composite_fs_config_descriptor;
|
||||
ctx->composite_tusb_cfg.descriptor.high_speed_config = ctx->composite_hs_config_descriptor;
|
||||
// The qualifier descriptor's class triad must mirror the device descriptor's (same IAD
|
||||
// reasoning). Built here rather than supplied per-primary since its content is boilerplate
|
||||
// (same bMaxPacketSize0/bNumConfigurations for every class) and the controller already knows
|
||||
@ -278,18 +290,20 @@ static error_t claim(struct Device* device, enum UsbDeviceClass usb_class, const
|
||||
.bNumConfigurations = 0x01,
|
||||
.bReserved = 0x00,
|
||||
};
|
||||
ctx->composite_tusb_cfg.qualifier_descriptor = &ctx->composite_device_qualifier;
|
||||
ctx->composite_tusb_cfg.descriptor.qualifier = &ctx->composite_device_qualifier;
|
||||
#else
|
||||
ctx->composite_tusb_cfg.configuration_descriptor = ctx->composite_fs_config_descriptor;
|
||||
ctx->composite_tusb_cfg.descriptor.full_speed_config = ctx->composite_fs_config_descriptor;
|
||||
#endif
|
||||
ctx->composite_tusb_cfg.self_powered = false;
|
||||
ctx->composite_tusb_cfg.vbus_monitor_io = 0;
|
||||
ctx->composite_tusb_cfg.phy.self_powered = false;
|
||||
ctx->composite_tusb_cfg.phy.vbus_monitor_io = 0;
|
||||
|
||||
route_phy_for_device_mode();
|
||||
ctx->phy_routed = true;
|
||||
|
||||
if (tinyusb_driver_install(&ctx->composite_tusb_cfg) != ESP_OK) {
|
||||
LOG_E(TAG, "claim: tinyusb_driver_install failed for class %d", usb_class);
|
||||
esp_err_t install_result = tinyusb_driver_install(&ctx->composite_tusb_cfg);
|
||||
if (install_result != ESP_OK) {
|
||||
LOG_E(TAG, "claim: tinyusb_driver_install failed for class %d: %s", usb_class, esp_err_to_name(install_result));
|
||||
snprintf(last_claim_error, sizeof(last_claim_error), "tinyusb_driver_install: %s", esp_err_to_name(install_result));
|
||||
if (ctx->phy_routed) {
|
||||
restore_default_phy_route();
|
||||
ctx->phy_routed = false;
|
||||
|
||||
@ -9,14 +9,24 @@
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <tinyusb.h>
|
||||
#include <tusb_msc_storage.h>
|
||||
#include <tinyusb_msc.h>
|
||||
#include <wear_levelling.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#define TAG "esp32_usb_device_msc"
|
||||
#define GET_CONFIG(device) ((const Esp32UsbDeviceChildConfig*)(device)->config)
|
||||
|
||||
// Detail for the most recent msc_device_start() failure - the console can be unreachable by the
|
||||
// time this fails (the controller already reassigned the PHY away from it), so callers read this
|
||||
// instead of relying on the LOG_E calls below having been visible.
|
||||
static char last_msc_error[48] = "";
|
||||
|
||||
extern "C" const char* usb_msc_device_get_last_error() {
|
||||
return last_msc_error;
|
||||
}
|
||||
|
||||
// ---- MSC device descriptor set ----
|
||||
|
||||
// Mutable, matching the other primary classes' descriptors, even though MSC's own
|
||||
@ -62,6 +72,7 @@ static uint8_t msc_hs_configuration_descriptor[TUD_MSC_DESC_LEN];
|
||||
struct UsbMscDeviceCtx {
|
||||
UsbMscDeviceMountChangedCallback mount_changed_cb = nullptr;
|
||||
void* mount_changed_context = nullptr;
|
||||
tinyusb_msc_storage_handle_t storage_handle = nullptr;
|
||||
bool storage_active = false;
|
||||
};
|
||||
|
||||
@ -70,12 +81,20 @@ struct UsbMscDeviceCtx {
|
||||
// device-mode slot the controller already enforces.
|
||||
static struct Device* active_msc_device = nullptr;
|
||||
|
||||
static void storage_mount_changed_cb(tinyusb_msc_event_t* event) {
|
||||
// esp_tinyusb 2.x's MOUNT_COMPLETE event fires for either owner taking the storage. Kernel-facing
|
||||
// UsbMscDeviceMountChangedCallback's `mounted` (\see usb_msc_device.h) means "mounted into our own
|
||||
// filesystem" (the pre-2.x meaning, kept for callers like the boot-into-MSC flow that reboot back
|
||||
// to normal OS once mounted==true) - i.e. ownership has passed to TINYUSB_MSC_STORAGE_MOUNT_APP,
|
||||
// the opposite of the initial USB-owned state this driver starts storage in.
|
||||
static void storage_mount_changed_cb(tinyusb_msc_storage_handle_t handle, tinyusb_msc_event_t* event, void* arg) {
|
||||
(void)handle;
|
||||
(void)arg;
|
||||
if (event->id != TINYUSB_MSC_EVENT_MOUNT_COMPLETE) return;
|
||||
if (active_msc_device == nullptr) return;
|
||||
auto* ctx = static_cast<UsbMscDeviceCtx*>(device_get_driver_data(active_msc_device));
|
||||
if (ctx == nullptr) return;
|
||||
|
||||
const bool mounted = event->mount_changed_data.is_mounted;
|
||||
const bool mounted = event->mount_point == TINYUSB_MSC_STORAGE_MOUNT_APP;
|
||||
LOG_I(TAG, "%s", mounted ? "MSC mounted" : "MSC unmounted");
|
||||
if (ctx->mount_changed_cb != nullptr) {
|
||||
ctx->mount_changed_cb(mounted, ctx->mount_changed_context);
|
||||
@ -131,6 +150,7 @@ static error_t msc_device_start(struct Device* device, enum UsbMscDeviceSource s
|
||||
|
||||
error_t claim_result = usb_device_controller_claim(controller, USB_DEVICE_CLASS_MSC, &claim_config);
|
||||
if (claim_result != ERROR_NONE) {
|
||||
snprintf(last_msc_error, sizeof(last_msc_error), "claim: %s", usb_device_controller_get_last_error());
|
||||
return claim_result;
|
||||
}
|
||||
|
||||
@ -139,44 +159,66 @@ static error_t msc_device_start(struct Device* device, enum UsbMscDeviceSource s
|
||||
ctx->mount_changed_context = context;
|
||||
active_msc_device = device;
|
||||
|
||||
esp_err_t result;
|
||||
if (source == USB_MSC_DEVICE_SOURCE_SDMMC) {
|
||||
const tinyusb_msc_sdmmc_config_t config_sdmmc = {
|
||||
.card = static_cast<sdmmc_card_t*>(source_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,
|
||||
},
|
||||
};
|
||||
result = tinyusb_msc_storage_init_sdmmc(&config_sdmmc);
|
||||
} else {
|
||||
const tinyusb_msc_spiflash_config_t config_flash = {
|
||||
.wl_handle = *static_cast<wl_handle_t*>(source_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,
|
||||
},
|
||||
};
|
||||
result = tinyusb_msc_storage_init_spiflash(&config_flash);
|
||||
}
|
||||
|
||||
// esp_tinyusb 2.x auto-remounts storage on every tud_mount_cb()/tud_umount_cb(), including
|
||||
// the bus resets that happen as a normal part of USB enumeration - not just a genuine host
|
||||
// eject. Left enabled, that fires a spurious "mounted into our own fs" transition almost
|
||||
// immediately after claim(), which callers like the boot-into-MSC flow read as "the host is
|
||||
// done with it" and act on right away. Disabling it restores the old (pre-2.x) behavior:
|
||||
// mount_point only changes via an explicit host SCSI eject or our own start/stop calls.
|
||||
const tinyusb_msc_driver_config_t driver_cfg = {
|
||||
.user_flags = { .val = 1 }, // auto_mount_off
|
||||
.callback = storage_mount_changed_cb,
|
||||
.callback_arg = nullptr,
|
||||
};
|
||||
esp_err_t result = tinyusb_msc_install_driver(&driver_cfg);
|
||||
if (result != ESP_OK) {
|
||||
LOG_E(TAG, "storage init failed: %s", esp_err_to_name(result));
|
||||
LOG_E(TAG, "MSC driver install failed: %s", esp_err_to_name(result));
|
||||
snprintf(last_msc_error, sizeof(last_msc_error), "install_driver: %s", esp_err_to_name(result));
|
||||
active_msc_device = nullptr;
|
||||
usb_device_controller_release(controller, USB_DEVICE_CLASS_MSC);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
const tinyusb_msc_fatfs_config_t fat_fs_config = {
|
||||
.base_path = nullptr, // use CONFIG_TINYUSB_MSC_MOUNT_PATH default
|
||||
.config = {
|
||||
.format_if_mount_failed = false,
|
||||
.max_files = 5,
|
||||
.allocation_unit_size = 0,
|
||||
.disk_status_check_enable = false,
|
||||
.use_one_fat = false,
|
||||
},
|
||||
.do_not_format = false,
|
||||
.format_flags = 0, // FM_ANY
|
||||
};
|
||||
|
||||
tinyusb_msc_storage_handle_t handle = nullptr;
|
||||
if (source == USB_MSC_DEVICE_SOURCE_SDMMC) {
|
||||
const tinyusb_msc_storage_config_t config_sdmmc = {
|
||||
.medium = { .card = static_cast<sdmmc_card_t*>(source_handle) },
|
||||
.fat_fs = fat_fs_config,
|
||||
.mount_point = TINYUSB_MSC_STORAGE_MOUNT_USB,
|
||||
};
|
||||
result = tinyusb_msc_new_storage_sdmmc(&config_sdmmc, &handle);
|
||||
} else {
|
||||
const tinyusb_msc_storage_config_t config_flash = {
|
||||
.medium = { .wl_handle = *static_cast<wl_handle_t*>(source_handle) },
|
||||
.fat_fs = fat_fs_config,
|
||||
.mount_point = TINYUSB_MSC_STORAGE_MOUNT_USB,
|
||||
};
|
||||
result = tinyusb_msc_new_storage_spiflash(&config_flash, &handle);
|
||||
}
|
||||
|
||||
if (result != ESP_OK) {
|
||||
LOG_E(TAG, "storage init failed: %s", esp_err_to_name(result));
|
||||
snprintf(last_msc_error, sizeof(last_msc_error), "new_storage: %s", esp_err_to_name(result));
|
||||
tinyusb_msc_uninstall_driver();
|
||||
active_msc_device = nullptr;
|
||||
usb_device_controller_release(controller, USB_DEVICE_CLASS_MSC);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
ctx->storage_handle = handle;
|
||||
ctx->storage_active = true;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
@ -194,8 +236,10 @@ static error_t msc_device_stop(struct Device* device) {
|
||||
auto* controller = device_get_parent(device);
|
||||
usb_device_controller_release(controller, USB_DEVICE_CLASS_MSC);
|
||||
|
||||
tinyusb_msc_storage_deinit();
|
||||
tinyusb_msc_delete_storage(ctx->storage_handle);
|
||||
tinyusb_msc_uninstall_driver();
|
||||
|
||||
ctx->storage_handle = nullptr;
|
||||
ctx->storage_active = false;
|
||||
ctx->mount_changed_cb = nullptr;
|
||||
ctx->mount_changed_context = nullptr;
|
||||
|
||||
@ -16,6 +16,8 @@ enum class BootMode {
|
||||
};
|
||||
|
||||
bool startMassStorageWithSdmmc(bool fromBootMode = false);
|
||||
// Reason the most recent startMassStorageWith*() call failed, or "" if it succeeded.
|
||||
const char* getLastError();
|
||||
void stop();
|
||||
Mode getMode();
|
||||
bool isSupported();
|
||||
|
||||
@ -4,4 +4,7 @@ bool tusbIsSupported();
|
||||
bool tusbStartMassStorageWithSdmmc(bool fromBootMode = false);
|
||||
bool tusbStartMassStorageWithFlash(bool fromBootMode = false);
|
||||
void tusbStop();
|
||||
bool tusbCanStartMassStorageWithFlash();
|
||||
bool tusbCanStartMassStorageWithFlash();
|
||||
|
||||
// Reason the most recent tusbStartMassStorageWith*() call failed, or "" if it succeeded.
|
||||
const char* tusbGetLastError();
|
||||
@ -1,3 +1,4 @@
|
||||
#include "Tactility/app/alertdialog/AlertDialog.h"
|
||||
#include "tactility/memory.h"
|
||||
#include "tactility/system_event.h"
|
||||
|
||||
@ -56,6 +57,10 @@ std::atomic<bool> isUsbBootSplash = false;
|
||||
// window to an error screen and halts before starting the next app.
|
||||
std::atomic<bool> sdCardMissing = false;
|
||||
|
||||
// Set when setupUsbBootMode() fails
|
||||
std::atomic<bool> usbBootModeFailed = false;
|
||||
std::string usbBootModeFailedReason;
|
||||
|
||||
uint32_t bootAppInstanceId = 0;
|
||||
WindowId bootWindowId = 0;
|
||||
|
||||
@ -108,6 +113,8 @@ void setupDisplay() {
|
||||
device_put(display);
|
||||
}
|
||||
|
||||
// Returns true if either the MSC screen or the failure screen now owns the display, in which
|
||||
// case the caller must not proceed to the normal boot path (registerApps()/startNextApp()).
|
||||
bool setupUsbBootMode() {
|
||||
if (!hal::usb::isUsbBootMode()) {
|
||||
return false;
|
||||
@ -116,16 +123,18 @@ bool setupUsbBootMode() {
|
||||
LOG_I(TAG, "Rebooting into mass storage device mode");
|
||||
auto mode = hal::usb::getUsbBootMode(); // Get mode before reset
|
||||
hal::usb::resetUsbBootMode();
|
||||
delay_millis(3000);
|
||||
|
||||
bool started = false;
|
||||
if (mode == hal::usb::BootMode::Flash) {
|
||||
if (!hal::usb::startMassStorageWithFlash(true)) {
|
||||
LOG_E(TAG, "Unable to start flash mass storage");
|
||||
return false;
|
||||
}
|
||||
started = hal::usb::startMassStorageWithFlash(true);
|
||||
} else if (mode == hal::usb::BootMode::Sdmmc) {
|
||||
if (!hal::usb::startMassStorageWithSdmmc(true)) {
|
||||
LOG_E(TAG, "Unable to start SD mass storage");
|
||||
return false;
|
||||
}
|
||||
started = hal::usb::startMassStorageWithSdmmc(true);
|
||||
}
|
||||
|
||||
if (!started) {
|
||||
usbBootModeFailedReason = hal::usb::getLastError();
|
||||
usbBootModeFailed = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -237,6 +246,36 @@ void showSdCardMissingScreen() {
|
||||
bootWindowId = window_manager_create(bootAppInstanceId, createSdCardMissingWidgets, nullptr);
|
||||
}
|
||||
|
||||
void createUsbBootModeFailedWidgets(lv_obj_t* root, void*) {
|
||||
lvgl::obj_set_style_bg_blacken(root);
|
||||
lv_obj_set_style_border_width(root, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_radius(root, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_set_flex_flow(root, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_align(root, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
|
||||
auto* label = lv_label_create(root);
|
||||
lv_label_set_text(label, std::format("Failed to start USB mass storage:\n{}", usbBootModeFailedReason).c_str());
|
||||
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_text_color(label, lv_color_white(), LV_STATE_DEFAULT);
|
||||
|
||||
auto* button = lv_button_create(root);
|
||||
lv_obj_set_style_margin_top(button, 16, LV_STATE_DEFAULT);
|
||||
auto* button_label = lv_label_create(button);
|
||||
lv_label_set_text(button_label, "Reboot");
|
||||
lv_obj_add_event_cb(button, [](lv_event_t*) {
|
||||
#ifdef ESP_PLATFORM
|
||||
esp_restart();
|
||||
#endif
|
||||
}, LV_EVENT_SHORT_CLICKED, nullptr);
|
||||
}
|
||||
|
||||
void showUsbBootModeFailedScreen() {
|
||||
if (bootWindowId != 0) {
|
||||
window_manager_remove(bootWindowId);
|
||||
}
|
||||
bootWindowId = window_manager_create(bootAppInstanceId, createUsbBootModeFailedWidgets, nullptr);
|
||||
}
|
||||
|
||||
void startNextApp() {
|
||||
if (sdCardMissing) {
|
||||
showSdCardMissingScreen();
|
||||
@ -278,8 +317,10 @@ void runBootSequence(TickType_t startTime) {
|
||||
#endif
|
||||
|
||||
if (setupUsbBootMode()) {
|
||||
// Stay open: the splash's "Return to OS" button is this app's only way to leave mass
|
||||
// storage mode, so it must not self-close here like the normal boot path does below.
|
||||
if (usbBootModeFailed) {
|
||||
showUsbBootModeFailedScreen();
|
||||
}
|
||||
// Stay open: the splash's "Return to OS" button or the failure screen's "Reboot" button.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -67,6 +67,10 @@ bool startMassStorageWithSdmmc(bool fromBootMode) {
|
||||
}
|
||||
}
|
||||
|
||||
const char* getLastError() {
|
||||
return tusbGetLastError();
|
||||
}
|
||||
|
||||
void stop() {
|
||||
if (canStartNewMode()) {
|
||||
return;
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
namespace tt::hal::usb {
|
||||
|
||||
bool startMassStorageWithSdmmc(bool /*fromBootMode*/) { return false; }
|
||||
const char* getLastError() { return ""; }
|
||||
void stop() {}
|
||||
Mode getMode() { return Mode::Default; }
|
||||
BootMode getUsbBootMode() { return BootMode::None; }
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
#include <freertos/task.h>
|
||||
#include <wear_levelling.h>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/drivers/esp32_sdcard.h>
|
||||
#include <tactility/drivers/usb_msc_device.h>
|
||||
@ -25,6 +27,8 @@ namespace tt::hal::usb {
|
||||
// Used to decide whether ejecting the volume should automatically reboot back to normal OS.
|
||||
static bool startedFromBootMode = false;
|
||||
|
||||
static char lastErrorMessage[96] = "";
|
||||
|
||||
static sdmmc_card_t* getCard() {
|
||||
sdmmc_card_t* card = nullptr;
|
||||
|
||||
@ -70,12 +74,14 @@ bool tusbStartMassStorageWithSdmmc(bool fromBootMode) {
|
||||
auto* device = usb_msc_device_get();
|
||||
if (device == nullptr) {
|
||||
LOG_E(TAG, "USB MSC device not available");
|
||||
snprintf(tt::hal::usb::lastErrorMessage, sizeof(tt::hal::usb::lastErrorMessage), "USB MSC device not available");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* card = tt::hal::usb::getCard();
|
||||
if (card == nullptr) {
|
||||
LOG_E(TAG, "SD card not mounted");
|
||||
snprintf(tt::hal::usb::lastErrorMessage, sizeof(tt::hal::usb::lastErrorMessage), "SD card not mounted");
|
||||
device_put(device);
|
||||
return false;
|
||||
}
|
||||
@ -86,6 +92,7 @@ bool tusbStartMassStorageWithSdmmc(bool fromBootMode) {
|
||||
tt::hal::usb::onMountChanged, nullptr);
|
||||
if (result != ERROR_NONE) {
|
||||
LOG_E(TAG, "TinyUSB SDMMC init failed: %s", error_to_string(result));
|
||||
snprintf(tt::hal::usb::lastErrorMessage, sizeof(tt::hal::usb::lastErrorMessage), "SDMMC init failed: %s (%s)", error_to_string(result), usb_msc_device_get_last_error());
|
||||
} else {
|
||||
LOG_I(TAG, "TinyUSB SDMMC init success");
|
||||
}
|
||||
@ -100,12 +107,14 @@ bool tusbStartMassStorageWithFlash(bool fromBootMode) {
|
||||
auto* device = usb_msc_device_get();
|
||||
if (device == nullptr) {
|
||||
LOG_E(TAG, "USB MSC device not available");
|
||||
snprintf(tt::hal::usb::lastErrorMessage, sizeof(tt::hal::usb::lastErrorMessage), "USB MSC device not available");
|
||||
return false;
|
||||
}
|
||||
|
||||
wl_handle_t handle = tt::getDataPartitionWlHandle();
|
||||
if (handle == WL_INVALID_HANDLE) {
|
||||
LOG_E(TAG, "WL not mounted for /data");
|
||||
snprintf(tt::hal::usb::lastErrorMessage, sizeof(tt::hal::usb::lastErrorMessage), "WL not mounted for /data");
|
||||
device_put(device);
|
||||
return false;
|
||||
}
|
||||
@ -116,6 +125,7 @@ bool tusbStartMassStorageWithFlash(bool fromBootMode) {
|
||||
&handle, tt::hal::usb::onMountChanged, nullptr);
|
||||
if (result != ERROR_NONE) {
|
||||
LOG_E(TAG, "TinyUSB flash init failed: %s", error_to_string(result));
|
||||
snprintf(tt::hal::usb::lastErrorMessage, sizeof(tt::hal::usb::lastErrorMessage), "Flash init failed: %s (%s)", error_to_string(result), usb_msc_device_get_last_error());
|
||||
} else {
|
||||
LOG_I(TAG, "TinyUSB flash init success");
|
||||
}
|
||||
@ -123,6 +133,10 @@ bool tusbStartMassStorageWithFlash(bool fromBootMode) {
|
||||
return result == ERROR_NONE;
|
||||
}
|
||||
|
||||
const char* tusbGetLastError() {
|
||||
return tt::hal::usb::lastErrorMessage;
|
||||
}
|
||||
|
||||
void tusbStop() {
|
||||
auto* device = usb_msc_device_get();
|
||||
if (device != nullptr) {
|
||||
@ -142,6 +156,7 @@ bool tusbStartMassStorageWithSdmmc(bool /*fromBootMode*/) { return false; }
|
||||
bool tusbStartMassStorageWithFlash(bool /*fromBootMode*/) { return false; }
|
||||
void tusbStop() {}
|
||||
bool tusbCanStartMassStorageWithFlash() { return false; }
|
||||
const char* tusbGetLastError() { return ""; }
|
||||
|
||||
#endif // CONFIG_TINYUSB_MSC_ENABLED
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@ dependencies:
|
||||
- if: "target in [esp32p4]"
|
||||
espressif/esp_lcd_panel_io_additions: "1.0.1"
|
||||
espressif/esp_tinyusb:
|
||||
version: "1.7.6~1"
|
||||
version: "2.2.1"
|
||||
rules:
|
||||
- if: "target in [esp32s3, esp32p4]"
|
||||
espressif/esp_lvgl_port: "2.7.2"
|
||||
|
||||
@ -183,6 +183,9 @@ error_t usb_device_controller_allocate_interfaces(struct Device* device, uint8_t
|
||||
struct UsbInterfaceAllocation* out_allocation);
|
||||
error_t usb_device_controller_claim(struct Device* device, enum UsbDeviceClass usb_class,
|
||||
const struct UsbDeviceClaimConfig* config);
|
||||
|
||||
/** Detail string (e.g. an esp_err_t name) for the most recent claim() failure, or "" if none. */
|
||||
const char* usb_device_controller_get_last_error(void);
|
||||
error_t usb_device_controller_release(struct Device* device, enum UsbDeviceClass usb_class);
|
||||
enum UsbDeviceClass usb_device_controller_get_active_class(struct Device* device);
|
||||
bool usb_device_controller_is_cdc_enabled(struct Device* device);
|
||||
|
||||
@ -85,6 +85,9 @@ error_t usb_msc_device_start(struct Device* device, enum UsbMscDeviceSource sour
|
||||
error_t usb_msc_device_stop(struct Device* device);
|
||||
bool usb_msc_device_is_connected(struct Device* device);
|
||||
|
||||
/** Detail string for the most recent usb_msc_device_start() failure, or "" if none. */
|
||||
const char* usb_msc_device_get_last_error(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user