* Copyright (c) 2026 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 DRIVER_BLE_COMMNON_H
#define DRIVER_BLE_COMMNON_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "bluetooth/bluetooth.h"
#include "bluetooth/hci.h"
#include "bluetooth/hci_lib.h"
#include "softbus_error_code.h"
#include "softbus_adapter_ble_gatt_client_struct.h"
#include "driver_log.h"
#undef LOG_TAG
#define LOG_TAG "AdapterBle"
#define OFFSET 1
#define WIDE_CHAR_MAX_LEN 8
#define WIDE_STR_MAX_LEN 128
#define MAC_BIT_ZERO 0
#define MAC_BIT_ONE 1
#define MAC_BIT_TWO 2
#define MAC_BIT_THREE 3
#define MAC_BIT_FOUR 4
#define MAC_BIT_FIVE 5
#define BT_ADDR_LEN 6
#define BT_ADDR_DELIMITER ":"
#define BT_ADDR_BASE 16
#define BUF_BYTE_LEN 64
#define BUF_HEX_LEN 128
#define GATT_PSM_ATT 0x001f
#define GATT_MTU_DEFAULT 23
#define GATT_MTU_MAX 512
#define ATT_OP_ERROR 0x01
#define ATT_OP_MTU_REQ 0x02
#define ATT_OP_MTU_RSP 0x03
#define ATT_OP_FIND_BY_TYPE_VALUE_RSP 0x07
#define ATT_OP_READ_REQ 0x0A
#define ATT_OP_READ_RSP 0x0B
#define ATT_OP_WRITE_REQ 0x12
#define ATT_OP_WRITE_RSP 0x13
#define ATT_OP_NOTIFY 0x1B
#define ATT_OP_INDICATE 0x1D
#define ATT_OP_INDICATE_RSP 0x1E
#define ATT_CID 0x0004
#define UUID_ARR_LEN 2
#define UUID_INT_LEN 16
#define UUID_STR_LEN 37
#define ARR_VALUE 0
#define ARR_SIGNATURE 12
#define BT_MAC_LEN 18
#define BT_NO_ERROR 0
#define PROFILE_GATT_CLIENT "profile_gatt_client"
#define BLUETOOTH_HOST "bluetooth_host"
#define BLE_ADVERTISER_SERVER "ble_advertiser_server"
#define BLE_CENTRAL_MANAGER_SERVER "ble_central_manager_server"
#define EOK 0
# define CLOCK_MONOTONIC 1
#define MAX_MALLOC_SIZE (512 * 1024 * 1024)
#define FILE_DESCRIPTOR_IN_BAD_STATE 77
#define ATT_OP_FIND_BY_TYPE_REQ 0x06
#define ATT_OP_FIND_BY_TYPE_RESP 0x07
#define ATT_OP_READ_BY_GROUP_REQ 0x10
#define ATT_OP_READ_BY_GROUP_RESP 0x11
#define GATT_PRIM_SVC_UUID 0x2800
#define ATT_ECODE_INVALID_PDU 0x04
#define ATT_ECODE_ATTR_NOT_FOUND 0x0A
#define ATT_ECODE_INSUFF_RESOURCES 0x0D
#define ATT_ECODE_UNLIKELY 0x0E
#define ATT_ECODE_IO 0x0F
#define ATT_OP_FIND_BY_TYPE_VALUE_REQ 0x06
#define ATT_OP_FIND_BY_TYPE_VALUE_RSP 0x07
#define ATT_OP_READ_BY_TYPE_REQ 0x08
#define ATT_OP_READ_BY_TYPE_RSP 0x09
#define GATT_PSM_ATT 0x001f
#define GATT_MTU_DEFAULT 23
#define UUID_16BIT_LEN 2
#define UUID_128BIT_LEN 16
#define MIN_PKT_LEN 3
void *DriverBleMalloc(unsigned int size);
void *DriverBleCalloc(unsigned int size);
void DriverBleFree(void *pt);
void DriverBleClearFree(void *pt, unsigned int size);
#define TASK_NAME_MAX_LEN (16)
typedef enum {
SOFTBUS_SCHED_OTHER,
SOFTBUS_SCHED_RR
} SoftBusSched;
typedef enum {
SOFTBUS_THREAD_JOINABLE,
SOFTBUS_THREAD_DETACH
} SoftBusDetachState;
typedef enum {
SOFTBUS_PRIORITY_LOWEST,
SOFTBUS_PRIORITY_LOW,
SOFTBUS_PRIORITY_DEFAULT,
SOFTBUS_PRIORITY_HIGH,
SOFTBUS_PRIORITY_HIGHEST
} SoftBusThreadPriority;
typedef struct {
int32_t policy;
int32_t detachState;
SoftBusThreadPriority prior;
const char *taskName;
uint64_t stackSize;
} SoftBusThreadAttr;
typedef enum {
SOFTBUS_MUTEX_NORMAL,
SOFTBUS_MUTEX_RECURSIVE
} SoftBusMutexType;
typedef struct {
SoftBusMutexType type;
} SoftBusMutexAttr;
typedef uintptr_t SoftBusThread;
typedef uintptr_t SoftBusMutex;
typedef uintptr_t SoftBusCond;
int32_t DriverBleMutexAttrInit(SoftBusMutexAttr *mutexAttr);
int32_t DriverBleMutexInit(SoftBusMutex *mutex, SoftBusMutexAttr *mutexAttr);
int32_t DriverBleMutexLockInner(SoftBusMutex *mutex);
int32_t DriverBleMutexUnlockInner(SoftBusMutex *mutex);
int32_t DriverBleMutexDestroy(SoftBusMutex *mutex);
static inline bool CheckMutexIsNull(const SoftBusMutex *mutex)
{
return (mutex == NULL) || ((void *)(*mutex) == NULL);
}
#define SoftBusMutexLock(mutex) \
({ \
int32_t ret = SOFTBUS_OK; \
if (CheckMutexIsNull(mutex)) { \
LOGE("SoftBusMutexLock mutex is null"); \
ret = SOFTBUS_INVALID_PARAM; \
} else { \
ret = DriverBleMutexLockInner(mutex); \
if (ret != 0) { \
LOGE("SoftBusMutexLock failed, ret=%d", ret); \
ret = SOFTBUS_LOCK_ERR; \
} \
} \
ret; \
}) \
#define SoftBusMutexUnlock(mutex) \
({ \
int32_t ret = SOFTBUS_OK; \
if (CheckMutexIsNull(mutex)) { \
LOGE("SoftBusMutexUnlock mutex is null"); \
ret = SOFTBUS_INVALID_PARAM; \
} else { \
ret = DriverBleMutexUnlockInner(mutex); \
if (ret != 0) { \
LOGE("SoftBusMutexUnlock failed, ret=%d\n", ret); \
ret = SOFTBUS_LOCK_ERR; \
} \
} \
ret; \
})
static inline void DriverBleMutexUnlockAuto(SoftBusMutex **mutex)
{
if (mutex) {
SoftBusMutexUnlock(*mutex);
}
}
#define SOFTBUS_LOCK_GUARD(mutex) \
__attribute__((cleanup(DriverBleMutexUnlockAuto), unused)) SoftBusMutex *lockGuard##mutex = &mutex
typedef void *(*task_func_t)(void *arg);
typedef struct task {
task_func_t function;
void *arg;
struct task *next;
} task_t;
typedef struct threadpool {
pthread_mutex_t lock;
pthread_cond_t notify;
pthread_t *threads;
task_t *taskQueueFront;
task_t *taskQueueRear;
int threadCount;
int queueSize;
int queueCapacity;
int shutdown;
int started;
} threadpool_t;
typedef enum {
THREADPOOL_INVALID = -1,
THREADPOOL_LOCK_FAILURE = -2,
THREADPOOL_QUEUE_FULL = -3,
THREADPOOL_SHUTDOWN = -4,
THREADPOOL_THREAD_FAILURE = -5,
THREADPOOL_SUCCESS = 0
} threadpool_error_t;
typedef enum {
IMMEDIATE_SHUTDOWN = 1,
GRACEFUL_SHUTDOWN = 2
} threadpool_shutdown_t;
threadpool_t *ThreadPoolCreate(int threadCount, int queueCapacity);
int ThreadPoolAdd(threadpool_t *pool, task_func_t function, void *arg);
int ThreadPoolDestroy(threadpool_t *pool, int flags);
int ThreadPoolFree(threadpool_t *pool);
int ThreadPoolWait(threadpool_t *pool);
int ThreadPoolThreadCount(threadpool_t *pool);
int ThreadPoolQueueSize(threadpool_t *pool);
int ThreadPoolQueueCapacity(threadpool_t *pool);
typedef struct ListNode {
struct ListNode *prev;
struct ListNode *next;
} ListNode;
__attribute__((always_inline)) static inline void ListInit(ListNode *list)
{
list->next = list;
list->prev = list;
}
#define GET_LIST_HEAD(object) ((object)->next)
#define GET_LIST_TAIL(object) ((object)->prev)
__attribute__((always_inline)) static inline void ListAdd(ListNode *list, ListNode *node)
{
node->next = list->next;
node->prev = list;
list->next->prev = node;
list->next = node;
}
__attribute__((always_inline)) static inline void ListTailInsert(ListNode *list, ListNode *node)
{
ListAdd(list->prev, node);
}
__attribute__((always_inline)) static inline void ListNodeInsert(ListNode *list, ListNode *node)
{
ListAdd(list, node);
}
__attribute__((always_inline)) static inline void ListDelete(ListNode *node)
{
if (node->next != 0 && node->prev != 0) {
node->next->prev = node->prev;
node->prev->next = node->next;
}
node->next = node;
node->prev = node;
}
__attribute__((always_inline)) static inline bool IsListEmpty(const ListNode *node)
{
return (bool)(node->next == node);
}
* @brief Obtain the pointer to a list in a structure
*
* @param type [IN] Structure name.
* @param member [IN] Member name of the list in the structure.
*/
#define OFF_SET_OF(type, member) ((size_t)&(((type *)0)->member))
#ifndef CONTAINER_OF
#define CONTAINER_OF(ptr, type, member) \
(type *)((char *)(ptr) - (char *) &((type *)0)->member)
#endif
* @brief Obtain the pointer to a structure that contains a list.
* @param item [IN] Current node's pointer to the next node.
* @param type [IN] Structure name.
* @param member [IN] Member name of the list in the structure.
*/
#define LIST_ENTRY(item, type, member) \
((type *)(void *)((char *)(item) - OFF_SET_OF(type, member))) \
#define LIST_FOR_EACH_ENTRY(item, list, type, member) \
for ((item) = LIST_ENTRY((list)->next, type, member); \
((item) != NULL) && (&(item)->member != (list)); \
(item) = LIST_ENTRY((item)->member.next, type, member))
#define LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, list, type, member) \
for ((item) = LIST_ENTRY((list)->next, type, member), \
(nextItem) = LIST_ENTRY((item)->member.next, type, member); \
&((item)->member) != (list); \
(item) = (nextItem), (nextItem) = LIST_ENTRY((item)->member.next, type, member))
__attribute__((always_inline)) static inline void ListDel(ListNode *prevNode, ListNode *nextNode)
{
nextNode->prev = prevNode;
prevNode->next = nextNode;
}
__attribute__((always_inline)) static inline void ListDelInit(ListNode *list)
{
ListDel(list->prev, list->next);
ListInit(list);
}
#define LIST_FOR_EACH(item, list) \
for ((item) = (list)->next; (item) != (list); (item) = (item)->next)
#define LIST_FOR_EACH_SAFE(item, nextItem, list) \
for ((item) = (list)->next, (nextItem) = (item)->next; (item) != (list); \
(item) = (nextItem), (nextItem) = (item)->next)
#define LIST_HEAD(list) ListNode list = { &(list), &(list) }
typedef enum {
TYPE_ADV_DATA = 0,
TYPE_RSP_DATA,
TYPE_PAYLOAD_ID,
TYPE_MAC_ADDR,
TYPE_UUID,
TYPE_FULL_DATA,
TYPE_TEST_DATA
} HexDataType;
void PrintHexFormat(const char *descriptor, HexDataType type, const uint8_t *data, uint32_t len);
int GetLocalBleName(char *data, size_t len);
void GetDeviceName(uint8_t *target_addr, uint32_t len);
bool OpenBleDevice(void);
void CloseBleDevice(void);
void SetCmdDeviceDescriptor(int dd);
int GetCmdDeviceDescriptor(void);
void SetEventDeviceDescriptor(int dd);
int GetEventDeviceDescriptor(void);
int SoftBusStartBtStateMonitor(void);
int SoftBusStopBtStateMonitor(void);
bool DriverExtendBleAdvSwitch(bool enable);
bool DriverExtendBleScanSwitch(bool enable);
#ifdef BLUEZ_GENERAL_CONFIG
bool DriverExtendBleSetScanParams(void);
#endif
enum GattStatus {
AUTHENTICATION_FAILED = -33,
GATT_CONGESTION = -32,
EMPTY_FILTER = -31,
MAX_FILTERS = -30,
INVALID_REMOTE_DEVICE = -29,
INCLUDE_SERVICE_NOT_FOUND,
REFERENCED_BY_OTHER_SERVICE,
INVALID_CHARACTERISTIC,
INVALID_CHARACTERISTIC_DATA,
INVALID_CHARACTERISTIC_DESCRIPTOR,
INVALID_CHARACTERISTIC_DESCRIPTOR_DATA,
NOT_ENOUGH_HANDLES,
HANDLE_NOT_FOUND,
INVALID_PARAMETER,
INTERNAL_ERROR,
REQUEST_NOT_SUPPORT,
REMOTE_DEVICE_BUSY,
MAX_CONNECTIONS,
MAX_APPLICATIONS,
DEVICE_ALREADY_BIND,
INVALID_HANDLE,
INVALID_OFFSET,
READ_NOT_PERMITTED,
WRITE_NOT_PERMITTED,
INSUFFICIENT_ENCRYPTION,
INSUFFICIENT_AUTHENTICATION,
INSUFFICIENT_AUTHORIZATION,
INSUFFICIENT_ENCRYPTION_KEY_SIZE,
PREPARE_QUEUE_FULL,
ATTRIBUTE_NOT_LONG,
INVALID_ATTRIBUTE_VALUE_LENGTH,
WRITE_REQUEST_REJECTED,
GATT_FAILURE,
GATT_SUCCESS
};
typedef enum {
GATT_SERVICE_PRIMARY = 0x2800,
GATT_SERVICE_SECONDARY = 0x2801,
GATT_CHARACTERISTIC = 0x2803
} GattAttrTypeAttStu;
typedef struct {
uint16_t start_handle;
uint16_t end_handle;
uint8_t uuid[UUID_INT_LEN];
uint8_t uuid_len;
char uuid_str[UUID_STR_LEN];
} GattServiceAttStu;
typedef struct {
uint16_t handle;
uint16_t properties;
uint16_t value_handle;
uint8_t uuid[UUID_INT_LEN];
uint8_t uuid_len;
char uuid_str[UUID_STR_LEN];
} GattCharactAttStu;
typedef struct GattDescAtt {
uint8_t uuid[UUID_INT_LEN];
uint8_t uuid_len;
} GattDescAttStu;
typedef struct GattClient {
int clientId;
int sock;
uint16_t clientMTU;
int dd;
int handle;
char *data;
int dataLen;
} GattClient;
typedef struct ClientCharacteristic {
GattServiceAttStu service;
GattCharactAttStu characteristic;
uint8_t *data;
int dataLen;
} ClientCharacteristic;
typedef struct ClientDescriptor {
GattServiceAttStu service;
GattCharactAttStu characteristic;
GattDescAttStu descriptor;
uint8_t *data;
int dataLen;
} ClientDescriptor;
typedef struct {
int sock;
SoftBusGattWriteType writeType;
int len;
char *value;
bool is_pending;
} WriteRequestContext;
typedef SoftBusGattWriteType GattWriteTypeAttStu;
typedef void (*gatt_write_callback_t)(const char *device_addr,
uint16_t handle,
bool success,
void *user_data);
struct AttWriteReq {
uint8_t opcode;
uint16_t handle;
uint8_t value[ARR_VALUE];
} __attribute__((packed));
struct AttSignedWriteReq {
uint8_t opcode;
uint16_t handle;
uint8_t value[ARR_VALUE];
uint8_t signature[ARR_SIGNATURE];
} __attribute__((packed));
typedef enum {
OHOS_BT_STATUS_SUCCESS = 0x00,
OHOS_BT_STATUS_FAIL,
OHOS_BT_STATUS_NOT_READY,
OHOS_BT_STATUS_NOMEM,
OHOS_BT_STATUS_BUSY,
OHOS_BT_STATUS_DONE,
OHOS_BT_STATUS_UNSUPPORTED,
OHOS_BT_STATUS_PARM_INVALID,
OHOS_BT_STATUS_UNHANDLED,
OHOS_BT_STATUS_AUTH_FAILURE,
OHOS_BT_STATUS_RMT_DEV_DOWN,
OHOS_BT_STATUS_AUTH_REJECTED,
OHOS_BT_STATUS_DUPLICATED_ADDR
} BtStatus;
typedef struct {
uint8_t uuidLen;
char *uuid;
} BtUuid;
typedef enum {
OHOS_BT_TRANSPORT_TYPE_AUTO = 0x0,
OHOS_BT_TRANSPORT_TYPE_LE,
OHOS_BT_TRANSPORT_TYPE_CLASSIC,
} BtTransportType;
typedef enum {
OHOS_BT_GATT_PRIORITY_BALANCED = 0x0,
OHOS_BT_GATT_PRIORITY_HIGH,
OHOS_BT_GATT_PRIORITY_LOW_POWER,
} BtGattPriority;
typedef struct {
BtUuid serviceUuid;
BtUuid characteristicUuid;
} BtGattCharacteristic;
typedef struct {
BtGattCharacteristic characteristic;
BtUuid descriptorUuid;
} BtGattDescriptor;
typedef struct {
union {
BtGattCharacteristic characteristic;
BtGattDescriptor descriptor;
} attribute;
unsigned short dataLen;
unsigned char *data;
} BtGattReadData;
typedef void (*ConnectionStateChangedCallback)(int clientId, int connectionState, int status);
typedef void (*ConnectParaUpdateCallback)(int clientId, int interval, int latency, int timeout, int status);
typedef void (*SearchServiceCompleteCallback)(int clientId, int status);
typedef void (*ReadCharacteristicCallback)(int clientId, BtGattReadData *readData, int status);
typedef void (*WriteCharacteristicCallback)(int clientId, BtGattCharacteristic *characteristic, int status);
typedef void (*ReadDescriptorCallback)(int clientId, BtGattReadData *readData, int status);
typedef void (*WriteDescriptorCallback)(int clientId, BtGattDescriptor *descriptor, int status);
typedef void (*ConfigureMtuSizeCallback)(int clientId, int mtuSize, int status);
typedef void (*RegisterNotificationCallback)(int clientId, int status);
typedef void (*NotificationCallback)(int clientId, BtGattReadData *notifyData, int status);
typedef struct {
ConnectionStateChangedCallback ConnectionStateCb;
ConnectParaUpdateCallback connectParaUpdateCb;
SearchServiceCompleteCallback searchServiceCompleteCb;
ReadCharacteristicCallback readCharacteristicCb;
WriteCharacteristicCallback writeCharacteristicCb;
ReadDescriptorCallback readDescriptorCb;
WriteDescriptorCallback writeDescriptorCb;
ConfigureMtuSizeCallback configureMtuSizeCb;
RegisterNotificationCallback registerNotificationCb;
NotificationCallback notificationCb;
} BtGattClientCallbacks;
enum BTConnectState {
CONNECTING,
CONNECTED,
DISCONNECTING,
DISCONNECTED,
};
int GetGattcResult(int ret);
typedef struct GattClientCallbackWrapper {
void (*OnConnectionStateChanged)(struct GattClientCallbackWrapper *self, int connectionState, int ret);
void (*OnConnectionParameterChanged)(struct GattClientCallbackWrapper *self, int interval, int latency, int timeout, int status);
void (*OnMtuUpdate)(struct GattClientCallbackWrapper *self, int mtu, int ret);
void (*OnServicesDiscovered)(struct GattClientCallbackWrapper *self, int status);
void (*OnCharacteristicChanged)(struct GattClientCallbackWrapper *self, const ClientCharacteristic characteristic);
void (*OnCharacteristicReadResult)(struct GattClientCallbackWrapper *self, const ClientCharacteristic characteristic, int ret);
void (*OnReadRemoteRssiValueResult)(struct GattClientCallbackWrapper *self, int rssi, int status);
void (*OnCharacteristicWriteResult)(struct GattClientCallbackWrapper *self, const ClientCharacteristic characteristic, int ret);
void (*OnDescriptorReadResult)(struct GattClientCallbackWrapper *self, const ClientDescriptor descriptor, int ret);
void (*OnDescriptorWriteResult)(struct GattClientCallbackWrapper *self, const ClientDescriptor descriptor, int ret);
void (*OnSetNotifyCharacteristic)(struct GattClientCallbackWrapper *self, const ClientCharacteristic haracteristic, int status);
BtGattClientCallbacks *appCallback_;
int clientId_;
} GattClientCallbackWrapper;
typedef void (*gatt_service_discovered_cb)(const char *device_addr,
GattServiceAttStu *service,
void *user_data);
typedef void (*gatt_characteristic_discovered_cb)(const char *device_addr,
GattCharactAttStu *characteristic,
void *user_data);
typedef struct GattClientWrapper {
int clientId;
GattClient gattClient;
pthread_t thread;
bool isRunning;
pthread_mutex_t clientMutex;
GattClientCallbackWrapper *gattClientCallback;
SoftBusBtAddr remoteAddr;
bool fastestConnFlag;
gatt_service_discovered_cb service_discovered_cb;
void *service_cb_user_data;
gatt_characteristic_discovered_cb char_discovered_cb;
void *char_cb_user_data;
WriteRequestContext write_context;
} GattClientWrapper;
GattClientCallbackWrapper *GattClientCallbackWrapperCreate(BtGattClientCallbacks *appCallback_, int clientId_);
typedef uintptr_t SoftBusThread;
typedef uintptr_t SoftBusMutex;
typedef uintptr_t SoftBusCond;
typedef struct {
char *uuid;
} UUID;
typedef struct {
enum {
BT_UUID_UNSPEC = 0,
BT_UUID16 = 16,
BT_UUID32 = 32,
BT_UUID128 = 128,
} type;
union {
uint16_t u16;
uint32_t u32;
uint128_t u128;
} value;
} bt_uuid_t;
struct AttReadByTypeReq {
uint8_t opcode;
uint16_t start_handle;
uint16_t end_handle;
uint8_t uuid[2];
} __attribute__((packed));
void PrintUuid(const uint8_t *data, uint32_t len);
#endif