Skip to content

Commit bf0bef9

Browse files
committed
Split listdir entries across two packets
when the MTU of the BLE connection is smaller than the 28 bytes of the header. (The smallest possible MTU is 20.) Fixes #5511
1 parent a8b69f2 commit bf0bef9

File tree

2 files changed

+26
-8
lines changed

2 files changed

+26
-8
lines changed

ports/nrf/common-hal/_bleio/PacketBuffer.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,12 @@ mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, c
356356
if (self->conn_handle == BLE_CONN_HANDLE_INVALID) {
357357
return -1;
358358
}
359-
uint16_t outgoing_packet_length = common_hal_bleio_packet_buffer_get_outgoing_packet_length(self);
359+
mp_int_t outgoing_packet_length = common_hal_bleio_packet_buffer_get_outgoing_packet_length(self);
360+
if (outgoing_packet_length < 0) {
361+
return -1;
362+
}
360363

361-
uint16_t total_len = len + header_len;
364+
mp_int_t total_len = len + header_len;
362365
if (total_len > outgoing_packet_length) {
363366
// Supplied data will not fit in a single BLE packet.
364367
mp_raise_ValueError_varg(translate("Total data to write is larger than %q"), MP_QSTR_outgoing_packet_length);
@@ -369,7 +372,7 @@ mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, c
369372
}
370373
outgoing_packet_length = MIN(outgoing_packet_length, self->max_packet_size);
371374

372-
if (len + self->pending_size > outgoing_packet_length) {
375+
if (len + self->pending_size > (size_t)outgoing_packet_length) {
373376
// No room to append len bytes to packet. Wait until we get a free buffer,
374377
// and keep checking that we haven't been disconnected.
375378
while (self->pending_size != 0 &&

supervisor/shared/bluetooth/file_transfer.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -525,18 +525,33 @@ STATIC uint8_t _process_mkdir(const uint8_t *raw_buf, size_t command_len) {
525525
return ANY_COMMAND;
526526
}
527527

528+
STATIC void send_listdir_entry_header(const struct listdir_entry *entry, mp_int_t max_packet_size) {
529+
mp_int_t response_size = sizeof(struct listdir_entry);
530+
if (max_packet_size >= response_size) {
531+
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)entry, response_size, NULL, 0);
532+
return;
533+
}
534+
// Split into 16 + 12 size packets to fit into 20 byte minimum packet size.
535+
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)entry, 16, NULL, 0);
536+
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, ((const uint8_t *)entry) + 16, response_size - 16, NULL, 0);
537+
}
538+
528539
STATIC uint8_t _process_listdir(uint8_t *raw_buf, size_t command_len) {
529540
const struct listdir_command *command = (struct listdir_command *)raw_buf;
530541
struct listdir_entry *entry = (struct listdir_entry *)raw_buf;
531542
size_t header_size = sizeof(struct listdir_command);
532-
size_t response_size = sizeof(struct listdir_entry);
543+
mp_int_t max_packet_size = common_hal_bleio_packet_buffer_get_outgoing_packet_length(&_transfer_packet_buffer);
544+
if (max_packet_size < 0) {
545+
// -1 means we're disconnected
546+
return ANY_COMMAND;
547+
}
533548
// We reuse the command buffer so that we can produce long packets without
534549
// making the stack large.
535550
if (command->path_length > (COMMAND_SIZE - header_size - 1)) { // -1 for the null we'll write
536551
// TODO: throw away any more packets of path.
537552
entry->command = LISTDIR_ENTRY;
538553
entry->status = STATUS_ERROR;
539-
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)entry, response_size, NULL, 0);
554+
send_listdir_entry_header(entry, max_packet_size);
540555
return ANY_COMMAND;
541556
}
542557
// We need to receive another packet to have the full path.
@@ -560,7 +575,7 @@ STATIC uint8_t _process_listdir(uint8_t *raw_buf, size_t command_len) {
560575

561576
if (res != FR_OK) {
562577
entry->status = STATUS_ERROR_NO_FILE;
563-
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)entry, response_size, NULL, 0);
578+
send_listdir_entry_header(entry, max_packet_size);
564579
return ANY_COMMAND;
565580
}
566581
FILINFO file_info;
@@ -594,7 +609,7 @@ STATIC uint8_t _process_listdir(uint8_t *raw_buf, size_t command_len) {
594609

595610
size_t name_length = strlen(file_info.fname);
596611
entry->path_length = name_length;
597-
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)entry, response_size, NULL, 0);
612+
send_listdir_entry_header(entry, max_packet_size);
598613
size_t fn_offset = 0;
599614
while (fn_offset < name_length) {
600615
size_t fn_size = MIN(name_length - fn_offset, 4);
@@ -607,7 +622,7 @@ STATIC uint8_t _process_listdir(uint8_t *raw_buf, size_t command_len) {
607622
entry->entry_number = entry->entry_count;
608623
entry->flags = 0;
609624
entry->file_size = 0;
610-
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)entry, response_size, NULL, 0);
625+
send_listdir_entry_header(entry, max_packet_size);
611626
return ANY_COMMAND;
612627
}
613628

0 commit comments

Comments
 (0)