Skip to content

Commit a5f2f6e

Browse files
committed
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 adafruit/Adafruit_CircuitPython_BLE_File_Transfer#7
1 parent da320c3 commit a5f2f6e

File tree

4 files changed

+68
-14
lines changed

4 files changed

+68
-14
lines changed

main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ STATIC int run_repl(void) {
755755
usb_setup_with_vm();
756756
#endif
757757

758-
autoreload_suspend();
758+
autoreload_suspend(AUTORELOAD_LOCK_REPL);
759759

760760
// Set the status LED to the REPL color before running the REPL. For
761761
// NeoPixels and DotStars this will be sticky but for PWM or single LED it
@@ -785,7 +785,7 @@ STATIC int run_repl(void) {
785785
status_led_deinit();
786786
#endif
787787

788-
autoreload_resume();
788+
autoreload_resume(AUTORELOAD_LOCK_REPL);
789789
return exit_code;
790790
}
791791

supervisor/shared/autoreload.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ supervisor_allocation *next_code_allocation;
3535

3636
static volatile uint32_t autoreload_delay_ms = 0;
3737
static bool autoreload_enabled = false;
38-
static bool autoreload_suspended = false;
38+
static size_t autoreload_suspended = 0;
3939

4040
volatile bool reload_requested = false;
4141

@@ -44,7 +44,7 @@ inline void autoreload_tick() {
4444
return;
4545
}
4646
if (autoreload_delay_ms == 1 && autoreload_enabled &&
47-
!autoreload_suspended && !reload_requested) {
47+
autoreload_suspended == 0 && !reload_requested) {
4848
mp_raise_reload_exception();
4949
reload_requested = true;
5050
supervisor_set_run_reason(RUN_REASON_AUTO_RELOAD);
@@ -62,12 +62,12 @@ void autoreload_disable() {
6262
autoreload_enabled = false;
6363
}
6464

65-
void autoreload_suspend() {
66-
autoreload_suspended = true;
65+
void autoreload_suspend(size_t lock_mask) {
66+
autoreload_suspended |= lock_mask;
6767
}
6868

69-
void autoreload_resume() {
70-
autoreload_suspended = false;
69+
void autoreload_resume(size_t lock_mask) {
70+
autoreload_suspended &= ~lock_mask;
7171
}
7272

7373
inline bool autoreload_is_enabled() {

supervisor/shared/autoreload.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ enum {
4040
SUPERVISOR_NEXT_CODE_OPT_NEWLY_SET = 0x20,
4141
};
4242

43+
enum {
44+
AUTORELOAD_LOCK_REPL = 0x1,
45+
AUTORELOAD_LOCK_BLE = 0x2
46+
};
47+
4348
typedef struct {
4449
uint8_t options;
4550
char filename[];
@@ -58,8 +63,8 @@ void autoreload_disable(void);
5863
bool autoreload_is_enabled(void);
5964

6065
// Temporarily turn it off. Used during the REPL.
61-
void autoreload_suspend(void);
62-
void autoreload_resume(void);
66+
void autoreload_suspend(size_t lock_mask);
67+
void autoreload_resume(size_t lock_mask);
6368

6469
void autoreload_now(void);
6570

supervisor/shared/bluetooth/file_transfer.c

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "supervisor/usb.h"
4848

4949
#include "py/mpstate.h"
50+
#include "py/stackctrl.h"
5051

5152
STATIC bleio_service_obj_t supervisor_ble_service;
5253
STATIC bleio_uuid_obj_t supervisor_ble_service_uuid;
@@ -97,7 +98,7 @@ void supervisor_start_bluetooth_file_transfer(void) {
9798
NULL, // no initial value
9899
NULL); // no description
99100

100-
uint32_t version = 1;
101+
uint32_t version = 2;
101102
mp_buffer_info_t bufinfo;
102103
bufinfo.buf = &version;
103104
bufinfo.len = sizeof(version);
@@ -291,7 +292,7 @@ STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) {
291292
// Don't reload until everything is written out of the packet buffer.
292293
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
293294
// Trigger an autoreload
294-
autoreload_now();
295+
autoreload_start();
295296
return ANY_COMMAND;
296297
}
297298

@@ -345,12 +346,45 @@ STATIC uint8_t _process_write_data(const uint8_t *raw_buf, size_t command_len) {
345346
// Don't reload until everything is written out of the packet buffer.
346347
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
347348
// Trigger an autoreload
348-
autoreload_now();
349+
autoreload_start();
349350
return ANY_COMMAND;
350351
}
351352
return WRITE_DATA;
352353
}
353354

355+
STATIC FRESULT _delete_directory_contents(FATFS *fs, const TCHAR *path) {
356+
FF_DIR dir;
357+
FRESULT res = f_opendir(fs, &dir, path);
358+
FILINFO file_info;
359+
// Check the stack since we're putting paths on it.
360+
if (mp_stack_usage() >= MP_STATE_THREAD(stack_limit)) {
361+
return FR_INT_ERR;
362+
}
363+
while (res == FR_OK) {
364+
res = f_readdir(&dir, &file_info);
365+
if (res != FR_OK || file_info.fname[0] == '\0') {
366+
break;
367+
}
368+
size_t pathlen = strlen(path);
369+
size_t fnlen = strlen(file_info.fname);
370+
TCHAR full_path[pathlen + 1 + fnlen];
371+
memcpy(full_path, path, pathlen);
372+
full_path[pathlen] = '/';
373+
size_t full_pathlen = pathlen + 1 + fnlen;
374+
memcpy(full_path + pathlen + 1, file_info.fname, fnlen);
375+
full_path[full_pathlen] = '\0';
376+
if ((file_info.fattrib & AM_DIR) != 0) {
377+
res = _delete_directory_contents(fs, full_path);
378+
}
379+
if (res != FR_OK) {
380+
break;
381+
}
382+
res = f_unlink(fs, full_path);
383+
}
384+
f_closedir(&dir);
385+
return res;
386+
}
387+
354388
STATIC uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) {
355389
const struct delete_command *command = (struct delete_command *)raw_buf;
356390
size_t header_size = 4;
@@ -370,7 +404,16 @@ STATIC uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) {
370404
FATFS *fs = &((fs_user_mount_t *)MP_STATE_VM(vfs_mount_table)->obj)->fatfs;
371405
char *path = (char *)((uint8_t *)command) + header_size;
372406
path[command->path_length] = '\0';
373-
FRESULT result = f_unlink(fs, path);
407+
FRESULT result;
408+
FILINFO file;
409+
if (f_stat(fs, path, &file) == FR_OK) {
410+
if ((file.fattrib & AM_DIR) != 0) {
411+
result = _delete_directory_contents(fs, path);
412+
}
413+
if (result == FR_OK) {
414+
result = f_unlink(fs, path);
415+
}
416+
}
374417
if (result != FR_OK) {
375418
response.status = STATUS_ERROR;
376419
}
@@ -504,6 +547,7 @@ void supervisor_bluetooth_file_transfer_background(void) {
504547
if (size == 0) {
505548
break;
506549
}
550+
autoreload_suspend(AUTORELOAD_LOCK_BLE);
507551
// TODO: If size < 0 return an error.
508552
current_offset += size;
509553
#if CIRCUITPY_VERBOSE_BLE
@@ -521,6 +565,7 @@ void supervisor_bluetooth_file_transfer_background(void) {
521565
response[0] = next_command;
522566
response[1] = STATUS_ERROR_PROTOCOL;
523567
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, response, 2, NULL, 0);
568+
autoreload_resume(AUTORELOAD_LOCK_BLE);
524569
break;
525570
}
526571
switch (current_state) {
@@ -550,6 +595,9 @@ void supervisor_bluetooth_file_transfer_background(void) {
550595
if (next_command != THIS_COMMAND) {
551596
current_offset = 0;
552597
}
598+
if (next_command == ANY_COMMAND) {
599+
autoreload_resume(AUTORELOAD_LOCK_BLE);
600+
}
553601
}
554602
running = false;
555603
}
@@ -558,4 +606,5 @@ void supervisor_bluetooth_file_transfer_disconnected(void) {
558606
next_command = ANY_COMMAND;
559607
current_offset = 0;
560608
f_close(&active_file);
609+
autoreload_resume(AUTORELOAD_LOCK_BLE);
561610
}

0 commit comments

Comments
 (0)