/* * Copyright (c) 2024 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 "bluetooth_ble_common.h" #include "bluetooth_ble_ffi.h" #include "bluetooth_log.h" #include #include namespace OHOS { namespace CJSystemapi { namespace CJBluetoothBle { using Bluetooth::BTConnectState; using Bluetooth::GattCharacteristic; using Bluetooth::GattDescriptor; using Bluetooth::GattPermission; using Bluetooth::GattService; using namespace std; namespace { std::string g_deviceAddr; } // namespace char *MallocCString(const std::string &origin) { if (origin.empty()) { return nullptr; } auto length = origin.length() + 1; char *res = static_cast(malloc(sizeof(char) * length)); if (res == nullptr) { return nullptr; } return std::char_traits::copy(res, origin.c_str(), length); } CArrString Convert2CArrString(std::vector &tids) { CArrString res{}; if (tids.empty()) { return res; } size_t size = tids.size(); if (size == 0 || size > std::numeric_limits::max() / sizeof(char *)) { return res; } res.head = static_cast(malloc(sizeof(char *) * size)); if (res.head == nullptr) { return res; } size_t i = 0; for (; i < size; ++i) { res.head[i] = MallocCString(tids[i]); } res.size = static_cast(i); return res; } CArrUI8 Convert2CArrUI8(std::vector vec) { CArrUI8 res{}; if (vec.empty()) { return res; } size_t size = vec.size(); if (size == 0 || size > std::numeric_limits::max() / sizeof(uint8_t)) { return res; } res.head = static_cast(malloc(sizeof(uint8_t) * vec.size())); if (res.head == nullptr) { return res; } size_t i = 0; for (; i < vec.size(); i++) { res.head[i] = vec[i]; } res.size = static_cast(i); return res; } NativeBLEDescriptor ConvertBLEDescriptorToCJ(GattDescriptor &descriptor) { NativeBLEDescriptor outDescriptor{}; outDescriptor.descriptorUuid = MallocCString(descriptor.GetUuid().ToString()); if (descriptor.GetCharacteristic() != nullptr) { outDescriptor.characteristicUuid = MallocCString(descriptor.GetCharacteristic()->GetUuid().ToString()); if (descriptor.GetCharacteristic()->GetService() != nullptr) { outDescriptor.serviceUuid = MallocCString(descriptor.GetCharacteristic()->GetService()->GetUuid().ToString()); } } size_t valueSize; uint8_t *valueData = descriptor.GetValue(&valueSize).get(); vector vec(valueData, valueData + valueSize); outDescriptor.descriptorValue = Convert2CArrUI8(vec); return outDescriptor; } CArrBLEDescriptor Convert2CArrBLEDescriptor(vector &descriptors) { CArrBLEDescriptor res{}; if (descriptors.empty()) { return res; } size_t size = descriptors.size(); if (size == 0 || size > (std::numeric_limits::max() / sizeof(NativeBLEDescriptor))) { return res; } res.head = static_cast(malloc(sizeof(NativeBLEDescriptor) * size)); if (res.head == nullptr) { return res; } size_t i = 0; for (; i < descriptors.size(); i++) { res.head[i] = ConvertBLEDescriptorToCJ(descriptors[i]); } res.size = static_cast(i); return res; } bool HasProperty(int properties, int propertyMask) { if (properties < 0 || propertyMask < 0) { HILOGE("properties or propertyMask is less than 0"); return false; } return (static_cast(properties) & static_cast(propertyMask)) != 0; } NativeGattProperties ConvertGattPropertiesToCJ(int properties) { NativeGattProperties outProperties{}; outProperties.write = HasProperty(properties, GattCharacteristic::WRITE); outProperties.writeNoResponse = HasProperty(properties, GattCharacteristic::WRITE_WITHOUT_RESPONSE); outProperties.read = HasProperty(properties, GattCharacteristic::READ); outProperties.notify = HasProperty(properties, GattCharacteristic::NOTIFY); outProperties.indicate = HasProperty(properties, GattCharacteristic::INDICATE); return outProperties; } NativeBLECharacteristic ConvertBLECharacteristicToCJ(GattCharacteristic &characteristic) { NativeBLECharacteristic outCharacteristic{}; outCharacteristic.characteristicUuid = MallocCString(characteristic.GetUuid().ToString()); if (characteristic.GetService() != nullptr) { outCharacteristic.serviceUuid = MallocCString(characteristic.GetService()->GetUuid().ToString()); } size_t valueSize = 0; uint8_t *valueData = characteristic.GetValue(&valueSize).get(); vector vec(valueData, valueData + valueSize); outCharacteristic.characteristicValue = Convert2CArrUI8(vec); outCharacteristic.descriptors = Convert2CArrBLEDescriptor(characteristic.GetDescriptors()); outCharacteristic.properties = ConvertGattPropertiesToCJ(characteristic.GetProperties()); return outCharacteristic; } CArrBLECharacteristic Convert2CArrBLECharacteristic(std::vector characteristics) { CArrBLECharacteristic res{}; if (characteristics.empty()) { return res; } size_t size = characteristics.size(); if (size == 0 || size > std::numeric_limits::max() / sizeof(NativeBLECharacteristic)) { return res; } res.head = static_cast(malloc(sizeof(NativeBLECharacteristic) * size)); if (res.head == nullptr) { return res; } size_t i = 0; for (; i < characteristics.size(); i++) { res.head[i] = ConvertBLECharacteristicToCJ(characteristics[i]); } res.size = static_cast(i); return res; } NativeGattService ConvertGattServiceToCJ(GattService service) { NativeGattService outService{}; outService.serviceUuid = MallocCString(service.GetUuid().ToString()); outService.isPrimary = service.IsPrimary(); outService.characteristics = Convert2CArrBLECharacteristic(service.GetCharacteristics()); vector services; vector> srvs = service.GetIncludedServices(); for (auto &srv : srvs) { services.push_back(srv.get()); } outService.includeServices = Convert2CArrGattService(services); return outService; } CArrGattService Convert2CArrGattService(std::vector services) { CArrGattService res{}; if (services.empty()) { return res; } size_t size = services.size(); if (size == 0 || size > std::numeric_limits::max() / sizeof(NativeGattService)) { return res; } res.head = static_cast(malloc(sizeof(NativeGattService) * services.size())); if (res.head == nullptr) { return res; } size_t i = 0; for (; i < services.size(); i++) { res.head[i] = ConvertGattServiceToCJ(services[i]); } res.size = static_cast(i); return res; } std::string GetGattClientDeviceId() { return g_deviceAddr; } uint16_t ConvertGattPermissions(const NativeGattPermission &nativePermissions) { uint16_t permissions = 0; if (nativePermissions.readable) { permissions |= static_cast(GattPermission::READABLE); } if (nativePermissions.writeable) { permissions |= static_cast(GattPermission::WRITEABLE); } if (nativePermissions.readEncrypted) { permissions |= static_cast(GattPermission::READ_ENCRYPTED_MITM); } if (nativePermissions.writeEncrypted) { permissions |= static_cast(GattPermission::WRITE_ENCRYPTED_MITM); } return permissions; } uint16_t ConvertGattProperties(const NativeGattProperties &nativeProperties) { uint16_t properties = 0; if (nativeProperties.read) { properties |= static_cast(GattCharacteristic::READ); } if (nativeProperties.write) { properties |= static_cast(GattCharacteristic::WRITE); } if (nativeProperties.writeNoResponse) { properties |= static_cast(GattCharacteristic::WRITE_WITHOUT_RESPONSE); } if (nativeProperties.notify) { properties |= static_cast(GattCharacteristic::NOTIFY); } if (nativeProperties.indicate) { properties |= static_cast(GattCharacteristic::INDICATE); } return properties; } int GetProfileConnectionState(int state) { int32_t profileConnectionState = ProfileConnectionState::STATE_DISCONNECTED; switch (state) { case static_cast(BTConnectState::CONNECTING): HILOGD("STATE_CONNECTING(1)"); profileConnectionState = ProfileConnectionState::STATE_CONNECTING; break; case static_cast(BTConnectState::CONNECTED): HILOGD("STATE_CONNECTED(2)"); profileConnectionState = ProfileConnectionState::STATE_CONNECTED; break; case static_cast(BTConnectState::DISCONNECTING): HILOGD("STATE_DISCONNECTING(3)"); profileConnectionState = ProfileConnectionState::STATE_DISCONNECTING; break; case static_cast(BTConnectState::DISCONNECTED): HILOGD("STATE_DISCONNECTED(0)"); profileConnectionState = ProfileConnectionState::STATE_DISCONNECTED; break; default: break; } return profileConnectionState; } void FreeNativeBLECharacteristic(NativeBLECharacteristic characteristic) { free(characteristic.characteristicUuid); free(characteristic.serviceUuid); for (int64_t i = 0; i < characteristic.descriptors.size; i++) { NativeBLEDescriptor descriptor = characteristic.descriptors.head[i]; FreeNativeBLEDescriptor(descriptor); } free(characteristic.descriptors.head); characteristic.characteristicUuid = nullptr; characteristic.serviceUuid = nullptr; characteristic.descriptors.head = nullptr; } void FreeNativeBLEDescriptor(NativeBLEDescriptor descriptor) { free(descriptor.descriptorUuid); free(descriptor.characteristicUuid); free(descriptor.serviceUuid); free(descriptor.descriptorValue.head); descriptor.descriptorUuid = nullptr; descriptor.characteristicUuid = nullptr; descriptor.serviceUuid = nullptr; descriptor.descriptorValue.head = nullptr; } } // namespace CJBluetoothBle } // namespace CJSystemapi } // namespace OHOS