/****************************************************************************** * * Copyright 2017 Google, Inc. * * 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. * ******************************************************************************/ #define LOG_TAG "bt_hci" #include "hci_layer.h" #include #include #include #include #include #include "buffer_allocator.h" #include "osi/include/log.h" #include #include #include #include #include #include #define LOG_PATH "/data/misc/bluetooth/logs/firmware_events.log" #define LAST_LOG_PATH "/data/misc/bluetooth/logs/firmware_events.log.last" using ::android::hardware::hidl_death_recipient; using ::android::hardware::hidl_vec; using ::android::hardware::ProcessState; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::hardware::bluetooth::V1_0::HciPacket; using ::android::hardware::bluetooth::V1_0::Status; using namespace ::android::hardware::bluetooth; extern void initialization_complete(); extern void hci_event_received(const base::Location& from_here, BT_HDR* packet); extern void acl_event_received(BT_HDR* packet); extern void sco_data_received(BT_HDR* packet); extern void iso_data_received(BT_HDR* packet); extern void hal_service_died(); extern bool hci_is_root_inflammation_event_received(); android::sp btHci; android::sp btHci_1_1; class BluetoothHciDeathRecipient : public hidl_death_recipient { public: virtual void serviceDied(uint64_t /*cookie*/, const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) { LOG_ERROR("Bluetooth HAL service died!"); hal_service_died(); } }; android::sp bluetoothHciDeathRecipient = new BluetoothHciDeathRecipient(); class BluetoothHciCallbacks : public V1_1::IBluetoothHciCallbacks { public: BluetoothHciCallbacks() { buffer_allocator = buffer_allocator_get_interface(); } BT_HDR* WrapPacketAndCopy(uint16_t event, const hidl_vec& data) { size_t packet_size = data.size() + BT_HDR_SIZE; BT_HDR* packet = reinterpret_cast(buffer_allocator->alloc(packet_size)); packet->offset = 0; packet->len = data.size(); packet->layer_specific = 0; packet->event = event; // TODO(eisenbach): Avoid copy here; if BT_HDR->data can be ensured to // be the only way the data is accessed, a pointer could be passed here... memcpy(packet->data, data.data(), data.size()); return packet; } Return initializationComplete(Status status) override { if (hci_is_root_inflammation_event_received()) { // Ignore the initializationComplete here as we have already received // root inflammation event earlier. LOG_ERROR( "initializationComplete after root inflammation event! status=%d", status); return Void(); } CHECK(status == Status::SUCCESS); initialization_complete(); return Void(); } Return hciEventReceived(const hidl_vec& event) override { BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_EVT, event); hci_event_received(FROM_HERE, packet); return Void(); } Return aclDataReceived(const hidl_vec& data) override { BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_ACL, data); acl_event_received(packet); return Void(); } Return scoDataReceived(const hidl_vec& data) override { BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_SCO, data); sco_data_received(packet); return Void(); } Return isoDataReceived(const hidl_vec& data) override { BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_ISO, data); iso_data_received(packet); return Void(); } const allocator_t* buffer_allocator; }; void hci_initialize() { LOG_INFO("%s", __func__); btHci_1_1 = V1_1::IBluetoothHci::getService(); if (btHci_1_1 != nullptr) { btHci = btHci_1_1; } else { btHci = V1_0::IBluetoothHci::getService(); } // If android.hardware.bluetooth* is not found, Bluetooth can not continue. CHECK(btHci != nullptr); auto death_link = btHci->linkToDeath(bluetoothHciDeathRecipient, 0); if (!death_link.isOk()) { LOG_ERROR("%s: Unable to set the death recipient for the Bluetooth HAL", __func__); abort(); } LOG_INFO("%s: IBluetoothHci::getService() returned %p (%s)", __func__, btHci.get(), (btHci->isRemote() ? "remote" : "local")); // Block allows allocation of a variable that might be bypassed by goto. { android::sp callbacks = new BluetoothHciCallbacks(); if (btHci_1_1 != nullptr) { btHci_1_1->initialize_1_1(callbacks); } else { btHci->initialize(callbacks); } } } void hci_close() { if (btHci != nullptr) { auto death_unlink = btHci->unlinkToDeath(bluetoothHciDeathRecipient); if (!death_unlink.isOk()) { LOG_ERROR("%s: Error unlinking death recipient from the Bluetooth HAL", __func__); } auto close_status = btHci->close(); if (!close_status.isOk()) { LOG_ERROR("%s: Error closing the Bluetooth HAL", __func__); } btHci = nullptr; } } void hci_transmit(BT_HDR* packet) { HciPacket data; data.setToExternal(packet->data + packet->offset, packet->len); uint16_t event = packet->event & MSG_EVT_MASK; switch (event & MSG_EVT_MASK) { case MSG_STACK_TO_HC_HCI_CMD: btHci->sendHciCommand(data); break; case MSG_STACK_TO_HC_HCI_ACL: btHci->sendAclData(data); break; case MSG_STACK_TO_HC_HCI_SCO: btHci->sendScoData(data); break; case MSG_STACK_TO_HC_HCI_ISO: if (btHci_1_1 != nullptr) { btHci_1_1->sendIsoData(data); } else { LOG_ERROR("ISO is not supported in HAL v1.0"); } break; default: LOG_ERROR("Unknown packet type (%d)", event); break; } } int hci_open_firmware_log_file() { if (rename(LOG_PATH, LAST_LOG_PATH) == -1 && errno != ENOENT) { LOG_ERROR("%s unable to rename '%s' to '%s': %s", __func__, LOG_PATH, LAST_LOG_PATH, strerror(errno)); } mode_t prevmask = umask(0); int logfile_fd = open(LOG_PATH, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); umask(prevmask); if (logfile_fd == INVALID_FD) { LOG_ERROR("%s unable to open '%s': %s", __func__, LOG_PATH, strerror(errno)); } return logfile_fd; } void hci_close_firmware_log_file(int fd) { if (fd != INVALID_FD) close(fd); } void hci_log_firmware_debug_packet(int fd, BT_HDR* packet) { TEMP_FAILURE_RETRY(write(fd, packet->data, packet->len)); }