8000 Bump to v4 with move and dir path tweaks · domdfcoding/circuitpython@b0adf65 · GitHub
[go: up one dir, main page]

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)
0