From c535bf10bfe8a7d5f0c1611e492448c414cd4f03 Mon Sep 17 00:00:00 2001
From: Serge Bazanski <q3k@q3k.org>
Date: Thu, 3 Aug 2023 15:25:26 +0200
Subject: [PATCH] recovery: implement SD card disk mode

---
 recovery/main/rec_main.c | 27 +++++++++++++++++++++++----
 recovery/main/rec_vfs.c  | 38 +++++++++++++++++++++++++++++++++++---
 recovery/main/rec_vfs.h  |  3 ++-
 3 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/recovery/main/rec_main.c b/recovery/main/rec_main.c
index 5729a49f30..91aaf94c74 100644
--- a/recovery/main/rec_main.c
+++ b/recovery/main/rec_main.c
@@ -6,6 +6,7 @@
 #include "flow3r_bsp.h"
 #include "st3m_fs.h"
 #include "st3m_fs_flash.h"
+#include "st3m_fs_sd.h"
 #include "st3m_gfx.h"
 #include "st3m_io.h"
 #include "st3m_usb.h"
@@ -25,7 +26,7 @@ static bool _usb_initialized = false;
 
 static void _main_reboot(void) { esp_restart(); }
 
-static void _main_disk_mode(void) {
+static void _main_disk_mode_flash(void) {
     _cur_menu = &_diskmode_menu;
     _cur_menu->selected = 0;
 
@@ -35,7 +36,20 @@ static void _main_disk_mode(void) {
         vTaskDelay(100 / portTICK_PERIOD_MS);
     }
 
-    rec_vfs_wl_msc_start();
+    rec_vfs_wl_msc_start_flash();
+}
+
+static void _main_disk_mode_sd(void) {
+    _cur_menu = &_diskmode_menu;
+    _cur_menu->selected = 0;
+
+    if (!_usb_initialized) {
+        _usb_initialized = true;
+        st3m_usb_init();
+        vTaskDelay(100 / portTICK_PERIOD_MS);
+    }
+
+    rec_vfs_wl_msc_start_sd();
 }
 
 static void _main_erase_fat32(void) {
@@ -60,13 +74,14 @@ static void _diskmode_exit(void) {
 
 static menu_entry_t _main_menu_entries[] = {
     { .label = "Reboot", .enter = _main_reboot },
-    { .label = "Disk Mode", .enter = _main_disk_mode },
+    { .label = "Disk Mode (Flash)", .enter = _main_disk_mode_flash },
+    { .label = "Disk Mode (SD)", .enter = _main_disk_mode_sd },
     { .label = "Erase FAT32", .enter = _main_erase_fat32 },
 };
 
 static menu_t _main_menu = {
     .entries = _main_menu_entries,
-    .entries_count = 3,
+    .entries_count = 4,
     .selected = 0,
 };
 
@@ -107,6 +122,10 @@ void app_main(void) {
     st3m_io_init();
     st3m_fs_init();
 
+    if (st3m_fs_sd_get_status() != st3m_fs_sd_status_probed) {
+        _main_menu_entries[2].disabled = true;
+    }
+
     TickType_t last_wake;
     last_wake = xTaskGetTickCount();
 
diff --git a/recovery/main/rec_vfs.c b/recovery/main/rec_vfs.c
index 37accfbdef..5d802a8cb5 100644
--- a/recovery/main/rec_vfs.c
+++ b/recovery/main/rec_vfs.c
@@ -3,16 +3,17 @@
 #include "rec_fatal.h"
 
 #include "st3m_fs_flash.h"
+#include "st3m_fs_sd.h"
 #include "st3m_usb.h"
 
 #include <string.h>
 
-void rec_vfs_wl_msc_start(void) {
+void rec_vfs_wl_msc_start_flash(void) {
     st3m_usb_msc_conf_t msc = {
         .block_size = st3m_fs_flash_get_blocksize(),
         .block_count = st3m_fs_flash_get_blockcount(),
-        .product_id = { 'f', 'l', 'o', 'w', '3', 'r', 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                        0 },
+        .product_id = { 'f', 'l', 'o', 'w', '3', 'r', ' ', 'f', 'l', 'a', 's',
+                        'h', 0, 0, 0, 0 },
         .fn_read10 = st3m_fs_flash_read,
         .fn_write10 = st3m_fs_flash_write,
     };
@@ -21,4 +22,35 @@ void rec_vfs_wl_msc_start(void) {
         .disk = &msc,
     };
     st3m_usb_mode_switch(&usb_mode);
+}
+
+void rec_vfs_wl_msc_start_sd(void) {
+    st3m_fs_sd_status_t st = st3m_fs_sd_get_status();
+    if (st != st3m_fs_sd_status_probed) {
+        // TODO(q3k): don't panic
+        rec_fatal("no SD card");
+        return;
+    }
+
+    st3m_fs_sd_props_t props;
+    esp_err_t ret = st3m_fs_sd_probe(&props);
+    if (ret != ESP_OK) {
+        // TODO(q3k): don't panic
+        rec_fatal("SD card probe failed");
+        return;
+    }
+
+    st3m_usb_msc_conf_t msc = {
+        .block_size = props.sector_size,
+        .block_count = props.sector_count,
+        .product_id = { 'f', 'l', 'o', 'w', '3', 'r', ' ', 'S', 'D', 0, 0, 0, 0,
+                        0, 0, 0 },
+        .fn_read10 = st3m_fs_sd_read10,
+        .fn_write10 = st3m_fs_sd_write10,
+    };
+    st3m_usb_mode_t usb_mode = {
+        .kind = st3m_usb_mode_kind_disk,
+        .disk = &msc,
+    };
+    st3m_usb_mode_switch(&usb_mode);
 }
\ No newline at end of file
diff --git a/recovery/main/rec_vfs.h b/recovery/main/rec_vfs.h
index c74229f4a8..eadcfef907 100644
--- a/recovery/main/rec_vfs.h
+++ b/recovery/main/rec_vfs.h
@@ -1,5 +1,6 @@
 #pragma once
 
 void rec_vfs_wl_init(void);
-void rec_vfs_wl_msc_start(void);
+void rec_vfs_wl_msc_start_flash(void);
+void rec_vfs_wl_msc_start_sd(void);
 void rec_vfs_wl_erase(void);
\ No newline at end of file
-- 
GitLab