Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c3c286f authored by Myles Watson's avatar Myles Watson Committed by Automerger Merge Worker
Browse files

Merge "HCI: Remove unused ACL fragmentation" am: a24c9114

parents f285ca44 a24c9114
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -40,7 +40,6 @@
#define MSG_HC_TO_STACK_HCI_EVT 0x1000      /* eq. BT_EVT_TO_BTU_HCI_EVT */

/* Message event ID passed from stack to vendor lib */
#define MSG_STACK_TO_HC_HCI_ACL 0x2100 /* eq. BT_EVT_TO_LM_HCI_ACL */
#define MSG_STACK_TO_HC_HCI_SCO 0x2200 /* eq. BT_EVT_TO_LM_HCI_SCO */
#define MSG_STACK_TO_HC_HCI_ISO 0x2d00 /* eq. BT_EVT_TO_LM_HCI_ISO */
#define MSG_STACK_TO_HC_HCI_CMD 0x2000 /* eq. BT_EVT_TO_LM_HCI_CMD */
+1 −53
Original line number Diff line number Diff line
@@ -100,7 +100,6 @@ static bool check_uint16_overflow(uint16_t a, uint16_t b) {
  return (UINT16_MAX - a) < b;
}

static void fragment_and_dispatch_acl(BT_HDR* packet);
static void fragment_and_dispatch_iso(BT_HDR* packet);

static void fragment_and_dispatch(BT_HDR* packet) {
@@ -108,9 +107,7 @@ static void fragment_and_dispatch(BT_HDR* packet) {

  uint16_t event = packet->event & MSG_EVT_MASK;

  if (event == MSG_STACK_TO_HC_HCI_ACL) {
    fragment_and_dispatch_acl(packet);
  } else if (event == MSG_HC_TO_STACK_HCI_SCO) {
  if (event == MSG_HC_TO_STACK_HCI_SCO) {
    callbacks->fragmented(packet, true);
  } else if (event == MSG_STACK_TO_HC_HCI_ISO) {
    fragment_and_dispatch_iso(packet);
@@ -119,55 +116,6 @@ static void fragment_and_dispatch(BT_HDR* packet) {
  }
}

static void fragment_and_dispatch_acl(BT_HDR* packet) {
  uint16_t max_data_size =
      SUB_EVENT(packet->event) == LOCAL_BR_EDR_CONTROLLER_ID
          ? controller->get_acl_data_size_classic()
          : controller->get_acl_data_size_ble();

  uint16_t max_packet_size = max_data_size + HCI_ACL_PREAMBLE_SIZE;
  uint16_t remaining_length = packet->len;

  uint8_t* stream = packet->data + packet->offset;

  uint16_t continuation_handle;
  STREAM_TO_UINT16(continuation_handle, stream);
  continuation_handle = APPLY_CONTINUATION_FLAG(continuation_handle);

  while (remaining_length > max_packet_size) {
    // Make sure we use the right ACL packet size
    stream = packet->data + packet->offset;
    STREAM_SKIP_UINT16(stream);
    UINT16_TO_STREAM(stream, max_data_size);

    packet->len = max_packet_size;
    callbacks->fragmented(packet, false);

    packet->offset += max_data_size;
    remaining_length -= max_data_size;
    packet->len = remaining_length;

    // Write the ACL header for the next fragment
    stream = packet->data + packet->offset;
    UINT16_TO_STREAM(stream, continuation_handle);
    UINT16_TO_STREAM(stream, remaining_length - HCI_ACL_PREAMBLE_SIZE);

    // Apparently L2CAP can set layer_specific to a max number of segments to
    // transmit
    if (packet->layer_specific) {
      packet->layer_specific--;

      if (packet->layer_specific == 0) {
        packet->event = BT_EVT_TO_BTU_L2C_SEG_XMIT;
        callbacks->transmit_finished(packet, false);
        return;
      }
    }
  }

  callbacks->fragmented(packet, true);
}

static void fragment_and_dispatch_iso(BT_HDR* packet) {
  uint8_t* stream = packet->data + packet->offset;
  uint16_t max_data_size = controller->get_iso_data_size();
+5 −182
Original line number Diff line number Diff line
@@ -28,10 +28,6 @@
#include "stack/include/bt_hdr.h"
#include "test_stubs.h"

#ifndef HCI_ACL_PREAMBLE_SIZE
#define HCI_ACL_PREAMBLE_SIZE 4
#endif

#ifndef HCI_ISO_PREAMBLE_SIZE
#define HCI_ISO_PREAMBLE_SIZE 4
#endif
@@ -60,8 +56,6 @@ static const char* sample_data =
    "a breed from off the face of the earth.\"";

static const char* small_sample_data = "\"What giants?\" said Sancho Panza.";
static const uint16_t test_handle_start = (0x1992 & 0xCFFF) | 0x2000;
static const uint16_t test_handle_continuation = (0x1992 & 0xCFFF) | 0x1000;
static const uint16_t test_iso_handle_complete_with_ts =
    (0x0666 | (0x0002 << 12) | (0x0001 << 14));
static const uint16_t test_iso_handle_complete_without_ts =
@@ -85,9 +79,7 @@ static BT_HDR* manufacture_packet_for_fragmentation(uint16_t event,
                                                    const char* data) {
  uint16_t data_length = strlen(data);
  uint16_t size = data_length;
  if (event == MSG_STACK_TO_HC_HCI_ACL) {
    size += 4;  // 2 for the handle, 2 for the length;
  } else if (event == MSG_STACK_TO_HC_HCI_ISO) {
  if (event == MSG_STACK_TO_HC_HCI_ISO) {
    size += 8;  // handle (2), length (2), packet_seq (2), sdu_len(2)
    if (iso_has_ts) {
      size += 4;
@@ -101,10 +93,7 @@ static BT_HDR* manufacture_packet_for_fragmentation(uint16_t event,
  packet->layer_specific = 0;
  uint8_t* packet_data = packet->data;

  if (event == MSG_STACK_TO_HC_HCI_ACL) {
    UINT16_TO_STREAM(packet_data, test_handle_start);
    UINT16_TO_STREAM(packet_data, data_length);
  } else if (event == MSG_STACK_TO_HC_HCI_ISO) {
  if (event == MSG_STACK_TO_HC_HCI_ISO) {
    if (iso_has_ts) {
      packet->layer_specific |= BT_ISO_HDR_CONTAINS_TS;
      UINT16_TO_STREAM(packet_data, test_iso_handle_start_with_ts);
@@ -129,28 +118,7 @@ static void expect_packet_fragmented(uint16_t event, int max_acl_data_size,
  int expected_data_offset;
  int length_to_check;

  if (event == MSG_STACK_TO_HC_HCI_ACL) {
    uint16_t handle;
    uint16_t length;
    STREAM_TO_UINT16(handle, data);
    STREAM_TO_UINT16(length, data);

    if (packet_index == 0)
      EXPECT_EQ(test_handle_start, handle);
    else
      EXPECT_EQ(test_handle_continuation, handle);

    int length_remaining = strlen(expected_data) - data_size_sum;
    int packet_data_length = packet->len - HCI_ACL_PREAMBLE_SIZE;
    EXPECT_EQ(packet_data_length, length);

    if (length_remaining > max_acl_data_size)
      EXPECT_EQ(max_acl_data_size, packet_data_length);

    length_to_check = packet_data_length;
    expected_data_offset = packet_index * max_acl_data_size;
    packet_index++;
  } else if (event == MSG_STACK_TO_HC_HCI_ISO) {
  if (event == MSG_STACK_TO_HC_HCI_ISO) {
    uint16_t handle;
    uint16_t length;

@@ -221,49 +189,12 @@ static void expect_packet_fragmented(uint16_t event, int max_acl_data_size,
    data_size_sum++;
  }

  if (event == MSG_STACK_TO_HC_HCI_ISO || event == MSG_STACK_TO_HC_HCI_ACL)
  if (event == MSG_STACK_TO_HC_HCI_ISO)
    EXPECT_TRUE(send_complete == (data_size_sum == strlen(expected_data)));

  if (send_complete) osi_free(packet);
}

static void manufacture_acl_packet_and_then_reassemble(uint16_t event,
                                                       uint16_t acl_size,
                                                       const char* data) {
  uint16_t data_length = strlen(data);
  uint16_t total_length = data_length + 2;  // 2 for l2cap length;
  uint16_t length_sent = 0;
  uint16_t l2cap_length = data_length - 2;  // l2cap length field, 2 for the
                                            // pretend channel id borrowed
                                            // from the data

  do {
    int length_to_send = (length_sent + (acl_size - 4) < total_length)
                             ? (acl_size - 4)
                             : (total_length - length_sent);
    BT_HDR* packet = (BT_HDR*)osi_malloc(length_to_send + 4 + sizeof(BT_HDR));
    packet->len = length_to_send + 4;
    packet->offset = 0;
    packet->event = event;
    packet->layer_specific = 0;

    uint8_t* packet_data = packet->data;
    if (length_sent == 0) {  // first packet
      UINT16_TO_STREAM(packet_data, test_handle_start);
      UINT16_TO_STREAM(packet_data, length_to_send);
      UINT16_TO_STREAM(packet_data, l2cap_length);
      memcpy(packet_data, data, length_to_send - 2);
    } else {
      UINT16_TO_STREAM(packet_data, test_handle_continuation);
      UINT16_TO_STREAM(packet_data, length_to_send);
      memcpy(packet_data, data + length_sent - 2, length_to_send);
    }

    length_sent += length_to_send;
    fragmenter->reassemble_and_dispatch(packet);
  } while (length_sent < total_length);
}

static void manufacture_iso_packet_and_then_reassemble(uint16_t event,
                                                       uint16_t iso_size,
                                                       const char* data) {
@@ -338,9 +269,7 @@ static void manufacture_packet_and_then_reassemble(uint16_t event,
                                                   const char* data) {
  uint16_t data_length = strlen(data);

  if (event == MSG_HC_TO_STACK_HCI_ACL) {
    manufacture_acl_packet_and_then_reassemble(event, packet_size, data);
  } else if (event == MSG_HC_TO_STACK_HCI_ISO) {
  if (event == MSG_HC_TO_STACK_HCI_ISO) {
    manufacture_iso_packet_and_then_reassemble(event, packet_size, data);
  } else {
    BT_HDR* packet = (BT_HDR*)osi_malloc(data_length + sizeof(BT_HDR));
@@ -359,20 +288,6 @@ static void expect_packet_reassembled(uint16_t event, BT_HDR* packet,
  uint16_t expected_data_length = strlen(expected_data);
  uint8_t* data = packet->data + packet->offset;

  if (event == MSG_HC_TO_STACK_HCI_ACL) {
    uint16_t handle;
    uint16_t length;
    uint16_t l2cap_length;
    STREAM_TO_UINT16(handle, data);
    STREAM_TO_UINT16(length, data);
    STREAM_TO_UINT16(l2cap_length, data);

    EXPECT_EQ(test_handle_start, handle);
    EXPECT_EQ(expected_data_length + 2, length);
    EXPECT_EQ(expected_data_length - 2,
              l2cap_length);  // -2 for the pretend channel id
  }

  for (int i = 0; i < expected_data_length; i++) {
    EXPECT_EQ(expected_data[i], data[i]);
    data_size_sum++;
@@ -431,30 +346,6 @@ static void expect_packet_reassembled_iso(uint16_t event, BT_HDR* packet,
}

STUB_FUNCTION(void, fragmented_callback, (BT_HDR * packet, bool send_complete))
DURING(no_fragmentation) AT_CALL(0) {
  expect_packet_fragmented(MSG_STACK_TO_HC_HCI_ACL, 42, packet,
                           small_sample_data, send_complete);
  return;
}

DURING(fragmentation) {
  expect_packet_fragmented(MSG_STACK_TO_HC_HCI_ACL, 10, packet, sample_data,
                           send_complete);
  return;
}

DURING(ble_no_fragmentation) AT_CALL(0) {
  expect_packet_fragmented(MSG_STACK_TO_HC_HCI_ACL, 42, packet,
                           small_sample_data, send_complete);
  return;
}

DURING(ble_fragmentation) {
  expect_packet_fragmented(MSG_STACK_TO_HC_HCI_ACL, 10, packet, sample_data,
                           send_complete);
  return;
}

DURING(iso_fragmentation) {
  expect_packet_fragmented(MSG_STACK_TO_HC_HCI_ISO, 10, packet, sample_data,
                           send_complete);
@@ -477,16 +368,6 @@ UNEXPECTED_CALL;
}

STUB_FUNCTION(void, reassembled_callback, (BT_HDR * packet))
DURING(no_reassembly) AT_CALL(0) {
  expect_packet_reassembled(MSG_HC_TO_STACK_HCI_ACL, packet, small_sample_data);
  return;
}

DURING(reassembly) AT_CALL(0) {
  expect_packet_reassembled(MSG_HC_TO_STACK_HCI_ACL, packet, sample_data);
  return;
}

DURING(iso_reassembly) AT_CALL(0) {
  expect_packet_reassembled_iso(MSG_HC_TO_STACK_HCI_ISO, packet, sample_data,
                                iso_timestamp, iso_packet_seq);
@@ -580,46 +461,6 @@ class PacketFragmenterTest : public AllocationTestHarness {
  packet_fragmenter_callbacks_t callbacks;
};

TEST_F(PacketFragmenterTest, test_no_fragment_necessary) {
  reset_for(no_fragmentation);
  BT_HDR* packet = manufacture_packet_for_fragmentation(MSG_STACK_TO_HC_HCI_ACL,
                                                        small_sample_data);
  fragmenter->fragment_and_dispatch(packet);

  EXPECT_EQ(strlen(small_sample_data), data_size_sum);
  EXPECT_CALL_COUNT(fragmented_callback, 1);
}

TEST_F(PacketFragmenterTest, test_fragment_necessary) {
  reset_for(fragmentation);
  BT_HDR* packet = manufacture_packet_for_fragmentation(MSG_STACK_TO_HC_HCI_ACL,
                                                        sample_data);
  fragmenter->fragment_and_dispatch(packet);

  EXPECT_EQ(strlen(sample_data), data_size_sum);
}

TEST_F(PacketFragmenterTest, test_ble_no_fragment_necessary) {
  reset_for(ble_no_fragmentation);
  BT_HDR* packet = manufacture_packet_for_fragmentation(MSG_STACK_TO_HC_HCI_ACL,
                                                        small_sample_data);
  packet->event |= LOCAL_BLE_CONTROLLER_ID;
  fragmenter->fragment_and_dispatch(packet);

  EXPECT_EQ(strlen(small_sample_data), data_size_sum);
  EXPECT_CALL_COUNT(fragmented_callback, 1);
}

TEST_F(PacketFragmenterTest, test_ble_fragment_necessary) {
  reset_for(ble_fragmentation);
  BT_HDR* packet = manufacture_packet_for_fragmentation(MSG_STACK_TO_HC_HCI_ACL,
                                                        sample_data);
  packet->event |= LOCAL_BLE_CONTROLLER_ID;
  fragmenter->fragment_and_dispatch(packet);

  EXPECT_EQ(strlen(sample_data), data_size_sum);
}

TEST_F(PacketFragmenterTest, test_non_acl_passthrough_fragmentation) {
  reset_for(non_acl_passthrough_fragmentation);
  BT_HDR* packet = manufacture_packet_for_fragmentation(MSG_STACK_TO_HC_HCI_CMD,
@@ -630,24 +471,6 @@ TEST_F(PacketFragmenterTest, test_non_acl_passthrough_fragmentation) {
  EXPECT_CALL_COUNT(fragmented_callback, 1);
}

TEST_F(PacketFragmenterTest, test_no_reassembly_necessary) {
  reset_for(no_reassembly);
  manufacture_packet_and_then_reassemble(MSG_HC_TO_STACK_HCI_ACL, 1337,
                                         small_sample_data);

  EXPECT_EQ(strlen(small_sample_data), data_size_sum);
  EXPECT_CALL_COUNT(reassembled_callback, 1);
}

TEST_F(PacketFragmenterTest, test_reassembly_necessary) {
  reset_for(reassembly);
  manufacture_packet_and_then_reassemble(MSG_HC_TO_STACK_HCI_ACL, 42,
                                         sample_data);

  EXPECT_EQ(strlen(sample_data), data_size_sum);
  EXPECT_CALL_COUNT(reassembled_callback, 1);
}

TEST_F(PacketFragmenterTest, test_non_acl_passthrough_reasseembly) {
  reset_for(non_acl_passthrough_reassembly);
  manufacture_packet_and_then_reassemble(MSG_HC_TO_STACK_HCI_EVT, 42,
+1 −26
Original line number Diff line number Diff line
@@ -381,27 +381,6 @@ static void transmit_command(const BT_HDR* command,
  }
}

static void transmit_fragment(const uint8_t* stream, size_t length) {
  uint16_t handle_with_flags;
  STREAM_TO_UINT16(handle_with_flags, stream);
  auto pb_flag = static_cast<bluetooth::hci::PacketBoundaryFlag>(
      handle_with_flags >> 12 & 0b11);
  auto bc_flag =
      static_cast<bluetooth::hci::BroadcastFlag>(handle_with_flags >> 14);
  uint16_t handle = HCID_GET_HANDLE(handle_with_flags);
  ASSERT_LOG(handle <= HCI_HANDLE_MAX, "Require handle <= 0x%X, but is 0x%X",
             HCI_HANDLE_MAX, handle);
  length -= 2;
  // skip data total length
  stream += 2;
  length -= 2;
  auto payload = MakeUniquePacket(stream, length);
  auto acl_packet = bluetooth::hci::AclBuilder::Create(handle, pb_flag, bc_flag,
                                                       std::move(payload));
  pending_data->Enqueue(std::move(acl_packet),
                        bluetooth::shim::GetGdShimHandler());
}

static void transmit_sco_fragment(const uint8_t* stream, size_t length) {
  uint16_t handle_with_flags;
  STREAM_TO_UINT16(handle_with_flags, stream);
@@ -598,11 +577,7 @@ static void transmit_fragment(BT_HDR* packet, bool send_transmit_finished) {
  bool free_after_transmit =
      event != MSG_STACK_TO_HC_HCI_CMD && send_transmit_finished;

  if (event == MSG_STACK_TO_HC_HCI_ACL) {
    const uint8_t* stream = packet->data + packet->offset;
    size_t length = packet->len;
    cpp::transmit_fragment(stream, length);
  } else if (event == MSG_STACK_TO_HC_HCI_SCO) {
  if (event == MSG_STACK_TO_HC_HCI_SCO) {
    const uint8_t* stream = packet->data + packet->offset;
    size_t length = packet->len;
    cpp::transmit_sco_fragment(stream, length);