1#include <kindlebt/kindlebt_utils.h>
12#include <kindlebt/kindlebt_log.h>
14#define ADDR_WITH_COLON_LEN 17
15#define ADDR_WITHOUT_COLON_LEN 12
16#define PRINT_UUID_STR_LEN 49
18static void remove_all_chars(
char* str,
char c) {
19 char *pr = str, *pw = str;
27void utilsConvertBdAddrToStr(
bdAddr_t* paddr,
char* outStr) {
29 outStr,
"%02X:%02X:%02X:%02X:%02X:%02X", paddr->address[0], paddr->address[1],
30 paddr->address[2], paddr->address[3], paddr->address[4], paddr->address[5]
34uint8_t utilsConvertCharToHex(
char input) {
35 if (input >=
'0' && input <=
'9') {
36 return (uint8_t)(input -
'0');
37 }
else if (input >=
'A' && input <=
'F') {
38 return (uint8_t)(input -
'A') + 10;
39 }
else if (input >=
'a' && input <=
'f') {
40 return (uint8_t)(input -
'a') + 10;
46uint16_t utilsConvertHexStrToByteArray(
char* input, uint8_t* output) {
48 char* hex_string = input;
49 uint8_t hex_length = strlen(input);
51 for (
int i = 0; i < hex_length; i += 2) {
52 uint8_t value = utilsConvertCharToHex(hex_string[i]) << 4;
54 if (i + 1 < hex_length) {
55 value |= utilsConvertCharToHex(hex_string[i + 1]);
57 output[length] = value;
65 if (str == NULL || pAddr == NULL) {
66 return ACE_STATUS_BAD_PARAM;
69 int length = strlen(str);
70 if (length != ADDR_WITH_COLON_LEN && length != ADDR_WITHOUT_COLON_LEN) {
71 log_error(
"Invalid string format. Must be xx:xx:xx:xx:xx:xx or xxxxxxxxxxxx");
72 return ACE_STATUS_BAD_PARAM;
75 if (length == ADDR_WITH_COLON_LEN && str[2] ==
':' && str[5] ==
':' && str[8] ==
':' &&
76 str[11] ==
':' && str[14] ==
':') {
77 remove_all_chars(str,
':');
80 if (strlen(str) != ADDR_WITHOUT_COLON_LEN) {
81 log_error(
"Invalid string format. Must be xx:xx:xx:xx:xx:xx or xxxxxxxxxxxx");
82 return ACE_STATUS_BAD_PARAM;
85 for (
int i = 0; i < ADDR_WITHOUT_COLON_LEN; i++) {
86 if (!((str[i] >=
'0' && str[i] <=
'9') || (str[i] >=
'A' && str[i] <=
'F') ||
87 (str[i] >=
'a' && str[i] <=
'f'))) {
88 log_error(
"Contains non-hex character at index %d", i);
89 return ACE_STATUS_BAD_PARAM;
93 log_debug(
"Converting str->BT addr, str: %s", str);
95 length = utilsConvertHexStrToByteArray(str, pAddr->address);
97 return ACE_STATUS_BAD_PARAM;
100 return ACE_STATUS_OK;
103void utilsPrintUuid(
char* uuid_str,
uuid_t* uuid,
int max) {
106 "%02x %02x %02x %02x %02x %02x %02x %02x %02x"
107 " %02x %02x %02x %02x %02x %02x %02x",
108 uuid->uu[0], uuid->uu[1], uuid->uu[2], uuid->uu[3], uuid->uu[4], uuid->uu[5], uuid->uu[6],
109 uuid->uu[7], uuid->uu[8], uuid->uu[9], uuid->uu[10], uuid->uu[11], uuid->uu[12],
110 uuid->uu[13], uuid->uu[14], uuid->uu[15]
114char* utilsDumpServer(
bleGattsService_t* server,
char* log_buff,
size_t* size,
size_t* offset) {
115 if (!server)
return NULL;
117 int inc_svc_count = 0;
118 char buff[PRINT_UUID_STR_LEN];
119 memset(buff, 0,
sizeof(
char) * PRINT_UUID_STR_LEN);
120 utilsPrintUuid(buff, &server->uuid, PRINT_UUID_STR_LEN);
121 log_buff = append_to_buffer(
122 log_buff, size, offset,
"Service 0 uuid %s serviceType %d\n", buff, server->serviceType
125 struct aceBT_gattIncSvcRec_t* svc_rec;
126 STAILQ_FOREACH(svc_rec, &server->incSvcList, link) {
127 memset(buff, 0,
sizeof(
char) * PRINT_UUID_STR_LEN);
128 utilsPrintUuid(buff, &svc_rec->value.uuid, PRINT_UUID_STR_LEN);
129 log_buff = append_to_buffer(
130 log_buff, size, offset,
"Included Services %d service Type %d uuid %s\n",
131 inc_svc_count++, svc_rec->value.serviceType, buff
134 uint8_t char_count = 0;
135 struct aceBT_gattCharRec_t* char_rec = NULL;
136 STAILQ_FOREACH(char_rec, &server->charsList, link) {
137 memset(buff, 0,
sizeof(
char) * PRINT_UUID_STR_LEN);
138 utilsPrintUuid(buff, &char_rec->value.gattRecord.uuid, PRINT_UUID_STR_LEN);
139 if (char_rec->value.gattDescriptor.is_notify && char_rec->value.gattDescriptor.is_set) {
140 log_buff = append_to_buffer(
141 log_buff, size, offset,
"\tGatt Characteristics with Notifications %d uuid %s\n",
145 log_buff = append_to_buffer(
146 log_buff, size, offset,
"\tGatt Characteristics %d uuid %s\n", char_count++, buff
150 if (char_rec->value.gattDescriptor.is_set) {
152 buff, &char_rec->value.gattDescriptor.gattRecord.uuid, PRINT_UUID_STR_LEN
154 log_buff = append_to_buffer(log_buff, size, offset,
"\t\tDescriptor UUID %s\n", buff);
156 }
else if (char_rec->value.multiDescCount) {
157 uint8_t desc_num = 1;
158 struct aceBT_gattDescRec_t* desc_rec = NULL;
160 STAILQ_FOREACH(desc_rec, &char_rec->value.descList, link) {
161 utilsPrintUuid(buff, &desc_rec->value.gattRecord.uuid, PRINT_UUID_STR_LEN);
162 log_buff = append_to_buffer(
163 log_buff, size, offset,
"\t\tDescriptor %d UUID %s\n", desc_num++, buff
173 struct aceBT_gattCharRec_t* char_rec = NULL;
176 log_error(
"GATT DB has not been populated yet!");
181 for (uint32_t i = 0; i <
gNo_svc; i++) {
185 STAILQ_FOREACH(char_rec, &services->charsList, link) {
187 if (!memcmp(char_rec->value.gattRecord.uuid.uu, &uuid.uu, uuid_len)) {
192 log_error(
"GATT Characteristic UUID could not be found!");
196void setGattBlobFromBytes(
199 if (chars_value == NULL || data == NULL || size == 0)
return;
201 free(chars_value->blobValue.data);
203 uint8_t* blob = malloc(size);
204 if (blob == NULL)
return;
206 memcpy(blob, data, size);
208 chars_value->blobValue.data = blob;
209 chars_value->blobValue.size = size;
210 chars_value->blobValue.offset = 0;
215 if (chars_value == NULL || chars_value->blobValue.data == NULL)
return;
217 free(chars_value->blobValue.data);
218 chars_value->blobValue.data = NULL;
219 chars_value->blobValue.size = 0;
220 chars_value->blobValue.offset = 0;
223status_t waitForCondition(pthread_mutex_t* lock, pthread_cond_t* cond,
bool* flag) {
226 clock_gettime(CLOCK_REALTIME, &ts);
229 pthread_mutex_lock(lock);
231 int res = pthread_cond_timedwait(cond, lock, &ts);
232 if (res == ETIMEDOUT) {
233 pthread_mutex_unlock(lock);
234 log_error(
"Timed out waiting for condition");
235 return ACE_STATUS_TIMEOUT;
238 pthread_mutex_unlock(lock);
240 return ACE_STATUS_OK;
243void setCallbackVariable(pthread_mutex_t* lock, pthread_cond_t* cond,
bool* flag,
bool value) {
244 pthread_mutex_lock(lock);
246 pthread_cond_signal(cond);
247 pthread_mutex_unlock(lock);
aceBT_bdAddr_t bdAddr_t
Bluetooth address.
ace_status_t status_t
Bluetooth API status codes.
#define MAC_ADDR_LEN
MAC address length.
aceBT_bleGattsService_t bleGattsService_t
Structure for a GATT Server service.
aceBT_uuid_t uuid_t
Bluetooth UUID struct.
#define BLE_FORMAT_BLOB
BLOB format.
aceBT_bleGattCharacteristicsValue_t bleGattCharacteristicsValue_t
BLE GATT Characteristic.
struct aceBT_gattCharRec_t * utilsFindCharRec(uuid_t uuid, uint8_t uuid_len)
Find a GATT Characteristic Record by UUID.
bleGattsService_t * pGgatt_service
Internal reference to a GATT service.
uint32_t gNo_svc
Internal number of GATT services, often paired with pGgatt_service.