3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2014 Google Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 #include "src/shared/queue.h"
30 #include "src/shared/att.h"
31 #include "lib/bluetooth.h"
33 #include "src/shared/gatt-helpers.h"
34 #include "src/shared/util.h"
37 #define MIN(a, b) ((a) < (b) ? (a) : (b))
40 struct bt_gatt_result {
46 void *op; /* Discovery operation data */
48 struct bt_gatt_result *next;
51 static struct bt_gatt_result *result_create(uint8_t opcode, const void *pdu,
56 struct bt_gatt_result *result;
58 result = new0(struct bt_gatt_result, 1);
59 result->pdu = malloc(pdu_len);
65 result->opcode = opcode;
66 result->pdu_len = pdu_len;
67 result->data_len = data_len;
70 memcpy(result->pdu, pdu, pdu_len);
75 static void result_destroy(struct bt_gatt_result *result)
77 struct bt_gatt_result *next;
89 static unsigned int result_element_count(struct bt_gatt_result *result)
91 unsigned int count = 0;
92 struct bt_gatt_result *cur;
97 count += cur->pdu_len / cur->data_len;
104 unsigned int bt_gatt_result_service_count(struct bt_gatt_result *result)
109 if (result->opcode != BT_ATT_OP_READ_BY_GRP_TYPE_RSP &&
110 result->opcode != BT_ATT_OP_FIND_BY_TYPE_RSP)
113 return result_element_count(result);
116 unsigned int bt_gatt_result_characteristic_count(struct bt_gatt_result *result)
121 if (result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
125 * Data length contains 7 or 21 octets:
126 * 2 octets: Attribute handle
127 * 1 octet: Characteristic properties
128 * 2 octets: Characteristic value handle
129 * 2 or 16 octets: characteristic UUID
131 if (result->data_len != 21 && result->data_len != 7)
134 return result_element_count(result);
137 unsigned int bt_gatt_result_descriptor_count(struct bt_gatt_result *result)
142 if (result->opcode != BT_ATT_OP_FIND_INFO_RSP)
145 return result_element_count(result);
148 unsigned int bt_gatt_result_included_count(struct bt_gatt_result *result)
150 struct bt_gatt_result *cur;
151 unsigned int count = 0;
156 if (result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
160 * Data length can be of length 6 or 8 octets:
161 * 2 octets - include service handle
162 * 2 octets - start handle of included service
163 * 2 octets - end handle of included service
164 * 2 octets (optionally) - 16 bit Bluetooth UUID
166 if (result->data_len != 6 && result->data_len != 8)
169 for (cur = result; cur; cur = cur->next)
170 if (cur->opcode == BT_ATT_OP_READ_BY_TYPE_RSP)
171 count += cur->pdu_len / cur->data_len;
176 bool bt_gatt_iter_init(struct bt_gatt_iter *iter, struct bt_gatt_result *result)
178 if (!iter || !result)
181 iter->result = result;
187 static const uint8_t bt_base_uuid[16] = {
188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
189 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
192 static bool convert_uuid_le(const uint8_t *src, size_t len, uint8_t dst[16])
202 memcpy(dst, bt_base_uuid, sizeof(bt_base_uuid));
209 struct bt_gatt_request {
212 uint16_t start_handle;
216 uint16_t service_type;
217 struct bt_gatt_result *result_head;
218 struct bt_gatt_result *result_tail;
219 bt_gatt_request_callback_t callback;
221 bt_gatt_destroy_func_t destroy;
224 static struct bt_gatt_result *result_append(uint8_t opcode, const void *pdu,
227 struct bt_gatt_request *op)
229 struct bt_gatt_result *result;
231 result = result_create(opcode, pdu, pdu_len, data_len, op);
235 if (!op->result_head)
236 op->result_head = op->result_tail = result;
238 op->result_tail->next = result;
239 op->result_tail = result;
245 bool bt_gatt_iter_next_included_service(struct bt_gatt_iter *iter,
246 uint16_t *handle, uint16_t *start_handle,
247 uint16_t *end_handle, uint8_t uuid[16])
249 struct bt_gatt_result *read_result;
250 struct bt_gatt_request *op;
254 if (!iter || !iter->result || !handle || !start_handle || !end_handle
259 if (iter->result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
262 /* UUID in discovery_op is set in read_by_type and service_discovery */
263 op = iter->result->op;
264 if (op->uuid.type != BT_UUID_UNSPEC)
267 * iter->result points to READ_BY_TYPE_RSP with data length containing:
268 * 2 octets - include service handle
269 * 2 octets - start handle of included service
270 * 2 octets - end handle of included service
271 * optional 2 octets - Bluetooth UUID
273 if (iter->result->data_len != 8 && iter->result->data_len != 6)
276 pdu_ptr = iter->result->pdu + iter->pos;
278 /* This result contains 16 bit UUID */
279 if (iter->result->data_len == 8) {
280 *handle = get_le16(pdu_ptr);
281 *start_handle = get_le16(pdu_ptr + 2);
282 *end_handle = get_le16(pdu_ptr + 4);
283 convert_uuid_le(pdu_ptr + 6, 2, uuid);
285 iter->pos += iter->result->data_len;
287 if (iter->pos == iter->result->pdu_len) {
288 iter->result = iter->result->next;
295 *handle = get_le16(pdu_ptr);
296 *start_handle = get_le16(pdu_ptr + 2);
297 *end_handle = get_le16(pdu_ptr + 4);
298 read_result = iter->result;
301 * Find READ_RSP with include service UUID.
302 * If number of current data set in READ_BY_TYPE_RSP is n, then we must
303 * go to n'th PDU next to current item->result
305 for (read_result = read_result->next; read_result; i++) {
306 if (i >= (iter->pos / iter->result->data_len))
309 read_result = read_result->next;
315 convert_uuid_le(read_result->pdu, read_result->data_len, uuid);
316 iter->pos += iter->result->data_len;
317 if (iter->pos == iter->result->pdu_len) {
318 iter->result = read_result->next;
325 bool bt_gatt_iter_next_service(struct bt_gatt_iter *iter,
326 uint16_t *start_handle, uint16_t *end_handle,
329 struct bt_gatt_request *op;
333 if (!iter || !iter->result || !start_handle || !end_handle || !uuid)
336 op = iter->result->op;
337 pdu_ptr = iter->result->pdu + iter->pos;
339 switch (iter->result->opcode) {
340 case BT_ATT_OP_READ_BY_GRP_TYPE_RSP:
341 *start_handle = get_le16(pdu_ptr);
342 *end_handle = get_le16(pdu_ptr + 2);
343 convert_uuid_le(pdu_ptr + 4, iter->result->data_len - 4, uuid);
345 case BT_ATT_OP_FIND_BY_TYPE_RSP:
346 *start_handle = get_le16(pdu_ptr);
347 *end_handle = get_le16(pdu_ptr + 2);
349 bt_uuid_to_uuid128(&op->uuid, &tmp);
350 memcpy(uuid, tmp.value.u128.data, 16);
357 iter->pos += iter->result->data_len;
358 if (iter->pos == iter->result->pdu_len) {
359 iter->result = iter->result->next;
366 bool bt_gatt_iter_next_characteristic(struct bt_gatt_iter *iter,
367 uint16_t *start_handle, uint16_t *end_handle,
368 uint16_t *value_handle, uint8_t *properties,
371 struct bt_gatt_request *op;
374 if (!iter || !iter->result || !start_handle || !end_handle ||
375 !value_handle || !properties || !uuid)
378 if (iter->result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
381 /* UUID in discovery_op is set in read_by_type and service_discovery */
382 op = iter->result->op;
383 if (op->uuid.type != BT_UUID_UNSPEC)
386 * Data length contains 7 or 21 octets:
387 * 2 octets: Attribute handle
388 * 1 octet: Characteristic properties
389 * 2 octets: Characteristic value handle
390 * 2 or 16 octets: characteristic UUID
392 if (iter->result->data_len != 21 && iter->result->data_len != 7)
395 pdu_ptr = iter->result->pdu + iter->pos;
397 *start_handle = get_le16(pdu_ptr);
398 *properties = ((uint8_t *) pdu_ptr)[2];
399 *value_handle = get_le16(pdu_ptr + 3);
400 convert_uuid_le(pdu_ptr + 5, iter->result->data_len - 5, uuid);
402 iter->pos += iter->result->data_len;
403 if (iter->pos == iter->result->pdu_len) {
404 iter->result = iter->result->next;
409 *end_handle = op->end_handle;
413 *end_handle = get_le16(iter->result->pdu + iter->pos) - 1;
418 bool bt_gatt_iter_next_descriptor(struct bt_gatt_iter *iter, uint16_t *handle,
423 if (!iter || !iter->result || !handle || !uuid)
426 if (iter->result->opcode != BT_ATT_OP_FIND_INFO_RSP)
429 pdu_ptr = iter->result->pdu + iter->pos;
431 *handle = get_le16(pdu_ptr);
432 convert_uuid_le(pdu_ptr + 2, iter->result->data_len - 2, uuid);
434 iter->pos += iter->result->data_len;
435 if (iter->pos == iter->result->pdu_len) {
436 iter->result = iter->result->next;
443 bool bt_gatt_iter_next_read_by_type(struct bt_gatt_iter *iter,
444 uint16_t *handle, uint16_t *length,
445 const uint8_t **value)
447 struct bt_gatt_request *op;
450 if (!iter || !iter->result || !handle || !length || !value)
453 if (iter->result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
457 * Check if UUID is set, otherwise results can contain characteristic
458 * discovery service or included service discovery results
460 op = iter->result->op;
461 if (op->uuid.type == BT_UUID_UNSPEC)
464 pdu_ptr = iter->result->pdu + iter->pos;
466 *handle = get_le16(pdu_ptr);
467 *length = iter->result->data_len - 2;
468 *value = pdu_ptr + 2;
470 iter->pos += iter->result->data_len;
471 if (iter->pos == iter->result->pdu_len) {
472 iter->result = iter->result->next;
481 uint16_t client_rx_mtu;
482 bt_gatt_result_callback_t callback;
484 bt_gatt_destroy_func_t destroy;
487 static void destroy_mtu_op(void *user_data)
489 struct mtu_op *op = user_data;
492 op->destroy(op->user_data);
497 static uint8_t process_error(const void *pdu, uint16_t length)
499 const struct bt_att_pdu_error_rsp *error_pdu;
501 if (!pdu || length != sizeof(struct bt_att_pdu_error_rsp))
506 return error_pdu->ecode;
509 static void mtu_cb(uint8_t opcode, const void *pdu, uint16_t length,
512 struct mtu_op *op = user_data;
514 uint8_t att_ecode = 0;
515 uint16_t server_rx_mtu;
517 if (opcode == BT_ATT_OP_ERROR_RSP) {
519 att_ecode = process_error(pdu, length);
523 if (opcode != BT_ATT_OP_MTU_RSP || !pdu || length != 2) {
528 server_rx_mtu = get_le16(pdu);
529 bt_att_set_mtu(op->att, MIN(op->client_rx_mtu, server_rx_mtu));
533 op->callback(success, att_ecode, op->user_data);
536 unsigned int bt_gatt_exchange_mtu(struct bt_att *att, uint16_t client_rx_mtu,
537 bt_gatt_result_callback_t callback,
539 bt_gatt_destroy_func_t destroy)
545 if (!att || !client_rx_mtu)
548 op = new0(struct mtu_op, 1);
550 op->client_rx_mtu = client_rx_mtu;
551 op->callback = callback;
552 op->user_data = user_data;
553 op->destroy = destroy;
555 put_le16(client_rx_mtu, pdu);
557 id = bt_att_send(att, BT_ATT_OP_MTU_REQ, pdu, sizeof(pdu), mtu_cb, op,
565 static inline int get_uuid_len(const bt_uuid_t *uuid)
570 return (uuid->type == BT_UUID16) ? 2 : 16;
573 struct bt_gatt_request *bt_gatt_request_ref(struct bt_gatt_request *req)
578 __sync_fetch_and_add(&req->ref_count, 1);
583 void bt_gatt_request_unref(struct bt_gatt_request *req)
588 if (__sync_sub_and_fetch(&req->ref_count, 1))
591 bt_gatt_request_cancel(req);
594 req->destroy(req->user_data);
596 result_destroy(req->result_head);
601 void bt_gatt_request_cancel(struct bt_gatt_request *req)
609 bt_att_cancel(req->att, req->id);
613 static void async_req_unref(void *data)
615 struct bt_gatt_request *req = data;
617 bt_gatt_request_unref(req);
620 static void discovery_op_complete(struct bt_gatt_request *op, bool success,
623 /* Reset success if there is some result to report */
624 if (ecode == BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND && op->result_head)
628 op->callback(success, ecode, success ? op->result_head : NULL,
638 static void read_by_grp_type_cb(uint8_t opcode, const void *pdu,
639 uint16_t length, void *user_data)
641 struct bt_gatt_request *op = user_data;
643 uint8_t att_ecode = 0;
644 struct bt_gatt_result *cur_result;
649 if (opcode == BT_ATT_OP_ERROR_RSP) {
651 att_ecode = process_error(pdu, length);
655 /* PDU must contain at least the following (sans opcode):
656 * - Attr Data Length (1 octet)
657 * - Attr Data List (at least 6 octets):
658 * -- 2 octets: Attribute handle
659 * -- 2 octets: End group handle
660 * -- 2 or 16 octets: service UUID
662 if (opcode != BT_ATT_OP_READ_BY_GRP_TYPE_RSP || !pdu || length < 7) {
667 data_length = ((uint8_t *) pdu)[0];
668 list_length = length - 1;
670 if ((data_length != 6 && data_length != 20) ||
671 (list_length % data_length)) {
676 /* PDU is correctly formatted. Get the last end handle to process the
677 * next request and store the PDU.
679 cur_result = result_append(opcode, pdu + 1, list_length, data_length,
686 last_end = get_le16(pdu + length - data_length + 2);
689 * If last handle is lower from previous start handle then it is smth
690 * wrong. Let's stop search, otherwise we might enter infinite loop.
692 if (last_end < op->start_handle) {
697 op->start_handle = last_end + 1;
699 if (last_end < op->end_handle) {
702 put_le16(op->start_handle, pdu);
703 put_le16(op->end_handle, pdu + 2);
704 put_le16(op->service_type, pdu + 4);
706 op->id = bt_att_send(op->att, BT_ATT_OP_READ_BY_GRP_TYPE_REQ,
709 bt_gatt_request_ref(op),
718 /* Some devices incorrectly return 0xffff as the end group handle when
719 * the read-by-group-type request is performed within a smaller range.
720 * Manually set the end group handle that we report in the result to the
721 * end handle in the original request.
723 if (last_end == 0xffff && last_end != op->end_handle)
724 put_le16(op->end_handle,
725 cur_result->pdu + length - data_length + 1);
730 discovery_op_complete(op, success, att_ecode);
733 static void find_by_type_val_cb(uint8_t opcode, const void *pdu,
734 uint16_t length, void *user_data)
736 struct bt_gatt_request *op = user_data;
738 uint8_t att_ecode = 0;
741 if (opcode == BT_ATT_OP_ERROR_RSP) {
743 att_ecode = process_error(pdu, length);
747 /* PDU must contain 4 bytes and it must be a multiple of 4, where each
748 * 4 bytes contain the 16-bit attribute and group end handles.
750 if (opcode != BT_ATT_OP_FIND_BY_TYPE_RSP || !pdu || !length ||
756 if (!result_append(opcode, pdu, length, 4, op)) {
762 * Each data set contains:
763 * 2 octets with start handle
764 * 2 octets with end handle
765 * last_end is end handle of last data set
767 last_end = get_le16(pdu + length - 2);
770 * If last handle is lower from previous start handle then it is smth
771 * wrong. Let's stop search, otherwise we might enter infinite loop.
773 if (last_end < op->start_handle) {
778 op->start_handle = last_end + 1;
780 if (last_end < op->end_handle) {
781 uint8_t pdu[6 + get_uuid_len(&op->uuid)];
783 put_le16(op->start_handle, pdu);
784 put_le16(op->end_handle, pdu + 2);
785 put_le16(op->service_type, pdu + 4);
786 bt_uuid_to_le(&op->uuid, pdu + 6);
788 op->id = bt_att_send(op->att, BT_ATT_OP_FIND_BY_TYPE_REQ,
791 bt_gatt_request_ref(op),
803 discovery_op_complete(op, success, att_ecode);
806 static struct bt_gatt_request *discover_services(struct bt_att *att,
808 uint16_t start, uint16_t end,
809 bt_gatt_request_callback_t callback,
811 bt_gatt_destroy_func_t destroy,
814 struct bt_gatt_request *op;
819 op = new0(struct bt_gatt_request, 1);
821 op->start_handle = start;
822 op->end_handle = end;
823 op->callback = callback;
824 op->user_data = user_data;
825 op->destroy = destroy;
826 /* set service uuid to primary or secondary */
827 op->service_type = primary ? GATT_PRIM_SVC_UUID : GATT_SND_SVC_UUID;
829 /* If UUID is NULL, then discover all primary services */
833 put_le16(start, pdu);
834 put_le16(end, pdu + 2);
835 put_le16(op->service_type, pdu + 4);
837 op->id = bt_att_send(att, BT_ATT_OP_READ_BY_GRP_TYPE_REQ,
840 bt_gatt_request_ref(op),
843 uint8_t pdu[6 + get_uuid_len(uuid)];
845 if (uuid->type == BT_UUID_UNSPEC) {
850 /* Discover by UUID */
853 put_le16(start, pdu);
854 put_le16(end, pdu + 2);
855 put_le16(op->service_type, pdu + 4);
856 bt_uuid_to_le(&op->uuid, pdu + 6);
858 op->id = bt_att_send(att, BT_ATT_OP_FIND_BY_TYPE_REQ,
861 bt_gatt_request_ref(op),
870 return bt_gatt_request_ref(op);
873 struct bt_gatt_request *bt_gatt_discover_all_primary_services(
874 struct bt_att *att, bt_uuid_t *uuid,
875 bt_gatt_request_callback_t callback,
877 bt_gatt_destroy_func_t destroy)
879 return bt_gatt_discover_primary_services(att, uuid, 0x0001, 0xffff,
884 struct bt_gatt_request *bt_gatt_discover_primary_services(
885 struct bt_att *att, bt_uuid_t *uuid,
886 uint16_t start, uint16_t end,
887 bt_gatt_request_callback_t callback,
889 bt_gatt_destroy_func_t destroy)
891 return discover_services(att, uuid, start, end, callback, user_data,
895 struct bt_gatt_request *bt_gatt_discover_secondary_services(
896 struct bt_att *att, bt_uuid_t *uuid,
897 uint16_t start, uint16_t end,
898 bt_gatt_request_callback_t callback,
900 bt_gatt_destroy_func_t destroy)
902 return discover_services(att, uuid, start, end, callback, user_data,
906 struct read_incl_data {
907 struct bt_gatt_request *op;
908 struct bt_gatt_result *result;
913 static struct read_incl_data *new_read_included(struct bt_gatt_result *res)
915 struct read_incl_data *data;
917 data = new0(struct read_incl_data, 1);
918 data->op = bt_gatt_request_ref(res->op);
924 static struct read_incl_data *read_included_ref(struct read_incl_data *data)
926 __sync_fetch_and_add(&data->ref_count, 1);
931 static void read_included_unref(void *data)
933 struct read_incl_data *read_data = data;
935 if (__sync_sub_and_fetch(&read_data->ref_count, 1))
938 async_req_unref(read_data->op);
943 static void discover_included_cb(uint8_t opcode, const void *pdu,
944 uint16_t length, void *user_data);
946 static void read_included_cb(uint8_t opcode, const void *pdu,
947 uint16_t length, void *user_data)
949 struct read_incl_data *data = user_data;
950 struct bt_gatt_request *op = data->op;
951 uint8_t att_ecode = 0;
955 if (opcode == BT_ATT_OP_ERROR_RSP) {
957 att_ecode = process_error(pdu, length);
961 if (opcode != BT_ATT_OP_READ_RSP || (!pdu && length)) {
967 * UUID should be in 128 bit format, as it couldn't be read in
968 * READ_BY_TYPE request
975 if (!result_append(opcode, pdu, length, length, op)) {
980 if (data->pos == data->result->pdu_len) {
981 uint16_t last_handle;
984 last_handle = get_le16(data->result->pdu + data->pos -
985 data->result->data_len);
986 if (last_handle == op->end_handle) {
991 put_le16(last_handle + 1, pdu);
992 put_le16(op->end_handle, pdu + 2);
993 put_le16(GATT_INCLUDE_UUID, pdu + 4);
995 op->id = bt_att_send(op->att, BT_ATT_OP_READ_BY_TYPE_REQ,
997 discover_included_cb,
998 bt_gatt_request_ref(op),
1007 memcpy(read_pdu, data->result->pdu + data->pos + 2, sizeof(uint16_t));
1009 data->pos += data->result->data_len;
1011 if (bt_att_send(op->att, BT_ATT_OP_READ_REQ, read_pdu, sizeof(read_pdu),
1012 read_included_cb, read_included_ref(data),
1013 read_included_unref))
1016 read_included_unref(data);
1020 discovery_op_complete(op, success, att_ecode);
1023 static void read_included(struct read_incl_data *data)
1025 struct bt_gatt_request *op = data->op;
1028 memcpy(pdu, data->result->pdu + 2, sizeof(uint16_t));
1030 data->pos += data->result->data_len;
1032 if (bt_att_send(op->att, BT_ATT_OP_READ_REQ, pdu, sizeof(pdu),
1034 read_included_ref(data),
1035 read_included_unref))
1039 op->callback(false, 0, NULL, data->op->user_data);
1041 read_included_unref(data);
1044 static void discover_included_cb(uint8_t opcode, const void *pdu,
1045 uint16_t length, void *user_data)
1047 struct bt_gatt_request *op = user_data;
1048 struct bt_gatt_result *cur_result;
1049 uint8_t att_ecode = 0;
1050 uint16_t last_handle;
1054 if (opcode == BT_ATT_OP_ERROR_RSP) {
1055 att_ecode = process_error(pdu, length);
1060 if (opcode != BT_ATT_OP_READ_BY_TYPE_RSP || !pdu || length < 6) {
1065 data_length = ((const uint8_t *) pdu)[0];
1068 * Check if PDU contains data sets with length declared in the beginning
1069 * of frame and if this length is correct.
1070 * Data set length may be 6 or 8 octets:
1071 * 2 octets - include service handle
1072 * 2 octets - start handle of included service
1073 * 2 octets - end handle of included service
1074 * optional 2 octets - Bluetooth UUID of included service
1076 if ((data_length != 8 && data_length != 6) ||
1077 (length - 1) % data_length) {
1082 cur_result = result_append(opcode, pdu + 1, length - 1, data_length,
1089 if (data_length == 6) {
1090 struct read_incl_data *data;
1092 data = new_read_included(cur_result);
1098 read_included(data);
1102 last_handle = get_le16(pdu + length - data_length);
1105 * If last handle is lower from previous start handle then it is smth
1106 * wrong. Let's stop search, otherwise we might enter infinite loop.
1108 if (last_handle < op->start_handle) {
1113 op->start_handle = last_handle + 1;
1114 if (last_handle != op->end_handle) {
1117 put_le16(op->start_handle, pdu);
1118 put_le16(op->end_handle, pdu + 2);
1119 put_le16(GATT_INCLUDE_UUID, pdu + 4);
1121 op->id = bt_att_send(op->att, BT_ATT_OP_READ_BY_TYPE_REQ,
1123 discover_included_cb,
1124 bt_gatt_request_ref(op),
1136 discovery_op_complete(op, success, att_ecode);
1139 struct bt_gatt_request *bt_gatt_discover_included_services(struct bt_att *att,
1140 uint16_t start, uint16_t end,
1141 bt_gatt_request_callback_t callback,
1143 bt_gatt_destroy_func_t destroy)
1145 struct bt_gatt_request *op;
1151 op = new0(struct bt_gatt_request, 1);
1153 op->callback = callback;
1154 op->user_data = user_data;
1155 op->destroy = destroy;
1156 op->start_handle = start;
1157 op->end_handle = end;
1159 put_le16(start, pdu);
1160 put_le16(end, pdu + 2);
1161 put_le16(GATT_INCLUDE_UUID, pdu + 4);
1163 op->id = bt_att_send(att, BT_ATT_OP_READ_BY_TYPE_REQ, pdu, sizeof(pdu),
1164 discover_included_cb, bt_gatt_request_ref(op),
1171 return bt_gatt_request_ref(op);
1174 static void discover_chrcs_cb(uint8_t opcode, const void *pdu,
1175 uint16_t length, void *user_data)
1177 struct bt_gatt_request *op = user_data;
1179 uint8_t att_ecode = 0;
1181 uint16_t last_handle;
1183 if (opcode == BT_ATT_OP_ERROR_RSP) {
1185 att_ecode = process_error(pdu, length);
1189 /* PDU must contain at least the following (sans opcode):
1190 * - Attr Data Length (1 octet)
1191 * - Attr Data List (at least 7 octets):
1192 * -- 2 octets: Attribute handle
1193 * -- 1 octet: Characteristic properties
1194 * -- 2 octets: Characteristic value handle
1195 * -- 2 or 16 octets: characteristic UUID
1197 if (opcode != BT_ATT_OP_READ_BY_TYPE_RSP || !pdu || length < 8) {
1202 data_length = ((uint8_t *) pdu)[0];
1204 if ((data_length != 7 && data_length != 21) ||
1205 ((length - 1) % data_length)) {
1210 if (!result_append(opcode, pdu + 1, length - 1,
1215 last_handle = get_le16(pdu + length - data_length);
1218 * If last handle is lower from previous start handle then it is smth
1219 * wrong. Let's stop search, otherwise we might enter infinite loop.
1221 if (last_handle < op->start_handle) {
1226 op->start_handle = last_handle + 1;
1228 if (last_handle != op->end_handle) {
1231 put_le16(op->start_handle, pdu);
1232 put_le16(op->end_handle, pdu + 2);
1233 put_le16(GATT_CHARAC_UUID, pdu + 4);
1235 op->id = bt_att_send(op->att, BT_ATT_OP_READ_BY_TYPE_REQ,
1238 bt_gatt_request_ref(op),
1250 discovery_op_complete(op, success, att_ecode);
1253 struct bt_gatt_request *bt_gatt_discover_characteristics(struct bt_att *att,
1254 uint16_t start, uint16_t end,
1255 bt_gatt_request_callback_t callback,
1257 bt_gatt_destroy_func_t destroy)
1259 struct bt_gatt_request *op;
1265 op = new0(struct bt_gatt_request, 1);
1267 op->callback = callback;
1268 op->user_data = user_data;
1269 op->destroy = destroy;
1270 op->start_handle = start;
1271 op->end_handle = end;
1273 put_le16(start, pdu);
1274 put_le16(end, pdu + 2);
1275 put_le16(GATT_CHARAC_UUID, pdu + 4);
1277 op->id = bt_att_send(att, BT_ATT_OP_READ_BY_TYPE_REQ, pdu, sizeof(pdu),
1278 discover_chrcs_cb, bt_gatt_request_ref(op),
1285 return bt_gatt_request_ref(op);
1288 static void read_by_type_cb(uint8_t opcode, const void *pdu,
1289 uint16_t length, void *user_data)
1291 struct bt_gatt_request *op = user_data;
1293 uint8_t att_ecode = 0;
1295 uint16_t last_handle;
1297 if (opcode == BT_ATT_OP_ERROR_RSP) {
1298 att_ecode = process_error(pdu, length);
1303 if (opcode != BT_ATT_OP_READ_BY_TYPE_RSP || !pdu) {
1309 data_length = ((uint8_t *) pdu)[0];
1310 if (((length - 1) % data_length)) {
1316 if (!result_append(opcode, pdu + 1, length - 1, data_length, op)) {
1322 last_handle = get_le16(pdu + length - data_length);
1325 * If last handle is lower from previous start handle then it is smth
1326 * wrong. Let's stop search, otherwise we might enter infinite loop.
1328 if (last_handle < op->start_handle) {
1333 op->start_handle = last_handle + 1;
1335 if (last_handle != op->end_handle) {
1336 uint8_t pdu[4 + get_uuid_len(&op->uuid)];
1338 put_le16(op->start_handle, pdu);
1339 put_le16(op->end_handle, pdu + 2);
1340 bt_uuid_to_le(&op->uuid, pdu + 4);
1342 op->id = bt_att_send(op->att, BT_ATT_OP_READ_BY_TYPE_REQ,
1345 bt_gatt_request_ref(op),
1357 discovery_op_complete(op, success, att_ecode);
1360 bool bt_gatt_read_by_type(struct bt_att *att, uint16_t start, uint16_t end,
1361 const bt_uuid_t *uuid,
1362 bt_gatt_request_callback_t callback,
1364 bt_gatt_destroy_func_t destroy)
1366 struct bt_gatt_request *op;
1367 uint8_t pdu[4 + get_uuid_len(uuid)];
1369 if (!att || !uuid || uuid->type == BT_UUID_UNSPEC)
1372 op = new0(struct bt_gatt_request, 1);
1374 op->callback = callback;
1375 op->user_data = user_data;
1376 op->destroy = destroy;
1377 op->start_handle = start;
1378 op->end_handle = end;
1381 put_le16(start, pdu);
1382 put_le16(end, pdu + 2);
1383 bt_uuid_to_le(uuid, pdu + 4);
1385 op->id = bt_att_send(att, BT_ATT_OP_READ_BY_TYPE_REQ, pdu, sizeof(pdu),
1387 bt_gatt_request_ref(op),
1396 static void discover_descs_cb(uint8_t opcode, const void *pdu,
1397 uint16_t length, void *user_data)
1399 struct bt_gatt_request *op = user_data;
1401 uint8_t att_ecode = 0;
1403 uint16_t last_handle;
1406 if (opcode == BT_ATT_OP_ERROR_RSP) {
1408 att_ecode = process_error(pdu, length);
1412 /* The PDU should contain the following data (sans opcode):
1413 * - Format (1 octet)
1414 * - Attr Data List (at least 4 octets):
1415 * -- 2 octets: Attribute handle
1416 * -- 2 or 16 octets: UUID.
1418 if (opcode != BT_ATT_OP_FIND_INFO_RSP || !pdu || length < 5) {
1423 format = ((uint8_t *) pdu)[0];
1427 else if (format == 0x02)
1434 if ((length - 1) % data_length) {
1439 if (!result_append(opcode, pdu + 1, length - 1, data_length, op)) {
1444 last_handle = get_le16(pdu + length - data_length);
1447 * If last handle is lower from previous start handle then it is smth
1448 * wrong. Let's stop search, otherwise we might enter infinite loop.
1450 if (last_handle < op->start_handle) {
1455 op->start_handle = last_handle + 1;
1457 if (last_handle != op->end_handle) {
1460 put_le16(op->start_handle, pdu);
1461 put_le16(op->end_handle, pdu + 2);
1463 op->id = bt_att_send(op->att, BT_ATT_OP_FIND_INFO_REQ,
1466 bt_gatt_request_ref(op),
1478 discovery_op_complete(op, success, att_ecode);
1481 struct bt_gatt_request *bt_gatt_discover_descriptors(struct bt_att *att,
1482 uint16_t start, uint16_t end,
1483 bt_gatt_request_callback_t callback,
1485 bt_gatt_destroy_func_t destroy)
1487 struct bt_gatt_request *op;
1493 op = new0(struct bt_gatt_request, 1);
1495 op->callback = callback;
1496 op->user_data = user_data;
1497 op->destroy = destroy;
1498 op->start_handle = start;
1499 op->end_handle = end;
1501 put_le16(start, pdu);
1502 put_le16(end, pdu + 2);
1504 op->id = bt_att_send(att, BT_ATT_OP_FIND_INFO_REQ, pdu, sizeof(pdu),
1506 bt_gatt_request_ref(op),
1513 return bt_gatt_request_ref(op);