Message ID | 20200605142541.28412-3-amitx.k.singh@intel.com |
---|---|
State | New |
Headers | show |
Series | bluetoothctl:Add support for read characteristics value | expand |
Hi Luiz, > -----Original Message----- > From: Luiz Augusto von Dentz <luiz.dentz@gmail.com> > Sent: Friday, June 5, 2020 10:32 PM > To: Singh, AmitX K <amitx.k.singh@intel.com> > Cc: linux-bluetooth@vger.kernel.org > Subject: Re: [PATCH] bluetoothctl:Add support for read characteristics value > > Hi Amit, > > On Fri, Jun 5, 2020 at 7:30 AM Amitsi5x <amitx.k.singh@intel.com> wrote: > > > > From: amit <amitx.k.singh@intel.com> > > > > Changes made to add support for read charateristic value by uuid in > > bluetoothctl. > > > > Signed-off-by: amit <amitx.k.singh@intel.com> > > --- > > client/gatt.c | 70 ++++++++++++++++++++++++++++++++ > > client/gatt.h | 1 + > > client/main.c | 18 +++++++++ > > src/gatt-client.c | 70 ++++++++++++++++++++++++++++++++ > > src/shared/gatt-client.c | 86 > > +++++++++++++++++++++++++++++++++++++++- > > src/shared/gatt-client.h | 5 +++ > > 6 files changed, 249 insertions(+), 1 deletion(-) > > > > diff --git a/client/gatt.c b/client/gatt.c index 53f875050..8c2844ed6 > > 100644 > > --- a/client/gatt.c > > +++ b/client/gatt.c > > @@ -681,6 +681,76 @@ void gatt_read_attribute(GDBusProxy *proxy, int > argc, char *argv[]) > > return bt_shell_noninteractive_quit(EXIT_FAILURE); > > } > > > > +static void charreadbyuuid_reply(DBusMessage *message, void > > +*user_data) { > > + DBusError error; > > + DBusMessageIter iter, array; > > + uint8_t *value; > > + int len; > > + > > + dbus_error_init(&error); > > + > > + if (dbus_set_error_from_message(&error, message) == TRUE) { > > + bt_shell_printf("Failed to read: %s\n", error.name); > > + dbus_error_free(&error); > > + return bt_shell_noninteractive_quit(EXIT_FAILURE); > > + } > > + > > + dbus_message_iter_init(message, &iter); > > + > > + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) { > > + bt_shell_printf("Invalid response to read\n"); > > + return bt_shell_noninteractive_quit(EXIT_FAILURE); > > + } > > + > > + dbus_message_iter_recurse(&iter, &array); > > + dbus_message_iter_get_fixed_array(&array, &value, &len); > > + > > + if (len < 0) { > > + bt_shell_printf("Unable to parse value\n"); > > + return bt_shell_noninteractive_quit(EXIT_FAILURE); > > + } > > + > > + bt_shell_hexdump(value, len); > > + > > + return bt_shell_noninteractive_quit(EXIT_SUCCESS); > > +} > > + > > +static void charreadbyuuid_setup(DBusMessageIter *iter, void > > +*user_data) { > > + char *uuid = user_data; > > + > > + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid); > > +} > > + > > +static void charreadbyuuid_attribute(GDBusProxy *proxy, char *uuid) { > > + if (g_dbus_proxy_method_call(proxy, "CharReadByUUID", > charreadbyuuid_setup, charreadbyuuid_reply, > > + uuid, NULL) == FALSE) { > > + bt_shell_printf("Failed to set uuid\n"); > > + return bt_shell_noninteractive_quit(EXIT_FAILURE); > > + } > > + > > + bt_shell_printf("Attempting to read service handle %s\n", > > +g_dbus_proxy_get_path(proxy)); } > > + > > +void gatt_charreadbyuuid_attribute(GDBusProxy *proxy, int argc, char > > +*argv[]) { > > + const char *iface; > > + > > + iface = g_dbus_proxy_get_interface(proxy); > > + > > + if (!strcmp(iface, "org.bluez.GattCharacteristic1")) { > > + charreadbyuuid_attribute(proxy, argv[1]); > > + return; > > + } > > + > > + bt_shell_printf("Unable to read attribute %s\n", > > + > > + g_dbus_proxy_get_path(proxy)); > > + > > + return bt_shell_noninteractive_quit(EXIT_FAILURE); > > +} > > + > > static void charbyuuid_reply(DBusMessage *message, void *user_data) > > { > > DBusError error; > > diff --git a/client/gatt.h b/client/gatt.h index 692fb5758..8f96d8665 > > 100644 > > --- a/client/gatt.h > > +++ b/client/gatt.h > > @@ -35,6 +35,7 @@ GDBusProxy *gatt_select_attribute(GDBusProxy > > *parent, const char *path); char *gatt_attribute_generator(const char > > *text, int state); void gatt_servbyuuid_attribute(GDBusProxy *proxy, > > int argc, char *argv[]); void gatt_charbyuuid_attribute(GDBusProxy > > *proxy, int argc, char *argv[]); > > +void gatt_charreadbyuuid_attribute(GDBusProxy *proxy, int argc, char > > +*argv[]); > > void gatt_read_attribute(GDBusProxy *proxy, int argc, char *argv[]); > > void gatt_write_attribute(GDBusProxy *proxy, int argc, char *argv[]); > > void gatt_notify_attribute(GDBusProxy *proxy, bool enable); diff --git > > a/client/main.c b/client/main.c index 10e64e17b..4dd1e593a 100644 > > --- a/client/main.c > > +++ b/client/main.c > > @@ -2071,6 +2071,22 @@ static void cmd_attribute_info(int argc, char > *argv[]) > > return bt_shell_noninteractive_quit(EXIT_SUCCESS); > > } > > > > +static void cmd_char_read_by_uuid(int argc, char *argv[]) { > > + GDBusProxy *proxy; > > + > > + proxy = find_attribute(argc, argv); > > + > > + set_default_attribute(proxy); > > + > > + if (!default_attr) { > > + bt_shell_printf("No attribute selected\n"); > > + return bt_shell_noninteractive_quit(EXIT_FAILURE); > > + } > > + > > + gatt_charreadbyuuid_attribute(default_attr, argc, argv); } > > + > > static void cmd_char_by_uuid(int argc, char *argv[]) { > > GDBusProxy *proxy; > > @@ -2718,6 +2734,8 @@ static const struct bt_shell_menu gatt_menu = { > > "Discover Primary Services by UUID" }, > > { "char-by-uuid", "[UUID]", cmd_char_by_uuid, > > "Discover Characteristic Services by > > UUID" }, > > + { "char-read-by-uuid", "[UUID]", cmd_char_read_by_uuid, > > + "Read Characteristic by UUID" }, > > { "select-attribute", "<attribute/UUID>", cmd_select_attribute, > > "Select attribute", attribute_generator }, > > { "attribute-info", "[attribute/UUID]", cmd_attribute_info, > > diff --git a/src/gatt-client.c b/src/gatt-client.c index > > da811ea4f..cd6d6dfde 100644 > > --- a/src/gatt-client.c > > +++ b/src/gatt-client.c > > @@ -444,6 +444,27 @@ static struct async_dbus_op > *async_dbus_op_new(DBusMessage *msg, void *data) > > return op; > > } > > > > +static struct async_dbus_op *fetch_char_read_by_uuid(struct > bt_gatt_client *gatt, > > + DBusMessage *msg, > > + char *uuid, > > + bt_gatt_client_char_by_uuid_callback_t callback, > > + void *data) { > > + struct async_dbus_op *op; > > + > > + op = async_dbus_op_new(msg, data); > > + op->id = bt_gatt_client_char_read_by_uuid(gatt, uuid, callback, > > + async_dbus_op_ref(op), > > + async_dbus_op_unref); > > + > > + if (op->id) > > + return op; > > + > > + async_dbus_op_free(op); > > + > > + return NULL; > > +} > > + > > static struct async_dbus_op *fetch_char_by_uuid(struct bt_gatt_client > *gatt, > > DBusMessage *msg, > > char *uuid, @@ -972,6 +993,52 > > @@ fail: > > chrc->read_op = NULL; > > } > > > > +static void char_read_by_uuid_cb(bool success, uint8_t att_ecode, const > uint8_t *value, > > + uint16_t length, void > > +*user_data) { > > + struct async_dbus_op *op = user_data; > > + struct characteristic *opchar = op->data; > > + > > + if (!success) > > + goto fail; > > + > > + async_dbus_op_reply(op, att_ecode, value, length); > > + > > + return; > > + > > +fail: > > + async_dbus_op_reply(op, att_ecode, NULL, 0); > > + > > + opchar->type_op = NULL; > > +} > > + > > +static DBusMessage *char_read_by_uuid(DBusConnection *conn, > > + DBusMessage *msg, void > > +*user_data) { > > + struct characteristic *chardata = user_data; > > + struct bt_gatt_client *gatt = chardata->service->client->gatt; > > + DBusMessageIter iter; > > + > > + char *uuid = 0; > > + > > + if (!gatt) > > + return btd_error_failed(msg, "Not connected"); > > + > > + dbus_message_iter_init(msg, &iter); > > + > > + if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) > > + dbus_message_iter_get_basic(&iter,&uuid); > > + else > > + return NULL; > > + > > + chardata->type_op = fetch_char_read_by_uuid(gatt, msg,uuid, > > + char_read_by_uuid_cb, chardata); > > + > > + if (!chardata->type_op) > > + return btd_error_failed(msg, "Failed to send read > > + request"); > > + > > + return NULL; > > +} > > + > > static void characteristic_by_uuid_cb(bool success, uint8_t att_ecode, > const uint8_t *value, > > uint16_t length, void > > *user_data) { @@ -1786,6 +1853,9 @@ static const GDBusMethodTable > > characteristic_methods[] = { > > { GDBUS_ASYNC_METHOD("CharByUUID", GDBUS_ARGS({ "options", > "s" }), > > GDBUS_ARGS({ "value", "ay" }), > > chardiscover_by_uuid) }, > > + { GDBUS_ASYNC_METHOD("CharReadByUUID", GDBUS_ARGS({ > "options", "s" }), > > + GDBUS_ARGS({ "value", "ay" }), > > + char_read_by_uuid) }, > > It would have helped if you had communicated that you would be looking > into add support for this type of operation, these procedures obviously > cannot be part of Characteristic interface since that is only available after the > discovery procedure then you can just lookup internally in the cache. So this > type of procedure will probably need to be under a Device object and lets > please agree on the documentation first before we move forward. > When we verify the PTS test case GATT/CL/GAR/BV-03-C "Read using characterisitic UUID", the Test case expect read request from device . Added a code for sending read request for reading characteristic value using UUID over characteristic interface > > { GDBUS_ASYNC_METHOD("ReadValue", GDBUS_ARGS({ "options", > "a{sv}" }), > > GDBUS_ARGS({ "value", "ay" }), > > characteristic_read_value) }, > > diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c index > > 8a696c77f..7c9d25ec3 100644 > > --- a/src/shared/gatt-client.c > > +++ b/src/shared/gatt-client.c > > @@ -2725,6 +2725,90 @@ done: > > op->callback(success, att_ecode, value, length, > > op->user_data); } > > > > +unsigned int bt_gatt_client_char_read_by_uuid(struct bt_gatt_client > *client, > > + char *uuid, > > + bt_gatt_client_char_by_uuid_callback_t callback, > > + void *user_data, > > + > > +bt_gatt_client_destroy_func_t destroy) { > > + struct request *req; > > + struct char_by_uuid_op *op; > > + unsigned char *pdu; > > + uint16_t len ; > > + uint16_t start_handle = 0x0001; > > + uint16_t end_handle = 0xffff; > > + bt_uuid_t btuuid; > > + uint8_t uuid128[16]; > > + > > + /* Length of pdu will be vary according to uuid type > > + for 2 byte uuid total length is 8 (start handle(2) + end handle(2) + > uuid(2)) > > + for 16 byte uuid total length is 22 (start handle(2) + end handle(2) + > uuid(16)) > > + */ > > + uint16_t pdu_len_16bit_uuid = 6; > > + uint16_t pdu_len_128bit_uuid = 20; > > + > > + if (bt_string_to_uuid(&btuuid, uuid) < 0) { > > + return 0; > > + } > > + > > + if (btuuid.type == BT_UUID16){ > > + pdu = (unsigned char *) malloc(pdu_len_16bit_uuid); > > + len = pdu_len_16bit_uuid; > > + } else { > > + pdu = (unsigned char *) malloc(pdu_len_128bit_uuid); > > + len = pdu_len_128bit_uuid; > > + } > > + > > + if (!client) > > + return 0; > > + > > + op = new0(struct char_by_uuid_op, 1); > > + req = request_create(client); > > + if (!req) { > > + free(op); > > + return 0; > > + } > > + if (!client) > > + return 0; > > + > > + op = new0(struct char_by_uuid_op, 1); > > + req = request_create(client); > > + > > + if (!req) { > > + free(op); > > + return 0; > > + } > > + > > + op->callback = callback; > > + op->user_data = user_data; > > + op->destroy = destroy; > > + req->data = op; > > + req->destroy = destroy_char_by_uuid_op; > > + > > + put_le16(start_handle, pdu); > > + put_le16(end_handle, pdu+2); > > + > > + if (btuuid.type == BT_UUID16) > > + put_le16(btuuid.value.u16, pdu+4); > > + else { > > + bswap_128(&btuuid.value.u128.data[0], &uuid128[0]); > > + memcpy(pdu + 4, uuid128, 16); > > + } > > + > > + req->att_id = bt_att_send(client->att, > BT_ATT_OP_READ_BY_TYPE_REQ, > > + pdu, len, > > + char_by_uuid_cb, req, > > + > > + request_unref); > > + > > + if (!req->att_id) { > > + op->destroy = NULL; > > + request_unref(req); > > + return 0; > > + } > > + > > + return req->id; > > +} > > + > > unsigned int bt_gatt_client_char_by_uuid(struct bt_gatt_client *client, > > char *uuid, > > > > bt_gatt_client_char_by_uuid_callback_t callback, @@ -2754,7 +2838,7 @@ > unsigned int bt_gatt_client_char_by_uuid(struct bt_gatt_client *client, > > if (btuuid.type == BT_UUID16){ > > pdu = (unsigned char *) malloc(pdu_len_16bit_uuid); > > len = pdu_len_16bit_uuid; > > - } else { > > + }else { > > pdu = (unsigned char *) malloc(pdu_len_128bit_uuid); > > len = pdu_len_128bit_uuid; > > } > > diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h index > > f5d5169ce..50859ce52 100644 > > --- a/src/shared/gatt-client.h > > +++ b/src/shared/gatt-client.h > > @@ -97,6 +97,11 @@ unsigned int bt_gatt_client_char_by_uuid(struct > bt_gatt_client *client, > > bt_gatt_client_read_callback_t callback, > > void *user_data, > > bt_gatt_client_destroy_func_t > > destroy); > > +unsigned int bt_gatt_client_char_read_by_uuid(struct bt_gatt_client > *client, > > + char *uuid, > > + bt_gatt_client_read_callback_t callback, > > + void *user_data, > > + bt_gatt_client_destroy_func_t > > +destroy); > > unsigned int bt_gatt_client_read_value(struct bt_gatt_client *client, > > uint16_t value_handle, > > bt_gatt_client_read_callback_t > > callback, > > -- > > 2.17.1 > > > > > -- > Luiz Augusto von Dentz
diff --git a/client/gatt.c b/client/gatt.c index 53f875050..8c2844ed6 100644 --- a/client/gatt.c +++ b/client/gatt.c @@ -681,6 +681,76 @@ void gatt_read_attribute(GDBusProxy *proxy, int argc, char *argv[]) return bt_shell_noninteractive_quit(EXIT_FAILURE); } +static void charreadbyuuid_reply(DBusMessage *message, void *user_data) +{ + DBusError error; + DBusMessageIter iter, array; + uint8_t *value; + int len; + + dbus_error_init(&error); + + if (dbus_set_error_from_message(&error, message) == TRUE) { + bt_shell_printf("Failed to read: %s\n", error.name); + dbus_error_free(&error); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + + dbus_message_iter_init(message, &iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) { + bt_shell_printf("Invalid response to read\n"); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + + dbus_message_iter_recurse(&iter, &array); + dbus_message_iter_get_fixed_array(&array, &value, &len); + + if (len < 0) { + bt_shell_printf("Unable to parse value\n"); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + + bt_shell_hexdump(value, len); + + return bt_shell_noninteractive_quit(EXIT_SUCCESS); +} + +static void charreadbyuuid_setup(DBusMessageIter *iter, void *user_data) +{ + char *uuid = user_data; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid); +} + +static void charreadbyuuid_attribute(GDBusProxy *proxy, char *uuid) +{ + if (g_dbus_proxy_method_call(proxy, "CharReadByUUID", charreadbyuuid_setup, charreadbyuuid_reply, + uuid, NULL) == FALSE) { + bt_shell_printf("Failed to set uuid\n"); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + + bt_shell_printf("Attempting to read service handle %s\n", g_dbus_proxy_get_path(proxy)); +} + +void gatt_charreadbyuuid_attribute(GDBusProxy *proxy, int argc, char *argv[]) +{ + const char *iface; + + iface = g_dbus_proxy_get_interface(proxy); + + if (!strcmp(iface, "org.bluez.GattCharacteristic1")) { + charreadbyuuid_attribute(proxy, argv[1]); + return; + } + + bt_shell_printf("Unable to read attribute %s\n", + g_dbus_proxy_get_path(proxy)); + + return bt_shell_noninteractive_quit(EXIT_FAILURE); +} + static void charbyuuid_reply(DBusMessage *message, void *user_data) { DBusError error; diff --git a/client/gatt.h b/client/gatt.h index 692fb5758..8f96d8665 100644 --- a/client/gatt.h +++ b/client/gatt.h @@ -35,6 +35,7 @@ GDBusProxy *gatt_select_attribute(GDBusProxy *parent, const char *path); char *gatt_attribute_generator(const char *text, int state); void gatt_servbyuuid_attribute(GDBusProxy *proxy, int argc, char *argv[]); void gatt_charbyuuid_attribute(GDBusProxy *proxy, int argc, char *argv[]); +void gatt_charreadbyuuid_attribute(GDBusProxy *proxy, int argc, char *argv[]); void gatt_read_attribute(GDBusProxy *proxy, int argc, char *argv[]); void gatt_write_attribute(GDBusProxy *proxy, int argc, char *argv[]); void gatt_notify_attribute(GDBusProxy *proxy, bool enable); diff --git a/client/main.c b/client/main.c index 10e64e17b..4dd1e593a 100644 --- a/client/main.c +++ b/client/main.c @@ -2071,6 +2071,22 @@ static void cmd_attribute_info(int argc, char *argv[]) return bt_shell_noninteractive_quit(EXIT_SUCCESS); } +static void cmd_char_read_by_uuid(int argc, char *argv[]) +{ + GDBusProxy *proxy; + + proxy = find_attribute(argc, argv); + + set_default_attribute(proxy); + + if (!default_attr) { + bt_shell_printf("No attribute selected\n"); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + + gatt_charreadbyuuid_attribute(default_attr, argc, argv); +} + static void cmd_char_by_uuid(int argc, char *argv[]) { GDBusProxy *proxy; @@ -2718,6 +2734,8 @@ static const struct bt_shell_menu gatt_menu = { "Discover Primary Services by UUID" }, { "char-by-uuid", "[UUID]", cmd_char_by_uuid, "Discover Characteristic Services by UUID" }, + { "char-read-by-uuid", "[UUID]", cmd_char_read_by_uuid, + "Read Characteristic by UUID" }, { "select-attribute", "<attribute/UUID>", cmd_select_attribute, "Select attribute", attribute_generator }, { "attribute-info", "[attribute/UUID]", cmd_attribute_info, diff --git a/src/gatt-client.c b/src/gatt-client.c index da811ea4f..cd6d6dfde 100644 --- a/src/gatt-client.c +++ b/src/gatt-client.c @@ -444,6 +444,27 @@ static struct async_dbus_op *async_dbus_op_new(DBusMessage *msg, void *data) return op; } +static struct async_dbus_op *fetch_char_read_by_uuid(struct bt_gatt_client *gatt, + DBusMessage *msg, + char *uuid, + bt_gatt_client_char_by_uuid_callback_t callback, + void *data) +{ + struct async_dbus_op *op; + + op = async_dbus_op_new(msg, data); + op->id = bt_gatt_client_char_read_by_uuid(gatt, uuid, callback, + async_dbus_op_ref(op), + async_dbus_op_unref); + + if (op->id) + return op; + + async_dbus_op_free(op); + + return NULL; +} + static struct async_dbus_op *fetch_char_by_uuid(struct bt_gatt_client *gatt, DBusMessage *msg, char *uuid, @@ -972,6 +993,52 @@ fail: chrc->read_op = NULL; } +static void char_read_by_uuid_cb(bool success, uint8_t att_ecode, const uint8_t *value, + uint16_t length, void *user_data) +{ + struct async_dbus_op *op = user_data; + struct characteristic *opchar = op->data; + + if (!success) + goto fail; + + async_dbus_op_reply(op, att_ecode, value, length); + + return; + +fail: + async_dbus_op_reply(op, att_ecode, NULL, 0); + + opchar->type_op = NULL; +} + +static DBusMessage *char_read_by_uuid(DBusConnection *conn, + DBusMessage *msg, void *user_data) +{ + struct characteristic *chardata = user_data; + struct bt_gatt_client *gatt = chardata->service->client->gatt; + DBusMessageIter iter; + + char *uuid = 0; + + if (!gatt) + return btd_error_failed(msg, "Not connected"); + + dbus_message_iter_init(msg, &iter); + + if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) + dbus_message_iter_get_basic(&iter,&uuid); + else + return NULL; + + chardata->type_op = fetch_char_read_by_uuid(gatt, msg,uuid, char_read_by_uuid_cb, chardata); + + if (!chardata->type_op) + return btd_error_failed(msg, "Failed to send read request"); + + return NULL; +} + static void characteristic_by_uuid_cb(bool success, uint8_t att_ecode, const uint8_t *value, uint16_t length, void *user_data) { @@ -1786,6 +1853,9 @@ static const GDBusMethodTable characteristic_methods[] = { { GDBUS_ASYNC_METHOD("CharByUUID", GDBUS_ARGS({ "options", "s" }), GDBUS_ARGS({ "value", "ay" }), chardiscover_by_uuid) }, + { GDBUS_ASYNC_METHOD("CharReadByUUID", GDBUS_ARGS({ "options", "s" }), + GDBUS_ARGS({ "value", "ay" }), + char_read_by_uuid) }, { GDBUS_ASYNC_METHOD("ReadValue", GDBUS_ARGS({ "options", "a{sv}" }), GDBUS_ARGS({ "value", "ay" }), characteristic_read_value) }, diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c index 8a696c77f..7c9d25ec3 100644 --- a/src/shared/gatt-client.c +++ b/src/shared/gatt-client.c @@ -2725,6 +2725,90 @@ done: op->callback(success, att_ecode, value, length, op->user_data); } +unsigned int bt_gatt_client_char_read_by_uuid(struct bt_gatt_client *client, + char *uuid, + bt_gatt_client_char_by_uuid_callback_t callback, + void *user_data, + bt_gatt_client_destroy_func_t destroy) +{ + struct request *req; + struct char_by_uuid_op *op; + unsigned char *pdu; + uint16_t len ; + uint16_t start_handle = 0x0001; + uint16_t end_handle = 0xffff; + bt_uuid_t btuuid; + uint8_t uuid128[16]; + + /* Length of pdu will be vary according to uuid type + for 2 byte uuid total length is 8 (start handle(2) + end handle(2) + uuid(2)) + for 16 byte uuid total length is 22 (start handle(2) + end handle(2) + uuid(16)) + */ + uint16_t pdu_len_16bit_uuid = 6; + uint16_t pdu_len_128bit_uuid = 20; + + if (bt_string_to_uuid(&btuuid, uuid) < 0) { + return 0; + } + + if (btuuid.type == BT_UUID16){ + pdu = (unsigned char *) malloc(pdu_len_16bit_uuid); + len = pdu_len_16bit_uuid; + } else { + pdu = (unsigned char *) malloc(pdu_len_128bit_uuid); + len = pdu_len_128bit_uuid; + } + + if (!client) + return 0; + + op = new0(struct char_by_uuid_op, 1); + req = request_create(client); + if (!req) { + free(op); + return 0; + } + if (!client) + return 0; + + op = new0(struct char_by_uuid_op, 1); + req = request_create(client); + + if (!req) { + free(op); + return 0; + } + + op->callback = callback; + op->user_data = user_data; + op->destroy = destroy; + req->data = op; + req->destroy = destroy_char_by_uuid_op; + + put_le16(start_handle, pdu); + put_le16(end_handle, pdu+2); + + if (btuuid.type == BT_UUID16) + put_le16(btuuid.value.u16, pdu+4); + else { + bswap_128(&btuuid.value.u128.data[0], &uuid128[0]); + memcpy(pdu + 4, uuid128, 16); + } + + req->att_id = bt_att_send(client->att, BT_ATT_OP_READ_BY_TYPE_REQ, + pdu, len, + char_by_uuid_cb, req, + request_unref); + + if (!req->att_id) { + op->destroy = NULL; + request_unref(req); + return 0; + } + + return req->id; +} + unsigned int bt_gatt_client_char_by_uuid(struct bt_gatt_client *client, char *uuid, bt_gatt_client_char_by_uuid_callback_t callback, @@ -2754,7 +2838,7 @@ unsigned int bt_gatt_client_char_by_uuid(struct bt_gatt_client *client, if (btuuid.type == BT_UUID16){ pdu = (unsigned char *) malloc(pdu_len_16bit_uuid); len = pdu_len_16bit_uuid; - } else { + }else { pdu = (unsigned char *) malloc(pdu_len_128bit_uuid); len = pdu_len_128bit_uuid; } diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h index f5d5169ce..50859ce52 100644 --- a/src/shared/gatt-client.h +++ b/src/shared/gatt-client.h @@ -97,6 +97,11 @@ unsigned int bt_gatt_client_char_by_uuid(struct bt_gatt_client *client, bt_gatt_client_read_callback_t callback, void *user_data, bt_gatt_client_destroy_func_t destroy); +unsigned int bt_gatt_client_char_read_by_uuid(struct bt_gatt_client *client, + char *uuid, + bt_gatt_client_read_callback_t callback, + void *user_data, + bt_gatt_client_destroy_func_t destroy); unsigned int bt_gatt_client_read_value(struct bt_gatt_client *client, uint16_t value_handle, bt_gatt_client_read_callback_t callback,