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

Commit b4151e6f authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "GD HCI: Support vendor specific event in GD"

parents 70149680 464efded
Loading
Loading
Loading
Loading
+39 −1
Original line number Diff line number Diff line
@@ -228,6 +228,20 @@ struct HciLayer::impl {
    subevent_handlers_.erase(subevent_handlers_.find(event));
  }

  void register_vendor_specific_event(
      VseSubeventCode vse_subevent_code, ContextualCallback<void(VendorSpecificEventView)> event_handler) {
    ASSERT_LOG(
        vendor_specific_event_handlers_.count(vse_subevent_code) == 0,
        "Can not register a second handler for %02hhx (%s)",
        vse_subevent_code,
        VseSubeventCodeText(vse_subevent_code).c_str());
    vendor_specific_event_handlers_[vse_subevent_code] = event_handler;
  }

  void unregister_vendor_specific_event(VseSubeventCode vse_subevent_code) {
    vendor_specific_event_handlers_.erase(vendor_specific_event_handlers_.find(vse_subevent_code));
  }

  void on_hci_event(EventView event) {
    ASSERT(event.IsValid());
    EventCode event_code = event.GetEventCode();
@@ -251,6 +265,20 @@ struct HciLayer::impl {
    subevent_handlers_[subevent_code].Invoke(meta_event_view);
  }

  void on_vendor_specific_event(EventView event) {
    VendorSpecificEventView vendor_specific_event_view = VendorSpecificEventView::Create(event);
    ASSERT(vendor_specific_event_view.IsValid());
    VseSubeventCode vse_subevent_code = vendor_specific_event_view.GetSubeventCode();
    if (vendor_specific_event_handlers_.find(vse_subevent_code) == vendor_specific_event_handlers_.end()) {
      LOG_ERROR(
          "Unhandled vendor specific event of type 0x%02hhx (%s)",
          vse_subevent_code,
          VseSubeventCodeText(vse_subevent_code).c_str());
      return;
    }
    vendor_specific_event_handlers_[vse_subevent_code].Invoke(vendor_specific_event_view);
  }

  hal::HciHal* hal_;
  HciLayer& module_;

@@ -259,6 +287,7 @@ struct HciLayer::impl {

  std::map<EventCode, ContextualCallback<void(EventView)>> event_handlers_;
  std::map<SubeventCode, ContextualCallback<void(LeMetaEventView)>> subevent_handlers_;
  std::map<VseSubeventCode, ContextualCallback<void(VendorSpecificEventView)>> vendor_specific_event_handlers_;
  OpCode waiting_command_{OpCode::NONE};
  uint8_t command_credits_{1};  // Send reset first
  Alarm* hci_timeout_alarm_{nullptr};
@@ -344,6 +373,15 @@ void HciLayer::UnregisterLeEventHandler(SubeventCode event) {
  CallOn(impl_, &impl::unregister_le_event, event);
}

void HciLayer::RegisterVendorSpecificEventHandler(
    VseSubeventCode vse_subevent_code, common::ContextualCallback<void(VendorSpecificEventView)> event_handler) {
  CallOn(impl_, &impl::register_vendor_specific_event, vse_subevent_code, event_handler);
}

void HciLayer::UnregisterVendorSpecificEventHandler(VseSubeventCode vse_subevent_code) {
  CallOn(impl_, &impl::unregister_vendor_specific_event, vse_subevent_code);
}

void HciLayer::on_disconnection_complete(EventView event_view) {
  auto disconnection_view = DisconnectionCompleteView::Create(event_view);
  if (!disconnection_view.IsValid()) {
@@ -470,7 +508,7 @@ void HciLayer::Start() {
  auto drop_packet = handler->BindOn(impl_, &impl::drop);
  RegisterEventHandler(EventCode::PAGE_SCAN_REPETITION_MODE_CHANGE, drop_packet);
  RegisterEventHandler(EventCode::MAX_SLOTS_CHANGE, drop_packet);
  RegisterEventHandler(EventCode::VENDOR_SPECIFIC, drop_packet);
  RegisterEventHandler(EventCode::VENDOR_SPECIFIC, handler->BindOn(impl_, &impl::on_vendor_specific_event));

  EnqueueCommand(ResetBuilder::Create(), handler->BindOnce(&fail_if_reset_complete_not_success));
  hal->registerIncomingPacketCallback(hal_callbacks_);
+5 −0
Original line number Diff line number Diff line
@@ -67,6 +67,11 @@ class HciLayer : public Module, public CommandInterface<CommandBuilder> {

  virtual void UnregisterLeEventHandler(SubeventCode subevent_code);

  virtual void RegisterVendorSpecificEventHandler(
      VseSubeventCode vse_subevent_code, common::ContextualCallback<void(VendorSpecificEventView)> event_handler);

  virtual void UnregisterVendorSpecificEventHandler(VseSubeventCode vse_subevent_code);

  virtual SecurityInterface* GetSecurityInterface(common::ContextualCallback<void(EventView)> event_handler);

  virtual LeSecurityInterface* GetLeSecurityInterface(common::ContextualCallback<void(LeMetaEventView)> event_handler);
+122 −13
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include "hci/hci_layer.h"

#include <gtest/gtest.h>

#include <list>
#include <memory>

@@ -35,7 +36,20 @@ using std::vector;

namespace {
vector<uint8_t> information_request = {
    0xfe, 0x2e, 0x0a, 0x00, 0x06, 0x00, 0x01, 0x00, 0x0a, 0x02, 0x02, 0x00, 0x02, 0x00,
    0xfe,
    0x2e,
    0x0a,
    0x00,
    0x06,
    0x00,
    0x01,
    0x00,
    0x0a,
    0x02,
    0x02,
    0x00,
    0x02,
    0x00,
};
// 0x00, 0x01, 0x02, 0x03, ...
vector<uint8_t> counting_bytes;
@@ -170,13 +184,13 @@ class DependsOnHci : public Module {
  DependsOnHci() : Module() {}

  void SendHciCommandExpectingStatus(std::unique_ptr<CommandBuilder> command) {
    hci_->EnqueueCommand(std::move(command),
                         GetHandler()->BindOnceOn(this, &DependsOnHci::handle_event<CommandStatusView>));
    hci_->EnqueueCommand(
        std::move(command), GetHandler()->BindOnceOn(this, &DependsOnHci::handle_event<CommandStatusView>));
  }

  void SendHciCommandExpectingComplete(std::unique_ptr<CommandBuilder> command) {
    hci_->EnqueueCommand(std::move(command),
                         GetHandler()->BindOnceOn(this, &DependsOnHci::handle_event<CommandCompleteView>));
    hci_->EnqueueCommand(
        std::move(command), GetHandler()->BindOnceOn(this, &DependsOnHci::handle_event<CommandCompleteView>));
  }

  void SendSecurityCommandExpectingComplete(std::unique_ptr<SecurityCommandBuilder> command) {
@@ -184,8 +198,8 @@ class DependsOnHci : public Module {
      security_interface_ =
          hci_->GetSecurityInterface(GetHandler()->BindOn(this, &DependsOnHci::handle_event<EventView>));
    }
    hci_->EnqueueCommand(std::move(command),
                         GetHandler()->BindOnceOn(this, &DependsOnHci::handle_event<CommandCompleteView>));
    hci_->EnqueueCommand(
        std::move(command), GetHandler()->BindOnceOn(this, &DependsOnHci::handle_event<CommandCompleteView>));
  }

  void SendLeSecurityCommandExpectingComplete(std::unique_ptr<LeSecurityCommandBuilder> command) {
@@ -193,8 +207,8 @@ class DependsOnHci : public Module {
      le_security_interface_ =
          hci_->GetLeSecurityInterface(GetHandler()->BindOn(this, &DependsOnHci::handle_event<LeMetaEventView>));
    }
    hci_->EnqueueCommand(std::move(command),
                         GetHandler()->BindOnceOn(this, &DependsOnHci::handle_event<CommandCompleteView>));
    hci_->EnqueueCommand(
        std::move(command), GetHandler()->BindOnceOn(this, &DependsOnHci::handle_event<CommandCompleteView>));
  }

  void SendAclData(std::unique_ptr<AclBuilder> acl) {
@@ -256,14 +270,23 @@ class DependsOnHci : public Module {
    return packetview;
  }

  void RegisterVendorSpecificEvent(VseSubeventCode event) {
    hci_->RegisterVendorSpecificEventHandler(
        event, GetHandler()->BindOn(this, &DependsOnHci::handle_event<VendorSpecificEventView>));
  }

  void UnregisterVendorSpecificEvent(VseSubeventCode event) {
    hci_->UnregisterVendorSpecificEventHandler(event);
  }

  void Start() {
    hci_ = GetDependency<HciLayer>();
    hci_->RegisterEventHandler(
        EventCode::CONNECTION_COMPLETE, GetHandler()->BindOn(this, &DependsOnHci::handle_event<EventView>));
    hci_->RegisterLeEventHandler(SubeventCode::CONNECTION_COMPLETE,
                                 GetHandler()->BindOn(this, &DependsOnHci::handle_event<LeMetaEventView>));
    hci_->GetAclQueueEnd()->RegisterDequeue(GetHandler(),
                                            common::Bind(&DependsOnHci::handle_acl, common::Unretained(this)));
    hci_->RegisterLeEventHandler(
        SubeventCode::CONNECTION_COMPLETE, GetHandler()->BindOn(this, &DependsOnHci::handle_event<LeMetaEventView>));
    hci_->GetAclQueueEnd()->RegisterDequeue(
        GetHandler(), common::Bind(&DependsOnHci::handle_acl, common::Unretained(this)));
    hci_->GetIsoQueueEnd()->RegisterDequeue(
        GetHandler(), common::Bind(&DependsOnHci::handle_iso, common::Unretained(this)));
  }
@@ -436,6 +459,92 @@ TEST_F(HciTest, leMetaEvent) {
  ASSERT_TRUE(LeConnectionCompleteView::Create(LeMetaEventView::Create(EventView::Create(event))).IsValid());
}

TEST_F(HciTest, vendorSpecificEventRegistration) {
  auto event_future = upper->GetReceivedEventFuture();

  upper->RegisterVendorSpecificEvent(VseSubeventCode::BQR_EVENT);

  // Send a vendor specific event
  hal->callbacks->hciEventReceived(GetPacketBytes(BqrLinkQualityEventBuilder::Create(
      QualityReportId::A2DP_AUDIO_CHOPPY,
      BqrPacketType::TYPE_2DH1,
      /* handle */ 0x123,
      Role::CENTRAL,
      /* TX_Power_Level */ 0x05,
      /* RSSI */ 65,
      /* SNR */ 30,
      /* Unused_AFH_Channel_Count */ 0,
      /* AFH_Select_Unideal_Channel_Count */ 0,
      /* LSTO */ 12,
      /* Connection_Piconet_Clock */ 42,
      /* Retransmission_Count */ 1,
      /* No_RX_Count */ 1,
      /* NAK_Count */ 1,
      /* Last_TX_ACK_Timestamp */ 123456,
      /* Flow_Off_Count */ 78910,
      /* Last_Flow_On_Timestamp */ 123457,
      /* Buffer_Overflow_Bytes */ 42,
      /* Buffer_Underflow_Bytes */ 24,
      /* Vendor Specific Parameter */ std::make_unique<RawBuilder>())));

  // Wait for the event
  auto event_status = event_future.wait_for(kTimeout);
  ASSERT_EQ(event_status, std::future_status::ready);

  auto event = upper->GetReceivedEvent();
  ASSERT_TRUE(
      BqrLinkQualityEventView::Create(BqrEventView::Create(VendorSpecificEventView::Create(EventView::Create(event))))
          .IsValid());

  // Now test if we can unregister the vendor specific event handler
  event_future = upper->GetReceivedEventFuture();

  upper->UnregisterVendorSpecificEvent(VseSubeventCode::BQR_EVENT);

  hal->callbacks->hciEventReceived(GetPacketBytes(BqrLinkQualityEventBuilder::Create(
      QualityReportId::A2DP_AUDIO_CHOPPY,
      BqrPacketType::TYPE_2DH1,
      /* handle */ 0x123,
      Role::CENTRAL,
      /* TX_Power_Level */ 0x05,
      /* RSSI */ 65,
      /* SNR */ 30,
      /* Unused_AFH_Channel_Count */ 0,
      /* AFH_Select_Unideal_Channel_Count */ 0,
      /* LSTO */ 12,
      /* Connection_Piconet_Clock */ 42,
      /* Retransmission_Count */ 1,
      /* No_RX_Count */ 1,
      /* NAK_Count */ 1,
      /* Last_TX_ACK_Timestamp */ 123456,
      /* Flow_Off_Count */ 78910,
      /* Last_Flow_On_Timestamp */ 123457,
      /* Buffer_Overflow_Bytes */ 42,
      /* Buffer_Underflow_Bytes */ 24,
      /* Vendor Specific Parameter */ std::make_unique<RawBuilder>())));

  // Wait for unregistered event should timeout
  event_status = event_future.wait_for(kTimeout);
  ASSERT_NE(event_status, std::future_status::ready);
}

TEST_F(HciTest, vendorSpecificEventUnknown) {
  auto event_future = upper->GetReceivedEventFuture();

  upper->RegisterVendorSpecificEvent(VseSubeventCode::BQR_EVENT);

  // Send a vendor specific event
  // Make sure 0xFE is not used for any VSE, if not change this value to an unused one
  auto raw_builder = std::make_unique<RawBuilder>();
  raw_builder->AddOctets1(42);
  hal->callbacks->hciEventReceived(
      GetPacketBytes(VendorSpecificEventBuilder::Create(static_cast<VseSubeventCode>(0xFE), std::move(raw_builder))));

  // Wait for the event should timeout
  auto event_status = event_future.wait_for(kTimeout);
  ASSERT_NE(event_status, std::future_status::ready);
}

TEST_F(HciTest, noOpCredits) {
  ASSERT_EQ(0, hal->GetNumSentCommands());