diff --git a/bluetooth/1.0/default/Android.bp b/bluetooth/1.0/default/Android.bp index f82bc1fedc..69cefd6698 100644 --- a/bluetooth/1.0/default/Android.bp +++ b/bluetooth/1.0/default/Android.bp @@ -34,6 +34,7 @@ cc_library_shared { ], static_libs: [ "android.hardware.bluetooth-async", + "android.hardware.bluetooth-hci", ], } @@ -51,6 +52,21 @@ cc_library_static { ], } +cc_library_static { + name: "android.hardware.bluetooth-hci", + srcs: [ + "hci_packetizer.cc", + ], + export_include_dirs: ["."], + shared_libs: [ + "libbase", + "libcutils", + "libhidlbase", + "liblog", + "libutils", + ], +} + cc_test { name: "bluetooth-vendor-interface-unit-tests", srcs: [ diff --git a/bluetooth/1.0/default/hci_internals.h b/bluetooth/1.0/default/hci_internals.h index d5714be184..1e1f3001c0 100644 --- a/bluetooth/1.0/default/hci_internals.h +++ b/bluetooth/1.0/default/hci_internals.h @@ -16,6 +16,8 @@ #pragma once +#include + // HCI UART transport packet types (Volume 4, Part A, 2) enum HciPacketType { HCI_PACKET_TYPE_UNKNOWN = 0, diff --git a/bluetooth/1.0/default/hci_packetizer.cc b/bluetooth/1.0/default/hci_packetizer.cc new file mode 100644 index 0000000000..1a5019600f --- /dev/null +++ b/bluetooth/1.0/default/hci_packetizer.cc @@ -0,0 +1,115 @@ +// +// Copyright 2017 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 "hci_packetizer.h" + +#define LOG_TAG "android.hardware.bluetooth.hci_packetizer" +#include +#include +#include + +#include +#include + +namespace { + +const size_t preamble_size_for_type[] = { + 0, HCI_COMMAND_PREAMBLE_SIZE, HCI_ACL_PREAMBLE_SIZE, HCI_SCO_PREAMBLE_SIZE, + HCI_EVENT_PREAMBLE_SIZE}; +const size_t packet_length_offset_for_type[] = { + 0, HCI_LENGTH_OFFSET_CMD, HCI_LENGTH_OFFSET_ACL, HCI_LENGTH_OFFSET_SCO, + HCI_LENGTH_OFFSET_EVT}; + +size_t HciGetPacketLengthForType(HciPacketType type, const uint8_t* preamble) { + size_t offset = packet_length_offset_for_type[type]; + if (type != HCI_PACKET_TYPE_ACL_DATA) return preamble[offset]; + return (((preamble[offset + 1]) << 8) | preamble[offset]); +} + +} // namespace + +namespace android { +namespace hardware { +namespace bluetooth { +namespace hci { + +HciPacketType HciPacketizer::GetPacketType() const { + return hci_packet_type_; +} + +const hidl_vec& HciPacketizer::GetPacket() const { + return hci_packet_; +} + +void HciPacketizer::OnDataReady(int fd) { + switch (hci_parser_state_) { + case HCI_IDLE: { + uint8_t buffer[1] = {0}; + size_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, 1)); + CHECK(bytes_read == 1); + hci_packet_type_ = static_cast(buffer[0]); + CHECK(hci_packet_type_ >= HCI_PACKET_TYPE_ACL_DATA && + hci_packet_type_ <= HCI_PACKET_TYPE_EVENT) + << "buffer[0] = " << static_cast(buffer[0]); + hci_parser_state_ = HCI_TYPE_READY; + hci_packet_bytes_remaining_ = preamble_size_for_type[hci_packet_type_]; + hci_packet_bytes_read_ = 0; + break; + } + + case HCI_TYPE_READY: { + size_t bytes_read = TEMP_FAILURE_RETRY( + read(fd, hci_packet_preamble_ + hci_packet_bytes_read_, + hci_packet_bytes_remaining_)); + CHECK(bytes_read > 0); + hci_packet_bytes_remaining_ -= bytes_read; + hci_packet_bytes_read_ += bytes_read; + if (hci_packet_bytes_remaining_ == 0) { + size_t packet_length = + HciGetPacketLengthForType(hci_packet_type_, hci_packet_preamble_); + hci_packet_.resize(preamble_size_for_type[hci_packet_type_] + + packet_length); + memcpy(hci_packet_.data(), hci_packet_preamble_, + preamble_size_for_type[hci_packet_type_]); + hci_packet_bytes_remaining_ = packet_length; + hci_parser_state_ = HCI_PAYLOAD; + hci_packet_bytes_read_ = 0; + } + break; + } + + case HCI_PAYLOAD: { + size_t bytes_read = TEMP_FAILURE_RETRY( + read(fd, + hci_packet_.data() + preamble_size_for_type[hci_packet_type_] + + hci_packet_bytes_read_, + hci_packet_bytes_remaining_)); + CHECK(bytes_read > 0); + hci_packet_bytes_remaining_ -= bytes_read; + hci_packet_bytes_read_ += bytes_read; + if (hci_packet_bytes_remaining_ == 0) { + hci_packet_ready_cb_(); + hci_parser_state_ = HCI_IDLE; + } + break; + } + } +} + +} // namespace hci +} // namespace bluetooth +} // namespace hardware +} // namespace android diff --git a/bluetooth/1.0/default/hci_packetizer.h b/bluetooth/1.0/default/hci_packetizer.h new file mode 100644 index 0000000000..e9c01dcf2c --- /dev/null +++ b/bluetooth/1.0/default/hci_packetizer.h @@ -0,0 +1,54 @@ +// +// Copyright 2017 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. +// + +#pragma once + +#include + +#include + +#include "hci_internals.h" + +namespace android { +namespace hardware { +namespace bluetooth { +namespace hci { + +using ::android::hardware::hidl_vec; +using HciPacketReadyCallback = std::function; + +class HciPacketizer { + public: + HciPacketizer(HciPacketReadyCallback packet_cb) : hci_packet_ready_cb_(packet_cb) {}; + void OnDataReady(int fd); + const hidl_vec& GetPacket() const; + HciPacketType GetPacketType() const; + + protected: + enum HciParserState { HCI_IDLE, HCI_TYPE_READY, HCI_PAYLOAD }; + HciParserState hci_parser_state_{HCI_IDLE}; + HciPacketType hci_packet_type_{HCI_PACKET_TYPE_UNKNOWN}; + uint8_t hci_packet_preamble_[HCI_PREAMBLE_SIZE_MAX]; + hidl_vec hci_packet_; + size_t hci_packet_bytes_remaining_; + size_t hci_packet_bytes_read_; + HciPacketReadyCallback hci_packet_ready_cb_; +}; + +} // namespace hci +} // namespace bluetooth +} // namespace hardware +} // namespace android diff --git a/bluetooth/1.0/default/vendor_interface.cc b/bluetooth/1.0/default/vendor_interface.cc index 7737dd20f4..3878129493 100644 --- a/bluetooth/1.0/default/vendor_interface.cc +++ b/bluetooth/1.0/default/vendor_interface.cc @@ -51,19 +51,6 @@ bool recent_activity_flag; VendorInterface* g_vendor_interface = nullptr; -const size_t preamble_size_for_type[] = { - 0, HCI_COMMAND_PREAMBLE_SIZE, HCI_ACL_PREAMBLE_SIZE, HCI_SCO_PREAMBLE_SIZE, - HCI_EVENT_PREAMBLE_SIZE}; -const size_t packet_length_offset_for_type[] = { - 0, HCI_LENGTH_OFFSET_CMD, HCI_LENGTH_OFFSET_ACL, HCI_LENGTH_OFFSET_SCO, - HCI_LENGTH_OFFSET_EVT}; - -size_t HciGetPacketLengthForType(HciPacketType type, const uint8_t* preamble) { - size_t offset = packet_length_offset_for_type[type]; - if (type != HCI_PACKET_TYPE_ACL_DATA) return preamble[offset]; - return (((preamble[offset + 1]) << 8) | preamble[offset]); -} - HC_BT_HDR* WrapPacketAndCopy(uint16_t event, const hidl_vec& data) { size_t packet_size = data.size() + sizeof(HC_BT_HDR); HC_BT_HDR* packet = reinterpret_cast(new uint8_t[packet_size]); @@ -274,7 +261,7 @@ bool VendorInterface::Open(InitializeCompleteCallback initialize_complete_cb, ALOGI("%s UART fd: %d", __func__, uart_fd_); fd_watcher_.WatchFdForNonBlockingReads(uart_fd_, - [this](int fd) { OnDataReady(fd); }); + [this](int fd) { hci_packetizer_.OnDataReady(fd); }); // Initially, the power management is off. lpm_wake_deasserted = true; @@ -370,72 +357,26 @@ void VendorInterface::OnTimeout() { recent_activity_flag = false; } -void VendorInterface::OnDataReady(int fd) { - switch (hci_parser_state_) { - case HCI_IDLE: { - uint8_t buffer[1] = {0}; - size_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, 1)); - CHECK(bytes_read == 1); - hci_packet_type_ = static_cast(buffer[0]); - // TODO(eisenbach): Check for workaround(s) - CHECK(hci_packet_type_ >= HCI_PACKET_TYPE_ACL_DATA && - hci_packet_type_ <= HCI_PACKET_TYPE_EVENT) - << "buffer[0] = " << static_cast(buffer[0]); - hci_parser_state_ = HCI_TYPE_READY; - hci_packet_bytes_remaining_ = preamble_size_for_type[hci_packet_type_]; - hci_packet_bytes_read_ = 0; - break; - } +void VendorInterface::OnPacketReady() { + VendorInterface::get()->HandleIncomingPacket(); +} - case HCI_TYPE_READY: { - size_t bytes_read = TEMP_FAILURE_RETRY( - read(fd, hci_packet_preamble_ + hci_packet_bytes_read_, - hci_packet_bytes_remaining_)); - CHECK(bytes_read > 0); - hci_packet_bytes_remaining_ -= bytes_read; - hci_packet_bytes_read_ += bytes_read; - if (hci_packet_bytes_remaining_ == 0) { - size_t packet_length = - HciGetPacketLengthForType(hci_packet_type_, hci_packet_preamble_); - hci_packet_.resize(preamble_size_for_type[hci_packet_type_] + - packet_length); - memcpy(hci_packet_.data(), hci_packet_preamble_, - preamble_size_for_type[hci_packet_type_]); - hci_packet_bytes_remaining_ = packet_length; - hci_parser_state_ = HCI_PAYLOAD; - hci_packet_bytes_read_ = 0; - } - break; - } - - case HCI_PAYLOAD: { - size_t bytes_read = TEMP_FAILURE_RETRY( - read(fd, - hci_packet_.data() + preamble_size_for_type[hci_packet_type_] + - hci_packet_bytes_read_, - hci_packet_bytes_remaining_)); - CHECK(bytes_read > 0); - hci_packet_bytes_remaining_ -= bytes_read; - hci_packet_bytes_read_ += bytes_read; - if (hci_packet_bytes_remaining_ == 0) { +void VendorInterface::HandleIncomingPacket() { + HciPacketType hci_packet_type = hci_packetizer_.GetPacketType(); + hidl_vec hci_packet = hci_packetizer_.GetPacket(); if (internal_command.cb != nullptr && - hci_packet_type_ == HCI_PACKET_TYPE_EVENT && - internal_command_event_match(hci_packet_)) { + hci_packet_type == HCI_PACKET_TYPE_EVENT && + internal_command_event_match(hci_packet)) { HC_BT_HDR* bt_hdr = - WrapPacketAndCopy(HCI_PACKET_TYPE_EVENT, hci_packet_); + WrapPacketAndCopy(HCI_PACKET_TYPE_EVENT, hci_packet); // The callbacks can send new commands, so don't zero after calling. tINT_CMD_CBACK saved_cb = internal_command.cb; internal_command.cb = nullptr; saved_cb(bt_hdr); } else { - packet_read_cb_(hci_packet_type_, hci_packet_); + packet_read_cb_(hci_packet_type, hci_packet); } - hci_parser_state_ = HCI_IDLE; - } - break; - } - } } } // namespace implementation diff --git a/bluetooth/1.0/default/vendor_interface.h b/bluetooth/1.0/default/vendor_interface.h index 98357f573d..81156405a0 100644 --- a/bluetooth/1.0/default/vendor_interface.h +++ b/bluetooth/1.0/default/vendor_interface.h @@ -20,7 +20,7 @@ #include "async_fd_watcher.h" #include "bt_vendor_lib.h" -#include "hci_internals.h" +#include "hci_packetizer.h" namespace android { namespace hardware { @@ -46,6 +46,8 @@ class VendorInterface { void OnFirmwareConfigured(uint8_t result); + static void OnPacketReady(); + private: virtual ~VendorInterface() = default; @@ -55,7 +57,7 @@ class VendorInterface { void OnTimeout(); - void OnDataReady(int fd); + void HandleIncomingPacket(); void *lib_handle_; bt_vendor_interface_t *lib_interface_; @@ -64,13 +66,7 @@ class VendorInterface { PacketReadCallback packet_read_cb_; InitializeCompleteCallback initialize_complete_cb_; - enum HciParserState { HCI_IDLE, HCI_TYPE_READY, HCI_PAYLOAD }; - HciParserState hci_parser_state_{HCI_IDLE}; - HciPacketType hci_packet_type_{HCI_PACKET_TYPE_UNKNOWN}; - uint8_t hci_packet_preamble_[HCI_PREAMBLE_SIZE_MAX]; - hidl_vec hci_packet_; - size_t hci_packet_bytes_remaining_; - size_t hci_packet_bytes_read_; + hci::HciPacketizer hci_packetizer_ {VendorInterface::OnPacketReady}; FirmwareStartupTimer *firmware_startup_timer_; };