Skip to content

Commit b0adf65

Browse files
committed
Bump to v4 with move and dir path tweaks
1 parent 64ff8d9 commit b0adf65

File tree

2 files changed

+122
-7
lines changed

2 files changed

+122
-7
lines changed

supervisor/shared/bluetooth/file_transfer.c

Lines changed: 104 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ void supervisor_start_bluetooth_file_transfer(void) {
100100
NULL, // no initial value
101101
NULL); // no description
102102

103-
uint32_t version = 3;
103+
uint32_t version = 4;
104104
mp_buffer_info_t bufinfo;
105105
bufinfo.buf = &version;
106106
bufinfo.len = sizeof(version);
@@ -269,7 +269,7 @@ STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) {
269269
// Check to see if USB has already been mounted. If not, then we "eject" from USB until we're done.
270270
#if CIRCUITPY_USB && CIRCUITPY_USB_MSC
271271
if (storage_usb_enabled() && !usb_msc_lock()) {
272-
response.status = STATUS_ERROR;
272+
response.status = STATUS_ERROR_READONLY;
273273
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0);
274274
return ANY_COMMAND;
275275
}
@@ -421,27 +421,44 @@ STATIC uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) {
421421
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct delete_status), NULL, 0);
422422
return ANY_COMMAND;
423423
}
424+
// Check to see if USB has already been mounted. If not, then we "eject" from USB until we're done.
425+
#if CIRCUITPY_USB && CIRCUITPY_USB_MSC
426+
if (storage_usb_enabled() && !usb_msc_lock()) {
427+
response.status = STATUS_ERROR_READONLY;
428+
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct delete_status), NULL, 0);
429+
return ANY_COMMAND;
430+
}
431+
#endif
424432
// We need to receive another packet to have the full path.
425433
if (command_len < header_size + command->path_length) {
426434
return THIS_COMMAND;
427435
}
428436
FATFS *fs = &((fs_user_mount_t *)MP_STATE_VM(vfs_mount_table)->obj)->fatfs;
429437
char *path = (char *)((uint8_t *)command) + header_size;
430438
path[command->path_length] = '\0';
431-
FRESULT result = FR_OK;
432439
FILINFO file;
433-
if (f_stat(fs, path, &file) == FR_OK) {
440+
FRESULT result = f_stat(fs, path, &file);
441+
if (result == FR_OK) {
434442
if ((file.fattrib & AM_DIR) != 0) {
435443
result = _delete_directory_contents(fs, path);
436444
}
437445
if (result == FR_OK) {
438446
result = f_unlink(fs, path);
439447
}
440448
}
449+
#if CIRCUITPY_USB_MSC
450+
usb_msc_unlock();
451+
#endif
441452
if (result != FR_OK) {
442453
response.status = STATUS_ERROR;
443454
}
444455
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct delete_status), NULL, 0);
456+
if (result == FR_OK) {
457+
// Don't reload until everything is written out of the packet buffer.
458+
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
459+
// Trigger an autoreload
460+
autoreload_start();
461+
}
445462
return ANY_COMMAND;
446463
}
447464

@@ -457,23 +474,44 @@ STATIC uint8_t _process_mkdir(const uint8_t *raw_buf, size_t command_len) {
457474
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct mkdir_status), NULL, 0);
458475
return ANY_COMMAND;
459476
}
477+
// Check to see if USB has already been mounted. If not, then we "eject" from USB until we're done.
478+
#if CIRCUITPY_USB && CIRCUITPY_USB_MSC
479+
if (storage_usb_enabled() && !usb_msc_lock()) {
480+
response.status = STATUS_ERROR_READONLY;
481+
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct mkdir_status), NULL, 0);
482+
return ANY_COMMAND;
483+
}
484+
#endif
460485
// We need to receive another packet to have the full path.
461486
if (command_len < header_size + command->path_length) {
462487
return THIS_COMMAND;
463488
}
464489
FATFS *fs = &((fs_user_mount_t *)MP_STATE_VM(vfs_mount_table)->obj)->fatfs;
465490
char *path = (char *)command->path;
466-
// TODO: Check that the final character is a `/`
467-
path[command->path_length - 1] = '\0';
491+
// -1 because fatfs doesn't want a trailing /
492+
if (path[command->path_length - 1] == '/') {
493+
path[command->path_length - 1] = '\0';
494+
} else {
495+
path[command->path_length] = '\0';
496+
}
468497
DWORD fattime;
469498
response.truncated_time = truncate_time(command->modification_time, &fattime);
470499
override_fattime(fattime);
471500
FRESULT result = f_mkdir(fs, path);
472501
override_fattime(0);
502+
#if CIRCUITPY_USB_MSC
503+
usb_msc_unlock();
504+
#endif
473505
if (result != FR_OK) {
474506
response.status = STATUS_ERROR;
475507
}
476508
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct mkdir_status), NULL, 0);
509+
if (result == FR_OK) {
510+
// Don't reload until everything is written out of the packet buffer.
511+
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
512+
// Trigger an autoreload
513+
autoreload_start();
514+
}
477515
return ANY_COMMAND;
478516
}
479517

@@ -499,7 +537,11 @@ STATIC uint8_t _process_listdir(uint8_t *raw_buf, size_t command_len) {
499537
FATFS *fs = &((fs_user_mount_t *)MP_STATE_VM(vfs_mount_table)->obj)->fatfs;
500538
char *path = (char *)&command->path;
501539
// -1 because fatfs doesn't want a trailing /
502-
path[command->path_length - 1] = '\0';
540+
if (path[command->path_length - 1] == '/') {
541+
path[command->path_length - 1] = '\0';
542+
} else {
543+
path[command->path_length] = '\0';
544+
}
503545
// mp_printf(&mp_plat_print, "list %s\n", path);
504546
FF_DIR dir;
505547
FRESULT res = f_opendir(fs, &dir, path);
@@ -564,6 +606,58 @@ STATIC uint8_t _process_listdir(uint8_t *raw_buf, size_t command_len) {
564606
return ANY_COMMAND;
565607
}
566608

609+
STATIC uint8_t _process_move(const uint8_t *raw_buf, size_t command_len) {
610+
const struct move_command *command = (struct move_command *)raw_buf;
611+
size_t header_size = sizeof(struct move_command);
612+
struct move_status response;
613+
response.command = MOVE_STATUS;
614+
response.status = STATUS_OK;
615+
// +2 for null terminators.
616+
uint32_t total_path_length = command->old_path_length + command->new_path_length + 1;
617+
if (total_path_length > (COMMAND_SIZE - header_size - 1)) {
618+
// TODO: throw away any more packets of path.
619+
response.status = STATUS_ERROR;
620+
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct move_status), NULL, 0);
621+
return ANY_COMMAND;
622+
}
623+
// Check to see if USB has already been mounted. If not, then we "eject" from USB until we're done.
624+
#if CIRCUITPY_USB && CIRCUITPY_USB_MSC
625+
if (storage_usb_enabled() && !usb_msc_lock()) {
626+
response.status = STATUS_ERROR_READONLY;
627+
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct move_status), NULL, 0);
628+
return ANY_COMMAND;
629+
}
630+
#endif
631+
// We need to receive another packet to have the full path.
632+
if (command_len < header_size + total_path_length) {
633+
return THIS_COMMAND;
634+
}
635+
FATFS *fs = &((fs_user_mount_t *)MP_STATE_VM(vfs_mount_table)->obj)->fatfs;
636+
char *old_path = (char *)command->paths;
637+
old_path[command->old_path_length] = '\0';
638+
639+
char *new_path = old_path + command->old_path_length + 1;
640+
new_path[command->new_path_length] = '\0';
641+
642+
// mp_printf(&mp_plat_print, "move %s to %s\n", old_path, new_path);
643+
644+
FRESULT result = f_rename(fs, old_path, new_path);
645+
#if CIRCUITPY_USB_MSC
646+
usb_msc_unlock();
647+
#endif
648+
if (result != FR_OK) {
649+
response.status = STATUS_ERROR;
650+
}
651+
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct move_status), NULL, 0);
652+
if (result == FR_OK) {
653+
// Don't reload until everything is written out of the packet buffer.
654+
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
655+
// Trigger an autoreload
656+
autoreload_start();
657+
}
658+
return ANY_COMMAND;
659+
}
660+
567661
// Background state that must live across background calls. After the _process
568662
// helpers to force them to not use them.
569663
STATIC uint8_t current_command[COMMAND_SIZE] __attribute__ ((aligned(4)));
@@ -625,6 +719,9 @@ void supervisor_bluetooth_file_transfer_background(void) {
625719
case LISTDIR:
626720
next_command = _process_listdir(current_command, current_offset);
627721
break;
722+
case MOVE:
723+
next_command = _process_move(current_command, current_offset);
724+
break;
628725
}
629726
// Preserve the offset if we are waiting for more from this command.
630727
if (next_command != THIS_COMMAND) {

supervisor/shared/bluetooth/file_transfer_protocol.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,28 @@ struct listdir_entry {
153153
uint8_t path[];
154154
} __attribute__((packed));
155155

156+
#define MOVE 0x60
157+
struct move_command {
158+
uint8_t command;
159+
uint8_t reserved;
160+
uint16_t old_path_length;
161+
uint16_t new_path_length;
162+
// paths is two strings. The first is old_path and then a reserved byte.
163+
// The last path is new_path.
164+
uint8_t paths[];
165+
} __attribute__((packed));
166+
167+
#define MOVE_STATUS 0x61
168+
struct move_status {
169+
uint8_t command;
170+
uint8_t status;
171+
} __attribute__((packed));
172+
156173
#define STATUS_OK 0x01
157174
#define STATUS_ERROR 0x02
158175
#define STATUS_ERROR_NO_FILE 0x03
159176
#define STATUS_ERROR_PROTOCOL 0x04
177+
#define STATUS_ERROR_READONLY 0x05
160178

161179

162180
#endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_FILE_TRANSFER_PROTOCOL_H

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy