OSDN Git Service

GD HCI: Support vendor specific event in GD
authorJack He <siyuanh@google.com>
Thu, 25 Mar 2021 00:53:18 +0000 (17:53 -0700)
committerJack He <siyuanh@google.com>
Thu, 25 Mar 2021 01:00:35 +0000 (18:00 -0700)
* Add a handler for vendor specific command
* Add registration and unregistration APIs
* LOG_ERROR when an unknown vendor specific event is received
* Add unit tests to validate the above functions

Tag: #gd-refactor
Bug: 183057550
Test: bluetooth_test_gd
Change-Id: I00d6d892f3d60a8909352061dcae45f92d47b91d

gd/hci/hci_layer.cc
gd/hci/hci_layer.h
gd/hci/hci_layer_test.cc

index 8eb91f0..8fea49a 100644 (file)
@@ -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_);
index c78b94d..4db0c19 100644 (file)
@@ -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);
index 017a0b9..7ea31e4 100644 (file)
@@ -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());