* 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.
*/
#ifndef LOG_TAG
#define LOG_TAG "bt_fwk_gatt_server"
#endif
#include <condition_variable>
#include <memory>
#include <set>
#include "bluetooth_gatt_server.h"
#include "bluetooth_host.h"
#include "bluetooth_log.h"
#include "bluetooth_utils.h"
#include "bluetooth_host_proxy.h"
#include "bluetooth_gatt_server_proxy.h"
#include "bluetooth_gatt_server_callback_stub.h"
#include "gatt_data.h"
#include "iservice_registry.h"
#include "raw_address.h"
#include "system_ability_definition.h"
#include "bluetooth_profile_manager.h"
namespace OHOS {
namespace Bluetooth {
const int EIGHT_BITS = 8;
constexpr uint8_t REQUEST_TYPE_CHARACTERISTICS_READ = 0x00;
constexpr uint8_t REQUEST_TYPE_CHARACTERISTICS_WRITE = 0x01;
constexpr uint8_t REQUEST_TYPE_DESCRIPTOR_READ = 0x02;
constexpr uint8_t REQUEST_TYPE_DESCRIPTOR_WRITE = 0x03;
struct RequestInformation {
uint8_t type_;
bluetooth::GattDevice device_;
union {
GattCharacteristic *characteristic_;
GattDescriptor *descriptor_;
} context_;
RequestInformation(uint8_t type, const bluetooth::GattDevice &device, GattCharacteristic *characteristic)
: type_(type), device_(device), context_ {
.characteristic_ = characteristic
}
{}
RequestInformation(uint8_t type, const bluetooth::GattDevice &device, GattDescriptor *decriptor)
: type_(type), device_(device), context_ {
.descriptor_ = decriptor
}
{}
RequestInformation(uint8_t type, const bluetooth::GattDevice &device) : type_(type), device_(device)
{}
bool operator==(const RequestInformation &rhs) const
{
return (device_ == rhs.device_ && type_ == rhs.type_);
};
bool operator<(const RequestInformation &rhs) const
{
return (device_ < rhs.device_ && type_ == rhs.type_);
};
};
struct GattServer::impl {
class BluetoothGattServerCallbackStubImpl;
bool isRegisterSucceeded_ = false;
std::mutex serviceListMutex_;
std::mutex requestListMutex_;
std::list<GattService> gattServices_;
sptr<BluetoothGattServerCallbackStubImpl> serviceCallback_;
std::optional<std::reference_wrapper<GattCharacteristic>> FindCharacteristic(uint16_t handle);
std::optional<std::reference_wrapper<GattDescriptor>> FindDescriptor(uint16_t handle);
std::set<RequestInformation> requests_;
std::list<bluetooth::GattDevice> devices_;
std::shared_ptr<GattServerCallback> callback_;
int BuildRequestId(uint8_t type, uint8_t transport);
int RespondCharacteristicRead(
const bluetooth::GattDevice &device, uint16_t handle, const uint8_t *value, size_t length, int ret);
int RespondCharacteristicWrite(const bluetooth::GattDevice &device, uint16_t handle, int ret);
int RespondDescriptorRead(
const bluetooth::GattDevice &device, uint16_t handle, const uint8_t *value, size_t length, int ret);
int RespondDescriptorWrite(const bluetooth::GattDevice &device, uint16_t handle, int ret);
int applicationId_ = 0;
std::mutex deviceListMutex_;
GattService *GetIncludeService(uint16_t handle);
bluetooth::GattDevice *FindConnectedDevice(const BluetoothRemoteDevice &device);
GattService BuildService(const BluetoothGattService &service);
void BuildIncludeService(GattService &svc, const std::vector<bluetooth::Service> &iSvcs);
impl(std::shared_ptr<GattServerCallback> callback);
bool Init(std::weak_ptr<GattServer>);
int32_t profileRegisterId = 0;
};
class GattServer::impl::BluetoothGattServerCallbackStubImpl : public BluetoothGattServerCallbackStub {
public:
inline std::shared_ptr<GattServer> GetServerSptr(void)
{
auto serverSptr = server_.lock();
if (!serverSptr) {
HILOGE("server_ is nullptr");
return nullptr;
}
if (!serverSptr->pimpl) {
HILOGE("impl is nullptr");
return nullptr;
}
return serverSptr;
}
void OnCharacteristicReadRequest(
const BluetoothGattDevice &device, const BluetoothGattCharacteristic &characteristic) override
{
HILOGI("remote device: %{public}s, handle: 0x%{public}04X",
GET_ENCRYPT_GATT_ADDR(device), characteristic.handle_);
auto serverSptr = GetServerSptr();
if (!serverSptr) {
return;
}
std::lock_guard<std::mutex> lock(serverSptr->pimpl->serviceListMutex_);
auto gattcharacter = serverSptr->pimpl->FindCharacteristic(characteristic.handle_);
if (gattcharacter.has_value()) {
{
std::lock_guard<std::mutex> lck(serverSptr->pimpl->requestListMutex_);
auto ret = serverSptr->pimpl->requests_.emplace(
RequestInformation(REQUEST_TYPE_CHARACTERISTICS_READ, device, &gattcharacter.value().get()));
if (!ret.second) {
HILOGE("insert request failed, type: %{public}u, addr: %{public}s",
REQUEST_TYPE_CHARACTERISTICS_READ, GET_ENCRYPT_GATT_ADDR(device));
}
}
if (serverSptr->pimpl->callback_) {
serverSptr->pimpl->callback_->OnCharacteristicReadRequest(
BluetoothRemoteDevice(device.addr_.GetAddress(),
(device.transport_ == GATT_TRANSPORT_TYPE_LE) ? BT_TRANSPORT_BLE : BT_TRANSPORT_BREDR),
gattcharacter.value().get(),
serverSptr->pimpl->BuildRequestId(REQUEST_TYPE_CHARACTERISTICS_READ, device.transport_));
}
return;
} else {
HILOGE("Can not Find Characteristic!");
}
return;
}
void OnCharacteristicWriteRequest(const BluetoothGattDevice &device,
const BluetoothGattCharacteristic &characteristic, bool needRespones) override
{
HILOGI("remote device: %{public}s, handle: 0x%{public}04X, length: %{public}zu",
GET_ENCRYPT_GATT_ADDR(device), characteristic.handle_, characteristic.length_);
auto serverSptr = GetServerSptr();
if (!serverSptr) {
return;
}
std::lock_guard<std::mutex> lock(serverSptr->pimpl->serviceListMutex_);
auto gattcharacter = serverSptr->pimpl->FindCharacteristic(characteristic.handle_);
if (gattcharacter.has_value()) {
gattcharacter.value().get().SetValue(characteristic.value_.get(), characteristic.length_);
gattcharacter.value().get().SetWriteType(
needRespones ? GattCharacteristic::WriteType::DEFAULT : GattCharacteristic::WriteType::NO_RESPONSE);
if (needRespones) {
std::lock_guard<std::mutex> lck(serverSptr->pimpl->requestListMutex_);
auto ret = serverSptr->pimpl->requests_.emplace(
RequestInformation(REQUEST_TYPE_CHARACTERISTICS_WRITE, device, &gattcharacter.value().get()));
if (!ret.second) {
HILOGE("insert request failed, type: %{public}u, addr: %{public}s",
REQUEST_TYPE_CHARACTERISTICS_WRITE, GET_ENCRYPT_GATT_ADDR(device));
}
}
if (serverSptr->pimpl->callback_) {
serverSptr->pimpl->callback_->OnCharacteristicWriteRequest(
BluetoothRemoteDevice(device.addr_.GetAddress(),
(device.transport_ == GATT_TRANSPORT_TYPE_LE) ? BT_TRANSPORT_BLE : BT_TRANSPORT_BREDR),
gattcharacter.value().get(),
serverSptr->pimpl->BuildRequestId(REQUEST_TYPE_CHARACTERISTICS_WRITE, device.transport_));
}
return;
} else {
HILOGE("Can not Find Characteristic!");
}
return;
}
void OnDescriptorReadRequest(const BluetoothGattDevice &device, const BluetoothGattDescriptor &descriptor) override
{
HILOGI("remote device: %{public}s, handle: 0x%{public}04X",
GET_ENCRYPT_GATT_ADDR(device), descriptor.handle_);
auto serverSptr = GetServerSptr();
if (!serverSptr) {
return;
}
std::lock_guard<std::mutex> lock(serverSptr->pimpl->serviceListMutex_);
auto gattdesc = serverSptr->pimpl->FindDescriptor(descriptor.handle_);
if (gattdesc.has_value()) {
{
std::lock_guard<std::mutex> lck(serverSptr->pimpl->requestListMutex_);
auto ret = serverSptr->pimpl->requests_.emplace(
RequestInformation(REQUEST_TYPE_DESCRIPTOR_READ, device, &gattdesc.value().get()));
if (!ret.second) {
HILOGE("insert request failed, type: %{public}u, addr: %{public}s",
REQUEST_TYPE_DESCRIPTOR_READ, GET_ENCRYPT_GATT_ADDR(device));
}
}
if (serverSptr->pimpl->callback_) {
serverSptr->pimpl->callback_->OnDescriptorReadRequest(
BluetoothRemoteDevice(device.addr_.GetAddress(),
(device.transport_ == GATT_TRANSPORT_TYPE_LE) ? BT_TRANSPORT_BLE : BT_TRANSPORT_BREDR),
gattdesc.value().get(),
serverSptr->pimpl->BuildRequestId(REQUEST_TYPE_DESCRIPTOR_READ, device.transport_));
}
return;
} else {
HILOGE("Can not Find Descriptor!");
}
return;
}
void OnDescriptorWriteRequest(const BluetoothGattDevice &device, const BluetoothGattDescriptor &descriptor) override
{
HILOGI("remote device: %{public}s, handle: 0x%{public}04X",
GET_ENCRYPT_GATT_ADDR(device), descriptor.handle_);
auto serverSptr = GetServerSptr();
if (!serverSptr) {
return;
}
std::lock_guard<std::mutex> lock(serverSptr->pimpl->serviceListMutex_);
auto gattdesc = serverSptr->pimpl->FindDescriptor(descriptor.handle_);
if (gattdesc.has_value()) {
gattdesc.value().get().SetValue(descriptor.value_.get(), descriptor.length_);
{
std::lock_guard<std::mutex> lck(serverSptr->pimpl->requestListMutex_);
auto ret = serverSptr->pimpl->requests_.emplace(
RequestInformation(REQUEST_TYPE_DESCRIPTOR_WRITE, device, &gattdesc.value().get()));
if (!ret.second) {
HILOGE("insert request failed, type: %{public}u, addr: %{public}s",
REQUEST_TYPE_DESCRIPTOR_WRITE, GET_ENCRYPT_GATT_ADDR(device));
}
}
if (serverSptr->pimpl->callback_) {
serverSptr->pimpl->callback_->OnDescriptorWriteRequest(
BluetoothRemoteDevice(device.addr_.GetAddress(),
(device.transport_ == GATT_TRANSPORT_TYPE_LE) ? BT_TRANSPORT_BLE : BT_TRANSPORT_BREDR),
gattdesc.value().get(),
serverSptr->pimpl->BuildRequestId(REQUEST_TYPE_DESCRIPTOR_WRITE, device.transport_));
}
return;
} else {
HILOGE("Can not Find Descriptor!");
}
return;
}
void OnNotifyConfirm(
const BluetoothGattDevice &device, const BluetoothGattCharacteristic &characteristic, int result) override
{
HILOGI("remote device: %{public}s, handle: 0x%{public}04X",
GET_ENCRYPT_GATT_ADDR(device), characteristic.handle_);
auto serverSptr = GetServerSptr();
if (!serverSptr) {
return;
}
if (serverSptr->pimpl->callback_) {
serverSptr->pimpl->callback_->OnNotificationCharacteristicChanged(
BluetoothRemoteDevice(device.addr_.GetAddress(),
(device.transport_ == GATT_TRANSPORT_TYPE_LE) ? BT_TRANSPORT_BLE : BT_TRANSPORT_BREDR),
result);
}
return;
}
void OnConnectionStateChanged(const BluetoothGattDevice &device,
int32_t ret, int32_t state, int32_t disconnectReason, const std::string &reasonMessage) override
{
HILOGD("gattServer conn state, remote device: %{public}s, ret: %{public}d, state: %{public}s",
GET_ENCRYPT_GATT_ADDR(device), ret, GetProfileConnStateName(state).c_str());
auto serverSptr = GetServerSptr();
if (!serverSptr) {
return;
}
if (state == static_cast<int>(BTConnectState::CONNECTED)) {
std::lock_guard<std::mutex> lck(serverSptr->pimpl->deviceListMutex_);
serverSptr->pimpl->devices_.push_back((bluetooth::GattDevice)device);
} else if (state == static_cast<int>(BTConnectState::DISCONNECTED)) {
std::lock_guard<std::mutex> lck(serverSptr->pimpl->deviceListMutex_);
for (auto it = serverSptr->pimpl->devices_.begin(); it != serverSptr->pimpl->devices_.end(); it++) {
if (*it == (bluetooth::GattDevice)device) {
serverSptr->pimpl->devices_.erase(it);
break;
}
}
}
if (serverSptr->pimpl->callback_) {
serverSptr->pimpl->callback_->OnConnectionStateUpdate(
BluetoothRemoteDevice(device.addr_.GetAddress(),
(device.transport_ == GATT_TRANSPORT_TYPE_LE) ? BT_TRANSPORT_BLE : BT_TRANSPORT_BREDR), state);
serverSptr->pimpl->callback_->OnConnectionStateUpdateWithReason(
BluetoothRemoteDevice(device.addr_.GetAddress(),
(device.transport_ == GATT_TRANSPORT_TYPE_LE) ? BT_TRANSPORT_BLE : BT_TRANSPORT_BREDR),
state, disconnectReason);
GattDisconnectParam disconnectParam(disconnectReason, reasonMessage);
serverSptr->pimpl->callback_->OnConnectionStateUpdateWithMessage(
BluetoothRemoteDevice(device.addr_.GetAddress(),
(device.transport_ == GATT_TRANSPORT_TYPE_LE) ? BT_TRANSPORT_BLE : BT_TRANSPORT_BREDR),
state, disconnectParam);
}
return;
}
void OnMtuChanged(const BluetoothGattDevice &device, int32_t mtu) override
{
HILOGI("remote device: %{public}s, mtu: %{public}d", GET_ENCRYPT_GATT_ADDR(device), mtu);
auto serverSptr = GetServerSptr();
if (!serverSptr) {
return;
}
if (serverSptr->pimpl->callback_) {
serverSptr->pimpl->callback_->OnMtuUpdate(
BluetoothRemoteDevice(device.addr_.GetAddress(),
(device.transport_ == GATT_TRANSPORT_TYPE_LE) ? BT_TRANSPORT_BLE : BT_TRANSPORT_BREDR),
mtu);
}
return;
}
void OnAddService(int32_t ret, const BluetoothGattService &service) override
{
HILOGI("enter, ret: %{public}d, handle: %{public}d", ret, service.handle_);
auto serverSptr = GetServerSptr();
if (!serverSptr) {
return;
}
GattService gattService(UUID(), GattServiceType::PRIMARY);
if (ret == GattStatus::GATT_SUCCESS) {
gattService = serverSptr->pimpl->BuildService(service);
serverSptr->pimpl->BuildIncludeService(gattService, service.includeServices_);
{
std::lock_guard<std::mutex> lck(serverSptr->pimpl->serviceListMutex_);
serverSptr->pimpl->gattServices_.emplace(serverSptr->pimpl->gattServices_.end(), gattService);
}
}
if (serverSptr->pimpl && serverSptr->pimpl->callback_) {
serverSptr->pimpl->callback_->OnServiceAdded(gattService, ret);
}
return;
}
void OnConnectionParameterChanged(
const BluetoothGattDevice &device, int32_t interval, int32_t latency, int32_t timeout, int32_t status) override
{
HILOGD("remote device: %{public}s, interval: %{public}d, "
"latency: %{public}d, timeout: %{public}d, status: %{public}d",
GET_ENCRYPT_GATT_ADDR(device), interval, latency, timeout, status);
auto serverSptr = GetServerSptr();
if (!serverSptr) {
return;
}
if (serverSptr->pimpl->callback_) {
serverSptr->pimpl->callback_->OnConnectionParameterChanged(
BluetoothRemoteDevice(device.addr_.GetAddress(),
(device.transport_ == GATT_TRANSPORT_TYPE_LE) ? BT_TRANSPORT_BLE : BT_TRANSPORT_BREDR),
interval,
latency,
timeout,
status);
}
return;
}
void OnBlePhyUpdate(const BluetoothGattDevice &device, int32_t txPhy, int32_t rxPhy, int32_t status) override
{
HILOGD("remote device: %{public}s, txPhy: %{public}d, rxPhy: %{public}d, status: %{public}d",
GET_ENCRYPT_GATT_ADDR(device), txPhy, rxPhy, status);
auto serverSptr = GetServerSptr();
if (!serverSptr) {
return;
}
if (serverSptr->pimpl->callback_) {
serverSptr->pimpl->callback_->OnBlePhyUpdate(BluetoothRemoteDevice(device.addr_.GetAddress(),
(device.transport_ == GATT_TRANSPORT_TYPE_LE) ? BT_TRANSPORT_BLE : BT_TRANSPORT_BREDR),
txPhy, rxPhy, status);
}
return;
}
void OnBlePhyRead(int32_t txPhy, int32_t rxPhy, int32_t status) override
{
HILOGD("txPhy: %{public}d, rxPhy: %{public}d, status: %{public}d", txPhy, rxPhy, status);
auto serverSptr = GetServerSptr();
if (!serverSptr) {
return;
}
if (serverSptr->pimpl->callback_) {
serverSptr->pimpl->callback_->OnBlePhyRead(txPhy, rxPhy, status);
}
return;
}
explicit BluetoothGattServerCallbackStubImpl(std::weak_ptr<GattServer> server) : server_(server)
{
HILOGD("enter");
}
~BluetoothGattServerCallbackStubImpl() override
{
HILOGD("enter");
}
private:
std::weak_ptr<GattServer> server_;
};
GattService GattServer::impl::BuildService(const BluetoothGattService &service)
{
GattService gattService(UUID::ConvertFrom128Bits(service.uuid_.ConvertTo128Bits()),
service.handle_,
service.endHandle_,
service.isPrimary_ ? GattServiceType::PRIMARY : GattServiceType::SECONDARY);
for (auto &character : service.characteristics_) {
GattCharacteristic gattcharacter(UUID::ConvertFrom128Bits(character.uuid_.ConvertTo128Bits()),
character.handle_,
character.permissions_,
character.properties_);
gattcharacter.SetValue(character.value_.get(), character.length_);
for (auto &desc : character.descriptors_) {
GattDescriptor gattDesc(
UUID::ConvertFrom128Bits(desc.uuid_.ConvertTo128Bits()), desc.handle_, desc.permissions_);
gattDesc.SetValue(desc.value_.get(), desc.length_);
gattcharacter.AddDescriptor(std::move(gattDesc));
}
gattService.AddCharacteristic(std::move(gattcharacter));
}
return gattService;
}
void GattServer::impl::BuildIncludeService(GattService &svc, const std::vector<bluetooth::Service> &iSvcs)
{
for (auto &iSvc : iSvcs) {
GattService *pSvc = GetIncludeService(iSvc.startHandle_);
if (!pSvc) {
HILOGE("Can not find include service entity in service ");
continue;
}
svc.AddService(std::ref(*pSvc));
}
}
GattService *GattServer::impl::GetIncludeService(uint16_t handle)
{
for (auto &svc : gattServices_) {
if (svc.GetHandle() == handle) {
return &svc;
}
}
return nullptr;
}
GattServer::impl::impl(std::shared_ptr<GattServerCallback> callback)
: isRegisterSucceeded_(false), callback_(callback), applicationId_(0)
{
HILOGD("enter");
};
GattServer::GattServer(std::shared_ptr<GattServerCallback> callback)
{
HILOGI("create GattServer start.");
pimpl = std::make_unique<GattServer::impl>(callback);
if (!pimpl) {
HILOGE("create GattServer failed.");
}
}
bool GattServer::impl::Init(std::weak_ptr<GattServer> server)
{
if (profileRegisterId != 0) {
return true;
}
serviceCallback_ = new BluetoothGattServerCallbackStubImpl(server);
profileRegisterId = BluetoothProfileManager::GetInstance().RegisterFunc(PROFILE_GATT_SERVER,
[this](sptr<IRemoteObject> remote) {
sptr<IBluetoothGattServer> proxy = iface_cast<IBluetoothGattServer>(remote);
CHECK_AND_RETURN_LOG(proxy != nullptr, "failed: no proxy");
int result = proxy->RegisterApplication(serviceCallback_);
if (result > 0) {
applicationId_ = result;
isRegisterSucceeded_ = true;
} else {
HILOGE("Can not Register to gatt server service! result = %{public}d", result);
}
});
return true;
}
std::shared_ptr<GattServer> GattServer::CreateInstance(std::shared_ptr<GattServerCallback> callback)
{
auto instance = std::make_shared<GattServer>(PassKey(), callback);
if (!instance->pimpl) {
HILOGE("failed: no impl");
return nullptr;
}
instance->pimpl->Init(instance);
return instance;
}
std::optional<std::reference_wrapper<GattCharacteristic>> GattServer::impl::FindCharacteristic(uint16_t handle)
{
for (auto &svc : gattServices_) {
for (auto &character : svc.GetCharacteristics()) {
if (character.GetHandle() == handle) {
return character;
}
}
}
return std::nullopt;
}
bluetooth::GattDevice *GattServer::impl::FindConnectedDevice(const BluetoothRemoteDevice &device)
{
std::lock_guard<std::mutex> lock(deviceListMutex_);
for (auto &gattDevice : devices_) {
if (device.GetDeviceAddr().compare(gattDevice.addr_.GetAddress()) == 0 &&
(device.GetTransportType() ==
(gattDevice.transport_ == GATT_TRANSPORT_TYPE_LE) ? BT_TRANSPORT_BLE : BT_TRANSPORT_BREDR)) {
return &gattDevice;
}
}
return nullptr;
}
std::optional<std::reference_wrapper<GattDescriptor>> GattServer::impl::FindDescriptor(uint16_t handle)
{
for (auto &svc : gattServices_) {
for (auto &character : svc.GetCharacteristics()) {
for (auto &desc : character.GetDescriptors()) {
if (desc.GetHandle() == handle) {
return desc;
}
}
}
}
return std::nullopt;
}
int GattServer::impl::BuildRequestId(uint8_t type, uint8_t transport)
{
int requestId = 0;
requestId = type << EIGHT_BITS;
requestId |= transport;
return requestId;
}
int GattServer::impl::RespondCharacteristicRead(
const bluetooth::GattDevice &device, uint16_t handle, const uint8_t *value, size_t length, int ret)
{
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, GattStatus::REQUEST_NOT_SUPPORT, "failed: no proxy");
if (ret == GattStatus::GATT_SUCCESS) {
BluetoothGattCharacteristic character(bluetooth::Characteristic(handle, value, length));
return proxy->RespondCharacteristicRead(device, &character, ret);
}
BluetoothGattCharacteristic character;
character.handle_ = handle;
return proxy->RespondCharacteristicRead(device, &character, ret);
}
int GattServer::impl::RespondCharacteristicWrite(const bluetooth::GattDevice &device, uint16_t handle, int ret)
{
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, GattStatus::REQUEST_NOT_SUPPORT, "failed: no proxy");
return proxy->RespondCharacteristicWrite(
device, (BluetoothGattCharacteristic)bluetooth::Characteristic(handle), ret);
}
int GattServer::impl::RespondDescriptorRead(
const bluetooth::GattDevice &device, uint16_t handle, const uint8_t *value, size_t length, int ret)
{
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, GattStatus::REQUEST_NOT_SUPPORT, "failed: no proxy");
if (ret == GattStatus::GATT_SUCCESS) {
BluetoothGattDescriptor desc(bluetooth::Descriptor(handle, value, length));
return proxy->RespondDescriptorRead(device, &desc, ret);
}
BluetoothGattDescriptor desc;
desc.handle_ = handle;
return proxy->RespondDescriptorRead(device, &desc, ret);
}
int GattServer::impl::RespondDescriptorWrite(const bluetooth::GattDevice &device, uint16_t handle, int ret)
{
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, GattStatus::REQUEST_NOT_SUPPORT, "failed: no proxy");
return proxy->RespondDescriptorWrite(device, (BluetoothGattDescriptor)bluetooth::Descriptor(handle), ret);
}
int GattServer::AddService(GattService &service)
{
HILOGD("enter");
if (!IS_BLE_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
BluetoothGattService svc;
svc.isPrimary_ = service.IsPrimary();
svc.uuid_ = bluetooth::Uuid::ConvertFrom128Bits(service.GetUuid().ConvertTo128Bits());
for (auto &isvc : service.GetIncludedServices()) {
svc.includeServices_.push_back(bluetooth::Service(isvc.get().GetHandle()));
}
for (auto &character : service.GetCharacteristics()) {
size_t length = 0;
uint8_t *value = character.GetValue(&length).get();
bluetooth::Characteristic c(bluetooth::Uuid::ConvertFrom128Bits(character.GetUuid().ConvertTo128Bits()),
character.GetHandle(),
character.GetProperties(),
character.GetPermissions(),
value,
length);
for (auto &desc : character.GetDescriptors()) {
value = desc.GetValue(&length).get();
bluetooth::Descriptor d(bluetooth::Uuid::ConvertFrom128Bits(desc.GetUuid().ConvertTo128Bits()),
desc.GetHandle(),
desc.GetPermissions(),
value,
length);
c.descriptors_.push_back(std::move(d));
}
svc.characteristics_.push_back(std::move(c));
}
int appId = pimpl->applicationId_;
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
int ret = proxy->AddService(appId, &svc);
HILOGI("appId = %{public}d, ret = %{public}d.", appId, ret);
return ret;
}
int GattServer::ClearServices()
{
HILOGD("enter");
if (!IS_BLE_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INVALID_STATE, "failed: no proxy");
int appId = pimpl->applicationId_;
int ret = proxy->ClearServices(int(appId));
pimpl->gattServices_.clear();
return ret;
}
int GattServer::Close()
{
HILOGD("enter");
if (!IS_BLE_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
int ret = proxy->DeregisterApplication(pimpl->applicationId_);
HILOGI("ret: %{public}d", ret);
if (ret == BT_NO_ERROR) {
pimpl->isRegisterSucceeded_ = false;
}
return ret;
}
int GattServer::Connect(const BluetoothRemoteDevice &device, bool isDirect)
{
CHECK_AND_RETURN_LOG_RET(IS_BLE_ENABLED(), BT_ERR_INVALID_STATE, "bluetooth is off");
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
CHECK_AND_RETURN_LOG_RET(device.IsValidBluetoothRemoteDevice(), BT_ERR_INTERNAL_ERROR, "Invalid remote device");
int appId = pimpl->applicationId_;
HILOGI("appId: %{public}d, device: %{public}s, isDirect: %{public}d", appId, GET_ENCRYPT_ADDR(device), isDirect);
bluetooth::GattDevice gattDevice(bluetooth::RawAddress(device.GetDeviceAddr()), GATT_TRANSPORT_TYPE_LE);
return proxy->Connect(appId, gattDevice, isDirect);
}
int GattServer::CancelConnection(const BluetoothRemoteDevice &device)
{
CHECK_AND_RETURN_LOG_RET(IS_BLE_ENABLED(), BT_ERR_INVALID_STATE, "bluetooth is off");
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
CHECK_AND_RETURN_LOG_RET(device.IsValidBluetoothRemoteDevice(), BT_ERR_INTERNAL_ERROR, "Invalid remote device");
auto gattDevice = pimpl->FindConnectedDevice(device);
if (gattDevice == nullptr) {
HILOGE("gattDevice is nullptr");
return BT_ERR_INTERNAL_ERROR;
}
int appId = pimpl->applicationId_;
HILOGI("appId: %{public}d, device: %{public}s", appId, GET_ENCRYPT_ADDR(device));
return proxy->CancelConnection(appId, *gattDevice);
}
std::optional<std::reference_wrapper<GattService>> GattServer::GetService(const UUID &uuid, bool isPrimary)
{
HILOGD("enter");
if (!IS_BLE_ENABLED()) {
HILOGE("bluetooth is off.");
return std::nullopt;
}
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, std::nullopt, "failed: no proxy");
std::unique_lock<std::mutex> lock(pimpl->serviceListMutex_);
for (auto &svc : pimpl->gattServices_) {
if (svc.GetUuid().Equals(uuid) && svc.IsPrimary() == isPrimary) {
HILOGI("Find service, handle: 0x%{public}04X", svc.GetHandle());
return svc;
}
}
return std::nullopt;
}
int GattServer::GetService(const UUID &uuid, bool isPrimary, GattService &outService)
{
HILOGD("enter");
if (!IS_BLE_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
std::unique_lock<std::mutex> lock(pimpl->serviceListMutex_);
for (auto &svc : pimpl->gattServices_) {
if (svc.GetUuid().Equals(uuid) && svc.IsPrimary() == isPrimary) {
HILOGI("Find service, handle: 0x%{public}04X", svc.GetHandle());
outService = svc;
return BT_NO_ERROR;
}
}
HILOGE("The service is not found.");
return BT_ERR_GATT_SERVICE_NOT_FOUND;
}
std::list<GattService> &GattServer::GetServices()
{
HILOGD("enter");
if (!IS_BLE_ENABLED()) {
HILOGE("bluetooth is off.");
return pimpl->gattServices_;
}
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, pimpl->gattServices_, "failed: no proxy");
std::unique_lock<std::mutex> lock(pimpl->serviceListMutex_);
return pimpl->gattServices_;
}
int GattServer::GetServices(std::list<GattService> &outServices)
{
HILOGD("enter");
if (!IS_BLE_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
std::unique_lock<std::mutex> lock(pimpl->serviceListMutex_);
outServices = pimpl->gattServices_;
return BT_NO_ERROR;
}
int GattServer::NotifyCharacteristicChanged(
const BluetoothRemoteDevice &device, const GattCharacteristic &characteristic, bool confirm)
{
HILOGI("remote device: %{public}s, handle: 0x%{public}04X, confirm: %{public}d",
GET_ENCRYPT_ADDR(device), characteristic.GetHandle(), confirm);
if (!IS_BLE_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("Invalid remote device");
return BT_ERR_INTERNAL_ERROR;
}
if (pimpl->FindConnectedDevice(device) == nullptr) {
HILOGE("No connection to device: %{public}s", GET_ENCRYPT_ADDR(device));
return BT_ERR_INTERNAL_ERROR;
}
size_t length = 0;
auto &characterValue = characteristic.GetValue(&length);
BluetoothGattCharacteristic character(
bluetooth::Characteristic(characteristic.GetHandle(), characterValue.get(), length));
std::string address = device.GetDeviceAddr();
int ret = proxy->NotifyClient(
bluetooth::GattDevice(bluetooth::RawAddress(address), 0), &character, confirm);
HILOGI("ret = %{public}d.", ret);
return ret;
}
int GattServer::RemoveGattService(const GattService &service)
{
HILOGD("enter");
if (!IS_BLE_ENABLED()) {
HILOGD("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
int ret = BT_ERR_INVALID_PARAM;
for (auto sIt = pimpl->gattServices_.begin(); sIt != pimpl->gattServices_.end(); sIt++) {
if (sIt->GetUuid().Equals(service.GetUuid())) {
ret = proxy->RemoveService(
pimpl->applicationId_, (BluetoothGattService)bluetooth::Service(sIt->GetHandle()));
pimpl->gattServices_.erase(sIt);
break;
}
}
HILOGI("result = %{public}d.", ret);
return ret;
}
int GattServer::SendResponse(
const BluetoothRemoteDevice &device, int requestId, int status, int offset, const uint8_t *value, int length)
{
HILOGI("remote device: %{public}s, status: %{public}d", GET_ENCRYPT_ADDR(device), status);
if (!IS_BLE_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
if (!device.IsValidBluetoothRemoteDevice()) {
HILOGE("pimpl or gatt server proxy is nullptr");
return BT_ERR_INTERNAL_ERROR;
}
if (pimpl->FindConnectedDevice(device) == nullptr) {
HILOGE("No connection to device: %{public}s", GET_ENCRYPT_ADDR(device));
return BT_ERR_INTERNAL_ERROR;
}
int result = BT_ERR_INTERNAL_ERROR;
uint8_t requestType = static_cast<uint32_t>(requestId) >> EIGHT_BITS;
uint8_t transport = static_cast<uint32_t>(requestId) & 0xFF;
if (transport != GATT_TRANSPORT_TYPE_CLASSIC && transport != GATT_TRANSPORT_TYPE_LE) {
return result;
}
bluetooth::GattDevice gattdevice(bluetooth::RawAddress(device.GetDeviceAddr()), transport);
std::lock_guard<std::mutex> lock(pimpl->requestListMutex_);
auto request = pimpl->requests_.find(RequestInformation(requestType, gattdevice));
if (request != pimpl->requests_.end()) {
switch (requestType) {
case REQUEST_TYPE_CHARACTERISTICS_READ:
result = pimpl->RespondCharacteristicRead(
gattdevice, request->context_.characteristic_->GetHandle(), value, length, status);
break;
case REQUEST_TYPE_CHARACTERISTICS_WRITE:
result = pimpl->RespondCharacteristicWrite(
gattdevice, request->context_.characteristic_->GetHandle(), status);
break;
case REQUEST_TYPE_DESCRIPTOR_READ:
result = pimpl->RespondDescriptorRead(
gattdevice, request->context_.descriptor_->GetHandle(), value, length, status);
break;
case REQUEST_TYPE_DESCRIPTOR_WRITE:
result = pimpl->RespondDescriptorWrite(gattdevice, request->context_.descriptor_->GetHandle(), status);
break;
default:
HILOGE("Error request Id!");
break;
}
if (result == BT_NO_ERROR) {
pimpl->requests_.erase(request);
}
}
HILOGD("result = %{public}d.", result);
return result;
}
int GattServer::GetConnectedState(const std::string &deviceId, int &state)
{
if (!IS_BLE_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_SERVICE_DISCONNECTED, "failed: no proxy");
return proxy->GetConnectedState(deviceId, state);
}
int GattServer::SetPhy(const std::string &deviceId, int32_t txPhy, int32_t rxPhy, int32_t phyOptions)
{
if (!IS_BLE_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
HILOGI("applicationId: %{public}d", pimpl->applicationId_);
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_INTERNAL_ERROR, "failed: no proxy");
return proxy->SetPhy(pimpl->applicationId_, deviceId, txPhy, rxPhy, phyOptions);
}
int GattServer::ReadPhy(const std::string &deviceId)
{
if (!IS_BLE_ENABLED()) {
HILOGE("bluetooth is off.");
return BT_ERR_INVALID_STATE;
}
HILOGI("applicationId: %{public}d", pimpl->applicationId_);
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG_RET(proxy != nullptr, BT_ERR_SERVICE_DISCONNECTED, "failed: no proxy");
return proxy->ReadPhy(pimpl->applicationId_, deviceId);
}
GattServer::~GattServer()
{
HILOGD("enter");
BluetoothProfileManager::GetInstance().DeregisterFunc(pimpl->profileRegisterId);
sptr<IBluetoothGattServer> proxy = GetRemoteProxy<IBluetoothGattServer>(PROFILE_GATT_SERVER);
CHECK_AND_RETURN_LOG(proxy != nullptr, "failed: no proxy");
if (pimpl->isRegisterSucceeded_) {
proxy->DeregisterApplication(pimpl->applicationId_);
}
HILOGI("end");
}
}
}