OSDN Git Service

HAL: Add ISO packet callbacks
authorMyles Watson <mylesgw@google.com>
Tue, 11 Aug 2020 12:47:40 +0000 (05:47 -0700)
committerMyles Watson <mylesgw@google.com>
Thu, 13 Aug 2020 17:22:15 +0000 (10:22 -0700)
Tag: #feature
Test: cert/run --host
Bug: 163818400
Change-Id: Iec2f432f2bff35bb74f3891eb3bcd8656c4f7f16

gd/hal/facade.cc
gd/hal/facade.proto
gd/hal/hci_hal.h
gd/hal/hci_hal_host_rootcanal.cc
gd/hal/hci_hal_host_rootcanal_test.cc
gd/hal/snoop_logger.cc
gd/hal/snoop_logger.h
gd/hci/hci_layer.cc
gd/hci/hci_packets.pdl

index 8e00f10..c5a7c73 100644 (file)
@@ -93,6 +93,13 @@ class HciHalFacadeService : public HciHalFacade::Service, public ::bluetooth::ha
     return pending_sco_events_.RunLoop(context, writer);
   };
 
+  ::grpc::Status FetchHciIso(
+      ::grpc::ServerContext* context,
+      const ::google::protobuf::Empty* request,
+      ::grpc::ServerWriter<HciIsoPacket>* writer) override {
+    return pending_iso_events_.RunLoop(context, writer);
+  };
+
   void hciEventReceived(bluetooth::hal::HciPacket event) override {
     {
       HciEventPacket response;
@@ -115,6 +122,12 @@ class HciHalFacadeService : public HciHalFacade::Service, public ::bluetooth::ha
     pending_sco_events_.OnIncomingEvent(std::move(response));
   }
 
+  void isoDataReceived(bluetooth::hal::HciPacket data) override {
+    HciIsoPacket response;
+    response.set_payload(std::string(data.begin(), data.end()));
+    pending_iso_events_.OnIncomingEvent(std::move(response));
+  }
+
  private:
   HciHal* hal_;
   bool can_send_hci_command_ = true;
@@ -123,6 +136,7 @@ class HciHalFacadeService : public HciHalFacade::Service, public ::bluetooth::ha
   ::bluetooth::grpc::GrpcEventQueue<HciEventPacket> pending_hci_events_{"FetchHciEvent"};
   ::bluetooth::grpc::GrpcEventQueue<HciAclPacket> pending_acl_events_{"FetchHciAcl"};
   ::bluetooth::grpc::GrpcEventQueue<HciScoPacket> pending_sco_events_{"FetchHciSco"};
+  ::bluetooth::grpc::GrpcEventQueue<HciIsoPacket> pending_iso_events_{"FetchHciIso"};
 };
 
 void HciHalFacadeModule::ListDependencies(ModuleList* list) {
index 539e810..ddc4330 100644 (file)
@@ -8,10 +8,12 @@ service HciHalFacade {
   rpc SendHciCommand(HciCommandPacket) returns (google.protobuf.Empty) {}
   rpc SendHciAcl(HciAclPacket) returns (google.protobuf.Empty) {}
   rpc SendHciSco(HciScoPacket) returns (google.protobuf.Empty) {}
+  rpc SendHciIso(HciIsoPacket) returns (google.protobuf.Empty) {}
 
   rpc FetchHciEvent(google.protobuf.Empty) returns (stream HciEventPacket) {}
   rpc FetchHciAcl(google.protobuf.Empty) returns (stream HciAclPacket) {}
   rpc FetchHciSco(google.protobuf.Empty) returns (stream HciScoPacket) {}
+  rpc FetchHciIso(google.protobuf.Empty) returns (stream HciIsoPacket) {}
 }
 
 message HciEventPacket {
@@ -29,3 +31,7 @@ message HciAclPacket {
 message HciScoPacket {
   bytes payload = 1;
 }
+
+message HciIsoPacket {
+  bytes payload = 1;
+}
index 23ac2b5..dcc6a10 100644 (file)
@@ -40,13 +40,17 @@ class HciHalCallbacks {
   // @param event is the HCI event to be sent to the Bluetooth stack
   virtual void hciEventReceived(HciPacket event) = 0;
 
-  // Send an ACL data packet form the controller to the host
+  // Send an ACL data packet from the controller to the host
   // @param data the ACL HCI packet to be passed to the host stack
   virtual void aclDataReceived(HciPacket data) = 0;
 
-  // Send a SCO data packet form the controller to the host
+  // Send a SCO data packet from the controller to the host
   // @param data the SCO HCI packet to be passed to the host stack
   virtual void scoDataReceived(HciPacket data) = 0;
+
+  // Send an ISO data packet from the controller to the host
+  // @param data the ISO HCI packet to be passed to the host stack
+  virtual void isoDataReceived(HciPacket data) = 0;
 };
 
 // Mirrors hardware/interfaces/bluetooth/1.0/IBluetoothHci.hal in Android
index 803a6b5..20b87a4 100644 (file)
@@ -39,11 +39,13 @@ constexpr uint8_t kH4Command = 0x01;
 constexpr uint8_t kH4Acl = 0x02;
 constexpr uint8_t kH4Sco = 0x03;
 constexpr uint8_t kH4Event = 0x04;
+constexpr uint8_t kH4Iso = 0x05;
 
 constexpr uint8_t kH4HeaderSize = 1;
 constexpr uint8_t kHciAclHeaderSize = 4;
 constexpr uint8_t kHciScoHeaderSize = 3;
 constexpr uint8_t kHciEvtHeaderSize = 2;
+constexpr uint8_t kHciIsoHeaderSize = 4;
 constexpr int kBufSize = 1024 + 4 + 1;  // DeviceProperties::acl_data_packet_size_ + ACL header + H4 header
 
 int ConnectToRootCanal(const std::string& server, int port) {
@@ -317,6 +319,30 @@ class HciHalHostRootcanal : public HciHal {
         incoming_packet_callback_->scoDataReceived(receivedHciPacket);
       }
     }
+
+    if (buf[0] == kH4Iso) {
+      RUN_NO_INTR(received_size = recv(sock_fd_, buf + kH4HeaderSize, kHciIsoHeaderSize, 0));
+      ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno));
+      ASSERT_LOG(received_size == kHciIsoHeaderSize, "malformed ISO header received");
+
+      uint8_t hci_iso_data_total_length = buf[3];
+      int payload_size;
+      RUN_NO_INTR(payload_size = recv(sock_fd_, buf + kH4HeaderSize + kHciIsoHeaderSize, hci_iso_data_total_length, 0));
+      ASSERT_LOG(payload_size != -1, "Can't receive from socket: %s", strerror(errno));
+      ASSERT_LOG(payload_size == hci_iso_data_total_length, "malformed ISO packet received: size mismatch");
+
+      HciPacket receivedHciPacket;
+      receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciIsoHeaderSize + payload_size);
+      btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::ISO);
+      {
+        std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
+        if (incoming_packet_callback_ == nullptr) {
+          LOG_INFO("Dropping a ISO packet after processing");
+          return;
+        }
+        incoming_packet_callback_->isoDataReceived(receivedHciPacket);
+      }
+    }
     memset(buf, 0, kBufSize);
   }
 };
index aa92b84..882cf6b 100644 (file)
@@ -50,6 +50,7 @@ constexpr uint8_t kH4Command = 0x01;
 constexpr uint8_t kH4Acl = 0x02;
 constexpr uint8_t kH4Sco = 0x03;
 constexpr uint8_t kH4Event = 0x04;
+constexpr uint8_t kH4Iso = 0x05;
 
 using H4Packet = std::vector<uint8_t>;
 
@@ -68,6 +69,10 @@ class TestHciHalCallbacks : public HciHalCallbacks {
   void scoDataReceived(HciPacket packet) override {
     incoming_packets_queue_.emplace(kH4Sco, packet);
   }
+
+  void isoDataReceived(HciPacket packet) override {
+    incoming_packets_queue_.emplace(kH4Iso, packet);
+  }
 };
 
 // An implementation of rootcanal desktop HCI server which listens on localhost:kListeningPort
@@ -223,6 +228,15 @@ HciPacket make_sample_h4_sco_pkt(uint8_t payload_size) {
   return pkt;
 }
 
+HciPacket make_sample_h4_iso_pkt(uint8_t payload_size) {
+  HciPacket pkt;
+  pkt.assign(1 + 4 + payload_size, 0x01);
+  pkt[0] = kH4Iso;
+  pkt[3] = payload_size;
+  pkt[4] = 0;
+  return pkt;
+}
+
 size_t read_with_retry(int socket, uint8_t* data, size_t length) {
   size_t bytes_read = 0;
   ssize_t bytes_read_current = 0;
@@ -265,6 +279,16 @@ TEST_F(HciHalRootcanalTest, receive_hci_sco) {
   check_packet_equal(packet, incoming_packet);
 }
 
+TEST_F(HciHalRootcanalTest, receive_hci_iso) {
+  H4Packet incoming_packet = make_sample_h4_iso_pkt(3);
+  write(fake_server_socket_, incoming_packet.data(), incoming_packet.size());
+  while (incoming_packets_queue_.size() != 1) {
+  }
+  auto packet = incoming_packets_queue_.front();
+  incoming_packets_queue_.pop();
+  check_packet_equal(packet, incoming_packet);
+}
+
 TEST_F(HciHalRootcanalTest, receive_two_hci_evts) {
   H4Packet incoming_packet = make_sample_h4_evt_pkt(3);
   H4Packet incoming_packet2 = make_sample_h4_evt_pkt(5);
index 5585c0d..ddb96be 100644 (file)
@@ -195,6 +195,10 @@ void SnoopLogger::Capture(const HciPacket& packet, Direction direction, PacketTy
       flags.set(0, true);
       flags.set(1, true);
       break;
+    case PacketType::ISO:
+      flags.set(0, direction == Direction::INCOMING);
+      flags.set(1, true);
+      break;
   }
   uint32_t length = packet.size() + /* type byte */ 1;
   PacketHeaderType header = {.length_original = htonl(length),
index 6ff5ebb..06f93d8 100644 (file)
@@ -77,6 +77,7 @@ class SnoopLogger : public ::bluetooth::Module {
     ACL = 2,
     SCO = 3,
     EVT = 4,
+    ISO = 5,
   };
 
   enum Direction {
index 740e5dc..eb4e711 100644 (file)
@@ -244,6 +244,10 @@ struct HciLayer::hal_callbacks : public hal::HciHalCallbacks {
     // Not implemented yet
   }
 
+  void isoDataReceived(hal::HciPacket data_bytes) override {
+    // Not implemented yet
+  }
+
   HciLayer& module_;
 };
 
index e99c5f2..3236045 100644 (file)
@@ -4709,3 +4709,50 @@ packet BqrBtSchedulingTraceEvent : BqrLogDumpEvent (quality_report_id = BT_SCHED
 packet BqrControllerDbgInfoEvent : BqrLogDumpEvent (quality_report_id = CONTROLLER_DBG_INFO) {
  _payload_, // vendor specific parameter
 }
+
+// Isochronous Adaptation Layer
+
+enum IsoPacketBoundaryFlag : 2 {
+  FIRST_FRAGMENT = 0,
+  CONTINUATION_FRAGMENT = 1,
+  COMPLETE_SDU = 2,
+  LAST_FRAGMENT = 3,
+}
+
+enum TimeStampFlag : 1 {
+  NOT_PRESENT = 0,
+  PRESENT = 1,
+}
+
+packet IsoPacket {
+  connection_handle : 12,
+  pb_flag : IsoPacketBoundaryFlag,
+  ts_flag : TimeStampFlag,
+  _reserved_ : 1,
+  _size_(_payload_) : 14,
+  _reserved_ : 2,
+  _payload_,
+}
+
+enum IsoPacketStatusFlag : 2 {
+  VALID = 0,
+  POSSIBLY_INVALID = 1,
+  LOST_DATA = 2,
+}
+
+packet IsoPacketWithTimestamp : IsoPacket (ts_flag = PRESENT) {
+  time_stamp : 32,
+  packet_sequence_number : 16,
+  _size_(_payload_) : 12, // iso_sdu_length
+  _reserved_ : 2,
+  packet_status_flag : IsoPacketStatusFlag,
+  _payload_,
+}
+
+packet IsoPacketWithoutTimestamp : IsoPacket (ts_flag = NOT_PRESENT) {
+  packet_sequence_number : 16,
+  _size_(_payload_) : 12, // iso_sdu_length
+  _reserved_ : 2,
+  packet_status_flag : IsoPacketStatusFlag,
+  _payload_,
+}