mirror of https://github.com/labapart/gattlib
gattlib: Added support for write-without-response
parent
1e0e57070f
commit
8020503ab6
|
@ -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).
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue