/* * Copyright (C) 2021-2022 Huawei Device Co., Ltd. * 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 "vendor_interface.h" #include <thread> #include <dlfcn.h> #include <hdf_log.h> #include <securec.h> #include "bluetooth_address.h" #include "bt_hal_constant.h" #include "h4_protocol.h" #include "mct_protocol.h" #ifdef LOG_DOMAIN #undef LOG_DOMAIN #endif #define LOG_DOMAIN 0xD000105 namespace OHOS { namespace HDI { namespace Bluetooth { namespace Hci { namespace V1_0 { constexpr size_t BT_VENDOR_INVALID_DATA_LEN = 0; BtVendorCallbacksT VendorInterface::vendorCallbacks_ = { .size = sizeof(BtVendorCallbacksT), .initCb = VendorInterface::OnInitCallback, .alloc = VendorInterface::OnMallocCallback, .dealloc = VendorInterface::OnFreeCallback, .xmitCb = VendorInterface::OnCmdXmitCallback, }; VendorInterface::VendorInterface() {} VendorInterface::~VendorInterface() { CleanUp(); } bool VendorInterface::WatchHciChannel(const ReceiveCallback &receiveCallback) { int channel[HCI_MAX_CHANNEL] = {0}; int channelCount = vendorInterface_->op(BtOpcodeT::BT_OP_HCI_CHANNEL_OPEN, channel); if (channelCount < 1 || channelCount > HCI_MAX_CHANNEL) { HDF_LOGE("vendorInterface_->op BT_OP_HCI_CHANNEL_OPEN failed ret:%d.", channelCount); return false; } if (channelCount == 1) { auto h4 = std::make_shared<Hci::H4Protocol>(channel[0], receiveCallback.onAclReceive, receiveCallback.onScoReceive, std::bind(&VendorInterface::OnEventReceived, this, std::placeholders::_1)); watcher_.AddFdToWatcher(channel[0], std::bind(&Hci::H4Protocol::ReadData, h4, std::placeholders::_1)); hci_ = h4; } else { auto mct = std::make_shared<Hci::MctProtocol>(channel, receiveCallback.onAclReceive, receiveCallback.onScoReceive, std::bind(&VendorInterface::OnEventReceived, this, std::placeholders::_1)); watcher_.AddFdToWatcher( channel[hci_channels_t::HCI_ACL_IN], std::bind(&Hci::MctProtocol::ReadAclData, mct, std::placeholders::_1)); watcher_.AddFdToWatcher( channel[hci_channels_t::HCI_EVT], std::bind(&Hci::MctProtocol::ReadEventData, mct, std::placeholders::_1)); hci_ = mct; } return true; } bool VendorInterface::Initialize( InitializeCompleteCallback initializeCompleteCallback, const ReceiveCallback &receiveCallback) { HDF_LOGI("VendorInterface %{public}s, ", __func__); std::lock_guard<std::mutex> lock(initAndCleanupProcessMutex_); initializeCompleteCallback_ = initializeCompleteCallback; eventDataCallback_ = receiveCallback.onEventReceive; vendorHandle_ = dlopen(BT_VENDOR_NAME, RTLD_NOW); if (vendorHandle_ == nullptr) { HDF_LOGE("VendorInterface dlopen %{public}s failed, error code: %{public}s", BT_VENDOR_NAME, dlerror()); return false; } vendorInterface_ = reinterpret_cast<BtVendorInterfaceT *>(dlsym(vendorHandle_, BT_VENDOR_INTERFACE_SYMBOL_NAME)); auto bluetoothAddress = BluetoothAddress::GetDeviceAddress(); std::vector<uint8_t> address = { 0, 0, 0, 0, 0, 0 }; if (bluetoothAddress != nullptr) { bluetoothAddress->ReadAddress(address); } if (vendorInterface_ == nullptr) { HDF_LOGE("VendorInterface dlsym %{public}s failed.", BT_VENDOR_INTERFACE_SYMBOL_NAME); return false; } int result = vendorInterface_->init(&vendorCallbacks_, address.data()); if (result != 0) { HDF_LOGE("vendorInterface_->init failed."); return false; } result = vendorInterface_->op(BtOpcodeT::BT_OP_POWER_ON, nullptr); if (result != 0) { HDF_LOGE("vendorInterface_->op BT_OP_POWER_ON failed."); return false; } if (!WatchHciChannel(receiveCallback)) { return false; } if (!watcher_.Start()) { HDF_LOGE("watcher start failed."); return false; } if (vendorInterface_ == nullptr) { HDF_LOGE("vendorInterface_ is nullptr"); return false; } vendorInterface_->op(BtOpcodeT::BT_OP_INIT, nullptr); return true; } void VendorInterface::CleanUp() { std::lock_guard<std::mutex> lock(initAndCleanupProcessMutex_); HDF_LOGE("vendorInterface clean up."); if (vendorInterface_ == nullptr) { HDF_LOGE("VendorInterface::CleanUp, vendorInterface_ is nullptr."); return; } watcher_.Stop(); vendorInterface_->op(BtOpcodeT::BT_OP_LPM_DISABLE, nullptr); vendorInterface_->op(BtOpcodeT::BT_OP_HCI_CHANNEL_CLOSE, nullptr); vendorInterface_->op(BtOpcodeT::BT_OP_POWER_OFF, nullptr); vendorInterface_->close(); hci_ = nullptr; vendorInterface_ = nullptr; initializeCompleteCallback_ = nullptr; eventDataCallback_ = nullptr; dlclose(vendorHandle_); } size_t VendorInterface::SendPacket(Hci::HciPacketType type, const std::vector<uint8_t> &packet) { if (vendorInterface_ == nullptr) { HDF_LOGE("VendorInterface::SendPacket, vendorInterface_ is nullptr."); return BT_VENDOR_INVALID_DATA_LEN; } { std::lock_guard<std::mutex> lock(wakeupMutex_); activity_ = true; watcher_.SetTimeout(std::chrono::milliseconds(lpmTimer_), std::bind(&VendorInterface::WatcherTimeout, this)); if (!wakeupLock_) { vendorInterface_->op(BtOpcodeT::BT_OP_WAKEUP_LOCK, nullptr); wakeupLock_ = true; } } if (hci_ == nullptr) { HDF_LOGE("VendorInterface::SendPacket, hci_ is nullptr."); return BT_VENDOR_INVALID_DATA_LEN; } return hci_->SendPacket(type, packet); } void VendorInterface::OnInitCallback(BtOpResultT result) { HDF_LOGI("%{public}s, ", __func__); if (VendorInterface::GetInstance()->initializeCompleteCallback_) { VendorInterface::GetInstance()->initializeCompleteCallback_(result == BTC_OP_RESULT_SUCCESS); VendorInterface::GetInstance()->initializeCompleteCallback_ = nullptr; } uint32_t lpmTimer = 0; if (VendorInterface::GetInstance()->vendorInterface_->op(BtOpcodeT::BT_OP_GET_LPM_TIMER, &lpmTimer) != 0) { HDF_LOGE("Vector interface BT_OP_GET_LPM_TIMER failed"); } VendorInterface::GetInstance()->lpmTimer_ = lpmTimer; VendorInterface::GetInstance()->vendorInterface_->op(BtOpcodeT::BT_OP_LPM_ENABLE, nullptr); VendorInterface::GetInstance()->watcher_.SetTimeout(std::chrono::milliseconds(lpmTimer), std::bind(&VendorInterface::WatcherTimeout, VendorInterface::GetInstance())); } void *VendorInterface::OnMallocCallback(int size) { static int MAX_BUFFER_SIZE = 1024; if (size <= 0 || size > MAX_BUFFER_SIZE) { HDF_LOGE("%{public}s, size is invalid", __func__); return nullptr; } return malloc(size); } void VendorInterface::OnFreeCallback(void *buf) { if (buf != nullptr) { free(buf); } } size_t VendorInterface::OnCmdXmitCallback(uint16_t opcode, void *buf) { HC_BT_HDR *hdr = reinterpret_cast<HC_BT_HDR *>(buf); VendorInterface::GetInstance()->vendorSentOpcode_ = opcode; return VendorInterface::GetInstance()->SendPacket( Hci::HCI_PACKET_TYPE_COMMAND, std::vector<uint8_t>(hdr->data, hdr->data + hdr->len)); } void VendorInterface::OnEventReceived(const std::vector<uint8_t> &data) { if (data[0] == Hci::HCI_EVENT_CODE_VENDOR_SPECIFIC) { size_t buffSize = sizeof(HC_BT_HDR) + data.size(); HC_BT_HDR *buff = reinterpret_cast<HC_BT_HDR *>(new uint8_t[buffSize]); buff->event = data[0]; buff->len = data.size(); buff->offset = 0; buff->layer_specific = 0; (void)memcpy_s(buff->data, buffSize - sizeof(HC_BT_HDR), data.data(), data.size()); if (vendorInterface_ && vendorInterface_->op) { vendorInterface_->op(BtOpcodeT::BT_OP_EVENT_CALLBACK, buff); } delete[] buff; } else if (vendorSentOpcode_ != 0 && data[0] == Hci::HCI_EVENT_CODE_COMMAND_COMPLETE) { uint8_t opcodeOffset = hci_->GetPacketHeaderInfo(Hci::HCI_PACKET_TYPE_EVENT).headerSize + 1; uint16_t opcode = data[opcodeOffset] + (data[opcodeOffset + 1] << 0x08); if (opcode == vendorSentOpcode_) { size_t buffSize = sizeof(HC_BT_HDR) + data.size(); HC_BT_HDR *buff = reinterpret_cast<HC_BT_HDR *>(new uint8_t[buffSize]); buff->event = data[0]; buff->len = data.size(); buff->offset = 0; buff->layer_specific = 0; (void)memcpy_s(buff->data, buffSize - sizeof(HC_BT_HDR), data.data(), data.size()); vendorSentOpcode_ = 0; if (vendorInterface_ && vendorInterface_->op) { vendorInterface_->op(BtOpcodeT::BT_OP_EVENT_CALLBACK, buff); } delete[] buff; } } eventDataCallback_(data); } void VendorInterface::WatcherTimeout() { std::lock_guard<std::mutex> lock(wakeupMutex_); if (!activity_ && wakeupLock_ && vendorInterface_ && vendorInterface_->op) { vendorInterface_->op(BtOpcodeT::BT_OP_WAKEUP_UNLOCK, nullptr); wakeupLock_ = false; } activity_ = false; } } // namespace V1_0 } // namespace Hci } // namespace Bluetooth } // namespace HDI } // namespace OHOS