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
31 #include "src/shared/att.h"
32 #include "lib/bluetooth.h"
34 #include "src/shared/queue.h"
35 #include "src/shared/gatt-db.h"
36 #include "src/shared/gatt-server.h"
37 #include "src/shared/gatt-helpers.h"
38 #include "src/shared/util.h"
41 #define MAX(a, b) ((a) > (b) ? (a) : (b))
45 #define MIN(a, b) ((a) < (b) ? (a) : (b))
49 * TODO: This is an arbitrary limit. Come up with something reasonable or
50 * perhaps an API to set this value if there is a use case for it.
52 #define DEFAULT_MAX_PREP_QUEUE_LEN 30
54 struct async_read_op {
55 struct bt_gatt_server *server;
61 struct queue *db_data;
64 struct async_write_op {
65 struct bt_gatt_server *server;
69 struct prep_write_data {
70 struct bt_gatt_server *server;
77 static void prep_write_data_destroy(void *user_data)
79 struct prep_write_data *data = user_data;
85 struct bt_gatt_server {
92 unsigned int read_by_grp_type_id;
93 unsigned int read_by_type_id;
94 unsigned int find_info_id;
95 unsigned int find_by_type_value_id;
96 unsigned int write_id;
97 unsigned int write_cmd_id;
99 unsigned int read_blob_id;
100 unsigned int read_multiple_id;
101 unsigned int prep_write_id;
102 unsigned int exec_write_id;
104 struct queue *prep_queue;
105 unsigned int max_prep_queue_len;
107 struct async_read_op *pending_read_op;
108 struct async_write_op *pending_write_op;
110 bt_gatt_server_debug_func_t debug_callback;
111 bt_gatt_server_destroy_func_t debug_destroy;
115 static void bt_gatt_server_free(struct bt_gatt_server *server)
117 if (server->debug_destroy)
118 server->debug_destroy(server->debug_data);
120 bt_att_unregister(server->att, server->mtu_id);
121 bt_att_unregister(server->att, server->read_by_grp_type_id);
122 bt_att_unregister(server->att, server->read_by_type_id);
123 bt_att_unregister(server->att, server->find_info_id);
124 bt_att_unregister(server->att, server->find_by_type_value_id);
125 bt_att_unregister(server->att, server->write_id);
126 bt_att_unregister(server->att, server->write_cmd_id);
127 bt_att_unregister(server->att, server->read_id);
128 bt_att_unregister(server->att, server->read_blob_id);
129 bt_att_unregister(server->att, server->read_multiple_id);
130 bt_att_unregister(server->att, server->prep_write_id);
131 bt_att_unregister(server->att, server->exec_write_id);
133 if (server->pending_read_op)
134 server->pending_read_op->server = NULL;
136 if (server->pending_write_op)
137 server->pending_write_op->server = NULL;
139 queue_destroy(server->prep_queue, prep_write_data_destroy);
141 gatt_db_unref(server->db);
142 bt_att_unref(server->att);
146 static bool get_uuid_le(const uint8_t *uuid, size_t len, bt_uuid_t *out_uuid)
152 bt_uuid16_create(out_uuid, get_le16(uuid));
155 bswap_128(uuid, &u128.data);
156 bt_uuid128_create(out_uuid, u128);
165 static void attribute_read_cb(struct gatt_db_attribute *attrib, int err,
166 const uint8_t *value, size_t length,
169 struct iovec *iov = user_data;
171 iov->iov_base = (void *) value;
172 iov->iov_len = length;
175 static bool encode_read_by_grp_type_rsp(struct gatt_db *db, struct queue *q,
177 uint16_t mtu, uint8_t *pdu,
181 uint16_t start_handle, end_handle;
183 uint8_t data_val_len;
187 while (queue_peek_head(q)) {
188 struct gatt_db_attribute *attrib = queue_pop_head(q);
190 value.iov_base = NULL;
194 * This should never be deferred to the read callback for
195 * primary/secondary service declarations.
197 if (!gatt_db_attribute_read(attrib, 0,
198 BT_ATT_OP_READ_BY_GRP_TYPE_REQ,
199 att, attribute_read_cb,
200 &value) || !value.iov_len)
204 * Use the first attribute to determine the length of each
205 * attribute data unit. Stop the list when a different attribute
209 data_val_len = MIN(MIN((unsigned)mtu - 6, 251),
211 pdu[0] = data_val_len + 4;
213 } else if (value.iov_len != data_val_len)
216 /* Stop if this unit would surpass the MTU */
217 if (iter + data_val_len + 4 > mtu - 1)
220 gatt_db_attribute_get_service_handles(attrib, &start_handle,
223 put_le16(start_handle, pdu + iter);
224 put_le16(end_handle, pdu + iter + 2);
225 memcpy(pdu + iter + 4, value.iov_base, data_val_len);
227 iter += data_val_len + 4;
235 static void read_by_grp_type_cb(uint8_t opcode, const void *pdu,
236 uint16_t length, void *user_data)
238 struct bt_gatt_server *server = user_data;
242 uint16_t mtu = bt_att_get_mtu(server->att);
243 uint8_t rsp_pdu[mtu];
246 uint16_t ehandle = 0;
247 struct queue *q = NULL;
249 if (length != 6 && length != 20) {
250 ecode = BT_ATT_ERROR_INVALID_PDU;
256 start = get_le16(pdu);
257 end = get_le16(pdu + 2);
258 get_uuid_le(pdu + 4, length - 4, &type);
260 util_debug(server->debug_callback, server->debug_data,
261 "Read By Grp Type - start: 0x%04x end: 0x%04x",
264 if (!start || !end) {
265 ecode = BT_ATT_ERROR_INVALID_HANDLE;
272 ecode = BT_ATT_ERROR_INVALID_HANDLE;
277 * GATT defines that only the <<Primary Service>> and
278 * <<Secondary Service>> group types can be used for the
279 * "Read By Group Type" request (Core v4.1, Vol 3, sec 2.5.3). Return an
280 * error if any other group type is given.
282 bt_uuid16_create(&prim, GATT_PRIM_SVC_UUID);
283 bt_uuid16_create(&snd, GATT_SND_SVC_UUID);
284 if (bt_uuid_cmp(&type, &prim) && bt_uuid_cmp(&type, &snd)) {
285 ecode = BT_ATT_ERROR_UNSUPPORTED_GROUP_TYPE;
289 gatt_db_read_by_group_type(server->db, start, end, type, q);
291 if (queue_isempty(q)) {
292 ecode = BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND;
296 if (!encode_read_by_grp_type_rsp(server->db, q, server->att, mtu,
297 rsp_pdu, &rsp_len)) {
298 ecode = BT_ATT_ERROR_UNLIKELY;
302 queue_destroy(q, NULL);
304 bt_att_send(server->att, BT_ATT_OP_READ_BY_GRP_TYPE_RSP,
311 queue_destroy(q, NULL);
312 bt_att_send_error_rsp(server->att, opcode, ehandle, ecode);
315 static void async_read_op_destroy(struct async_read_op *op)
318 op->server->pending_read_op = NULL;
320 queue_destroy(op->db_data, NULL);
325 static void process_read_by_type(struct async_read_op *op);
327 static void read_by_type_read_complete_cb(struct gatt_db_attribute *attr,
328 int err, const uint8_t *value,
329 size_t len, void *user_data)
331 struct async_read_op *op = user_data;
332 struct bt_gatt_server *server = op->server;
337 async_read_op_destroy(op);
341 mtu = bt_att_get_mtu(server->att);
342 handle = gatt_db_attribute_get_handle(attr);
344 /* Terminate the operation if there was an error */
346 bt_att_send_error_rsp(server->att, BT_ATT_OP_READ_BY_TYPE_REQ,
348 async_read_op_destroy(op);
352 if (op->pdu_len == 0) {
353 op->value_len = MIN(MIN((unsigned) mtu - 4, 253), len);
354 op->pdu[0] = op->value_len + 2;
356 } else if (len != op->value_len) {
361 /* Stop if this would surpass the MTU */
362 if (op->pdu_len + op->value_len + 2 > (unsigned) mtu - 1) {
367 /* Encode the current value */
368 put_le16(handle, op->pdu + op->pdu_len);
369 memcpy(op->pdu + op->pdu_len + 2, value, op->value_len);
371 op->pdu_len += op->value_len + 2;
373 if (op->pdu_len == (unsigned) mtu - 1)
377 process_read_by_type(op);
380 static uint8_t check_permissions(struct bt_gatt_server *server,
381 struct gatt_db_attribute *attr, uint32_t mask)
386 perm = gatt_db_attribute_get_permissions(attr);
388 if (perm && mask & BT_ATT_PERM_READ && !(perm & BT_ATT_PERM_READ))
389 return BT_ATT_ERROR_READ_NOT_PERMITTED;
391 if (perm && mask & BT_ATT_PERM_WRITE && !(perm & BT_ATT_PERM_WRITE))
392 return BT_ATT_ERROR_WRITE_NOT_PERMITTED;
398 security = bt_att_get_security(server->att);
399 if (perm & BT_ATT_PERM_AUTHEN && security < BT_ATT_SECURITY_HIGH)
400 return BT_ATT_ERROR_AUTHENTICATION;
402 if (perm & BT_ATT_PERM_ENCRYPT && security < BT_ATT_SECURITY_MEDIUM)
403 return BT_ATT_ERROR_INSUFFICIENT_ENCRYPTION;
408 static void process_read_by_type(struct async_read_op *op)
410 struct bt_gatt_server *server = op->server;
412 struct gatt_db_attribute *attr;
414 attr = queue_pop_head(op->db_data);
416 if (op->done || !attr) {
417 bt_att_send(server->att, BT_ATT_OP_READ_BY_TYPE_RSP, op->pdu,
421 async_read_op_destroy(op);
425 ecode = check_permissions(server, attr, BT_ATT_PERM_READ |
426 BT_ATT_PERM_READ_AUTHEN |
427 BT_ATT_PERM_READ_ENCRYPT);
431 if (gatt_db_attribute_read(attr, 0, op->opcode, server->att,
432 read_by_type_read_complete_cb, op))
435 ecode = BT_ATT_ERROR_UNLIKELY;
438 bt_att_send_error_rsp(server->att, BT_ATT_OP_READ_BY_TYPE_REQ,
439 gatt_db_attribute_get_handle(attr), ecode);
440 async_read_op_destroy(op);
443 static void read_by_type_cb(uint8_t opcode, const void *pdu,
444 uint16_t length, void *user_data)
446 struct bt_gatt_server *server = user_data;
449 uint16_t ehandle = 0;
451 struct queue *q = NULL;
452 struct async_read_op *op;
454 if (length != 6 && length != 20) {
455 ecode = BT_ATT_ERROR_INVALID_PDU;
461 start = get_le16(pdu);
462 end = get_le16(pdu + 2);
463 get_uuid_le(pdu + 4, length - 4, &type);
465 util_debug(server->debug_callback, server->debug_data,
466 "Read By Type - start: 0x%04x end: 0x%04x",
469 if (!start || !end) {
470 ecode = BT_ATT_ERROR_INVALID_HANDLE;
477 ecode = BT_ATT_ERROR_INVALID_HANDLE;
481 gatt_db_read_by_type(server->db, start, end, type, q);
483 if (queue_isempty(q)) {
484 ecode = BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND;
488 if (server->pending_read_op) {
489 ecode = BT_ATT_ERROR_UNLIKELY;
493 op = new0(struct async_read_op, 1);
494 op->pdu = malloc(bt_att_get_mtu(server->att));
497 ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
504 server->pending_read_op = op;
506 process_read_by_type(op);
511 bt_att_send_error_rsp(server->att, opcode, ehandle, ecode);
512 queue_destroy(q, NULL);
515 static bool encode_find_info_rsp(struct gatt_db *db, struct queue *q,
517 uint8_t *pdu, uint16_t *len)
520 struct gatt_db_attribute *attr;
521 const bt_uuid_t *type;
522 int uuid_len, cur_uuid_len;
527 while (queue_peek_head(q)) {
528 attr = queue_pop_head(q);
529 handle = gatt_db_attribute_get_handle(attr);
530 type = gatt_db_attribute_get_type(attr);
531 if (!handle || !type)
534 cur_uuid_len = bt_uuid_len(type);
537 switch (cur_uuid_len) {
552 } else if (cur_uuid_len != uuid_len)
555 if (iter + uuid_len + 2 > mtu - 1)
558 put_le16(handle, pdu + iter);
559 bt_uuid_to_le(type, pdu + iter + 2);
561 iter += uuid_len + 2;
569 static void find_info_cb(uint8_t opcode, const void *pdu,
570 uint16_t length, void *user_data)
572 struct bt_gatt_server *server = user_data;
574 uint16_t mtu = bt_att_get_mtu(server->att);
575 uint8_t rsp_pdu[mtu];
578 uint16_t ehandle = 0;
579 struct queue *q = NULL;
582 ecode = BT_ATT_ERROR_INVALID_PDU;
588 start = get_le16(pdu);
589 end = get_le16(pdu + 2);
591 util_debug(server->debug_callback, server->debug_data,
592 "Find Info - start: 0x%04x end: 0x%04x",
595 if (!start || !end) {
596 ecode = BT_ATT_ERROR_INVALID_HANDLE;
603 ecode = BT_ATT_ERROR_INVALID_HANDLE;
607 gatt_db_find_information(server->db, start, end, q);
609 if (queue_isempty(q)) {
610 ecode = BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND;
614 if (!encode_find_info_rsp(server->db, q, mtu, rsp_pdu, &rsp_len)) {
615 ecode = BT_ATT_ERROR_UNLIKELY;
619 bt_att_send(server->att, BT_ATT_OP_FIND_INFO_RSP, rsp_pdu, rsp_len,
621 queue_destroy(q, NULL);
626 bt_att_send_error_rsp(server->att, opcode, ehandle, ecode);
627 queue_destroy(q, NULL);
631 struct find_by_type_val_data {
638 static void find_by_type_val_att_cb(struct gatt_db_attribute *attrib,
641 uint16_t handle, end_handle;
642 struct find_by_type_val_data *data = user_data;
647 if (data->len + 4 > data->mtu - 1)
651 * This OP is only valid for Primary Service per the spec
652 * page 562, so this should work.
654 gatt_db_attribute_get_service_data(attrib, &handle, &end_handle, NULL,
657 if (!handle || !end_handle) {
658 data->ecode = BT_ATT_ERROR_UNLIKELY;
662 put_le16(handle, data->pdu + data->len);
663 put_le16(end_handle, data->pdu + data->len + 2);
668 static void find_by_type_val_cb(uint8_t opcode, const void *pdu,
669 uint16_t length, void *user_data)
671 struct bt_gatt_server *server = user_data;
672 uint16_t start, end, uuid16;
673 struct find_by_type_val_data data;
674 uint16_t mtu = bt_att_get_mtu(server->att);
675 uint8_t rsp_pdu[mtu];
676 uint16_t ehandle = 0;
680 data.ecode = BT_ATT_ERROR_INVALID_PDU;
689 start = get_le16(pdu);
690 end = get_le16(pdu + 2);
691 uuid16 = get_le16(pdu + 4);
693 util_debug(server->debug_callback, server->debug_data,
694 "Find By Type Value - start: 0x%04x end: 0x%04x uuid: 0x%04x",
698 data.ecode = BT_ATT_ERROR_INVALID_HANDLE;
702 bt_uuid16_create(&uuid, uuid16);
703 gatt_db_find_by_type_value(server->db, start, end, &uuid, pdu + 6,
705 find_by_type_val_att_cb,
709 data.ecode = BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND;
714 bt_att_send(server->att, BT_ATT_OP_FIND_BY_TYPE_RSP, data.pdu,
715 data.len, NULL, NULL, NULL);
720 bt_att_send_error_rsp(server->att, opcode, ehandle, data.ecode);
723 static void async_write_op_destroy(struct async_write_op *op)
726 op->server->pending_write_op = NULL;
731 static void write_complete_cb(struct gatt_db_attribute *attr, int err,
734 struct async_write_op *op = user_data;
735 struct bt_gatt_server *server = op->server;
738 if (!server || op->opcode == BT_ATT_OP_WRITE_CMD) {
739 async_write_op_destroy(op);
743 handle = gatt_db_attribute_get_handle(attr);
746 bt_att_send_error_rsp(server->att, op->opcode, handle, err);
748 bt_att_send(server->att, BT_ATT_OP_WRITE_RSP, NULL, 0,
751 async_write_op_destroy(op);
754 static void write_cb(uint8_t opcode, const void *pdu,
755 uint16_t length, void *user_data)
757 struct bt_gatt_server *server = user_data;
758 struct gatt_db_attribute *attr;
760 struct async_write_op *op = NULL;
764 ecode = BT_ATT_ERROR_INVALID_PDU;
768 handle = get_le16(pdu);
769 attr = gatt_db_get_attribute(server->db, handle);
771 ecode = BT_ATT_ERROR_INVALID_HANDLE;
775 util_debug(server->debug_callback, server->debug_data,
776 "Write %s - handle: 0x%04x",
777 (opcode == BT_ATT_OP_WRITE_REQ) ? "Req" : "Cmd",
780 ecode = check_permissions(server, attr, BT_ATT_PERM_WRITE |
781 BT_ATT_PERM_WRITE_AUTHEN |
782 BT_ATT_PERM_WRITE_ENCRYPT);
786 if (server->pending_write_op) {
787 #ifdef __TIZEN_PATCH__
788 if (opcode != BT_ATT_OP_WRITE_CMD) {
790 ecode = BT_ATT_ERROR_UNLIKELY;
792 #ifdef __TIZEN_PATCH__
797 op = new0(struct async_write_op, 1);
801 #ifdef __TIZEN_PATCH__
802 if (opcode != BT_ATT_OP_WRITE_CMD)
803 server->pending_write_op = op;
805 server->pending_write_op = op;
808 if (gatt_db_attribute_write(attr, 0, pdu + 2, length - 2, opcode,
810 write_complete_cb, op))
814 async_write_op_destroy(op);
816 ecode = BT_ATT_ERROR_UNLIKELY;
819 #ifdef __TIZEN_PATCH__
820 util_debug(server->debug_callback, server->debug_data,
821 "Handling \"Write %s\" is failed : %d",
822 (opcode == BT_ATT_OP_WRITE_REQ) ? "Req" : "Cmd",
826 if (opcode == BT_ATT_OP_WRITE_CMD)
829 bt_att_send_error_rsp(server->att, opcode, handle, ecode);
832 static uint8_t get_read_rsp_opcode(uint8_t opcode)
836 case BT_ATT_OP_READ_REQ:
837 return BT_ATT_OP_READ_RSP;
838 case BT_ATT_OP_READ_BLOB_REQ:
839 return BT_ATT_OP_READ_BLOB_RSP;
842 * Should never happen
844 * TODO: It would be nice to have a debug-mode assert macro
845 * for development builds. This way bugs could be easily catched
846 * during development and there would be self documenting code
847 * that wouldn't be crash release builds.
855 static void read_complete_cb(struct gatt_db_attribute *attr, int err,
856 const uint8_t *value, size_t len,
859 struct async_read_op *op = user_data;
860 struct bt_gatt_server *server = op->server;
866 async_read_op_destroy(op);
870 mtu = bt_att_get_mtu(server->att);
871 handle = gatt_db_attribute_get_handle(attr);
874 bt_att_send_error_rsp(server->att, op->opcode, handle, err);
875 async_read_op_destroy(op);
879 rsp_opcode = get_read_rsp_opcode(op->opcode);
881 bt_att_send(server->att, rsp_opcode, len ? value : NULL,
882 MIN((unsigned) mtu - 1, len),
884 async_read_op_destroy(op);
887 static void handle_read_req(struct bt_gatt_server *server, uint8_t opcode,
891 struct gatt_db_attribute *attr;
893 struct async_read_op *op = NULL;
895 attr = gatt_db_get_attribute(server->db, handle);
897 ecode = BT_ATT_ERROR_INVALID_HANDLE;
901 util_debug(server->debug_callback, server->debug_data,
902 "Read %sReq - handle: 0x%04x",
903 opcode == BT_ATT_OP_READ_BLOB_REQ ? "Blob " : "",
906 ecode = check_permissions(server, attr, BT_ATT_PERM_READ |
907 BT_ATT_PERM_READ_AUTHEN |
908 BT_ATT_PERM_READ_ENCRYPT);
912 if (server->pending_read_op) {
913 ecode = BT_ATT_ERROR_UNLIKELY;
917 op = new0(struct async_read_op, 1);
920 server->pending_read_op = op;
922 if (gatt_db_attribute_read(attr, offset, opcode, server->att,
923 read_complete_cb, op))
926 ecode = BT_ATT_ERROR_UNLIKELY;
930 async_read_op_destroy(op);
932 bt_att_send_error_rsp(server->att, opcode, handle, ecode);
935 static void read_cb(uint8_t opcode, const void *pdu,
936 uint16_t length, void *user_data)
938 struct bt_gatt_server *server = user_data;
942 bt_att_send_error_rsp(server->att, opcode, 0,
943 BT_ATT_ERROR_INVALID_PDU);
947 handle = get_le16(pdu);
949 handle_read_req(server, opcode, handle, 0);
952 static void read_blob_cb(uint8_t opcode, const void *pdu,
953 uint16_t length, void *user_data)
955 struct bt_gatt_server *server = user_data;
956 uint16_t handle, offset;
959 bt_att_send_error_rsp(server->att, opcode, 0,
960 BT_ATT_ERROR_INVALID_PDU);
964 handle = get_le16(pdu);
965 offset = get_le16(pdu + 2);
967 handle_read_req(server, opcode, handle, offset);
970 struct read_multiple_resp_data {
971 struct bt_gatt_server *server;
980 static void read_multiple_resp_data_free(struct read_multiple_resp_data *data)
983 data->handles = NULL;
985 free(data->rsp_data);
986 data->rsp_data = NULL;
989 static void read_multiple_complete_cb(struct gatt_db_attribute *attr, int err,
990 const uint8_t *value, size_t len,
993 struct read_multiple_resp_data *data = user_data;
994 struct gatt_db_attribute *next_attr;
995 uint16_t handle = gatt_db_attribute_get_handle(attr);
999 bt_att_send_error_rsp(data->server->att,
1000 BT_ATT_OP_READ_MULT_REQ, handle, err);
1001 read_multiple_resp_data_free(data);
1005 ecode = check_permissions(data->server, attr, BT_ATT_PERM_READ |
1006 BT_ATT_PERM_READ_AUTHEN |
1007 BT_ATT_PERM_READ_ENCRYPT);
1009 bt_att_send_error_rsp(data->server->att,
1010 BT_ATT_OP_READ_MULT_REQ, handle, ecode);
1011 read_multiple_resp_data_free(data);
1015 len = MIN(len, data->mtu - data->length - 1);
1017 memcpy(data->rsp_data + data->length, value, len);
1018 data->length += len;
1022 if ((data->length >= data->mtu - 1) ||
1023 (data->cur_handle == data->num_handles)) {
1024 bt_att_send(data->server->att, BT_ATT_OP_READ_MULT_RSP,
1025 data->rsp_data, data->length, NULL, NULL, NULL);
1026 read_multiple_resp_data_free(data);
1030 util_debug(data->server->debug_callback, data->server->debug_data,
1031 "Read Multiple Req - #%zu of %zu: 0x%04x",
1032 data->cur_handle + 1, data->num_handles,
1033 data->handles[data->cur_handle]);
1035 next_attr = gatt_db_get_attribute(data->server->db,
1036 data->handles[data->cur_handle]);
1039 bt_att_send_error_rsp(data->server->att,
1040 BT_ATT_OP_READ_MULT_REQ,
1041 data->handles[data->cur_handle],
1042 BT_ATT_ERROR_INVALID_HANDLE);
1043 read_multiple_resp_data_free(data);
1047 if (!gatt_db_attribute_read(next_attr, 0, BT_ATT_OP_READ_MULT_REQ,
1049 read_multiple_complete_cb, data)) {
1050 bt_att_send_error_rsp(data->server->att,
1051 BT_ATT_OP_READ_MULT_REQ,
1052 data->handles[data->cur_handle],
1053 BT_ATT_ERROR_UNLIKELY);
1054 read_multiple_resp_data_free(data);
1058 static void read_multiple_cb(uint8_t opcode, const void *pdu,
1059 uint16_t length, void *user_data)
1061 struct bt_gatt_server *server = user_data;
1062 struct gatt_db_attribute *attr;
1063 struct read_multiple_resp_data data;
1064 uint8_t ecode = BT_ATT_ERROR_UNLIKELY;
1067 data.handles = NULL;
1068 data.rsp_data = NULL;
1071 ecode = BT_ATT_ERROR_INVALID_PDU;
1075 data.server = server;
1076 data.num_handles = length / 2;
1077 data.cur_handle = 0;
1078 data.mtu = bt_att_get_mtu(server->att);
1080 data.rsp_data = malloc(data.mtu - 1);
1085 data.handles = new0(uint16_t, data.num_handles);
1087 for (i = 0; i < data.num_handles; i++)
1088 data.handles[i] = get_le16(pdu + i * 2);
1090 util_debug(server->debug_callback, server->debug_data,
1091 "Read Multiple Req - %zu handles, 1st: 0x%04x",
1092 data.num_handles, data.handles[0]);
1094 attr = gatt_db_get_attribute(server->db, data.handles[0]);
1097 ecode = BT_ATT_ERROR_INVALID_HANDLE;
1101 if (gatt_db_attribute_read(attr, 0, opcode, server->att,
1102 read_multiple_complete_cb, &data))
1106 read_multiple_resp_data_free(&data);
1107 bt_att_send_error_rsp(server->att, opcode, 0, ecode);
1110 static void prep_write_cb(uint8_t opcode, const void *pdu,
1111 uint16_t length, void *user_data)
1113 struct bt_gatt_server *server = user_data;
1114 struct prep_write_data *prep_data = NULL;
1115 uint16_t handle = 0;
1117 struct gatt_db_attribute *attr;
1121 ecode = BT_ATT_ERROR_INVALID_PDU;
1125 if (queue_length(server->prep_queue) >= server->max_prep_queue_len) {
1126 ecode = BT_ATT_ERROR_PREPARE_QUEUE_FULL;
1130 handle = get_le16(pdu);
1131 offset = get_le16(pdu + 2);
1133 attr = gatt_db_get_attribute(server->db, handle);
1135 ecode = BT_ATT_ERROR_INVALID_HANDLE;
1139 util_debug(server->debug_callback, server->debug_data,
1140 "Prep Write Req - handle: 0x%04x", handle);
1142 ecode = check_permissions(server, attr, BT_ATT_PERM_WRITE |
1143 BT_ATT_PERM_WRITE_AUTHEN |
1144 BT_ATT_PERM_WRITE_ENCRYPT);
1148 prep_data = new0(struct prep_write_data, 1);
1149 prep_data->length = length - 4;
1150 if (prep_data->length) {
1151 prep_data->value = malloc(prep_data->length);
1152 if (!prep_data->value) {
1153 ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
1158 prep_data->server = server;
1159 prep_data->handle = handle;
1160 prep_data->offset = offset;
1161 memcpy(prep_data->value, pdu + 4, prep_data->length);
1163 queue_push_tail(server->prep_queue, prep_data);
1165 bt_att_send(server->att, BT_ATT_OP_PREP_WRITE_RSP, pdu, length, NULL,
1171 prep_write_data_destroy(prep_data);
1173 bt_att_send_error_rsp(server->att, opcode, handle, ecode);
1177 static void exec_next_prep_write(struct bt_gatt_server *server,
1178 uint16_t ehandle, int err);
1180 static void exec_write_complete_cb(struct gatt_db_attribute *attr, int err,
1183 struct bt_gatt_server *server = user_data;
1184 uint16_t handle = gatt_db_attribute_get_handle(attr);
1186 exec_next_prep_write(server, handle, err);
1189 static void exec_next_prep_write(struct bt_gatt_server *server,
1190 uint16_t ehandle, int err)
1192 struct prep_write_data *next = NULL;
1193 struct gatt_db_attribute *attr;
1199 next = queue_pop_head(server->prep_queue);
1201 bt_att_send(server->att, BT_ATT_OP_EXEC_WRITE_RSP, NULL, 0,
1206 attr = gatt_db_get_attribute(server->db, next->handle);
1208 err = BT_ATT_ERROR_UNLIKELY;
1212 status = gatt_db_attribute_write(attr, next->offset,
1213 next->value, next->length,
1214 BT_ATT_OP_EXEC_WRITE_REQ,
1216 exec_write_complete_cb, server);
1218 prep_write_data_destroy(next);
1223 err = BT_ATT_ERROR_UNLIKELY;
1226 bt_att_send_error_rsp(server->att, BT_ATT_OP_EXEC_WRITE_REQ,
1230 static void exec_write_cb(uint8_t opcode, const void *pdu,
1231 uint16_t length, void *user_data)
1233 struct bt_gatt_server *server = user_data;
1239 ecode = BT_ATT_ERROR_INVALID_PDU;
1243 flags = ((uint8_t *) pdu)[0];
1245 util_debug(server->debug_callback, server->debug_data,
1246 "Exec Write Req - flags: 0x%02x", flags);
1250 else if (flags == 0x01)
1253 ecode = BT_ATT_ERROR_INVALID_PDU;
1258 queue_remove_all(server->prep_queue, NULL, NULL,
1259 prep_write_data_destroy);
1260 bt_att_send(server->att, BT_ATT_OP_EXEC_WRITE_RSP, NULL, 0,
1265 exec_next_prep_write(server, 0, 0);
1270 bt_att_send_error_rsp(server->att, opcode, 0, ecode);
1273 static void exchange_mtu_cb(uint8_t opcode, const void *pdu,
1274 uint16_t length, void *user_data)
1276 struct bt_gatt_server *server = user_data;
1277 uint16_t client_rx_mtu;
1282 bt_att_send_error_rsp(server->att, opcode, 0,
1283 BT_ATT_ERROR_INVALID_PDU);
1287 client_rx_mtu = get_le16(pdu);
1288 #ifndef __TIZEN_PACTH__
1289 final_mtu = MAX(MIN(client_rx_mtu, server->mtu), BT_ATT_DEFAULT_LE_MTU);
1291 /* Respond with the server MTU */
1292 put_le16(server->mtu, rsp_pdu);
1293 bt_att_send(server->att, BT_ATT_OP_MTU_RSP, rsp_pdu, 2, NULL, NULL,
1296 /* Set MTU to be the minimum */
1297 server->mtu = final_mtu;
1298 bt_att_set_mtu(server->att, final_mtu);
1300 final_mtu = MAX(MIN(client_rx_mtu, BT_ATT_MAX_LE_MTU), BT_ATT_DEFAULT_LE_MTU);
1302 /* Set MTU to be the minimum */
1303 server->mtu = final_mtu;
1304 bt_att_set_mtu(server->att, final_mtu);
1306 /* Respond with the server MTU */
1307 put_le16(server->mtu, rsp_pdu);
1308 bt_att_send(server->att, BT_ATT_OP_MTU_RSP, rsp_pdu, 2, NULL, NULL,
1312 util_debug(server->debug_callback, server->debug_data,
1313 "MTU exchange complete, with MTU: %u", final_mtu);
1316 static bool gatt_server_register_att_handlers(struct bt_gatt_server *server)
1319 server->mtu_id = bt_att_register(server->att, BT_ATT_OP_MTU_REQ,
1322 if (!server->mtu_id)
1325 /* Read By Group Type */
1326 server->read_by_grp_type_id = bt_att_register(server->att,
1327 BT_ATT_OP_READ_BY_GRP_TYPE_REQ,
1328 read_by_grp_type_cb,
1330 if (!server->read_by_grp_type_id)
1334 server->read_by_type_id = bt_att_register(server->att,
1335 BT_ATT_OP_READ_BY_TYPE_REQ,
1338 if (!server->read_by_type_id)
1341 /* Find Information */
1342 server->find_info_id = bt_att_register(server->att,
1343 BT_ATT_OP_FIND_INFO_REQ,
1346 if (!server->find_info_id)
1349 /* Find By Type Value */
1350 server->find_by_type_value_id = bt_att_register(server->att,
1351 BT_ATT_OP_FIND_BY_TYPE_REQ,
1352 find_by_type_val_cb,
1355 if (!server->find_by_type_value_id)
1359 server->write_id = bt_att_register(server->att, BT_ATT_OP_WRITE_REQ,
1362 if (!server->write_id)
1366 server->write_cmd_id = bt_att_register(server->att, BT_ATT_OP_WRITE_CMD,
1369 if (!server->write_cmd_id)
1373 server->read_id = bt_att_register(server->att, BT_ATT_OP_READ_REQ,
1376 if (!server->read_id)
1379 /* Read Blob Request */
1380 server->read_blob_id = bt_att_register(server->att,
1381 BT_ATT_OP_READ_BLOB_REQ,
1384 if (!server->read_blob_id)
1387 /* Read Multiple Request */
1388 server->read_multiple_id = bt_att_register(server->att,
1389 BT_ATT_OP_READ_MULT_REQ,
1393 if (!server->read_multiple_id)
1396 /* Prepare Write Request */
1397 server->prep_write_id = bt_att_register(server->att,
1398 BT_ATT_OP_PREP_WRITE_REQ,
1399 prep_write_cb, server, NULL);
1400 if (!server->prep_write_id)
1403 /* Execute Write Request */
1404 server->exec_write_id = bt_att_register(server->att,
1405 BT_ATT_OP_EXEC_WRITE_REQ,
1406 exec_write_cb, server, NULL);
1407 if (!server->exec_write_id)
1413 struct bt_gatt_server *bt_gatt_server_new(struct gatt_db *db,
1414 struct bt_att *att, uint16_t mtu)
1416 struct bt_gatt_server *server;
1421 server = new0(struct bt_gatt_server, 1);
1422 server->db = gatt_db_ref(db);
1423 server->att = bt_att_ref(att);
1424 server->mtu = MAX(mtu, BT_ATT_DEFAULT_LE_MTU);
1425 server->max_prep_queue_len = DEFAULT_MAX_PREP_QUEUE_LEN;
1426 server->prep_queue = queue_new();
1428 if (!gatt_server_register_att_handlers(server)) {
1429 bt_gatt_server_free(server);
1433 return bt_gatt_server_ref(server);
1436 struct bt_gatt_server *bt_gatt_server_ref(struct bt_gatt_server *server)
1441 __sync_fetch_and_add(&server->ref_count, 1);
1446 void bt_gatt_server_unref(struct bt_gatt_server *server)
1451 if (__sync_sub_and_fetch(&server->ref_count, 1))
1454 bt_gatt_server_free(server);
1457 bool bt_gatt_server_set_debug(struct bt_gatt_server *server,
1458 bt_gatt_server_debug_func_t callback,
1460 bt_gatt_server_destroy_func_t destroy)
1465 if (server->debug_destroy)
1466 server->debug_destroy(server->debug_data);
1468 server->debug_callback = callback;
1469 server->debug_destroy = destroy;
1470 server->debug_data = user_data;
1475 bool bt_gatt_server_send_notification(struct bt_gatt_server *server,
1476 uint16_t handle, const uint8_t *value,
1483 if (!server || (length && !value))
1486 pdu_len = MIN(bt_att_get_mtu(server->att) - 1, length + 2);
1487 pdu = malloc(pdu_len);
1491 put_le16(handle, pdu);
1492 memcpy(pdu + 2, value, pdu_len - 2);
1494 result = !!bt_att_send(server->att, BT_ATT_OP_HANDLE_VAL_NOT, pdu,
1495 pdu_len, NULL, NULL, NULL);
1502 bt_gatt_server_conf_func_t callback;
1503 bt_gatt_server_destroy_func_t destroy;
1507 static void destroy_ind_data(void *user_data)
1509 struct ind_data *data = user_data;
1512 data->destroy(data->user_data);
1517 static void conf_cb(uint8_t opcode, const void *pdu,
1518 uint16_t length, void *user_data)
1520 struct ind_data *data = user_data;
1523 data->callback(data->user_data);
1526 bool bt_gatt_server_send_indication(struct bt_gatt_server *server,
1527 uint16_t handle, const uint8_t *value,
1529 bt_gatt_server_conf_func_t callback,
1531 bt_gatt_server_destroy_func_t destroy)
1535 struct ind_data *data;
1538 if (!server || (length && !value))
1541 pdu_len = MIN(bt_att_get_mtu(server->att) - 1, length + 2);
1542 pdu = malloc(pdu_len);
1546 data = new0(struct ind_data, 1);
1548 data->callback = callback;
1549 data->destroy = destroy;
1550 data->user_data = user_data;
1552 put_le16(handle, pdu);
1553 memcpy(pdu + 2, value, pdu_len - 2);
1555 result = !!bt_att_send(server->att, BT_ATT_OP_HANDLE_VAL_IND, pdu,
1557 data, destroy_ind_data);
1559 destroy_ind_data(data);