@@ -100,7 +100,7 @@ void supervisor_start_bluetooth_file_transfer(void) {
100
100
NULL , // no initial value
101
101
NULL ); // no description
102
102
103
- uint32_t version = 3 ;
103
+ uint32_t version = 4 ;
104
104
mp_buffer_info_t bufinfo ;
105
105
bufinfo .buf = & version ;
106
106
bufinfo .len = sizeof (version );
@@ -269,7 +269,7 @@ STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) {
269
269
// Check to see if USB has already been mounted. If not, then we "eject" from USB until we're done.
270
270
#if CIRCUITPY_USB && CIRCUITPY_USB_MSC
271
271
if (storage_usb_enabled () && !usb_msc_lock ()) {
272
- response .status = STATUS_ERROR ;
272
+ response .status = STATUS_ERROR_READONLY ;
273
273
common_hal_bleio_packet_buffer_write (& _transfer_packet_buffer , (const uint8_t * )& response , sizeof (struct write_pacing ), NULL , 0 );
274
274
return ANY_COMMAND ;
275
275
}
@@ -421,27 +421,44 @@ STATIC uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) {
421
421
common_hal_bleio_packet_buffer_write (& _transfer_packet_buffer , (const uint8_t * )& response , sizeof (struct delete_status ), NULL , 0 );
422
422
return ANY_COMMAND ;
423
423
}
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
424
432
// We need to receive another packet to have the full path.
425
433
if (command_len < header_size + command -> path_length ) {
426
434
return THIS_COMMAND ;
427
435
}
428
436
FATFS * fs = & ((fs_user_mount_t * )MP_STATE_VM (vfs_mount_table )-> obj )-> fatfs ;
429
437
char * path = (char * )((uint8_t * )command ) + header_size ;
430
438
path [command -> path_length ] = '\0' ;
431
- FRESULT result = FR_OK ;
432
439
FILINFO file ;
433
- if (f_stat (fs , path , & file ) == FR_OK ) {
440
+ FRESULT result = f_stat (fs , path , & file );
441
+ if (result == FR_OK ) {
434
442
if ((file .fattrib & AM_DIR ) != 0 ) {
435
443
result = _delete_directory_contents (fs , path );
436
444
}
437
445
if (result == FR_OK ) {
438
446
result = f_unlink (fs , path );
439
447
}
440
448
}
449
+ #if CIRCUITPY_USB_MSC
450
+ usb_msc_unlock ();
451
+ #endif
441
452
if (result != FR_OK ) {
442
453
response .status = STATUS_ERROR ;
443
454
}
444
455
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
+ }
445
462
return ANY_COMMAND ;
446
463
}
447
464
@@ -457,23 +474,44 @@ STATIC uint8_t _process_mkdir(const uint8_t *raw_buf, size_t command_len) {
457
474
common_hal_bleio_packet_buffer_write (& _transfer_packet_buffer , (const uint8_t * )& response , sizeof (struct mkdir_status ), NULL , 0 );
458
475
return ANY_COMMAND ;
459
476
}
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
460
485
// We need to receive another packet to have the full path.
461
486
if (command_len < header_size + command -> path_length ) {
462
487
return THIS_COMMAND ;
463
488
}
464
489
FATFS * fs = & ((fs_user_mount_t * )MP_STATE_VM (vfs_mount_table )-> obj )-> fatfs ;
465
490
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
+ }
468
497
DWORD fattime ;
469
498
response .truncated_time = truncate_time (command -> modification_time , & fattime );
470
499
override_fattime (fattime );
471
500
FRESULT result = f_mkdir (fs , path );
472
501
override_fattime (0 );
502
+ #if CIRCUITPY_USB_MSC
503
+ usb_msc_unlock ();
504
+ #endif
473
505
if (result != FR_OK ) {
474
506
response .status = STATUS_ERROR ;
475
507
}
476
508
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
+ }
477
515
return ANY_COMMAND ;
478
516
}
479
517
@@ -499,7 +537,11 @@ STATIC uint8_t _process_listdir(uint8_t *raw_buf, size_t command_len) {
499
537
FATFS * fs = & ((fs_user_mount_t * )MP_STATE_VM (vfs_mount_table )-> obj )-> fatfs ;
500
538
char * path = (char * )& command -> path ;
501
539
// -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
+ }
503
545
// mp_printf(&mp_plat_print, "list %s\n", path);
504
546
FF_DIR dir ;
505
547
FRESULT res = f_opendir (fs , & dir , path );
@@ -564,6 +606,58 @@ STATIC uint8_t _process_listdir(uint8_t *raw_buf, size_t command_len) {
564
606
return ANY_COMMAND ;
565
607
}
566
608
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
+
567
661
// Background state that must live across background calls. After the _process
568
662
// helpers to force them to not use them.
569
663
STATIC uint8_t current_command [COMMAND_SIZE ] __attribute__ ((aligned (4 )));
@@ -625,6 +719,9 @@ void supervisor_bluetooth_file_transfer_background(void) {
625
719
case LISTDIR :
626
720
next_command = _process_listdir (current_command , current_offset );
627
721
break ;
722
+ case MOVE :
723
+ next_command = _process_move (current_command , current_offset );
724
+ break ;
628
725
}
629
726
// Preserve the offset if we are waiting for more from this command.
630
727
if (next_command != THIS_COMMAND ) {
0 commit comments