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

Commit 5c7be42e authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

GD: forward ISO packets to ISO manager

when packet_fragmenter fragments ISO packets, ensure GD shim properly
forwards them to HCI layer.
Also, when the credits are returned, forward them from GD to ISO manager
properly.

Test: Stream LE Audio
Bug: 177907117
Change-Id: I479ca2bd167559e3bbf240f68134a75f3480d1c2
parent 788396de
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -21,11 +21,13 @@ pub mod ffi {

        // HCI
        fn hci_set_acl_callback(hci: &mut Hci, callback: UniquePtr<u8SliceCallback>);
        fn hci_set_iso_callback(hci: &mut Hci, callback: UniquePtr<u8SliceCallback>);
        fn hci_set_evt_callback(hci: &mut Hci, callback: UniquePtr<u8SliceCallback>);
        fn hci_set_le_evt_callback(hci: &mut Hci, callback: UniquePtr<u8SliceCallback>);

        fn hci_send_command(hci: &mut Hci, data: &[u8], callback: UniquePtr<u8SliceOnceCallback>);
        fn hci_send_acl(hci: &mut Hci, data: &[u8]);
        fn hci_send_iso(hci: &mut Hci, data: &[u8]);
        fn hci_register_event(hci: &mut Hci, event: u8);
        fn hci_register_le_event(hci: &mut Hci, subevent: u8);

+17 −1
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
use crate::bridge::ffi;
use bt_facade_helpers::U8SliceRunnable;
use bt_hci::facade::HciFacadeService;
use bt_packets::hci::{AclPacket, CommandPacket, Packet};
use bt_packets::hci::{AclPacket, CommandPacket, IsoPacket, Packet};
use std::sync::Arc;
use tokio::runtime::Runtime;

@@ -62,6 +62,18 @@ pub fn hci_send_acl(hci: &mut Hci, data: &[u8]) {
    }
}

pub fn hci_send_iso(hci: &mut Hci, data: &[u8]) {
    match IsoPacket::parse(data) {
        Ok(packet) => {
            let tx = hci.internal.iso_tx.clone();
            hci.rt.spawn(async move {
                tx.send(packet).await.unwrap();
            });
        }
        Err(e) => panic!("could not parse iso: {:?} {:02x?}", e, data),
    }
}

pub fn hci_register_event(hci: &mut Hci, event: u8) {
    let mut hci_facade = hci.internal.clone();
    hci.rt.spawn(async move {
@@ -80,6 +92,10 @@ pub fn hci_set_acl_callback(hci: &mut Hci, cb: cxx::UniquePtr<ffi::u8SliceCallba
    hci.internal.acl_rx.stream_runnable(&hci.rt, CallbackWrapper { cb });
}

pub fn hci_set_iso_callback(hci: &mut Hci, cb: cxx::UniquePtr<ffi::u8SliceCallback>) {
    hci.internal.iso_rx.stream_runnable(&hci.rt, CallbackWrapper { cb });
}

pub fn hci_set_evt_callback(hci: &mut Hci, cb: cxx::UniquePtr<ffi::u8SliceCallback>) {
    hci.internal.evt_rx.stream_runnable(&hci.rt, CallbackWrapper { cb });
}
+108 −8
Original line number Diff line number Diff line
@@ -296,8 +296,13 @@ namespace cpp {
bluetooth::common::BidiQueueEnd<bluetooth::hci::AclBuilder,
                                bluetooth::hci::AclView>* hci_queue_end =
    nullptr;
bluetooth::common::BidiQueueEnd<bluetooth::hci::IsoBuilder,
                                bluetooth::hci::IsoView>* hci_iso_queue_end =
    nullptr;
static bluetooth::os::EnqueueBuffer<bluetooth::hci::AclBuilder>* pending_data =
    nullptr;
static bluetooth::os::EnqueueBuffer<bluetooth::hci::IsoBuilder>*
    pending_iso_data = nullptr;

static std::unique_ptr<bluetooth::packet::RawBuilder> MakeUniquePacket(
    const uint8_t* data, size_t len) {
@@ -427,6 +432,26 @@ static void transmit_fragment(const uint8_t* stream, size_t length) {
                        bluetooth::shim::GetGdShimHandler());
}

static void transmit_iso_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::IsoPacketBoundaryFlag>(
      handle_with_flags >> 12 & 0b11);
  auto ts_flag =
      static_cast<bluetooth::hci::TimeStampFlag>(handle_with_flags >> 14);
  uint16_t handle = handle_with_flags & 0xEFF;
  length -= 2;
  // skip data total length
  stream += 2;
  length -= 2;
  auto payload = MakeUniquePacket(stream, length);
  auto iso_packet = bluetooth::hci::IsoBuilder::Create(handle, pb_flag, ts_flag,
                                                       std::move(payload));

  pending_iso_data->Enqueue(std::move(iso_packet),
                            bluetooth::shim::GetGdShimHandler());
}

static void register_event(bluetooth::hci::EventCode event_code) {
  auto handler = bluetooth::shim::GetGdShimHandler();
  bluetooth::shim::GetHciLayer()->RegisterEventHandler(
@@ -456,6 +481,23 @@ static void acl_data_callback() {
  packet_fragmenter->reassemble_and_dispatch(data);
}

static void iso_data_callback() {
  if (hci_iso_queue_end == nullptr) {
    return;
  }
  auto packet = hci_queue_end->TryDequeue();
  ASSERT(packet != nullptr);
  if (!packet->IsValid()) {
    LOG_INFO("Dropping invalid packet of size %zu", packet->size());
    return;
  }
  if (!send_data_upwards) {
    return;
  }
  auto data = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_ISO, packet.get());
  packet_fragmenter->reassemble_and_dispatch(data);
}

static void register_for_acl() {
  hci_queue_end = bluetooth::shim::GetHciLayer()->GetAclQueueEnd();

@@ -472,12 +514,27 @@ static void register_for_acl() {
      hci_queue_end);
}

static void register_for_iso() {
  hci_iso_queue_end = bluetooth::shim::GetHciLayer()->GetIsoQueueEnd();
  hci_iso_queue_end->RegisterDequeue(
      bluetooth::shim::GetGdShimHandler(),
      bluetooth::common::Bind(iso_data_callback));
  pending_iso_data =
      new bluetooth::os::EnqueueBuffer<bluetooth::hci::IsoBuilder>(
          hci_iso_queue_end);
}

static void on_shutting_down() {
  if (pending_data != nullptr) {
    pending_data->Clear();
    delete pending_data;
    pending_data = nullptr;
  }
  if (pending_iso_data != nullptr) {
    pending_iso_data->Clear();
    delete pending_iso_data;
    pending_iso_data = nullptr;
  }
  if (hci_queue_end != nullptr) {
    if (!bluetooth::shim::is_gd_advertising_enabled() &&
        !bluetooth::shim::is_gd_l2cap_enabled()) {
@@ -501,6 +558,11 @@ static void on_shutting_down() {
    }
    hci_queue_end = nullptr;
  }

  if (hci_iso_queue_end != nullptr) {
    hci_iso_queue_end->UnregisterDequeue();
    hci_iso_queue_end = nullptr;
  }
}

}  // namespace cpp
@@ -534,6 +596,14 @@ static void on_acl(::rust::Slice<const uint8_t> data) {
  packet_fragmenter->reassemble_and_dispatch(legacy_data);
}

static void on_iso(::rust::Slice<const uint8_t> data) {
  if (!send_data_upwards) {
    return;
  }
  auto legacy_data = WrapRustPacketAndCopy(MSG_HC_TO_STACK_HCI_ISO, &data);
  packet_fragmenter->reassemble_and_dispatch(legacy_data);
}

static void on_event(::rust::Slice<const uint8_t> data) {
  if (!send_data_upwards) {
    return;
@@ -596,6 +666,12 @@ static void transmit_fragment(const uint8_t* stream, size_t length) {
      ::rust::Slice(stream, length));
}

static void transmit_iso_fragment(const uint8_t* stream, size_t length) {
  bluetooth::shim::rust::hci_send_iso(
      **bluetooth::shim::Stack::Stack::GetInstance()->GetRustHci(),
      ::rust::Slice(stream, length));
}

static void register_event(bluetooth::hci::EventCode event_code) {
  bluetooth::shim::rust::hci_register_event(
      **bluetooth::shim::Stack::GetInstance()->GetRustHci(),
@@ -623,6 +699,12 @@ static void register_for_acl() {
      std::make_unique<u8SliceCallback>(Bind(rust::on_acl)));
}

static void register_for_iso() {
  bluetooth::shim::rust::hci_set_iso_callback(
      **bluetooth::shim::Stack::GetInstance()->GetRustHci(),
      std::make_unique<u8SliceCallback>(Bind(rust::on_iso)));
}

static void on_shutting_down() {}

}  // namespace rust
@@ -662,12 +744,14 @@ static future_t* transmit_command_futured(BT_HDR* command) {
}

static void transmit_fragment(BT_HDR* packet, bool send_transmit_finished) {
  uint16_t event = packet->event & MSG_EVT_MASK;

  // HCI command packets are freed on a different thread when the matching
  // event is received. Check packet->event before sending to avoid a race.
  bool free_after_transmit =
      (packet->event & MSG_EVT_MASK) != MSG_STACK_TO_HC_HCI_CMD &&
      send_transmit_finished;
      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;
    if (bluetooth::common::init_flags::gd_rust_is_enabled()) {
@@ -675,6 +759,16 @@ static void transmit_fragment(BT_HDR* packet, bool send_transmit_finished) {
    } else {
      cpp::transmit_fragment(stream, length);
    }
  } else if (event == MSG_STACK_TO_HC_HCI_ISO) {
    const uint8_t* stream = packet->data + packet->offset;
    size_t length = packet->len;
    if (bluetooth::common::init_flags::gd_rust_is_enabled()) {
      rust::transmit_iso_fragment(stream, length);
    } else {
      cpp::transmit_iso_fragment(stream, length);
    }
  }

  if (free_after_transmit) {
    osi_free(packet);
  }
@@ -775,6 +869,12 @@ void bluetooth::shim::hci_on_reset_complete() {
      bluetooth::hci::VseSubeventCode::BQR_EVENT,
      handler->Bind(cpp::vendor_specific_event_callback));

  if (bluetooth::common::init_flags::gd_rust_is_enabled()) {
    ::rust::register_for_iso();
  } else {
    cpp::register_for_iso();
  }

  if (bluetooth::shim::is_gd_acl_enabled()) {
    return;
  }
+2 −0
Original line number Diff line number Diff line
@@ -2803,6 +2803,8 @@ void acl_link_segments_xmitted(BT_HDR* p_msg) {

void acl_packets_completed(uint16_t handle, uint16_t credits) {
  l2c_packets_completed(handle, credits);
  bluetooth::hci::IsoManager::GetInstance()->HandleGdNumComplDataPkts(handle,
                                                                      credits);
}

static void acl_parse_num_completed_pkts(uint8_t* p, uint8_t evt_len) {
+5 −0
Original line number Diff line number Diff line
@@ -122,6 +122,11 @@ void IsoManager::HandleNumComplDataPkts(uint8_t* p, uint8_t evt_len) {
    pimpl_->iso_impl_->handle_num_completed_pkts(p, evt_len);
}

void IsoManager::HandleGdNumComplDataPkts(uint16_t handle, uint16_t credits) {
  if (pimpl_->IsRunning())
    pimpl_->iso_impl_->handle_gd_num_completed_pkts(handle, credits);
}

void IsoManager::HandleHciEvent(uint8_t sub_code, uint8_t* params,
                                uint16_t length) {
  if (pimpl_->IsRunning())
Loading