diff --git a/BUILD.gn b/BUILD.gn index 56ed7d85d4aaee7f2af937548ec8b809be676bde..ca2855f4e6e6923090eb7fa6d69ac2b748ce125b 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -114,7 +114,6 @@ config("target_defaults") { "OS_GENERIC", "OS_LINUX_GENERIC", "TARGET_FLOSS", - "USE_LINUX_HCI_SOCKET", "EXPORT_SYMBOL=__attribute__((visibility(\"default\")))", "FALLTHROUGH_INTENDED=[[clang::fallthrough]]", ] diff --git a/system/gd/docs/architecture/style_guide.md b/system/gd/docs/architecture/style_guide.md index bd2adb275c1fc821860a1c2bae2986534eab3c6d..65953ffe78229bc56fe5a7ec991379a4113991e3 100644 --- a/system/gd/docs/architecture/style_guide.md +++ b/system/gd/docs/architecture/style_guide.md @@ -113,8 +113,10 @@ Root directory under Android tree: * hci_hal_android_hidl.cc: implementation of hci_hal.h using Android HIDL * hci_hal_android_hidl_test.cc: unit tests for the Android HIDL implementation - * hci_hal_host.cc: implementation of hci_hal.h using root-canal - emulator or linux Bluetooth HCI socket + * hci_hal_host.cc: implementation of hci_hal.h using linux Bluetooth HCI + socket + * hci_hal_host_rootcanal.cc: implementation of hci_hal.h using root-canal + emulator * hci_hal_host_test.cc: unit tests for the socket based HAL (root-canal) emulator implementation * facade.proto: gRPC automation interface definition for this layer diff --git a/system/gd/hal/Android.bp b/system/gd/hal/Android.bp index 1e7c18d9f1ce3226279ea38a61c4f08daedabce6..978b4cab79d2c8138b61859c7a709c4308fcabcc 100644 --- a/system/gd/hal/Android.bp +++ b/system/gd/hal/Android.bp @@ -24,7 +24,7 @@ filegroup { filegroup { name: "BluetoothHalSources_hci_host", srcs: [ - "hci_hal_host.cc", + "hci_hal_host_rootcanal.cc", ], } diff --git a/system/gd/hal/hci_hal_host.cc b/system/gd/hal/hci_hal_host.cc index f5e436d8070dad59ec70a9bf3989ca679f019298..b41fbd452f572ca52406653b17a58bf3c61ce845 100644 --- a/system/gd/hal/hci_hal_host.cc +++ b/system/gd/hal/hci_hal_host.cc @@ -50,7 +50,6 @@ 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 -#ifdef USE_LINUX_HCI_SOCKET constexpr uint8_t BTPROTO_HCI = 1; constexpr uint16_t HCI_CHANNEL_USER = 1; constexpr uint16_t HCI_CHANNEL_CONTROL = 3; @@ -197,51 +196,7 @@ int ConnectToSocket() { LOG_INFO("HCI device ready"); return socket_fd; } -#else -// Connect to root canal socket -int ConnectToSocket() { - auto* config = bluetooth::hal::HciHalHostRootcanalConfig::Get(); - const std::string& server = config->GetServerAddress(); - int port = config->GetPort(); - - int socket_fd = socket(AF_INET, SOCK_STREAM, 0); - if (socket_fd < 1) { - LOG_ERROR("can't create socket: %s", strerror(errno)); - return INVALID_FD; - } - - struct hostent* host; - host = gethostbyname(server.c_str()); - if (host == nullptr) { - LOG_ERROR("can't get server name"); - return INVALID_FD; - } - - struct sockaddr_in serv_addr; - memset((void*)&serv_addr, 0, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = INADDR_ANY; - serv_addr.sin_port = htons(port); - - int result = connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); - if (result < 0) { - LOG_ERROR("can't connect: %s", strerror(errno)); - return INVALID_FD; - } - - timeval socket_timeout{ - .tv_sec = 3, - .tv_usec = 0, - }; - int ret = setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &socket_timeout, sizeof(socket_timeout)); - if (ret == -1) { - LOG_ERROR("can't control socket fd: %s", strerror(errno)); - return INVALID_FD; - } - return socket_fd; } -#endif -} // namespace namespace bluetooth { namespace hal { @@ -396,7 +351,7 @@ class HciHalHost : public HciHal { uint8_t buf[kBufSize] = {}; ssize_t received_size; - RUN_NO_INTR(received_size = recv(sock_fd_, buf, kH4HeaderSize, 0)); + RUN_NO_INTR(received_size = read(sock_fd_, buf, kBufSize)); ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno)); if (received_size == 0) { LOG_WARN("Can't read H4 header. EOF received"); @@ -405,15 +360,10 @@ class HciHalHost : public HciHal { } if (buf[0] == kH4Event) { - RUN_NO_INTR(received_size = recv(sock_fd_, buf + kH4HeaderSize, kHciEvtHeaderSize, 0)); - ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno)); - ASSERT_LOG(received_size == kHciEvtHeaderSize, "malformed HCI event header received"); - + ASSERT_LOG( + received_size >= kH4HeaderSize + kHciEvtHeaderSize, "Received bad HCI_EVT packet size: %zu", received_size); uint8_t hci_evt_parameter_total_length = buf[2]; - ssize_t payload_size; - RUN_NO_INTR( - payload_size = recv(sock_fd_, buf + kH4HeaderSize + kHciEvtHeaderSize, hci_evt_parameter_total_length, 0)); - ASSERT_LOG(payload_size != -1, "Can't receive from socket: %s", strerror(errno)); + ssize_t payload_size = received_size - (kH4HeaderSize + kHciEvtHeaderSize); ASSERT_LOG( payload_size == hci_evt_parameter_total_length, "malformed HCI event total parameter size received: %zu != %d", @@ -434,14 +384,10 @@ class HciHalHost : public HciHal { } if (buf[0] == kH4Acl) { - RUN_NO_INTR(received_size = recv(sock_fd_, buf + kH4HeaderSize, kHciAclHeaderSize, 0)); - ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno)); - ASSERT_LOG(received_size == kHciAclHeaderSize, "malformed ACL header received"); - + ASSERT_LOG( + received_size >= kH4HeaderSize + kHciAclHeaderSize, "Received bad HCI_ACL packet size: %zu", received_size); + int payload_size = received_size - (kH4HeaderSize + kHciAclHeaderSize); uint16_t hci_acl_data_total_length = (buf[4] << 8) + buf[3]; - int payload_size; - RUN_NO_INTR(payload_size = recv(sock_fd_, buf + kH4HeaderSize + kHciAclHeaderSize, hci_acl_data_total_length, 0)); - ASSERT_LOG(payload_size != -1, "Can't receive from socket: %s", strerror(errno)); ASSERT_LOG( payload_size == hci_acl_data_total_length, "malformed ACL length received: %d != %d", @@ -463,15 +409,15 @@ class HciHalHost : public HciHal { } if (buf[0] == kH4Sco) { - RUN_NO_INTR(received_size = recv(sock_fd_, buf + kH4HeaderSize, kHciScoHeaderSize, 0)); - ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno)); - ASSERT_LOG(received_size == kHciScoHeaderSize, "malformed SCO header received"); - + ASSERT_LOG( + received_size >= kH4HeaderSize + kHciScoHeaderSize, "Received bad HCI_SCO packet size: %zu", received_size); + int payload_size = received_size - (kH4HeaderSize + kHciScoHeaderSize); uint8_t hci_sco_data_total_length = buf[3]; - int payload_size; - RUN_NO_INTR(payload_size = recv(sock_fd_, buf + kH4HeaderSize + kHciScoHeaderSize, hci_sco_data_total_length, 0)); - ASSERT_LOG(payload_size != -1, "Can't receive from socket: %s", strerror(errno)); - ASSERT_LOG(payload_size == hci_sco_data_total_length, "malformed SCO packet received: size mismatch"); + ASSERT_LOG( + payload_size == hci_sco_data_total_length, + "malformed SCO length received: %d != %d", + payload_size, + hci_sco_data_total_length); HciPacket receivedHciPacket; receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciScoHeaderSize + payload_size); @@ -487,15 +433,15 @@ class HciHalHost : public HciHal { } 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"); - + ASSERT_LOG( + received_size >= kH4HeaderSize + kHciIsoHeaderSize, "Received bad HCI_ISO packet size: %zu", received_size); + int payload_size = received_size - (kH4HeaderSize + kHciIsoHeaderSize); uint16_t hci_iso_data_total_length = ((buf[4] & 0x3f) << 8) + 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"); + ASSERT_LOG( + payload_size == hci_iso_data_total_length, + "malformed ISO length received: %d != %d", + payload_size, + hci_iso_data_total_length); HciPacket receivedHciPacket; receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciIsoHeaderSize + payload_size); diff --git a/system/gd/hal/hci_hal_host_rootcanal.cc b/system/gd/hal/hci_hal_host_rootcanal.cc new file mode 100644 index 0000000000000000000000000000000000000000..b05ae61e8c23fd2f175d066594cd3da9c83ed84f --- /dev/null +++ b/system/gd/hal/hci_hal_host_rootcanal.cc @@ -0,0 +1,369 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hal/hci_hal_host.h" + +#include <netdb.h> +#include <netinet/in.h> +#include <poll.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <unistd.h> + +#include <chrono> +#include <csignal> +#include <mutex> +#include <queue> + +#include "hal/hci_hal.h" +#include "hal/snoop_logger.h" +#include "os/log.h" +#include "os/reactor.h" +#include "os/thread.h" + +namespace { +constexpr int INVALID_FD = -1; + +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 ConnectToSocket() { + auto* config = bluetooth::hal::HciHalHostRootcanalConfig::Get(); + const std::string& server = config->GetServerAddress(); + int port = config->GetPort(); + + int socket_fd = socket(AF_INET, SOCK_STREAM, 0); + if (socket_fd < 1) { + LOG_ERROR("can't create socket: %s", strerror(errno)); + return INVALID_FD; + } + + struct hostent* host; + host = gethostbyname(server.c_str()); + if (host == nullptr) { + LOG_ERROR("can't get server name"); + return INVALID_FD; + } + + struct sockaddr_in serv_addr; + memset((void*)&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = INADDR_ANY; + serv_addr.sin_port = htons(port); + + int result = connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); + if (result < 0) { + LOG_ERROR("can't connect: %s", strerror(errno)); + return INVALID_FD; + } + + timeval socket_timeout{ + .tv_sec = 3, + .tv_usec = 0, + }; + int ret = setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &socket_timeout, sizeof(socket_timeout)); + if (ret == -1) { + LOG_ERROR("can't control socket fd: %s", strerror(errno)); + return INVALID_FD; + } + return socket_fd; +} +} // namespace + +namespace bluetooth { +namespace hal { + +class HciHalHost : public HciHal { + public: + void registerIncomingPacketCallback(HciHalCallbacks* callback) override { + std::lock_guard<std::mutex> lock(api_mutex_); + LOG_INFO("%s before", __func__); + { + std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_); + ASSERT(incoming_packet_callback_ == nullptr && callback != nullptr); + incoming_packet_callback_ = callback; + } + LOG_INFO("%s after", __func__); + } + + void unregisterIncomingPacketCallback() override { + std::lock_guard<std::mutex> lock(api_mutex_); + LOG_INFO("%s before", __func__); + { + std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_); + incoming_packet_callback_ = nullptr; + } + LOG_INFO("%s after", __func__); + } + + void sendHciCommand(HciPacket command) override { + std::lock_guard<std::mutex> lock(api_mutex_); + ASSERT(sock_fd_ != INVALID_FD); + std::vector<uint8_t> packet = std::move(command); + btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD); + packet.insert(packet.cbegin(), kH4Command); + write_to_fd(packet); + } + + void sendAclData(HciPacket data) override { + std::lock_guard<std::mutex> lock(api_mutex_); + ASSERT(sock_fd_ != INVALID_FD); + std::vector<uint8_t> packet = std::move(data); + btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL); + packet.insert(packet.cbegin(), kH4Acl); + write_to_fd(packet); + } + + void sendScoData(HciPacket data) override { + std::lock_guard<std::mutex> lock(api_mutex_); + ASSERT(sock_fd_ != INVALID_FD); + std::vector<uint8_t> packet = std::move(data); + btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::SCO); + packet.insert(packet.cbegin(), kH4Sco); + write_to_fd(packet); + } + + void sendIsoData(HciPacket data) override { + std::lock_guard<std::mutex> lock(api_mutex_); + ASSERT(sock_fd_ != INVALID_FD); + std::vector<uint8_t> packet = std::move(data); + btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ISO); + packet.insert(packet.cbegin(), kH4Iso); + write_to_fd(packet); + } + + protected: + void ListDependencies(ModuleList* list) override { + list->add<SnoopLogger>(); + } + + void Start() override { + std::lock_guard<std::mutex> lock(api_mutex_); + ASSERT(sock_fd_ == INVALID_FD); + sock_fd_ = ConnectToSocket(); + ASSERT(sock_fd_ != INVALID_FD); + reactable_ = hci_incoming_thread_.GetReactor()->Register( + sock_fd_, common::Bind(&HciHalHost::incoming_packet_received, common::Unretained(this)), common::Closure()); + btsnoop_logger_ = GetDependency<SnoopLogger>(); + LOG_INFO("HAL opened successfully"); + } + + void Stop() override { + std::lock_guard<std::mutex> lock(api_mutex_); + LOG_INFO("HAL is closing"); + if (reactable_ != nullptr) { + hci_incoming_thread_.GetReactor()->Unregister(reactable_); + LOG_INFO("HAL is stopping, start waiting for last callback"); + // Wait up to 1 second for the last incoming packet callback to finish + hci_incoming_thread_.GetReactor()->WaitForUnregisteredReactable(std::chrono::milliseconds(1000)); + LOG_INFO("HAL is stopping, finished waiting for last callback"); + ASSERT(sock_fd_ != INVALID_FD); + } + reactable_ = nullptr; + { + std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_); + incoming_packet_callback_ = nullptr; + } + ::close(sock_fd_); + sock_fd_ = INVALID_FD; + LOG_INFO("HAL is closed"); + } + + std::string ToString() const override { + return std::string("HciHalHost"); + } + + private: + // Held when APIs are called, NOT to be held during callbacks + std::mutex api_mutex_; + HciHalCallbacks* incoming_packet_callback_ = nullptr; + std::mutex incoming_packet_callback_mutex_; + int sock_fd_ = INVALID_FD; + bluetooth::os::Thread hci_incoming_thread_ = + bluetooth::os::Thread("hci_incoming_thread", bluetooth::os::Thread::Priority::NORMAL); + bluetooth::os::Reactor::Reactable* reactable_ = nullptr; + std::queue<std::vector<uint8_t>> hci_outgoing_queue_; + SnoopLogger* btsnoop_logger_ = nullptr; + + void write_to_fd(HciPacket packet) { + // TODO: replace this with new queue when it's ready + hci_outgoing_queue_.emplace(packet); + if (hci_outgoing_queue_.size() == 1) { + hci_incoming_thread_.GetReactor()->ModifyRegistration( + reactable_, + common::Bind(&HciHalHost::incoming_packet_received, common::Unretained(this)), + common::Bind(&HciHalHost::send_packet_ready, common::Unretained(this))); + } + } + + void send_packet_ready() { + std::lock_guard<std::mutex> lock(this->api_mutex_); + auto packet_to_send = this->hci_outgoing_queue_.front(); + auto bytes_written = write(this->sock_fd_, (void*)packet_to_send.data(), packet_to_send.size()); + this->hci_outgoing_queue_.pop(); + if (bytes_written == -1) { + abort(); + } + if (hci_outgoing_queue_.empty()) { + this->hci_incoming_thread_.GetReactor()->ModifyRegistration( + this->reactable_, + common::Bind(&HciHalHost::incoming_packet_received, common::Unretained(this)), + common::Closure()); + } + } + + void incoming_packet_received() { + { + std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_); + if (incoming_packet_callback_ == nullptr) { + LOG_INFO("Dropping a packet"); + return; + } + } + uint8_t buf[kBufSize] = {}; + + ssize_t received_size; + RUN_NO_INTR(received_size = recv(sock_fd_, buf, kH4HeaderSize, 0)); + ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno)); + if (received_size == 0) { + LOG_WARN("Can't read H4 header. EOF received"); + raise(SIGINT); + return; + } + + if (buf[0] == kH4Event) { + RUN_NO_INTR(received_size = recv(sock_fd_, buf + kH4HeaderSize, kHciEvtHeaderSize, 0)); + ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno)); + ASSERT_LOG(received_size == kHciEvtHeaderSize, "malformed HCI event header received"); + + uint8_t hci_evt_parameter_total_length = buf[2]; + ssize_t payload_size; + RUN_NO_INTR( + payload_size = recv(sock_fd_, buf + kH4HeaderSize + kHciEvtHeaderSize, hci_evt_parameter_total_length, 0)); + ASSERT_LOG(payload_size != -1, "Can't receive from socket: %s", strerror(errno)); + ASSERT_LOG( + payload_size == hci_evt_parameter_total_length, + "malformed HCI event total parameter size received: %zu != %d", + payload_size, + hci_evt_parameter_total_length); + + HciPacket receivedHciPacket; + receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciEvtHeaderSize + payload_size); + btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::EVT); + { + std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_); + if (incoming_packet_callback_ == nullptr) { + LOG_INFO("Dropping an event after processing"); + return; + } + incoming_packet_callback_->hciEventReceived(receivedHciPacket); + } + } + + if (buf[0] == kH4Acl) { + RUN_NO_INTR(received_size = recv(sock_fd_, buf + kH4HeaderSize, kHciAclHeaderSize, 0)); + ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno)); + ASSERT_LOG(received_size == kHciAclHeaderSize, "malformed ACL header received"); + + uint16_t hci_acl_data_total_length = (buf[4] << 8) + buf[3]; + int payload_size; + RUN_NO_INTR(payload_size = recv(sock_fd_, buf + kH4HeaderSize + kHciAclHeaderSize, hci_acl_data_total_length, 0)); + ASSERT_LOG(payload_size != -1, "Can't receive from socket: %s", strerror(errno)); + ASSERT_LOG( + payload_size == hci_acl_data_total_length, + "malformed ACL length received: %d != %d", + payload_size, + hci_acl_data_total_length); + ASSERT_LOG(hci_acl_data_total_length <= kBufSize - kH4HeaderSize - kHciAclHeaderSize, "packet too long"); + + HciPacket receivedHciPacket; + receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciAclHeaderSize + payload_size); + btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::ACL); + { + std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_); + if (incoming_packet_callback_ == nullptr) { + LOG_INFO("Dropping an ACL packet after processing"); + return; + } + incoming_packet_callback_->aclDataReceived(receivedHciPacket); + } + } + + if (buf[0] == kH4Sco) { + RUN_NO_INTR(received_size = recv(sock_fd_, buf + kH4HeaderSize, kHciScoHeaderSize, 0)); + ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno)); + ASSERT_LOG(received_size == kHciScoHeaderSize, "malformed SCO header received"); + + uint8_t hci_sco_data_total_length = buf[3]; + int payload_size; + RUN_NO_INTR(payload_size = recv(sock_fd_, buf + kH4HeaderSize + kHciScoHeaderSize, hci_sco_data_total_length, 0)); + ASSERT_LOG(payload_size != -1, "Can't receive from socket: %s", strerror(errno)); + ASSERT_LOG(payload_size == hci_sco_data_total_length, "malformed SCO packet received: size mismatch"); + + HciPacket receivedHciPacket; + receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciScoHeaderSize + payload_size); + btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::SCO); + { + std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_); + if (incoming_packet_callback_ == nullptr) { + LOG_INFO("Dropping a SCO packet after processing"); + return; + } + 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"); + + uint16_t hci_iso_data_total_length = ((buf[4] & 0x3f) << 8) + 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); + } +}; + +const ModuleFactory HciHal::Factory = ModuleFactory([]() { return new HciHalHost(); }); + +} // namespace hal +} // namespace bluetooth