Two tweaks to BLE workflow
1. Use autoreload for restarting after a write. This gives time for a follow up command before restarting BLE. 2. Switch to recursive deletion of directories. This greatly simplifies deleting directories with contents. Fixes https://github.com/adafruit/Adafruit_CircuitPython_BLE_File_Transfer/issues/7
This commit is contained in:
parent
da320c30f0
commit
a5f2f6e1b1
4
main.c
4
main.c
|
@ -755,7 +755,7 @@ STATIC int run_repl(void) {
|
||||||
usb_setup_with_vm();
|
usb_setup_with_vm();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
autoreload_suspend();
|
autoreload_suspend(AUTORELOAD_LOCK_REPL);
|
||||||
|
|
||||||
// Set the status LED to the REPL color before running the REPL. For
|
// Set the status LED to the REPL color before running the REPL. For
|
||||||
// NeoPixels and DotStars this will be sticky but for PWM or single LED it
|
// NeoPixels and DotStars this will be sticky but for PWM or single LED it
|
||||||
|
@ -785,7 +785,7 @@ STATIC int run_repl(void) {
|
||||||
status_led_deinit();
|
status_led_deinit();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
autoreload_resume();
|
autoreload_resume(AUTORELOAD_LOCK_REPL);
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ supervisor_allocation *next_code_allocation;
|
||||||
|
|
||||||
static volatile uint32_t autoreload_delay_ms = 0;
|
static volatile uint32_t autoreload_delay_ms = 0;
|
||||||
static bool autoreload_enabled = false;
|
static bool autoreload_enabled = false;
|
||||||
static bool autoreload_suspended = false;
|
static size_t autoreload_suspended = 0;
|
||||||
|
|
||||||
volatile bool reload_requested = false;
|
volatile bool reload_requested = false;
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ inline void autoreload_tick() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (autoreload_delay_ms == 1 && autoreload_enabled &&
|
if (autoreload_delay_ms == 1 && autoreload_enabled &&
|
||||||
!autoreload_suspended && !reload_requested) {
|
autoreload_suspended == 0 && !reload_requested) {
|
||||||
mp_raise_reload_exception();
|
mp_raise_reload_exception();
|
||||||
reload_requested = true;
|
reload_requested = true;
|
||||||
supervisor_set_run_reason(RUN_REASON_AUTO_RELOAD);
|
supervisor_set_run_reason(RUN_REASON_AUTO_RELOAD);
|
||||||
|
@ -62,12 +62,12 @@ void autoreload_disable() {
|
||||||
autoreload_enabled = false;
|
autoreload_enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void autoreload_suspend() {
|
void autoreload_suspend(size_t lock_mask) {
|
||||||
autoreload_suspended = true;
|
autoreload_suspended |= lock_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
void autoreload_resume() {
|
void autoreload_resume(size_t lock_mask) {
|
||||||
autoreload_suspended = false;
|
autoreload_suspended &= ~lock_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool autoreload_is_enabled() {
|
inline bool autoreload_is_enabled() {
|
||||||
|
|
|
@ -40,6 +40,11 @@ enum {
|
||||||
SUPERVISOR_NEXT_CODE_OPT_NEWLY_SET = 0x20,
|
SUPERVISOR_NEXT_CODE_OPT_NEWLY_SET = 0x20,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
AUTORELOAD_LOCK_REPL = 0x1,
|
||||||
|
AUTORELOAD_LOCK_BLE = 0x2
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t options;
|
uint8_t options;
|
||||||
char filename[];
|
char filename[];
|
||||||
|
@ -58,8 +63,8 @@ void autoreload_disable(void);
|
||||||
bool autoreload_is_enabled(void);
|
bool autoreload_is_enabled(void);
|
||||||
|
|
||||||
// Temporarily turn it off. Used during the REPL.
|
// Temporarily turn it off. Used during the REPL.
|
||||||
void autoreload_suspend(void);
|
void autoreload_suspend(size_t lock_mask);
|
||||||
void autoreload_resume(void);
|
void autoreload_resume(size_t lock_mask);
|
||||||
|
|
||||||
void autoreload_now(void);
|
void autoreload_now(void);
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include "supervisor/usb.h"
|
#include "supervisor/usb.h"
|
||||||
|
|
||||||
#include "py/mpstate.h"
|
#include "py/mpstate.h"
|
||||||
|
#include "py/stackctrl.h"
|
||||||
|
|
||||||
STATIC bleio_service_obj_t supervisor_ble_service;
|
STATIC bleio_service_obj_t supervisor_ble_service;
|
||||||
STATIC bleio_uuid_obj_t supervisor_ble_service_uuid;
|
STATIC bleio_uuid_obj_t supervisor_ble_service_uuid;
|
||||||
|
@ -97,7 +98,7 @@ void supervisor_start_bluetooth_file_transfer(void) {
|
||||||
NULL, // no initial value
|
NULL, // no initial value
|
||||||
NULL); // no description
|
NULL); // no description
|
||||||
|
|
||||||
uint32_t version = 1;
|
uint32_t version = 2;
|
||||||
mp_buffer_info_t bufinfo;
|
mp_buffer_info_t bufinfo;
|
||||||
bufinfo.buf = &version;
|
bufinfo.buf = &version;
|
||||||
bufinfo.len = sizeof(version);
|
bufinfo.len = sizeof(version);
|
||||||
|
@ -291,7 +292,7 @@ STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) {
|
||||||
// Don't reload until everything is written out of the packet buffer.
|
// Don't reload until everything is written out of the packet buffer.
|
||||||
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
|
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
|
||||||
// Trigger an autoreload
|
// Trigger an autoreload
|
||||||
autoreload_now();
|
autoreload_start();
|
||||||
return ANY_COMMAND;
|
return ANY_COMMAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,12 +346,45 @@ STATIC uint8_t _process_write_data(const uint8_t *raw_buf, size_t command_len) {
|
||||||
// Don't reload until everything is written out of the packet buffer.
|
// Don't reload until everything is written out of the packet buffer.
|
||||||
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
|
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
|
||||||
// Trigger an autoreload
|
// Trigger an autoreload
|
||||||
autoreload_now();
|
autoreload_start();
|
||||||
return ANY_COMMAND;
|
return ANY_COMMAND;
|
||||||
}
|
}
|
||||||
return WRITE_DATA;
|
return WRITE_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC FRESULT _delete_directory_contents(FATFS *fs, const TCHAR *path) {
|
||||||
|
FF_DIR dir;
|
||||||
|
FRESULT res = f_opendir(fs, &dir, path);
|
||||||
|
FILINFO file_info;
|
||||||
|
// Check the stack since we're putting paths on it.
|
||||||
|
if (mp_stack_usage() >= MP_STATE_THREAD(stack_limit)) {
|
||||||
|
return FR_INT_ERR;
|
||||||
|
}
|
||||||
|
while (res == FR_OK) {
|
||||||
|
res = f_readdir(&dir, &file_info);
|
||||||
|
if (res != FR_OK || file_info.fname[0] == '\0') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size_t pathlen = strlen(path);
|
||||||
|
size_t fnlen = strlen(file_info.fname);
|
||||||
|
TCHAR full_path[pathlen + 1 + fnlen];
|
||||||
|
memcpy(full_path, path, pathlen);
|
||||||
|
full_path[pathlen] = '/';
|
||||||
|
size_t full_pathlen = pathlen + 1 + fnlen;
|
||||||
|
memcpy(full_path + pathlen + 1, file_info.fname, fnlen);
|
||||||
|
full_path[full_pathlen] = '\0';
|
||||||
|
if ((file_info.fattrib & AM_DIR) != 0) {
|
||||||
|
res = _delete_directory_contents(fs, full_path);
|
||||||
|
}
|
||||||
|
if (res != FR_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
res = f_unlink(fs, full_path);
|
||||||
|
}
|
||||||
|
f_closedir(&dir);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
STATIC uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) {
|
STATIC uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) {
|
||||||
const struct delete_command *command = (struct delete_command *)raw_buf;
|
const struct delete_command *command = (struct delete_command *)raw_buf;
|
||||||
size_t header_size = 4;
|
size_t header_size = 4;
|
||||||
|
@ -370,7 +404,16 @@ STATIC uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) {
|
||||||
FATFS *fs = &((fs_user_mount_t *)MP_STATE_VM(vfs_mount_table)->obj)->fatfs;
|
FATFS *fs = &((fs_user_mount_t *)MP_STATE_VM(vfs_mount_table)->obj)->fatfs;
|
||||||
char *path = (char *)((uint8_t *)command) + header_size;
|
char *path = (char *)((uint8_t *)command) + header_size;
|
||||||
path[command->path_length] = '\0';
|
path[command->path_length] = '\0';
|
||||||
FRESULT result = f_unlink(fs, path);
|
FRESULT result;
|
||||||
|
FILINFO file;
|
||||||
|
if (f_stat(fs, path, &file) == FR_OK) {
|
||||||
|
if ((file.fattrib & AM_DIR) != 0) {
|
||||||
|
result = _delete_directory_contents(fs, path);
|
||||||
|
}
|
||||||
|
if (result == FR_OK) {
|
||||||
|
result = f_unlink(fs, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (result != FR_OK) {
|
if (result != FR_OK) {
|
||||||
response.status = STATUS_ERROR;
|
response.status = STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -504,6 +547,7 @@ void supervisor_bluetooth_file_transfer_background(void) {
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
autoreload_suspend(AUTORELOAD_LOCK_BLE);
|
||||||
// TODO: If size < 0 return an error.
|
// TODO: If size < 0 return an error.
|
||||||
current_offset += size;
|
current_offset += size;
|
||||||
#if CIRCUITPY_VERBOSE_BLE
|
#if CIRCUITPY_VERBOSE_BLE
|
||||||
|
@ -521,6 +565,7 @@ void supervisor_bluetooth_file_transfer_background(void) {
|
||||||
response[0] = next_command;
|
response[0] = next_command;
|
||||||
response[1] = STATUS_ERROR_PROTOCOL;
|
response[1] = STATUS_ERROR_PROTOCOL;
|
||||||
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, response, 2, NULL, 0);
|
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, response, 2, NULL, 0);
|
||||||
|
autoreload_resume(AUTORELOAD_LOCK_BLE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (current_state) {
|
switch (current_state) {
|
||||||
|
@ -550,6 +595,9 @@ void supervisor_bluetooth_file_transfer_background(void) {
|
||||||
if (next_command != THIS_COMMAND) {
|
if (next_command != THIS_COMMAND) {
|
||||||
current_offset = 0;
|
current_offset = 0;
|
||||||
}
|
}
|
||||||
|
if (next_command == ANY_COMMAND) {
|
||||||
|
autoreload_resume(AUTORELOAD_LOCK_BLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
|
@ -558,4 +606,5 @@ void supervisor_bluetooth_file_transfer_disconnected(void) {
|
||||||
next_command = ANY_COMMAND;
|
next_command = ANY_COMMAND;
|
||||||
current_offset = 0;
|
current_offset = 0;
|
||||||
f_close(&active_file);
|
f_close(&active_file);
|
||||||
|
autoreload_resume(AUTORELOAD_LOCK_BLE);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue