mirror of
https://github.com/meshtastic/firmware.git
synced 2026-05-29 19:24:46 -04:00
* Migrate esp32 families to pioarduino platform
* ESP32c6 align text.handler_execute same as C3
* Use pioarduino `develop`
The latest fixes and the latest bugs!
* preliminary esp32p4.ini
* pioarduino: Update LovyanGFX
Includes Manuel's recent commit
* pioarduino 3.3.6
* pioarduino 3.3.6 *release*
chasing the release
* pioarduino: Fix OG ESP32 duplicate libs
* pioarduino: T-Beam 1W CDC mode
* pioarduino: disable network provisioning (wifiprov)
* pioarduino: use legacy esptoolpy naming (forward-compatible)
* Update lovyangfx from `develop` commit to 1.2.19
* fix esp32p4.ini
* check for esp32 w/ wifi
* esp32-p4 specific adaptations
* Switch to meshtastic/esp32_https_server fork (idf5 branch)
* don't ignore esp_lcd
* config for MUI
* fix/workaround SDMMC
* revert a6f6175, update to 3.3.8
* enable esp_hosted for esp32-p4 (experimental)
* Pioarduino 55.03.38-1
* NimBLE-Arduino -> Arduino "BLE" (3.3.x) migration (#10164)
* NimBLE-Arduino -> Arduino "BLE" (3.3.x) migration
* More NimBLE
* Fix Device Name in ATT Read Request (0x2A00).
Device Name is exposed in two places:
- Advertisement data: this is set properly in startAdvertising.
- GATT attribute Device Name (0x2A00). This one is handled internally in NimBLE
and comes from ble_svc_gap_device_name_set. This is set initially, but then
BLEDevice::createServer calls ble_svc_gap_init which resets the device name.
This causes the device to apparently "change name after pairing":
< ACL Data TX:... flags 0x00 dlen 7 #113 [hci0] 14.241149
ATT: Read Request (0x0a) len 2
Handle: 0x0003 Type: Device Name (0x2a00)
> ACL Data RX: Handle 2048 flags 0x02 dlen 11 #115 [hci0] 14.269050
ATT: Read Response (0x0b) len 6
Value[6]: 6e696d626c65 # "nimble"
Workaround this by setting the device name once again after
BLEDevice::createServer.
* Temporarily lower CORE_DEBUG_LEVEL to INFO to avoid triggering an apparent ESP-IDF Bluetooth bug when re-connecting to Pixel 8 Android devices.
Initial pairing works, but after ESP32 is rebooted, phone fails to reconnect. Meshtastic app shows it as disconnecting immediately. LightBlue shows a more detailed error "Peripheral Connection - Warning: onConnectionStatusChange: status 61" (0x3D - MIC Failure).
Bug report to Espresssif: https://github.com/espressif/esp-idf/issues/18126#issuecomment-4286197744
* Temporarily disable ble_gap_set_data_len, causes crash with Pixel 8 Android reconnect.
Crash looks like this:
[ 11966][E][BLEAdvertising.cpp:341] setScanResponseData(): ble_gap_adv_rsp_set_data: 22
[ 11975][E][BLEAdvertising.cpp:1554] start(): Host reset, wait for sync.
ERROR | ??:??:?? 11 BLE failed to start advertising
Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x420e6190 PS : 0x00060730 A0 : 0x820e158b A1 : 0x3fce50c0
A2 : 0x00000000 A3 : 0x3fcb8600 A4 : 0x3fcb85cc A5 : 0x00000000
A6 : 0x00000000 A7 : 0x00000c03 A8 : 0x00000000 A9 : 0x3fce50b0
A10 : 0x0000000e A11 : 0x00000000 A12 : 0x00000010 A13 : 0x3fce50e0
A14 : 0x00000c03 A15 : 0x00000001 SAR : 0x0000001e EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000 LBEG : 0x400570e8 LEND : 0x400570f3 LCOUNT : 0x00000000
Backtrace: 0x420e618d:0x3fce50c0 0x420e1588:0x3fce5110 0x420dfe87:0x3fce5200 0x420dfefb:0x3fce5220 0x420dff3f:0x3fce5240 0x4219602b:0x3fce5260 0x4037b0e5:0x3fce5280 0x4201edf3:0x3fce52a0
Connection seems fast enough even without this. We'll investigate the
reason for the crash and re-enable once it's safe.
---------
Co-authored-by: Catalin Patulea <cronos586@gmail.com>
* Add extension from pioarduino nag
"Jason2866.esp-decoder"
* Cleanup after merge
* ESP32: Disable classic bluetooth
* Cleanup: Fix ADC channels on new variants
* InkHUD: Fix type casting for message size in saveToFlash method
inkhud compiles again!
* update p4 esp_hosted for BT
* I thought I fixed this
* fix linker error using response file (p4 only)
* fix infinite loop
* Fix Power.cpp check warning
Local variable 'config' shadows outer variable [shadowVariable]
* Build ESP32 original with NimBLE ('custom_sdkconfig' approach). (#10235)
* Re-enable littlefs json manifest
This works locally again :)
Not sure what changed
* Re-add tool-mklittlefs
* sensecap indicator fixes after upgrade arduino-esp & lovyanGFX libs
* hackaday fix
* robot tbeam cache error fix
Co-authored-by: Copilot <copilot@github.com>
* trunk fmt
* ignore trunk
* BLEDevice::deinit() added
Co-authored-by: Copilot <copilot@github.com>
* platformio-custom: Modify mtjson target dependency to prevent fake-success. (#10291)
Co-authored-by: Copilot <copilot@github.com>
* Fix ESP32-C6 linker errors.
Align .text.handler_execute section to 4 bytes and update watchdog timer core mask configuration
Co-authored-by: Copilot <copilot@github.com>
* tlora-c6: Disable Screen
MESHTASTIC_EXCLUDE_SCREEN=1 on tlora-c6.
It doesn't have a screen, and this gets it compiling again (saving flash).
* Use mverch's iram_memset hack for all OG-ESP32
* Refactor watchdog timer initialization and handling
* use adc_channel_t in variant.h
* Fix variant headers
* More idiomatic default ethernet that doesn't break the build
* Elecrows: Delete problematic variant.cpp
Not needed after USE_ETHERNET_DEFAULT
---------
Co-authored-by: mverch67 <manuel.verch@gmx.de>
Co-authored-by: Manuel <71137295+mverch67@users.noreply.github.com>
Co-authored-by: Catalin Patulea <cronos586@gmail.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
308 lines
8.7 KiB
C++
308 lines
8.7 KiB
C++
/**
|
|
* @file FSCommon.cpp
|
|
* @brief This file contains functions for common filesystem operations such as copying, renaming, listing and deleting files and
|
|
* directories.
|
|
*
|
|
* The functions in this file are used to perform common filesystem operations such as copying, renaming, listing and deleting
|
|
* files and directories. These functions are used in the Meshtastic-device project to manage files and directories on the
|
|
* device's filesystem.
|
|
*
|
|
*/
|
|
#include "FSCommon.h"
|
|
#include "SPILock.h"
|
|
#include "configuration.h"
|
|
|
|
// Software SPI is used by MUI so disable SD card here until it's also implemented
|
|
#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI)
|
|
#include <SD.h>
|
|
#include <SPI.h>
|
|
|
|
#ifdef SDCARD_USE_SPI1
|
|
SPIClass SPI_HSPI(HSPI);
|
|
#define SDHandler SPI_HSPI
|
|
#else
|
|
#define SDHandler SPI
|
|
#endif
|
|
|
|
#ifndef SD_SPI_FREQUENCY
|
|
#define SD_SPI_FREQUENCY 4000000U
|
|
#endif
|
|
|
|
#endif // HAS_SDCARD
|
|
|
|
/**
|
|
* @brief Copies a file from one location to another.
|
|
*
|
|
* @param from The path of the source file.
|
|
* @param to The path of the destination file.
|
|
* @return true if the file was successfully copied, false otherwise.
|
|
*/
|
|
bool copyFile(const char *from, const char *to)
|
|
{
|
|
#ifdef FSCom
|
|
// take SPI Lock
|
|
concurrency::LockGuard g(spiLock);
|
|
unsigned char cbuffer[16];
|
|
|
|
File f1 = FSCom.open(from, FILE_O_READ);
|
|
if (!f1) {
|
|
LOG_ERROR("Failed to open source file %s", from);
|
|
return false;
|
|
}
|
|
|
|
File f2 = FSCom.open(to, FILE_O_WRITE);
|
|
if (!f2) {
|
|
LOG_ERROR("Failed to open destination file %s", to);
|
|
return false;
|
|
}
|
|
|
|
while (f1.available() > 0) {
|
|
byte i = f1.read(cbuffer, 16);
|
|
f2.write(cbuffer, i);
|
|
}
|
|
|
|
f2.flush();
|
|
f2.close();
|
|
f1.close();
|
|
return true;
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Renames a file from pathFrom to pathTo.
|
|
*
|
|
* @param pathFrom The original path of the file.
|
|
* @param pathTo The new path of the file.
|
|
*
|
|
* @return True if the file was successfully renamed, false otherwise.
|
|
*/
|
|
bool renameFile(const char *pathFrom, const char *pathTo)
|
|
{
|
|
#ifdef FSCom
|
|
spiLock->lock();
|
|
bool result = FSCom.rename(pathFrom, pathTo);
|
|
spiLock->unlock();
|
|
return result;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
#include <vector>
|
|
|
|
/**
|
|
* @brief Platform-agnostic filesystem format / wipe.
|
|
*
|
|
* On embedded targets (ESP32, NRF52, STM32WL, RP2040) this calls the
|
|
* native FSCom.format() which erases and reinitialises the LittleFS
|
|
* partition.
|
|
*
|
|
* On Portduino the fs::FS backend has no format() method. We instead
|
|
* delete /prefs (the only meshtastic data directory written at runtime)
|
|
* and return. rmDir("/prefs") is already called unconditionally by
|
|
* factoryReset() so this is a proven primitive on Portduino.
|
|
* FSBegin() is a no-op (#define FSBegin() true) on Portduino.
|
|
*
|
|
* @return true on success, false on failure or if no filesystem is configured.
|
|
*/
|
|
bool fsFormat()
|
|
{
|
|
#ifdef FSCom
|
|
#if defined(ARCH_PORTDUINO)
|
|
rmDir("/prefs");
|
|
return FSBegin();
|
|
#else
|
|
return FSCom.format();
|
|
#endif
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Get the list of files in a directory.
|
|
*
|
|
* This function returns a list of files in a directory. The list includes the full path of each file.
|
|
* We can't use SPILOCK here because of recursion. Callers of this function should use SPILOCK.
|
|
*
|
|
* @param dirname The name of the directory.
|
|
* @param levels The number of levels of subdirectories to list.
|
|
* @return A vector of strings containing the full path of each file in the directory.
|
|
*/
|
|
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels)
|
|
{
|
|
std::vector<meshtastic_FileInfo> filenames = {};
|
|
#ifdef FSCom
|
|
File root = FSCom.open(dirname, FILE_O_READ);
|
|
if (!root)
|
|
return filenames;
|
|
if (!root.isDirectory())
|
|
return filenames;
|
|
|
|
File file = root.openNextFile();
|
|
while (file) {
|
|
#ifdef ARCH_ESP32
|
|
const char *filepath = file.path();
|
|
#else
|
|
const char *filepath = file.name();
|
|
#endif
|
|
if (file.isDirectory() && !String(file.name()).endsWith(".")) {
|
|
if (levels) {
|
|
std::vector<meshtastic_FileInfo> subDirFilenames = getFiles(filepath, levels - 1);
|
|
filenames.insert(filenames.end(), subDirFilenames.begin(), subDirFilenames.end());
|
|
file.close();
|
|
}
|
|
} else {
|
|
meshtastic_FileInfo fileInfo = {"", static_cast<uint32_t>(file.size())};
|
|
strncpy(fileInfo.file_name, filepath, sizeof(fileInfo.file_name) - 1);
|
|
fileInfo.file_name[sizeof(fileInfo.file_name) - 1] = '\0';
|
|
if (!String(fileInfo.file_name).endsWith(".")) {
|
|
filenames.push_back(fileInfo);
|
|
}
|
|
file.close();
|
|
}
|
|
file = root.openNextFile();
|
|
}
|
|
root.close();
|
|
#endif
|
|
return filenames;
|
|
}
|
|
|
|
/**
|
|
* Lists the contents of a directory.
|
|
* We can't use SPILOCK here because of recursion. Callers of this function should use SPILOCK.
|
|
*
|
|
* @param dirname The name of the directory to list.
|
|
* @param levels The number of levels of subdirectories to list.
|
|
* @param del Whether or not to delete the contents of the directory after listing.
|
|
*/
|
|
void listDir(const char *dirname, uint8_t levels, bool del)
|
|
{
|
|
#ifdef FSCom
|
|
char buffer[255];
|
|
File root = FSCom.open(dirname, FILE_O_READ);
|
|
if (!root || !root.isDirectory())
|
|
return;
|
|
|
|
File file = root.openNextFile();
|
|
while (file && file.name()[0]) { // file.name()[0] check: workaround for Adafruit LittleFS nRF52 bug #4395
|
|
#ifdef ARCH_ESP32
|
|
const char *filepath = file.path();
|
|
#else
|
|
const char *filepath = file.name();
|
|
#endif
|
|
if (file.isDirectory() && !String(file.name()).endsWith(".")) {
|
|
if (levels) {
|
|
listDir(filepath, levels - 1, del);
|
|
if (del) {
|
|
LOG_DEBUG("Remove %s", filepath);
|
|
strncpy(buffer, filepath, sizeof(buffer) - 1);
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
|
file.close();
|
|
FSCom.rmdir(buffer);
|
|
} else {
|
|
file.close();
|
|
}
|
|
}
|
|
} else {
|
|
if (del) {
|
|
LOG_DEBUG("Delete %s", filepath);
|
|
strncpy(buffer, filepath, sizeof(buffer) - 1);
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
|
file.close();
|
|
FSCom.remove(buffer);
|
|
} else {
|
|
LOG_DEBUG(" %s (%i Bytes)", filepath, file.size());
|
|
file.close();
|
|
}
|
|
}
|
|
file = root.openNextFile();
|
|
}
|
|
#ifdef ARCH_ESP32
|
|
const char *rootpath = root.path();
|
|
#else
|
|
const char *rootpath = root.name();
|
|
#endif
|
|
if (del) {
|
|
LOG_DEBUG("Remove %s", rootpath);
|
|
strncpy(buffer, rootpath, sizeof(buffer) - 1);
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
|
root.close();
|
|
FSCom.rmdir(buffer);
|
|
} else {
|
|
root.close();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Removes a directory and all its contents.
|
|
*
|
|
* This function recursively removes a directory and all its contents, including subdirectories and files.
|
|
*
|
|
* @param dirname The name of the directory to remove.
|
|
*/
|
|
void rmDir(const char *dirname)
|
|
{
|
|
#ifdef FSCom
|
|
listDir(dirname, 10, true);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Some platforms (nrf52) might need to do an extra step before FSBegin().
|
|
*/
|
|
__attribute__((weak, noinline)) void preFSBegin() {}
|
|
|
|
void fsInit()
|
|
{
|
|
#ifdef FSCom
|
|
concurrency::LockGuard g(spiLock);
|
|
preFSBegin();
|
|
if (!FSBegin()) {
|
|
LOG_ERROR("Filesystem mount failed");
|
|
// assert(0); This auto-formats the partition, so no need to fail here.
|
|
}
|
|
#if defined(ARCH_ESP32)
|
|
LOG_DEBUG("Filesystem files (%d/%d Bytes):", FSCom.usedBytes(), FSCom.totalBytes());
|
|
#else
|
|
LOG_DEBUG("Filesystem files:");
|
|
#endif
|
|
listDir("/", 10);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Initializes the SD card and mounts the file system.
|
|
*/
|
|
void setupSDCard()
|
|
{
|
|
#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI) && !defined(HAS_SD_MMC)
|
|
concurrency::LockGuard g(spiLock);
|
|
SDHandler.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
|
|
if (!SD.begin(SDCARD_CS, SDHandler, SD_SPI_FREQUENCY)) {
|
|
LOG_DEBUG("No SD_MMC card detected");
|
|
return;
|
|
}
|
|
uint8_t cardType = SD.cardType();
|
|
if (cardType == CARD_NONE) {
|
|
LOG_DEBUG("No SD_MMC card attached");
|
|
return;
|
|
}
|
|
LOG_DEBUG("SD_MMC Card Type: ");
|
|
if (cardType == CARD_MMC) {
|
|
LOG_DEBUG("MMC");
|
|
} else if (cardType == CARD_SD) {
|
|
LOG_DEBUG("SDSC");
|
|
} else if (cardType == CARD_SDHC) {
|
|
LOG_DEBUG("SDHC");
|
|
} else {
|
|
LOG_DEBUG("UNKNOWN");
|
|
}
|
|
|
|
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
|
|
LOG_DEBUG("SD Card Size: %lu MB", (uint32_t)cardSize);
|
|
LOG_DEBUG("Total space: %lu MB", (uint32_t)(SD.totalBytes() / (1024 * 1024)));
|
|
LOG_DEBUG("Used space: %lu MB", (uint32_t)(SD.usedBytes() / (1024 * 1024)));
|
|
#endif
|
|
} |