summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2016-04-26 13:41:02 +0300
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2016-05-18 14:16:28 +0300
commit93b64d9ca8a2bb663e37904d4b2c702c58a36e4f (patch)
tree7bddbd438d7e720133f356d6fa9e01afe35be311
parent1055cee3269c1d13ab0cea46395fe789b94fb365 (diff)
downloadbluez-93b64d9ca8a2bb663e37904d4b2c702c58a36e4f.tar.gz
doc/gatt-api: Add options dictionary to ReadValue/WriteValue
This adds the possibility to pass an offset to these operations, and also in the server case to give the device object.
-rw-r--r--doc/gatt-api.txt20
-rw-r--r--src/gatt-client.c180
-rw-r--r--src/gatt-database.c219
3 files changed, 296 insertions, 123 deletions
diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
index ad2ab1676..683b1b7df 100644
--- a/doc/gatt-api.txt
+++ b/doc/gatt-api.txt
@@ -61,23 +61,29 @@ Service org.bluez
Interface org.bluez.GattCharacteristic1 [Experimental]
Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY
-Methods array{byte} ReadValue()
+Methods array{byte} ReadValue(dict options)
Issues a request to read the value of the
characteristic and returns the value if the
operation was successful.
+ Possible options: "offset": uint16 offset
+ "device": Object Device (Server only)
+
Possible Errors: org.bluez.Error.Failed
org.bluez.Error.InProgress
org.bluez.Error.NotPermitted
org.bluez.Error.NotAuthorized
org.bluez.Error.NotSupported
- void WriteValue(array{byte} value)
+ void WriteValue(array{byte} value, dict options)
Issues a request to write the value of the
characteristic.
+ Possible options: "offset": Start offset
+ "device": Device path (Server only)
+
Possible Errors: org.bluez.Error.Failed
org.bluez.Error.InProgress
org.bluez.Error.NotPermitted
@@ -154,23 +160,29 @@ Service org.bluez
Interface org.bluez.GattDescriptor1 [Experimental]
Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY/descriptorZZZ
-Methods array{byte} ReadValue()
+Methods array{byte} ReadValue(dict flags)
Issues a request to read the value of the
characteristic and returns the value if the
operation was successful.
+ Possible options: "offset": Start offset
+ "device": Device path (Server only)
+
Possible Errors: org.bluez.Error.Failed
org.bluez.Error.InProgress
org.bluez.Error.NotPermitted
org.bluez.Error.NotAuthorized
org.bluez.Error.NotSupported
- void WriteValue(array{byte} value)
+ void WriteValue(array{byte} value, dict flags)
Issues a request to write the value of the
characteristic.
+ Possible options: "offset": Start offset
+ "device": Device path (Server only)
+
Possible Errors: org.bluez.Error.Failed
org.bluez.Error.InProgress
org.bluez.Error.NotPermitted
diff --git a/src/gatt-client.c b/src/gatt-client.c
index 16a1f6ce2..0cbacca53 100644
--- a/src/gatt-client.c
+++ b/src/gatt-client.c
@@ -23,6 +23,7 @@
#include <stdbool.h>
#include <stdint.h>
+#include <errno.h>
#include <dbus/dbus.h>
@@ -191,33 +192,17 @@ static gboolean descriptor_value_exists(const GDBusPropertyTable *property,
return ret;
}
-static bool parse_value_arg(DBusMessage *msg, uint8_t **value,
- size_t *value_len)
+static int parse_value_arg(DBusMessageIter *iter, uint8_t **value, int *len)
{
- DBusMessageIter iter, array;
- uint8_t *val;
- int len;
-
- if (!dbus_message_iter_init(msg, &iter))
- return false;
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
- return false;
-
- dbus_message_iter_recurse(&iter, &array);
- dbus_message_iter_get_fixed_array(&array, &val, &len);
- dbus_message_iter_next(&iter);
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID)
- return false;
+ DBusMessageIter array;
- if (len < 0)
- return false;
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+ return -EINVAL;
- *value = val;
- *value_len = len;
+ dbus_message_iter_recurse(iter, &array);
+ dbus_message_iter_get_fixed_array(&array, value, len);
- return true;
+ return 0;
}
typedef bool (*async_dbus_op_complete_t)(void *data);
@@ -390,12 +375,60 @@ fail:
return;
}
+static int parse_options(DBusMessageIter *iter, uint16_t *offset)
+{
+ DBusMessageIter dict;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(iter, &dict);
+
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ const char *key;
+ DBusMessageIter value, entry;
+ int var;
+
+ dbus_message_iter_recurse(&dict, &entry);
+ dbus_message_iter_get_basic(&entry, &key);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_recurse(&entry, &value);
+
+ var = dbus_message_iter_get_arg_type(&value);
+ if (strcasecmp(key, "offset") == 0) {
+ if (var != DBUS_TYPE_UINT16)
+ return -EINVAL;
+ dbus_message_iter_get_basic(&value, offset);
+ }
+ }
+
+ return 0;
+}
+
+static unsigned int read_value(struct bt_gatt_client *gatt, uint16_t handle,
+ bt_gatt_client_read_callback_t callback,
+ struct async_dbus_op *op)
+{
+ if (op->offset)
+ return bt_gatt_client_read_long_value(gatt, handle, op->offset,
+ callback,
+ async_dbus_op_ref(op),
+ async_dbus_op_unref);
+ else
+ return bt_gatt_client_read_value(gatt, handle, callback,
+ async_dbus_op_ref(op),
+ async_dbus_op_unref);
+}
+
static DBusMessage *descriptor_read_value(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
struct descriptor *desc = user_data;
struct bt_gatt_client *gatt = desc->chrc->service->client->gatt;
+ DBusMessageIter iter;
struct async_dbus_op *op;
+ uint16_t offset = 0;
if (!gatt)
return btd_error_failed(msg, "Not connected");
@@ -403,14 +436,17 @@ static DBusMessage *descriptor_read_value(DBusConnection *conn,
if (desc->read_id)
return btd_error_in_progress(msg);
+ dbus_message_iter_init(msg, &iter);
+
+ if (parse_options(&iter, &offset))
+ return btd_error_invalid_args(msg);
+
op = new0(struct async_dbus_op, 1);
op->msg = dbus_message_ref(msg);
op->data = desc;
+ op->offset = offset;
- desc->read_id = bt_gatt_client_read_value(gatt, desc->handle,
- desc_read_cb,
- async_dbus_op_ref(op),
- async_dbus_op_unref);
+ desc->read_id = read_value(gatt, desc->handle, desc_read_cb, op);
if (desc->read_id)
return NULL;
@@ -450,7 +486,6 @@ done:
g_dbus_send_message(btd_get_dbus_connection(), reply);
}
-
static void write_cb(bool success, uint8_t att_ecode, void *user_data)
{
write_result_cb(success, false, att_ecode, user_data);
@@ -459,7 +494,8 @@ static void write_cb(bool success, uint8_t att_ecode, void *user_data)
static unsigned int start_long_write(DBusMessage *msg, uint16_t handle,
struct bt_gatt_client *gatt,
bool reliable, const uint8_t *value,
- size_t value_len, void *data,
+ size_t value_len, uint16_t offset,
+ void *data,
async_dbus_op_complete_t complete)
{
struct async_dbus_op *op;
@@ -469,9 +505,10 @@ static unsigned int start_long_write(DBusMessage *msg, uint16_t handle,
op->msg = dbus_message_ref(msg);
op->data = data;
op->complete = complete;
+ op->offset = offset;
- id = bt_gatt_client_write_long_value(gatt, reliable, handle,
- 0, value, value_len,
+ id = bt_gatt_client_write_long_value(gatt, reliable, handle, offset,
+ value, value_len,
write_result_cb, op,
async_dbus_op_free);
@@ -522,8 +559,10 @@ static DBusMessage *descriptor_write_value(DBusConnection *conn,
{
struct descriptor *desc = user_data;
struct bt_gatt_client *gatt = desc->chrc->service->client->gatt;
+ DBusMessageIter iter;
uint8_t *value = NULL;
- size_t value_len = 0;
+ int value_len = 0;
+ uint16_t offset = 0;
if (!gatt)
return btd_error_failed(msg, "Not connected");
@@ -531,7 +570,12 @@ static DBusMessage *descriptor_write_value(DBusConnection *conn,
if (desc->write_id)
return btd_error_in_progress(msg);
- if (!parse_value_arg(msg, &value, &value_len))
+ dbus_message_iter_init(msg, &iter);
+
+ if (parse_value_arg(&iter, &value, &value_len))
+ return btd_error_invalid_args(msg);
+
+ if (parse_options(&iter, &offset))
return btd_error_invalid_args(msg);
/*
@@ -546,15 +590,15 @@ static DBusMessage *descriptor_write_value(DBusConnection *conn,
* Based on the value length and the MTU, either use a write or a long
* write.
*/
- if (value_len <= (unsigned) bt_gatt_client_get_mtu(gatt) - 3)
+ if (value_len <= bt_gatt_client_get_mtu(gatt) - 3 && !offset)
desc->write_id = start_write_request(msg, desc->handle,
gatt, value,
value_len, desc,
desc_write_complete);
else
- desc->write_id = start_long_write(msg, desc->handle,
- gatt, false, value,
- value_len, desc,
+ desc->write_id = start_long_write(msg, desc->handle, gatt,
+ false, value,
+ value_len, offset, desc,
desc_write_complete);
if (!desc->write_id)
@@ -574,13 +618,15 @@ static const GDBusPropertyTable descriptor_properties[] = {
};
static const GDBusMethodTable descriptor_methods[] = {
- { GDBUS_EXPERIMENTAL_ASYNC_METHOD("ReadValue", NULL,
- GDBUS_ARGS({ "value", "ay" }),
- descriptor_read_value) },
+ { GDBUS_EXPERIMENTAL_ASYNC_METHOD("ReadValue",
+ GDBUS_ARGS({ "options", "a{sv}" }),
+ GDBUS_ARGS({ "value", "ay" }),
+ descriptor_read_value) },
{ GDBUS_EXPERIMENTAL_ASYNC_METHOD("WriteValue",
- GDBUS_ARGS({ "value", "ay" }),
- NULL,
- descriptor_write_value) },
+ GDBUS_ARGS({ "value", "ay" },
+ { "options", "a{sv}" }),
+ NULL,
+ descriptor_write_value) },
{ }
};
@@ -837,7 +883,9 @@ static DBusMessage *characteristic_read_value(DBusConnection *conn,
{
struct characteristic *chrc = user_data;
struct bt_gatt_client *gatt = chrc->service->client->gatt;
+ DBusMessageIter iter;
struct async_dbus_op *op;
+ uint16_t offset = 0;
if (!gatt)
return btd_error_failed(msg, "Not connected");
@@ -845,14 +893,17 @@ static DBusMessage *characteristic_read_value(DBusConnection *conn,
if (chrc->read_id)
return btd_error_in_progress(msg);
+ dbus_message_iter_init(msg, &iter);
+
+ if (parse_options(&iter, &offset))
+ return btd_error_invalid_args(msg);
+
op = new0(struct async_dbus_op, 1);
op->msg = dbus_message_ref(msg);
op->data = chrc;
+ op->offset = offset;
- chrc->read_id = bt_gatt_client_read_value(gatt, chrc->value_handle,
- chrc_read_cb,
- async_dbus_op_ref(op),
- async_dbus_op_unref);
+ chrc->read_id = read_value(gatt, chrc->value_handle, chrc_read_cb, op);
if (chrc->read_id)
return NULL;
@@ -879,9 +930,11 @@ static DBusMessage *characteristic_write_value(DBusConnection *conn,
{
struct characteristic *chrc = user_data;
struct bt_gatt_client *gatt = chrc->service->client->gatt;
+ DBusMessageIter iter;
uint8_t *value = NULL;
- size_t value_len = 0;
+ int value_len = 0;
bool supported = false;
+ uint16_t offset = 0;
if (!gatt)
return btd_error_failed(msg, "Not connected");
@@ -889,7 +942,12 @@ static DBusMessage *characteristic_write_value(DBusConnection *conn,
if (chrc->write_id)
return btd_error_in_progress(msg);
- if (!parse_value_arg(msg, &value, &value_len))
+ dbus_message_iter_init(msg, &iter);
+
+ if (parse_value_arg(&iter, &value, &value_len))
+ return btd_error_invalid_args(msg);
+
+ if (parse_options(&iter, &offset))
return btd_error_invalid_args(msg);
/*
@@ -906,7 +964,7 @@ static DBusMessage *characteristic_write_value(DBusConnection *conn,
if ((chrc->ext_props & BT_GATT_CHRC_EXT_PROP_RELIABLE_WRITE)) {
supported = true;
chrc->write_id = start_long_write(msg, chrc->value_handle, gatt,
- true, value, value_len,
+ true, value, value_len, offset,
chrc, chrc_write_complete);
if (chrc->write_id)
return NULL;
@@ -920,7 +978,7 @@ static DBusMessage *characteristic_write_value(DBusConnection *conn,
if (!mtu)
return btd_error_failed(msg, "No ATT transport");
- if (value_len <= (unsigned) mtu - 3)
+ if (value_len <= mtu - 3 && !offset)
chrc->write_id = start_write_request(msg,
chrc->value_handle,
gatt, value, value_len,
@@ -928,7 +986,7 @@ static DBusMessage *characteristic_write_value(DBusConnection *conn,
else
chrc->write_id = start_long_write(msg,
chrc->value_handle, gatt,
- false, value, value_len,
+ false, value, value_len, offset,
chrc, chrc_write_complete);
if (chrc->write_id)
@@ -1242,17 +1300,19 @@ static const GDBusPropertyTable characteristic_properties[] = {
};
static const GDBusMethodTable characteristic_methods[] = {
- { GDBUS_EXPERIMENTAL_ASYNC_METHOD("ReadValue", NULL,
- GDBUS_ARGS({ "value", "ay" }),
- characteristic_read_value) },
+ { GDBUS_EXPERIMENTAL_ASYNC_METHOD("ReadValue",
+ GDBUS_ARGS({ "options", "a{sv}" }),
+ GDBUS_ARGS({ "value", "ay" }),
+ characteristic_read_value) },
{ GDBUS_EXPERIMENTAL_ASYNC_METHOD("WriteValue",
- GDBUS_ARGS({ "value", "ay" }),
- NULL,
- characteristic_write_value) },
+ GDBUS_ARGS({ "value", "ay" },
+ { "options", "a{sv}" }),
+ NULL,
+ characteristic_write_value) },
{ GDBUS_EXPERIMENTAL_ASYNC_METHOD("StartNotify", NULL, NULL,
- characteristic_start_notify) },
+ characteristic_start_notify) },
{ GDBUS_EXPERIMENTAL_METHOD("StopNotify", NULL, NULL,
- characteristic_stop_notify) },
+ characteristic_stop_notify) },
{ }
};
diff --git a/src/gatt-database.c b/src/gatt-database.c
index b8da955c6..99d084d9d 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -135,6 +135,7 @@ struct external_desc {
};
struct pending_op {
+ struct btd_device *device;
unsigned int id;
struct gatt_db_attribute *attrib;
struct queue *owner_queue;
@@ -1592,7 +1593,8 @@ static void pending_op_free(void *data)
free(op);
}
-static struct pending_op *pending_read_new(struct queue *owner_queue,
+static struct pending_op *pending_read_new(struct btd_device *device,
+ struct queue *owner_queue,
struct gatt_db_attribute *attrib,
unsigned int id)
{
@@ -1601,6 +1603,7 @@ static struct pending_op *pending_read_new(struct queue *owner_queue,
op = new0(struct pending_op, 1);
op->owner_queue = owner_queue;
+ op->device = device;
op->attrib = attrib;
op->id = id;
queue_push_tail(owner_queue, op);
@@ -1608,33 +1611,75 @@ static struct pending_op *pending_read_new(struct queue *owner_queue,
return op;
}
-static void send_read(struct gatt_db_attribute *attrib, GDBusProxy *proxy,
- struct queue *owner_queue,
- unsigned int id)
+static void append_options(DBusMessageIter *iter, void *user_data)
+{
+ struct pending_op *op = user_data;
+ const char *path = device_get_path(op->device);
+
+ dict_append_entry(iter, "device", DBUS_TYPE_OBJECT_PATH, &path);
+}
+
+static void read_setup_cb(DBusMessageIter *iter, void *user_data)
+{
+ struct pending_op *op = user_data;
+ DBusMessageIter dict;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &dict);
+
+ append_options(&dict, op);
+
+ dbus_message_iter_close_container(iter, &dict);
+}
+
+static struct pending_op *send_read(struct btd_device *device,
+ struct gatt_db_attribute *attrib,
+ GDBusProxy *proxy,
+ struct queue *owner_queue,
+ unsigned int id)
{
struct pending_op *op;
- uint8_t ecode = BT_ATT_ERROR_UNLIKELY;
- op = pending_read_new(owner_queue, attrib, id);
+ op = pending_read_new(device, owner_queue, attrib, id);
- if (g_dbus_proxy_method_call(proxy, "ReadValue", NULL, read_reply_cb,
- op, pending_op_free) == TRUE)
- return;
+ if (g_dbus_proxy_method_call(proxy, "ReadValue", read_setup_cb,
+ read_reply_cb, op, pending_op_free) == TRUE)
+ return op;
pending_op_free(op);
- gatt_db_attribute_read_result(attrib, id, ecode, NULL, 0);
+ return NULL;
}
static void write_setup_cb(DBusMessageIter *iter, void *user_data)
{
struct pending_op *op = user_data;
- DBusMessageIter array;
+ DBusMessageIter array, dict;
dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "y", &array);
dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
&op->data.iov_base, op->data.iov_len);
dbus_message_iter_close_container(iter, &array);
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &dict);
+
+ append_options(&dict, op);
+
+ dbus_message_iter_close_container(iter, &dict);
+
+ if (!op->owner_queue) {
+ gatt_db_attribute_write_result(op->attrib, op->id, 0);
+ pending_op_free(op);
+ }
}
static void write_reply_cb(DBusMessage *message, void *user_data)
@@ -1673,7 +1718,8 @@ done:
gatt_db_attribute_write_result(op->attrib, op->id, ecode);
}
-static struct pending_op *pending_write_new(struct queue *owner_queue,
+static struct pending_op *pending_write_new(struct btd_device *device,
+ struct queue *owner_queue,
struct gatt_db_attribute *attrib,
unsigned int id,
const uint8_t *value,
@@ -1686,6 +1732,7 @@ static struct pending_op *pending_write_new(struct queue *owner_queue,
op->data.iov_base = (uint8_t *) value;
op->data.iov_len = len;
+ op->device = device;
op->owner_queue = owner_queue;
op->attrib = attrib;
op->id = id;
@@ -1694,24 +1741,25 @@ static struct pending_op *pending_write_new(struct queue *owner_queue,
return op;
}
-static void send_write(struct gatt_db_attribute *attrib, GDBusProxy *proxy,
+static struct pending_op *send_write(struct btd_device *device,
+ struct gatt_db_attribute *attrib,
+ GDBusProxy *proxy,
struct queue *owner_queue,
unsigned int id,
const uint8_t *value, size_t len)
{
struct pending_op *op;
- uint8_t ecode = BT_ATT_ERROR_UNLIKELY;
- op = pending_write_new(owner_queue, attrib, id, value, len);
+ op = pending_write_new(device, owner_queue, attrib, id, value, len);
if (g_dbus_proxy_method_call(proxy, "WriteValue", write_setup_cb,
- write_reply_cb, op,
- pending_op_free) == TRUE)
- return;
+ owner_queue ? write_reply_cb : NULL,
+ op, pending_op_free) == TRUE)
+ return op;
pending_op_free(op);
- gatt_db_attribute_write_result(attrib, id, ecode);
+ return NULL;
}
static uint32_t permissions_from_props(uint8_t props, uint8_t ext_props)
@@ -1895,19 +1943,65 @@ static bool database_add_cep(struct external_service *service,
return true;
}
+static struct btd_device *att_get_device(struct bt_att *att)
+{
+ GIOChannel *io = NULL;
+ GError *gerr = NULL;
+ bdaddr_t src, dst;
+ uint8_t dst_type;
+ struct btd_adapter *adapter;
+
+ io = g_io_channel_unix_new(bt_att_get_fd(att));
+ if (!io)
+ return NULL;
+
+ bt_io_get(io, &gerr, BT_IO_OPT_SOURCE_BDADDR, &src,
+ BT_IO_OPT_DEST_BDADDR, &dst,
+ BT_IO_OPT_DEST_TYPE, &dst_type,
+ BT_IO_OPT_INVALID);
+ if (gerr) {
+ error("bt_io_get: %s", gerr->message);
+ g_error_free(gerr);
+ g_io_channel_unref(io);
+ return NULL;
+ }
+
+ g_io_channel_unref(io);
+
+ adapter = adapter_find(&src);
+ if (!adapter) {
+ error("Unable to find adapter object");
+ return NULL;
+ }
+
+ return btd_adapter_find_device(adapter, &dst, dst_type);
+}
+
static void desc_read_cb(struct gatt_db_attribute *attrib,
unsigned int id, uint16_t offset,
uint8_t opcode, struct bt_att *att,
void *user_data)
{
struct external_desc *desc = user_data;
+ struct btd_device *device;
if (desc->attrib != attrib) {
error("Read callback called with incorrect attribute");
- return;
+ goto fail;
}
- send_read(attrib, desc->proxy, desc->pending_reads, id);
+ device = att_get_device(att);
+ if (!device) {
+ error("Unable to find device object");
+ goto fail;
+ }
+
+ if (send_read(device, attrib, desc->proxy, desc->pending_reads, id))
+ return;
+
+fail:
+ gatt_db_attribute_read_result(attrib, id, BT_ATT_ERROR_UNLIKELY,
+ NULL, 0);
}
static void desc_write_cb(struct gatt_db_attribute *attrib,
@@ -1917,13 +2011,26 @@ static void desc_write_cb(struct gatt_db_attribute *attrib,
void *user_data)
{
struct external_desc *desc = user_data;
+ struct btd_device *device;
if (desc->attrib != attrib) {
error("Read callback called with incorrect attribute");
- return;
+ goto fail;
}
- send_write(attrib, desc->proxy, desc->pending_writes, id, value, len);
+ device = att_get_device(att);
+ if (!device) {
+ error("Unable to find device object");
+ goto fail;
+ }
+
+ if (send_write(device, attrib, desc->proxy, desc->pending_writes, id,
+ value, len))
+ return;
+
+fail:
+ gatt_db_attribute_read_result(attrib, id, BT_ATT_ERROR_UNLIKELY,
+ NULL, 0);
}
static bool database_add_desc(struct external_service *service,
@@ -1956,43 +2063,25 @@ static void chrc_read_cb(struct gatt_db_attribute *attrib,
void *user_data)
{
struct external_chrc *chrc = user_data;
+ struct btd_device *device;
if (chrc->attrib != attrib) {
error("Read callback called with incorrect attribute");
- return;
+ goto fail;
}
- send_read(attrib, chrc->proxy, chrc->pending_reads, id);
-}
-
-static void write_without_response_setup_cb(DBusMessageIter *iter,
- void *user_data)
-{
- struct iovec *iov = user_data;
- DBusMessageIter array;
-
- dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "y", &array);
- dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
- &iov->iov_base, iov->iov_len);
- dbus_message_iter_close_container(iter, &array);
-}
-
-static void send_write_without_response(struct gatt_db_attribute *attrib,
- GDBusProxy *proxy, unsigned int id,
- const uint8_t *value, size_t len)
-{
- struct iovec iov;
- uint8_t ecode = 0;
-
- iov.iov_base = (uint8_t *) value;
- iov.iov_len = len;
+ device = att_get_device(att);
+ if (!device) {
+ error("Unable to find device object");
+ goto fail;
+ }
- if (!g_dbus_proxy_method_call(proxy, "WriteValue",
- write_without_response_setup_cb,
- NULL, &iov, NULL))
- ecode = BT_ATT_ERROR_UNLIKELY;
+ if (send_read(device, attrib, chrc->proxy, chrc->pending_reads, id))
+ return;
- gatt_db_attribute_write_result(attrib, id, ecode);
+fail:
+ gatt_db_attribute_read_result(attrib, id, BT_ATT_ERROR_UNLIKELY,
+ NULL, 0);
}
static void chrc_write_cb(struct gatt_db_attribute *attrib,
@@ -2002,19 +2091,31 @@ static void chrc_write_cb(struct gatt_db_attribute *attrib,
void *user_data)
{
struct external_chrc *chrc = user_data;
+ struct btd_device *device;
+ struct queue *queue;
if (chrc->attrib != attrib) {
error("Write callback called with incorrect attribute");
- return;
+ goto fail;
}
- if (chrc->props & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP) {
- send_write_without_response(attrib, chrc->proxy, id, value,
- len);
- return;
+ device = att_get_device(att);
+ if (!device) {
+ error("Unable to find device object");
+ goto fail;
}
- send_write(attrib, chrc->proxy, chrc->pending_writes, id, value, len);
+ if (!(chrc->props & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP))
+ queue = chrc->pending_writes;
+ else
+ queue = NULL;
+
+ if (send_write(device, attrib, chrc->proxy, queue, id, value, len))
+ return;
+
+fail:
+ gatt_db_attribute_read_result(attrib, id, BT_ATT_ERROR_UNLIKELY,
+ NULL, 0);
}
static bool database_add_chrc(struct external_service *service,