@@ -133,6 +133,9 @@ void supervisor_start_bluetooth_file_transfer(void) {
133
133
#define ANY_COMMAND 0x00
134
134
#define THIS_COMMAND 0x01
135
135
136
+ // FATFS has a two second timestamp resolution but the BLE API allows for nanosecond resolution.
137
+ // This function truncates the time the time to a resolution storable by FATFS and fills in the
138
+ // FATFS encoded version into fattime.
136
139
uint64_t truncate_time (uint64_t input_time , DWORD * fattime ) {
137
140
timeutils_struct_time_t tm ;
138
141
uint64_t seconds_since_epoch = timeutils_seconds_since_epoch_from_nanoseconds_since_1970 (input_time );
@@ -245,6 +248,22 @@ STATIC uint8_t _process_read_pacing(const uint8_t *raw_buf, size_t command_len)
245
248
STATIC size_t total_write_length ;
246
249
STATIC uint64_t _truncated_time ;
247
250
251
+ // Returns true if usb is active and replies with an error if so. If not, it grabs
252
+ // the USB mass storage lock and returns false. Make sure to release the lock with
253
+ // usb_msc_unlock() when the transaction is complete.
254
+ STATIC bool _usb_active (void * response , size_t response_size ) {
255
+ // Check to see if USB has already been mounted. If not, then we "eject" from USB until we're done.
256
+ #if CIRCUITPY_USB && CIRCUITPY_USB_MSC
257
+ if (storage_usb_enabled () && !usb_msc_lock ()) {
258
+ // Status is always the second byte of the response.
259
+ ((uint8_t * )response )[1 ] = STATUS_ERROR_READONLY ;
260
+ common_hal_bleio_packet_buffer_write (& _transfer_packet_buffer , (const uint8_t * )response , response_size , NULL , 0 );
261
+ return true;
262
+ }
263
+ #endif
264
+ return false;
265
+ }
266
+
248
267
STATIC uint8_t _process_write (const uint8_t * raw_buf , size_t command_len ) {
249
268
struct write_command * command = (struct write_command * )raw_buf ;
250
269
size_t header_size = sizeof (struct write_command );
@@ -265,15 +284,9 @@ STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) {
265
284
266
285
char * path = (char * )command -> path ;
267
286
path [command -> path_length ] = '\0' ;
268
-
269
- // Check to see if USB has already been mounted. If not, then we "eject" from USB until we're done.
270
- #if CIRCUITPY_USB && CIRCUITPY_USB_MSC
271
- if (storage_usb_enabled () && !usb_msc_lock ()) {
272
- response .status = STATUS_ERROR_READONLY ;
273
- common_hal_bleio_packet_buffer_write (& _transfer_packet_buffer , (const uint8_t * )& response , sizeof (struct write_pacing ), NULL , 0 );
287
+ if (_usb_active (& response , sizeof (struct write_pacing ))) {
274
288
return ANY_COMMAND ;
275
289
}
276
- #endif
277
290
278
291
FATFS * fs = & ((fs_user_mount_t * )MP_STATE_VM (vfs_mount_table )-> obj )-> fatfs ;
279
292
DWORD fattime ;
@@ -421,14 +434,9 @@ STATIC uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) {
421
434
common_hal_bleio_packet_buffer_write (& _transfer_packet_buffer , (const uint8_t * )& response , sizeof (struct delete_status ), NULL , 0 );
422
435
return ANY_COMMAND ;
423
436
}
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 );
437
+ if (_usb_active (& response , sizeof (struct delete_status ))) {
429
438
return ANY_COMMAND ;
430
439
}
431
- #endif
432
440
// We need to receive another packet to have the full path.
433
441
if (command_len < header_size + command -> path_length ) {
434
442
return THIS_COMMAND ;
@@ -462,6 +470,17 @@ STATIC uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) {
462
470
return ANY_COMMAND ;
463
471
}
464
472
473
+ // NULL-terminate the path and remove any trailing /. Older versions of the
474
+ // protocol require it but newer ones do not.
475
+ STATIC void _terminate_path (char * path , size_t path_length ) {
476
+ // -1 because fatfs doesn't want a trailing /
477
+ if (path [path_length - 1 ] == '/' ) {
478
+ path [path_length - 1 ] = '\0' ;
479
+ } else {
480
+ path [path_length ] = '\0' ;
481
+ }
482
+ }
483
+
465
484
STATIC uint8_t _process_mkdir (const uint8_t * raw_buf , size_t command_len ) {
466
485
const struct mkdir_command * command = (struct mkdir_command * )raw_buf ;
467
486
size_t header_size = sizeof (struct mkdir_command );
@@ -474,26 +493,17 @@ STATIC uint8_t _process_mkdir(const uint8_t *raw_buf, size_t command_len) {
474
493
common_hal_bleio_packet_buffer_write (& _transfer_packet_buffer , (const uint8_t * )& response , sizeof (struct mkdir_status ), NULL , 0 );
475
494
return ANY_COMMAND ;
476
495
}
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 );
496
+ if (_usb_active (& response , sizeof (struct mkdir_status ))) {
482
497
return ANY_COMMAND ;
483
498
}
484
- #endif
485
499
// We need to receive another packet to have the full path.
486
500
if (command_len < header_size + command -> path_length ) {
487
501
return THIS_COMMAND ;
488
502
}
489
503
FATFS * fs = & ((fs_user_mount_t * )MP_STATE_VM (vfs_mount_table )-> obj )-> fatfs ;
490
504
char * path = (char * )command -> path ;
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
- }
505
+ _terminate_path (path , command -> path_length );
506
+
497
507
DWORD fattime ;
498
508
response .truncated_time = truncate_time (command -> modification_time , & fattime );
499
509
override_fattime (fattime );
@@ -536,12 +546,7 @@ STATIC uint8_t _process_listdir(uint8_t *raw_buf, size_t command_len) {
536
546
537
547
FATFS * fs = & ((fs_user_mount_t * )MP_STATE_VM (vfs_mount_table )-> obj )-> fatfs ;
538
548
char * path = (char * )& command -> path ;
539
- // -1 because fatfs doesn't want a trailing /
540
- if (path [command -> path_length - 1 ] == '/' ) {
541
- path [command -> path_length - 1 ] = '\0' ;
542
- } else {
543
- path [command -> path_length ] = '\0' ;
544
- }
549
+ _terminate_path (path , command -> path_length );
545
550
// mp_printf(&mp_plat_print, "list %s\n", path);
546
551
FF_DIR dir ;
547
552
FRESULT res = f_opendir (fs , & dir , path );
@@ -620,14 +625,9 @@ STATIC uint8_t _process_move(const uint8_t *raw_buf, size_t command_len) {
620
625
common_hal_bleio_packet_buffer_write (& _transfer_packet_buffer , (const uint8_t * )& response , sizeof (struct move_status ), NULL , 0 );
621
626
return ANY_COMMAND ;
622
627
}
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
+ if (_usb_active (& response , sizeof (struct move_status ))) {
628
629
return ANY_COMMAND ;
629
630
}
630
- #endif
631
631
// We need to receive another packet to have the full path.
632
632
if (command_len < header_size + total_path_length ) {
633
633
return THIS_COMMAND ;
0 commit comments