Skip to content

Commit 0d2d629

Browse files
committed
examples/nordic_uart: Port to new API
1 parent a074af0 commit 0d2d629

File tree

2 files changed

+141
-48
lines changed

2 files changed

+141
-48
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ if(GATTLIB_BUILD_EXAMPLES)
120120
add_subdirectory(examples/read_write)
121121
#add_subdirectory(examples/read_write_memory)
122122
add_subdirectory(examples/notification)
123-
#add_subdirectory(examples/nordic_uart)
123+
add_subdirectory(examples/nordic_uart)
124124
add_subdirectory(tests/test_continuous_connection)
125125

126126
# Some examples require Bluez code and other DBus support

examples/nordic_uart/nordic_uart.c

+140-47
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* GattLib - GATT Library
44
*
5-
* Copyright (C) 2016-2021 Olivier Martin <olivier@labapart.org>
5+
* Copyright (C) 2016-2024 Olivier Martin <olivier@labapart.org>
66
*
77
*
88
* This program is free software; you can redistribute it and/or modify
@@ -22,88 +22,89 @@
2222
*/
2323

2424
#include <assert.h>
25+
#include <ctype.h>
26+
#include <pthread.h>
27+
#include <signal.h>
2528
#include <stdio.h>
2629
#include <stdlib.h>
27-
#include <signal.h>
2830

2931
#ifdef GATTLIB_LOG_BACKEND_SYSLOG
3032
#include <syslog.h>
3133
#endif
3234

3335
#include "gattlib.h"
3436

35-
#define MIN(a,b) ((a)<(b)?(a):(b))
36-
3737
#define NUS_CHARACTERISTIC_TX_UUID "6e400002-b5a3-f393-e0a9-e50e24dcca9e"
3838
#define NUS_CHARACTERISTIC_RX_UUID "6e400003-b5a3-f393-e0a9-e50e24dcca9e"
3939

40-
gattlib_connection_t* m_connection;
40+
#define BLE_SCAN_TIMEOUT 10
41+
42+
#define MIN(a,b) ((a)<(b)?(a):(b))
4143

42-
void notification_cb(const uuid_t* uuid, const uint8_t* data, size_t data_length, void* user_data) {
43-
int i;
44+
static struct {
45+
char *adapter_name;
46+
char* mac_address;
47+
} m_argument;
48+
49+
// Declaration of thread condition variable
50+
static pthread_cond_t m_connection_terminated = PTHREAD_COND_INITIALIZER;
51+
52+
// declaring mutex
53+
static pthread_mutex_t m_connection_terminated_lock = PTHREAD_MUTEX_INITIALIZER;
54+
55+
static gattlib_connection_t* m_connection;
56+
57+
static void usage(char *argv[]) {
58+
printf("%s <device_address>\n", argv[0]);
59+
}
60+
61+
static void notification_handler(const uuid_t* uuid, const uint8_t* data, size_t data_length, void* user_data) {
62+
uintptr_t i;
63+
4464
for(i = 0; i < data_length; i++) {
4565
printf("%c", data[i]);
4666
}
4767
fflush(stdout);
4868
}
4969

50-
static void usage(char *argv[]) {
51-
printf("%s <device_address>\n", argv[0]);
52-
}
53-
54-
void int_handler(int dummy) {
70+
static void int_handler(int dummy) {
5571
gattlib_disconnect(m_connection, false /* wait_disconnection */);
5672
exit(0);
5773
}
5874

59-
int main(int argc, char *argv[]) {
60-
char input[256];
61-
char* input_ptr;
62-
int i, ret, total_length, length = 0;
75+
static void on_device_connect(gattlib_adapter_t* adapter, const char *dst, gattlib_connection_t* connection, int error, void* user_data) {
6376
uuid_t nus_characteristic_tx_uuid;
6477
uuid_t nus_characteristic_rx_uuid;
65-
66-
if (argc != 2) {
67-
usage(argv);
68-
return 1;
69-
}
70-
71-
#ifdef GATTLIB_LOG_BACKEND_SYSLOG
72-
openlog("gattlib_nordic_uart", LOG_CONS | LOG_NDELAY | LOG_PERROR, LOG_USER);
73-
setlogmask(LOG_UPTO(LOG_INFO));
74-
#endif
75-
76-
m_connection = gattlib_connect(NULL, argv[1],
77-
GATTLIB_CONNECTION_OPTIONS_LEGACY_BDADDR_LE_RANDOM |
78-
GATTLIB_CONNECTION_OPTIONS_LEGACY_BT_SEC_LOW);
79-
if (m_connection == NULL) {
80-
GATTLIB_LOG(GATTLIB_ERROR, "Fail to connect to the bluetooth device.");
81-
return 1;
82-
}
78+
char input[256];
79+
char* input_ptr;
80+
int ret, total_length, length = 0;
8381

8482
// Convert characteristics to their respective UUIDs
8583
ret = gattlib_string_to_uuid(NUS_CHARACTERISTIC_TX_UUID, strlen(NUS_CHARACTERISTIC_TX_UUID) + 1, &nus_characteristic_tx_uuid);
8684
if (ret) {
8785
GATTLIB_LOG(GATTLIB_ERROR, "Fail to convert characteristic TX to UUID.");
88-
return 1;
86+
goto EXIT;
8987
}
9088
ret = gattlib_string_to_uuid(NUS_CHARACTERISTIC_RX_UUID, strlen(NUS_CHARACTERISTIC_RX_UUID) + 1, &nus_characteristic_rx_uuid);
9189
if (ret) {
9290
GATTLIB_LOG(GATTLIB_ERROR, "Fail to convert characteristic RX to UUID.");
93-
return 1;
91+
goto EXIT;
9492
}
9593

9694
// Look for handle for NUS_CHARACTERISTIC_TX_UUID
9795
gattlib_characteristic_t* characteristics;
9896
int characteristic_count;
99-
ret = gattlib_discover_char(m_connection, &characteristics, &characteristic_count);
97+
ret = gattlib_discover_char(connection, &characteristics, &characteristic_count);
10098
if (ret) {
10199
GATTLIB_LOG(GATTLIB_ERROR, "Fail to discover characteristic.");
102-
return 1;
100+
goto EXIT;
103101
}
104102

103+
//
104+
// Confirm the Nordic UART RX and TX GATT characteristics are present
105+
//
105106
uint16_t tx_handle = 0, rx_handle = 0;
106-
for (i = 0; i < characteristic_count; i++) {
107+
for (int i = 0; i < characteristic_count; i++) {
107108
if (gattlib_uuid_cmp(&characteristics[i].uuid, &nus_characteristic_tx_uuid) == 0) {
108109
tx_handle = characteristics[i].value_handle;
109110
} else if (gattlib_uuid_cmp(&characteristics[i].uuid, &nus_characteristic_rx_uuid) == 0) {
@@ -112,23 +113,29 @@ int main(int argc, char *argv[]) {
112113
}
113114
if (tx_handle == 0) {
114115
GATTLIB_LOG(GATTLIB_ERROR, "Fail to find NUS TX characteristic.");
115-
return 1;
116+
goto FREE_GATT_CHARACTERISTICS;
116117
} else if (rx_handle == 0) {
117118
GATTLIB_LOG(GATTLIB_ERROR, "Fail to find NUS RX characteristic.");
118-
return 1;
119+
goto FREE_GATT_CHARACTERISTICS;
119120
}
120-
free(characteristics);
121121

122-
// Register notification handler
123-
gattlib_register_notification(m_connection, notification_cb, NULL);
122+
//
123+
// Listen for Nordic UART TX GATT characteristic
124+
//
125+
ret = gattlib_register_notification(connection, notification_handler, NULL);
126+
if (ret) {
127+
GATTLIB_LOG(GATTLIB_ERROR, "Fail to register notification callback.");
128+
goto FREE_GATT_CHARACTERISTICS;
129+
}
124130

125-
ret = gattlib_notification_start(m_connection, &nus_characteristic_rx_uuid);
131+
ret = gattlib_notification_start(connection, &nus_characteristic_rx_uuid);
126132
if (ret) {
127133
GATTLIB_LOG(GATTLIB_ERROR, "Fail to start notification.");
128-
return 2;
134+
goto FREE_GATT_CHARACTERISTICS;
129135
}
130136

131137
// Register handler to catch Ctrl+C
138+
m_connection = connection;
132139
signal(SIGINT, int_handler);
133140

134141
while(1) {
@@ -141,11 +148,97 @@ int main(int argc, char *argv[]) {
141148
ret = gattlib_write_without_response_char_by_handle(m_connection, tx_handle, input_ptr, length);
142149
if (ret) {
143150
GATTLIB_LOG(GATTLIB_ERROR, "Fail to send data to NUS TX characteristic.");
144-
return 1;
151+
goto FREE_GATT_CHARACTERISTICS;
145152
}
146153
input_ptr += length;
147154
}
148155
}
149156

157+
FREE_GATT_CHARACTERISTICS:
158+
free(characteristics);
159+
160+
EXIT:
161+
gattlib_disconnect(connection, false /* wait_disconnection */);
162+
163+
pthread_mutex_lock(&m_connection_terminated_lock);
164+
pthread_cond_signal(&m_connection_terminated);
165+
pthread_mutex_unlock(&m_connection_terminated_lock);
166+
}
167+
168+
static int stricmp(char const *a, char const *b) {
169+
for (;; a++, b++) {
170+
int d = tolower((unsigned char)*a) - tolower((unsigned char)*b);
171+
if (d != 0 || !*a)
172+
return d;
173+
}
174+
}
175+
176+
static void ble_discovered_device(gattlib_adapter_t* adapter, const char* addr, const char* name, void *user_data) {
177+
int ret;
178+
int16_t rssi;
179+
180+
if (stricmp(addr, m_argument.mac_address) != 0) {
181+
return;
182+
}
183+
184+
ret = gattlib_get_rssi_from_mac(adapter, addr, &rssi);
185+
if (ret == 0) {
186+
GATTLIB_LOG(GATTLIB_INFO, "Found bluetooth device '%s' with RSSI:%d", m_argument.mac_address, rssi);
187+
} else {
188+
GATTLIB_LOG(GATTLIB_INFO, "Found bluetooth device '%s'", m_argument.mac_address);
189+
}
190+
191+
ret = gattlib_connect(adapter, addr, GATTLIB_CONNECTION_OPTIONS_NONE, on_device_connect, NULL);
192+
if (ret != GATTLIB_SUCCESS) {
193+
GATTLIB_LOG(GATTLIB_ERROR, "Failed to connect to the bluetooth device '%s'", addr);
194+
}
195+
}
196+
197+
static void* ble_task(void* arg) {
198+
char* addr = arg;
199+
gattlib_adapter_t* adapter;
200+
int ret;
201+
202+
ret = gattlib_adapter_open(m_argument.adapter_name, &adapter);
203+
if (ret) {
204+
GATTLIB_LOG(GATTLIB_ERROR, "Failed to open adapter.");
205+
return NULL;
206+
}
207+
208+
ret = gattlib_adapter_scan_enable(adapter, ble_discovered_device, BLE_SCAN_TIMEOUT, addr);
209+
if (ret) {
210+
GATTLIB_LOG(GATTLIB_ERROR, "Failed to scan.");
211+
return NULL;
212+
}
213+
214+
// Wait for the device to be connected
215+
pthread_mutex_lock(&m_connection_terminated_lock);
216+
pthread_cond_wait(&m_connection_terminated, &m_connection_terminated_lock);
217+
pthread_mutex_unlock(&m_connection_terminated_lock);
218+
219+
return NULL;
220+
}
221+
222+
int main(int argc, char *argv[]) {
223+
int ret;
224+
225+
if (argc != 2) {
226+
usage(argv);
227+
return 1;
228+
}
229+
230+
#ifdef GATTLIB_LOG_BACKEND_SYSLOG
231+
openlog("gattlib_nordic_uart", LOG_CONS | LOG_NDELAY | LOG_PERROR, LOG_USER);
232+
setlogmask(LOG_UPTO(LOG_INFO));
233+
#endif
234+
235+
m_argument.adapter_name = NULL;
236+
m_argument.mac_address = argv[1];
237+
238+
ret = gattlib_mainloop(ble_task, NULL);
239+
if (ret != GATTLIB_SUCCESS) {
240+
GATTLIB_LOG(GATTLIB_ERROR, "Failed to create gattlib mainloop");
241+
}
242+
150243
return 0;
151244
}

0 commit comments

Comments
 (0)