gattlib: Added support for write-without-response

pull/109/head
Olivier Martin 2019-07-05 22:43:38 +02:00 committed by Olivier Martin
parent 1e0e57070f
commit 8020503ab6
5 changed files with 105 additions and 9 deletions

View File

@ -101,6 +101,10 @@ Examples
./examples/notification/notification
* [Demonstrate GATT Write Without Response](/examples/nordic_uart/nordic_uart.c):
./examples/nordic_uart/nordic_uart
**Note:** `examples/gatttool` has been partially ported to gattlib. There are two reasons: the laziness
(some of the GATT functions could be replaced by their gattlib equivalent) and the completeness (there
are still some missing functions in gattlib).

View File

@ -200,6 +200,18 @@ int gattlib_write_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, cons
return gattlib_write_char_by_handle(connection, handle, buffer, buffer_len);
}
int gattlib_write_without_response_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, const void* buffer, size_t buffer_len)
{
// Only supported in the DBUS API (ie: Bluez > v5.40) at the moment
return GATTLIB_NOT_SUPPORTED;
}
int gattlib_write_without_response_char_by_handle(gatt_connection_t* connection, uint16_t handle, const void* buffer, size_t buffer_len)
{
// Only supported in the DBUS API (ie: Bluez > v5.40) at the moment
return GATTLIB_NOT_SUPPORTED;
}
int gattlib_notification_start(gatt_connection_t* connection, const uuid_t* uuid) {
uint16_t handle;
uint16_t enable_notification = 0x0001;

View File

@ -31,6 +31,11 @@
#define CONNECT_TIMEOUT 4
#define BLUEZ_GATT_WRITE_VALUE_TYPE_MASK (0x7)
#define BLUEZ_GATT_WRITE_VALUE_TYPE_WRITE_WITH_RESPONSE (1 << 0)
#define BLUEZ_GATT_WRITE_VALUE_TYPE_WRITE_WITHOUT_RESPONSE (1 << 1)
#define BLUEZ_GATT_WRITE_VALUE_TYPE_RELIABLE_WRITE (1 << 2)
static const uuid_t m_battery_level_uuid = CREATE_UUID16(0x2A19);
static const uuid_t m_ccc_uuid = CREATE_UUID16(0x2902);
@ -1322,7 +1327,7 @@ int gattlib_read_char_by_uuid_async(gatt_connection_t* connection, uuid_t* uuid,
return GATTLIB_SUCCESS;
}
static int write_char(struct dbus_characteristic *dbus_characteristic, const void* buffer, size_t buffer_len)
static int write_char(struct dbus_characteristic *dbus_characteristic, const void* buffer, size_t buffer_len, uint32_t options)
{
GVariant *value = g_variant_new_from_data(G_VARIANT_TYPE ("ay"), buffer, buffer_len, TRUE, NULL, NULL);
GError *error = NULL;
@ -1330,9 +1335,14 @@ static int write_char(struct dbus_characteristic *dbus_characteristic, const voi
#if BLUEZ_VERSION < BLUEZ_VERSIONS(5, 40)
org_bluez_gatt_characteristic1_call_write_value_sync(dbus_characteristic->gatt, value, NULL, &error);
#else
GVariantBuilder *options = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
org_bluez_gatt_characteristic1_call_write_value_sync(dbus_characteristic->gatt, value, g_variant_builder_end(options), NULL, &error);
g_variant_builder_unref(options);
GVariantBuilder *variant_options = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
if ((options & BLUEZ_GATT_WRITE_VALUE_TYPE_MASK) == BLUEZ_GATT_WRITE_VALUE_TYPE_WRITE_WITHOUT_RESPONSE) {
g_variant_builder_add(variant_options, "{sv}", "type", g_variant_new("s", "request"));
}
org_bluez_gatt_characteristic1_call_write_value_sync(dbus_characteristic->gatt, value, g_variant_builder_end(variant_options), NULL, &error);
g_variant_builder_unref(variant_options);
#endif
if (error != NULL) {
@ -1358,7 +1368,7 @@ int gattlib_write_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, cons
assert(dbus_characteristic.type == TYPE_GATT);
}
return write_char(&dbus_characteristic, buffer, buffer_len);
return write_char(&dbus_characteristic, buffer, buffer_len, BLUEZ_GATT_WRITE_VALUE_TYPE_WRITE_WITH_RESPONSE);
}
int gattlib_write_char_by_handle(gatt_connection_t* connection, uint16_t handle, const void* buffer, size_t buffer_len) {
@ -1367,9 +1377,34 @@ int gattlib_write_char_by_handle(gatt_connection_t* connection, uint16_t handle,
return GATTLIB_NOT_FOUND;
}
return write_char(&dbus_characteristic, buffer, buffer_len);
return write_char(&dbus_characteristic, buffer, buffer_len, BLUEZ_GATT_WRITE_VALUE_TYPE_WRITE_WITH_RESPONSE);
}
int gattlib_write_without_response_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, const void* buffer, size_t buffer_len)
{
struct dbus_characteristic dbus_characteristic = get_characteristic_from_uuid(connection, uuid);
if (dbus_characteristic.type == TYPE_NONE) {
return GATTLIB_NOT_FOUND;
} else if (dbus_characteristic.type == TYPE_BATTERY_LEVEL) {
return GATTLIB_NOT_SUPPORTED; // Battery level does not support write
} else {
assert(dbus_characteristic.type == TYPE_GATT);
}
return write_char(&dbus_characteristic, buffer, buffer_len, BLUEZ_GATT_WRITE_VALUE_TYPE_WRITE_WITHOUT_RESPONSE);
}
int gattlib_write_without_response_char_by_handle(gatt_connection_t* connection, uint16_t handle, const void* buffer, size_t buffer_len)
{
struct dbus_characteristic dbus_characteristic = get_characteristic_from_handle(connection, handle);
if (dbus_characteristic.type == TYPE_NONE) {
return GATTLIB_NOT_FOUND;
}
return write_char(&dbus_characteristic, buffer, buffer_len, BLUEZ_GATT_WRITE_VALUE_TYPE_WRITE_WITHOUT_RESPONSE);
}
#if BLUEZ_VERSION > BLUEZ_VERSIONS(5, 40)
gboolean on_handle_battery_level_property_change(
OrgBluezBattery1 *object,

View File

@ -2,7 +2,7 @@
*
* GattLib - GATT Library
*
* Copyright (C) 2016-2017 Olivier Martin <olivier@labapart.org>
* Copyright (C) 2016-2019 Olivier Martin <olivier@labapart.org>
*
*
* This program is free software; you can redistribute it and/or modify
@ -125,8 +125,8 @@ int main(int argc, char *argv[]) {
// NUS TX can only receive 20 bytes at a time
input_ptr = input;
for (total_length = strlen(input) + 1; total_length > 0; total_length -= length) {
length = MIN(total_length, 20);
ret = gattlib_write_char_by_handle(m_connection, tx_handle, input_ptr, length);
length = MIN(total_length, 20);
ret = gattlib_write_without_response_char_by_handle(m_connection, tx_handle, input_ptr, length);
if (ret) {
fprintf(stderr, "Fail to send data to NUS TX characteristic.\n");
return 1;

View File

@ -224,9 +224,54 @@ int gattlib_read_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, void*
*/
int gattlib_read_char_by_uuid_async(gatt_connection_t* connection, uuid_t* uuid, gatt_read_cb_t gatt_read_cb);
/**
* @brief Function to write to the GATT characteristic UUID
*
* @param connection Active GATT connection
* @param uuid UUID of the GATT characteristic to read
* @param buffer contains the values to write to the GATT characteristic
* @param buffer_len is the length of the buffer to write
*
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code
*/
int gattlib_write_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, const void* buffer, size_t buffer_len);
/**
* @brief Function to write to the GATT characteristic handle
*
* @param connection Active GATT connection
* @param handle is the handle of the GATT characteristic
* @param buffer contains the values to write to the GATT characteristic
* @param buffer_len is the length of the buffer to write
*
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code
*/
int gattlib_write_char_by_handle(gatt_connection_t* connection, uint16_t handle, const void* buffer, size_t buffer_len);
/**
* @brief Function to write without response to the GATT characteristic UUID
*
* @param connection Active GATT connection
* @param uuid UUID of the GATT characteristic to read
* @param buffer contains the values to write to the GATT characteristic
* @param buffer_len is the length of the buffer to write
*
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code
*/
int gattlib_write_without_response_char_by_uuid(gatt_connection_t* connection, uuid_t* uuid, const void* buffer, size_t buffer_len);
/**
* @brief Function to write without response to the GATT characteristic handle
*
* @param connection Active GATT connection
* @param handle is the handle of the GATT characteristic
* @param buffer contains the values to write to the GATT characteristic
* @param buffer_len is the length of the buffer to write
*
* @return GATTLIB_SUCCESS on success or GATTLIB_* error code
*/
int gattlib_write_without_response_char_by_handle(gatt_connection_t* connection, uint16_t handle, const void* buffer, size_t buffer_len);
/*
* @param uuid UUID of the characteristic that will trigger the notification
*/