Skip to content

Commit

Permalink
examples/nordic_uart: Port to new API
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviermartin committed May 18, 2024
1 parent a074af0 commit 0d2d629
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 48 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ if(GATTLIB_BUILD_EXAMPLES)
add_subdirectory(examples/read_write)
#add_subdirectory(examples/read_write_memory)
add_subdirectory(examples/notification)
#add_subdirectory(examples/nordic_uart)
add_subdirectory(examples/nordic_uart)
add_subdirectory(tests/test_continuous_connection)

# Some examples require Bluez code and other DBus support
Expand Down
187 changes: 140 additions & 47 deletions examples/nordic_uart/nordic_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*
* GattLib - GATT Library
*
* Copyright (C) 2016-2021 Olivier Martin <[email protected]>
* Copyright (C) 2016-2024 Olivier Martin <[email protected]>
*
*
* This program is free software; you can redistribute it and/or modify
Expand All @@ -22,88 +22,89 @@
*/

#include <assert.h>
#include <ctype.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

#ifdef GATTLIB_LOG_BACKEND_SYSLOG
#include <syslog.h>
#endif

#include "gattlib.h"

#define MIN(a,b) ((a)<(b)?(a):(b))

#define NUS_CHARACTERISTIC_TX_UUID "6e400002-b5a3-f393-e0a9-e50e24dcca9e"
#define NUS_CHARACTERISTIC_RX_UUID "6e400003-b5a3-f393-e0a9-e50e24dcca9e"

gattlib_connection_t* m_connection;
#define BLE_SCAN_TIMEOUT 10

#define MIN(a,b) ((a)<(b)?(a):(b))

void notification_cb(const uuid_t* uuid, const uint8_t* data, size_t data_length, void* user_data) {
int i;
static struct {
char *adapter_name;
char* mac_address;
} m_argument;

// Declaration of thread condition variable
static pthread_cond_t m_connection_terminated = PTHREAD_COND_INITIALIZER;

// declaring mutex
static pthread_mutex_t m_connection_terminated_lock = PTHREAD_MUTEX_INITIALIZER;

static gattlib_connection_t* m_connection;

static void usage(char *argv[]) {
printf("%s <device_address>\n", argv[0]);
}

static void notification_handler(const uuid_t* uuid, const uint8_t* data, size_t data_length, void* user_data) {
uintptr_t i;

for(i = 0; i < data_length; i++) {
printf("%c", data[i]);
}
fflush(stdout);
}

static void usage(char *argv[]) {
printf("%s <device_address>\n", argv[0]);
}

void int_handler(int dummy) {
static void int_handler(int dummy) {
gattlib_disconnect(m_connection, false /* wait_disconnection */);
exit(0);
}

int main(int argc, char *argv[]) {
char input[256];
char* input_ptr;
int i, ret, total_length, length = 0;
static void on_device_connect(gattlib_adapter_t* adapter, const char *dst, gattlib_connection_t* connection, int error, void* user_data) {
uuid_t nus_characteristic_tx_uuid;
uuid_t nus_characteristic_rx_uuid;

if (argc != 2) {
usage(argv);
return 1;
}

#ifdef GATTLIB_LOG_BACKEND_SYSLOG
openlog("gattlib_nordic_uart", LOG_CONS | LOG_NDELAY | LOG_PERROR, LOG_USER);
setlogmask(LOG_UPTO(LOG_INFO));
#endif

m_connection = gattlib_connect(NULL, argv[1],
GATTLIB_CONNECTION_OPTIONS_LEGACY_BDADDR_LE_RANDOM |
GATTLIB_CONNECTION_OPTIONS_LEGACY_BT_SEC_LOW);
if (m_connection == NULL) {
GATTLIB_LOG(GATTLIB_ERROR, "Fail to connect to the bluetooth device.");
return 1;
}
char input[256];
char* input_ptr;
int ret, total_length, length = 0;

// Convert characteristics to their respective UUIDs
ret = gattlib_string_to_uuid(NUS_CHARACTERISTIC_TX_UUID, strlen(NUS_CHARACTERISTIC_TX_UUID) + 1, &nus_characteristic_tx_uuid);
if (ret) {
GATTLIB_LOG(GATTLIB_ERROR, "Fail to convert characteristic TX to UUID.");
return 1;
goto EXIT;
}
ret = gattlib_string_to_uuid(NUS_CHARACTERISTIC_RX_UUID, strlen(NUS_CHARACTERISTIC_RX_UUID) + 1, &nus_characteristic_rx_uuid);
if (ret) {
GATTLIB_LOG(GATTLIB_ERROR, "Fail to convert characteristic RX to UUID.");
return 1;
goto EXIT;
}

// Look for handle for NUS_CHARACTERISTIC_TX_UUID
gattlib_characteristic_t* characteristics;
int characteristic_count;
ret = gattlib_discover_char(m_connection, &characteristics, &characteristic_count);
ret = gattlib_discover_char(connection, &characteristics, &characteristic_count);
if (ret) {
GATTLIB_LOG(GATTLIB_ERROR, "Fail to discover characteristic.");
return 1;
goto EXIT;
}

//
// Confirm the Nordic UART RX and TX GATT characteristics are present
//
uint16_t tx_handle = 0, rx_handle = 0;
for (i = 0; i < characteristic_count; i++) {
for (int i = 0; i < characteristic_count; i++) {
if (gattlib_uuid_cmp(&characteristics[i].uuid, &nus_characteristic_tx_uuid) == 0) {
tx_handle = characteristics[i].value_handle;
} else if (gattlib_uuid_cmp(&characteristics[i].uuid, &nus_characteristic_rx_uuid) == 0) {
Expand All @@ -112,23 +113,29 @@ int main(int argc, char *argv[]) {
}
if (tx_handle == 0) {
GATTLIB_LOG(GATTLIB_ERROR, "Fail to find NUS TX characteristic.");
return 1;
goto FREE_GATT_CHARACTERISTICS;
} else if (rx_handle == 0) {
GATTLIB_LOG(GATTLIB_ERROR, "Fail to find NUS RX characteristic.");
return 1;
goto FREE_GATT_CHARACTERISTICS;
}
free(characteristics);

// Register notification handler
gattlib_register_notification(m_connection, notification_cb, NULL);
//
// Listen for Nordic UART TX GATT characteristic
//
ret = gattlib_register_notification(connection, notification_handler, NULL);
if (ret) {
GATTLIB_LOG(GATTLIB_ERROR, "Fail to register notification callback.");
goto FREE_GATT_CHARACTERISTICS;
}

ret = gattlib_notification_start(m_connection, &nus_characteristic_rx_uuid);
ret = gattlib_notification_start(connection, &nus_characteristic_rx_uuid);
if (ret) {
GATTLIB_LOG(GATTLIB_ERROR, "Fail to start notification.");
return 2;
goto FREE_GATT_CHARACTERISTICS;
}

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

while(1) {
Expand All @@ -141,11 +148,97 @@ int main(int argc, char *argv[]) {
ret = gattlib_write_without_response_char_by_handle(m_connection, tx_handle, input_ptr, length);
if (ret) {
GATTLIB_LOG(GATTLIB_ERROR, "Fail to send data to NUS TX characteristic.");
return 1;
goto FREE_GATT_CHARACTERISTICS;
}
input_ptr += length;
}
}

FREE_GATT_CHARACTERISTICS:
free(characteristics);

EXIT:
gattlib_disconnect(connection, false /* wait_disconnection */);

pthread_mutex_lock(&m_connection_terminated_lock);
pthread_cond_signal(&m_connection_terminated);
pthread_mutex_unlock(&m_connection_terminated_lock);
}

static int stricmp(char const *a, char const *b) {
for (;; a++, b++) {
int d = tolower((unsigned char)*a) - tolower((unsigned char)*b);
if (d != 0 || !*a)
return d;
}
}

static void ble_discovered_device(gattlib_adapter_t* adapter, const char* addr, const char* name, void *user_data) {
int ret;
int16_t rssi;

if (stricmp(addr, m_argument.mac_address) != 0) {
return;
}

ret = gattlib_get_rssi_from_mac(adapter, addr, &rssi);
if (ret == 0) {
GATTLIB_LOG(GATTLIB_INFO, "Found bluetooth device '%s' with RSSI:%d", m_argument.mac_address, rssi);
} else {
GATTLIB_LOG(GATTLIB_INFO, "Found bluetooth device '%s'", m_argument.mac_address);
}

ret = gattlib_connect(adapter, addr, GATTLIB_CONNECTION_OPTIONS_NONE, on_device_connect, NULL);
if (ret != GATTLIB_SUCCESS) {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to connect to the bluetooth device '%s'", addr);
}
}

static void* ble_task(void* arg) {
char* addr = arg;
gattlib_adapter_t* adapter;
int ret;

ret = gattlib_adapter_open(m_argument.adapter_name, &adapter);
if (ret) {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to open adapter.");
return NULL;
}

ret = gattlib_adapter_scan_enable(adapter, ble_discovered_device, BLE_SCAN_TIMEOUT, addr);
if (ret) {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to scan.");
return NULL;
}

// Wait for the device to be connected
pthread_mutex_lock(&m_connection_terminated_lock);
pthread_cond_wait(&m_connection_terminated, &m_connection_terminated_lock);
pthread_mutex_unlock(&m_connection_terminated_lock);

return NULL;
}

int main(int argc, char *argv[]) {
int ret;

if (argc != 2) {
usage(argv);
return 1;
}

#ifdef GATTLIB_LOG_BACKEND_SYSLOG
openlog("gattlib_nordic_uart", LOG_CONS | LOG_NDELAY | LOG_PERROR, LOG_USER);
setlogmask(LOG_UPTO(LOG_INFO));
#endif

m_argument.adapter_name = NULL;
m_argument.mac_address = argv[1];

ret = gattlib_mainloop(ble_task, NULL);
if (ret != GATTLIB_SUCCESS) {
GATTLIB_LOG(GATTLIB_ERROR, "Failed to create gattlib mainloop");
}

return 0;
}

0 comments on commit 0d2d629

Please sign in to comment.