3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2010 Nokia Corporation
6 * Copyright (C) 2010 Marcel Holtmann <marcel@holtmann.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 #include <bluetooth/bluetooth.h>
36 #include <bluetooth/uuid.h>
37 #include <bluetooth/sdp.h>
38 #include <bluetooth/sdp_lib.h>
41 #include "glib-helper.h"
48 #include "attrib-server.h"
53 static GSList *database = NULL;
75 static GIOChannel *l2cap_io = NULL;
76 static GIOChannel *le_io = NULL;
77 static GSList *clients = NULL;
78 static uint32_t gatt_sdp_handle = 0;
79 static uint32_t gap_sdp_handle = 0;
81 /* GAP attribute handles */
82 static uint16_t name_handle = 0x0000;
83 static uint16_t appearance_handle = 0x0000;
85 static bt_uuid_t prim_uuid = {
87 .value.u16 = GATT_PRIM_SVC_UUID
89 static bt_uuid_t snd_uuid = {
91 .value.u16 = GATT_SND_SVC_UUID
94 static sdp_record_t *server_record_new(uuid_t *uuid, uint16_t start, uint16_t end)
96 sdp_list_t *svclass_id, *apseq, *proto[2], *root, *aproto;
97 uuid_t root_uuid, proto_uuid, l2cap;
99 sdp_data_t *psm, *sh, *eh;
100 uint16_t lp = GATT_PSM;
108 record = sdp_record_alloc();
112 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
113 root = sdp_list_append(NULL, &root_uuid);
114 sdp_set_browse_groups(record, root);
115 sdp_list_free(root, NULL);
117 svclass_id = sdp_list_append(NULL, uuid);
118 sdp_set_service_classes(record, svclass_id);
119 sdp_list_free(svclass_id, NULL);
121 sdp_uuid16_create(&l2cap, L2CAP_UUID);
122 proto[0] = sdp_list_append(NULL, &l2cap);
123 psm = sdp_data_alloc(SDP_UINT16, &lp);
124 proto[0] = sdp_list_append(proto[0], psm);
125 apseq = sdp_list_append(NULL, proto[0]);
127 sdp_uuid16_create(&proto_uuid, ATT_UUID);
128 proto[1] = sdp_list_append(NULL, &proto_uuid);
129 sh = sdp_data_alloc(SDP_UINT16, &start);
130 proto[1] = sdp_list_append(proto[1], sh);
131 eh = sdp_data_alloc(SDP_UINT16, &end);
132 proto[1] = sdp_list_append(proto[1], eh);
133 apseq = sdp_list_append(apseq, proto[1]);
135 aproto = sdp_list_append(NULL, apseq);
136 sdp_set_access_protos(record, aproto);
141 sdp_list_free(proto[0], NULL);
142 sdp_list_free(proto[1], NULL);
143 sdp_list_free(apseq, NULL);
144 sdp_list_free(aproto, NULL);
149 static int handle_cmp(gconstpointer a, gconstpointer b)
151 const struct attribute *attrib = a;
152 uint16_t handle = GPOINTER_TO_UINT(b);
154 return attrib->handle - handle;
157 static int attribute_cmp(gconstpointer a1, gconstpointer a2)
159 const struct attribute *attrib1 = a1;
160 const struct attribute *attrib2 = a2;
162 return attrib1->handle - attrib2->handle;
165 static uint8_t att_check_reqs(struct gatt_channel *channel, uint8_t opcode,
168 /* FIXME: currently, it is assumed an encrypted link is enough for
169 * authentication. This will allow to enable the SMP negotiation once
170 * it is on upstream kernel. */
171 if (!channel->encrypted)
172 channel->encrypted = g_attrib_is_encrypted(channel->attrib);
173 if (reqs == ATT_AUTHENTICATION && !channel->encrypted)
174 return ATT_ECODE_INSUFF_ENC;
177 case ATT_OP_READ_BY_GROUP_REQ:
178 case ATT_OP_READ_BY_TYPE_REQ:
179 case ATT_OP_READ_REQ:
180 case ATT_OP_READ_BLOB_REQ:
181 case ATT_OP_READ_MULTI_REQ:
182 if (reqs == ATT_NOT_PERMITTED)
183 return ATT_ECODE_READ_NOT_PERM;
185 case ATT_OP_PREP_WRITE_REQ:
186 case ATT_OP_WRITE_REQ:
187 case ATT_OP_WRITE_CMD:
188 if (reqs == ATT_NOT_PERMITTED)
189 return ATT_ECODE_WRITE_NOT_PERM;
196 static uint8_t client_set_notifications(struct attribute *attr,
199 struct gatt_channel *channel = user_data;
200 struct attribute *last_chr_val = NULL;
206 cfg_val = att_get_u16(attr->data);
208 bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
209 for (l = database, props = 0; l != NULL; l = l->next) {
210 struct attribute *a = l->data;
211 static uint16_t handle = 0;
213 if (a->handle >= attr->handle)
216 if (bt_uuid_cmp(&a->uuid, &uuid) == 0) {
217 props = att_get_u8(&a->data[0]);
218 handle = att_get_u16(&a->data[1]);
222 if (handle && a->handle == handle)
226 if (last_chr_val == NULL)
229 if ((cfg_val & 0x0001) && !(props & ATT_CHAR_PROPER_NOTIFY))
230 return ATT_ECODE_WRITE_NOT_PERM;
232 if ((cfg_val & 0x0002) && !(props & ATT_CHAR_PROPER_INDICATE))
233 return ATT_ECODE_WRITE_NOT_PERM;
235 if (cfg_val & 0x0001)
236 channel->notify = g_slist_append(channel->notify, last_chr_val);
238 channel->notify = g_slist_remove(channel->notify, last_chr_val);
240 if (cfg_val & 0x0002)
241 channel->indicate = g_slist_append(channel->indicate,
244 channel->indicate = g_slist_remove(channel->indicate,
250 static struct attribute *client_cfg_attribute(struct gatt_channel *channel,
251 struct attribute *orig_attr,
252 const uint8_t *value, int vlen)
254 guint handle = orig_attr->handle;
258 bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
259 if (bt_uuid_cmp(&orig_attr->uuid, &uuid) != 0)
262 /* Value is unchanged, not need to create a private copy yet */
263 if (vlen == orig_attr->len && memcmp(orig_attr->data, value, vlen) == 0)
266 l = g_slist_find_custom(channel->configs, GUINT_TO_POINTER(handle),
271 /* Create a private copy of the Client Characteristic
272 * Configuration attribute */
273 a = g_malloc0(sizeof(*a) + vlen);
274 memcpy(a, orig_attr, sizeof(*a));
275 memcpy(a->data, value, vlen);
276 a->write_cb = client_set_notifications;
277 a->cb_user_data = channel;
279 channel->configs = g_slist_insert_sorted(channel->configs, a,
288 static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
289 uint16_t end, bt_uuid_t *uuid,
290 uint8_t *pdu, int len)
292 struct att_data_list *adl;
294 struct group_elem *cur, *old = NULL;
296 uint16_t length, last_handle, last_size = 0;
300 if (start > end || start == 0x0000)
301 return enc_error_resp(ATT_OP_READ_BY_GROUP_REQ, start,
302 ATT_ECODE_INVALID_HANDLE, pdu, len);
305 * Only <<Primary Service>> and <<Secondary Service>> grouping
306 * types may be used in the Read By Group Type Request.
309 if (bt_uuid_cmp(uuid, &prim_uuid) != 0 &&
310 bt_uuid_cmp(uuid, &snd_uuid) != 0)
311 return enc_error_resp(ATT_OP_READ_BY_GROUP_REQ, 0x0000,
312 ATT_ECODE_UNSUPP_GRP_TYPE, pdu, len);
315 for (l = database, groups = NULL; l; l = l->next) {
316 struct attribute *client_attr;
320 if (a->handle < start)
323 if (a->handle >= end)
326 /* The old group ends when a new one starts */
327 if (old && (bt_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
328 bt_uuid_cmp(&a->uuid, &snd_uuid) == 0)) {
329 old->end = last_handle;
333 if (bt_uuid_cmp(&a->uuid, uuid) != 0) {
334 /* Still inside a service, update its last handle */
336 last_handle = a->handle;
340 if (last_size && (last_size != a->len))
343 status = att_check_reqs(channel, ATT_OP_READ_BY_GROUP_REQ,
346 client_attr = client_cfg_attribute(channel, a, a->data, a->len);
350 if (status == 0x00 && a->read_cb)
351 status = a->read_cb(a, a->cb_user_data);
354 g_slist_foreach(groups, (GFunc) g_free, NULL);
355 g_slist_free(groups);
356 return enc_error_resp(ATT_OP_READ_BY_GROUP_REQ,
357 a->handle, status, pdu, len);
360 cur = g_new0(struct group_elem, 1);
361 cur->handle = a->handle;
365 /* Attribute Grouping Type found */
366 groups = g_slist_append(groups, cur);
370 last_handle = cur->handle;
374 return enc_error_resp(ATT_OP_READ_BY_GROUP_REQ, start,
375 ATT_ECODE_ATTR_NOT_FOUND, pdu, len);
378 cur->end = a->handle;
380 cur->end = last_handle;
382 length = g_slist_length(groups);
384 adl = att_data_list_alloc(length, last_size + 4);
386 for (i = 0, l = groups; l; l = l->next, i++) {
391 value = (void *) adl->data[i];
393 att_put_u16(cur->handle, value);
394 att_put_u16(cur->end, &value[2]);
395 /* Attribute Value */
396 memcpy(&value[4], cur->data, cur->len);
399 length = enc_read_by_grp_resp(adl, pdu, len);
401 att_data_list_free(adl);
402 g_slist_foreach(groups, (GFunc) g_free, NULL);
403 g_slist_free(groups);
408 static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
409 uint16_t end, bt_uuid_t *uuid,
410 uint8_t *pdu, int len)
412 struct att_data_list *adl;
415 uint16_t num, length;
419 if (start > end || start == 0x0000)
420 return enc_error_resp(ATT_OP_READ_BY_TYPE_REQ, start,
421 ATT_ECODE_INVALID_HANDLE, pdu, len);
423 for (l = database, length = 0, types = NULL; l; l = l->next) {
424 struct attribute *client_attr;
428 if (a->handle < start)
431 if (a->handle >= end)
434 if (bt_uuid_cmp(&a->uuid, uuid) != 0)
437 status = att_check_reqs(channel, ATT_OP_READ_BY_TYPE_REQ,
440 client_attr = client_cfg_attribute(channel, a, a->data, a->len);
444 if (status == 0x00 && a->read_cb)
445 status = a->read_cb(a, a->cb_user_data);
449 return enc_error_resp(ATT_OP_READ_BY_TYPE_REQ,
450 a->handle, status, pdu, len);
453 /* All elements must have the same length */
456 else if (a->len != length)
459 types = g_slist_append(types, a);
463 return enc_error_resp(ATT_OP_READ_BY_TYPE_REQ, start,
464 ATT_ECODE_ATTR_NOT_FOUND, pdu, len);
466 num = g_slist_length(types);
468 /* Handle length plus attribute value length */
471 adl = att_data_list_alloc(num, length);
473 for (i = 0, l = types; l; i++, l = l->next) {
478 value = (void *) adl->data[i];
480 att_put_u16(a->handle, value);
482 /* Attribute Value */
483 memcpy(&value[2], a->data, a->len);
486 length = enc_read_by_type_resp(adl, pdu, len);
488 att_data_list_free(adl);
494 static int find_info(uint16_t start, uint16_t end, uint8_t *pdu, int len)
497 struct att_data_list *adl;
499 uint8_t format, last_type = BT_UUID_UNSPEC;
500 uint16_t length, num;
503 if (start > end || start == 0x0000)
504 return enc_error_resp(ATT_OP_FIND_INFO_REQ, start,
505 ATT_ECODE_INVALID_HANDLE, pdu, len);
507 for (l = database, info = NULL, num = 0; l; l = l->next) {
510 if (a->handle < start)
516 if (last_type == BT_UUID_UNSPEC)
517 last_type = a->uuid.type;
519 if (a->uuid.type != last_type)
522 info = g_slist_append(info, a);
525 last_type = a->uuid.type;
529 return enc_error_resp(ATT_OP_FIND_INFO_REQ, start,
530 ATT_ECODE_ATTR_NOT_FOUND, pdu, len);
532 if (last_type == BT_UUID16) {
535 } else if (last_type == BT_UUID128) {
540 adl = att_data_list_alloc(num, length + 2);
542 for (i = 0, l = info; l; i++, l = l->next) {
547 value = (void *) adl->data[i];
549 att_put_u16(a->handle, value);
551 /* Attribute Value */
552 att_put_uuid(a->uuid, &value[2]);
555 length = enc_find_info_resp(format, adl, pdu, len);
557 att_data_list_free(adl);
563 static int find_by_type(uint16_t start, uint16_t end, bt_uuid_t *uuid,
564 const uint8_t *value, int vlen, uint8_t *opdu, int mtu)
567 struct att_range *range;
571 if (start > end || start == 0x0000)
572 return enc_error_resp(ATT_OP_FIND_BY_TYPE_REQ, start,
573 ATT_ECODE_INVALID_HANDLE, opdu, mtu);
575 /* Searching first requested handle number */
576 for (l = database, matches = NULL, range = NULL; l; l = l->next) {
579 if (a->handle < start)
585 /* Primary service? Attribute value matches? */
586 if ((bt_uuid_cmp(&a->uuid, uuid) == 0) && (a->len == vlen) &&
587 (memcmp(a->data, value, vlen) == 0)) {
589 range = g_new0(struct att_range, 1);
590 range->start = a->handle;
591 /* It is allowed to have end group handle the same as
592 * start handle, for groups with only one attribute. */
593 range->end = a->handle;
595 matches = g_slist_append(matches, range);
597 /* Update the last found handle or reset the pointer
598 * to track that a new group started: Primary or
599 * Secondary service. */
600 if (bt_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
601 bt_uuid_cmp(&a->uuid, &snd_uuid) == 0)
604 range->end = a->handle;
609 return enc_error_resp(ATT_OP_FIND_BY_TYPE_REQ, start,
610 ATT_ECODE_ATTR_NOT_FOUND, opdu, mtu);
612 len = enc_find_by_type_resp(matches, opdu, mtu);
614 g_slist_foreach(matches, (GFunc) g_free, NULL);
615 g_slist_free(matches);
620 static struct attribute *find_primary_range(uint16_t start, uint16_t *end)
622 struct attribute *attrib;
629 l = g_slist_find_custom(database, GUINT_TO_POINTER(h), handle_cmp);
635 if (bt_uuid_cmp(&attrib->uuid, &prim_uuid) != 0)
640 for (l = l->next; l; l = l->next) {
641 struct attribute *a = l->data;
643 if (bt_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
644 bt_uuid_cmp(&a->uuid, &snd_uuid) == 0)
653 static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
654 uint8_t *pdu, int len)
656 struct attribute *a, *client_attr;
661 l = g_slist_find_custom(database, GUINT_TO_POINTER(h), handle_cmp);
663 return enc_error_resp(ATT_OP_READ_REQ, handle,
664 ATT_ECODE_INVALID_HANDLE, pdu, len);
668 status = att_check_reqs(channel, ATT_OP_READ_REQ, a->read_reqs);
670 client_attr = client_cfg_attribute(channel, a, a->data, a->len);
674 if (status == 0x00 && a->read_cb)
675 status = a->read_cb(a, a->cb_user_data);
678 return enc_error_resp(ATT_OP_READ_REQ, handle, status, pdu,
681 return enc_read_resp(a->data, a->len, pdu, len);
684 static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
685 uint16_t offset, uint8_t *pdu, int len)
687 struct attribute *a, *client_attr;
692 l = g_slist_find_custom(database, GUINT_TO_POINTER(h), handle_cmp);
694 return enc_error_resp(ATT_OP_READ_BLOB_REQ, handle,
695 ATT_ECODE_INVALID_HANDLE, pdu, len);
699 if (a->len <= offset)
700 return enc_error_resp(ATT_OP_READ_BLOB_REQ, handle,
701 ATT_ECODE_INVALID_OFFSET, pdu, len);
703 status = att_check_reqs(channel, ATT_OP_READ_BLOB_REQ, a->read_reqs);
705 client_attr = client_cfg_attribute(channel, a, a->data, a->len);
709 if (status == 0x00 && a->read_cb)
710 status = a->read_cb(a, a->cb_user_data);
713 return enc_error_resp(ATT_OP_READ_BLOB_REQ, handle, status,
716 return enc_read_blob_resp(a->data, a->len, offset, pdu, len);
719 static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
720 const uint8_t *value, int vlen,
721 uint8_t *pdu, int len)
723 struct attribute *a, *client_attr;
728 l = g_slist_find_custom(database, GUINT_TO_POINTER(h), handle_cmp);
730 return enc_error_resp(ATT_OP_WRITE_REQ, handle,
731 ATT_ECODE_INVALID_HANDLE, pdu, len);
735 status = att_check_reqs(channel, ATT_OP_WRITE_REQ, a->write_reqs);
737 return enc_error_resp(ATT_OP_WRITE_REQ, handle, status, pdu,
740 client_attr = client_cfg_attribute(channel, a, value, vlen);
744 attrib_db_update(a->handle, &a->uuid, value, vlen);
747 status = a->write_cb(a, a->cb_user_data);
749 return enc_error_resp(ATT_OP_WRITE_REQ, handle, status,
753 DBG("Notifications: %d, indications: %d",
754 g_slist_length(channel->notify),
755 g_slist_length(channel->indicate));
757 return enc_write_resp(pdu, len);
760 static uint16_t mtu_exchange(struct gatt_channel *channel, uint16_t mtu,
761 uint8_t *pdu, int len)
763 guint old_mtu = channel->mtu;
765 if (mtu < ATT_DEFAULT_LE_MTU)
766 channel->mtu = ATT_DEFAULT_LE_MTU;
768 channel->mtu = MIN(mtu, channel->mtu);
770 bt_io_set(le_io, BT_IO_L2CAP, NULL,
771 BT_IO_OPT_OMTU, channel->mtu,
774 return enc_mtu_resp(old_mtu, pdu, len);
777 static void channel_disconnect(void *user_data)
779 struct gatt_channel *channel = user_data;
781 g_attrib_unref(channel->attrib);
782 clients = g_slist_remove(clients, channel);
784 g_slist_free(channel->notify);
785 g_slist_free(channel->indicate);
786 g_slist_foreach(channel->configs, (GFunc) g_free, NULL);
787 g_slist_free(channel->configs);
792 static void channel_handler(const uint8_t *ipdu, uint16_t len,
795 struct gatt_channel *channel = user_data;
796 uint8_t opdu[ATT_MAX_MTU], value[ATT_MAX_MTU];
797 uint16_t length, start, end, mtu, offset;
802 DBG("op 0x%02x", ipdu[0]);
805 case ATT_OP_READ_BY_GROUP_REQ:
806 length = dec_read_by_grp_req(ipdu, len, &start, &end, &uuid);
808 status = ATT_ECODE_INVALID_PDU;
812 length = read_by_group(channel, start, end, &uuid, opdu,
815 case ATT_OP_READ_BY_TYPE_REQ:
816 length = dec_read_by_type_req(ipdu, len, &start, &end, &uuid);
818 status = ATT_ECODE_INVALID_PDU;
822 length = read_by_type(channel, start, end, &uuid, opdu,
825 case ATT_OP_READ_REQ:
826 length = dec_read_req(ipdu, len, &start);
828 status = ATT_ECODE_INVALID_PDU;
832 length = read_value(channel, start, opdu, channel->mtu);
834 case ATT_OP_READ_BLOB_REQ:
835 length = dec_read_blob_req(ipdu, len, &start, &offset);
837 status = ATT_ECODE_INVALID_PDU;
841 length = read_blob(channel, start, offset, opdu, channel->mtu);
845 status = ATT_ECODE_REQ_NOT_SUPP;
849 length = dec_mtu_req(ipdu, len, &mtu);
851 status = ATT_ECODE_INVALID_PDU;
855 length = mtu_exchange(channel, mtu, opdu, channel->mtu);
857 case ATT_OP_FIND_INFO_REQ:
858 length = dec_find_info_req(ipdu, len, &start, &end);
860 status = ATT_ECODE_INVALID_PDU;
864 length = find_info(start, end, opdu, channel->mtu);
866 case ATT_OP_WRITE_REQ:
867 length = dec_write_req(ipdu, len, &start, value, &vlen);
869 status = ATT_ECODE_INVALID_PDU;
873 length = write_value(channel, start, value, vlen, opdu,
876 case ATT_OP_WRITE_CMD:
877 length = dec_write_cmd(ipdu, len, &start, value, &vlen);
879 write_value(channel, start, value, vlen, opdu,
882 case ATT_OP_FIND_BY_TYPE_REQ:
883 length = dec_find_by_type_req(ipdu, len, &start, &end,
884 &uuid, value, &vlen);
886 status = ATT_ECODE_INVALID_PDU;
890 length = find_by_type(start, end, &uuid, value, vlen,
893 case ATT_OP_HANDLE_CNF:
895 case ATT_OP_READ_MULTI_REQ:
896 case ATT_OP_PREP_WRITE_REQ:
897 case ATT_OP_EXEC_WRITE_REQ:
899 DBG("Unsupported request 0x%02x", ipdu[0]);
900 status = ATT_ECODE_REQ_NOT_SUPP;
905 status = ATT_ECODE_IO;
909 length = enc_error_resp(ipdu[0], 0x0000, status, opdu,
912 g_attrib_send(channel->attrib, 0, opdu[0], opdu, length,
916 static void connect_event(GIOChannel *io, GError *err, void *user_data)
918 struct gatt_channel *channel;
923 error("%s", err->message);
927 channel = g_new0(struct gatt_channel, 1);
929 bt_io_get(io, BT_IO_L2CAP, &gerr,
930 BT_IO_OPT_SOURCE_BDADDR, &channel->src,
931 BT_IO_OPT_DEST_BDADDR, &channel->dst,
933 BT_IO_OPT_OMTU, &channel->mtu,
936 error("bt_io_get: %s", gerr->message);
939 g_io_channel_shutdown(io, TRUE, NULL);
943 if (channel->mtu > ATT_MAX_MTU)
944 channel->mtu = ATT_MAX_MTU;
951 channel->attrib = g_attrib_new(io);
952 g_io_channel_unref(io);
954 channel->id = g_attrib_register(channel->attrib, GATTRIB_ALL_EVENTS,
955 channel_handler, channel, NULL);
957 g_attrib_set_disconnect_function(channel->attrib, channel_disconnect,
960 clients = g_slist_append(clients, channel);
963 static void confirm_event(GIOChannel *io, void *user_data)
967 if (bt_io_accept(io, connect_event, user_data, NULL, &gerr) == FALSE) {
968 error("bt_io_accept: %s", gerr->message);
970 g_io_channel_unref(io);
976 static void attrib_notify_clients(struct attribute *attr)
978 guint handle = attr->handle;
981 for (l = clients; l; l = l->next) {
982 struct gatt_channel *channel = l->data;
985 if (g_slist_find_custom(channel->notify,
986 GUINT_TO_POINTER(handle), handle_cmp)) {
987 uint8_t pdu[ATT_MAX_MTU];
990 len = enc_notification(attr, pdu, channel->mtu);
994 g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
999 if (g_slist_find_custom(channel->indicate,
1000 GUINT_TO_POINTER(handle), handle_cmp)) {
1001 uint8_t pdu[ATT_MAX_MTU];
1004 len = enc_indication(attr, pdu, channel->mtu);
1008 g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
1014 static gboolean register_core_services(void)
1018 uint16_t appearance = 0x0000;
1020 /* GAP service: primary service definition */
1021 bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
1022 att_put_u16(GENERIC_ACCESS_PROFILE_ID, &atval[0]);
1023 attrib_db_add(0x0001, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
1025 /* GAP service: device name characteristic */
1026 name_handle = 0x0006;
1027 bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
1028 atval[0] = ATT_CHAR_PROPER_READ;
1029 att_put_u16(name_handle, &atval[1]);
1030 att_put_u16(GATT_CHARAC_DEVICE_NAME, &atval[3]);
1031 attrib_db_add(0x0004, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
1033 /* GAP service: device name attribute */
1034 bt_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
1035 attrib_db_add(name_handle, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
1038 /* GAP service: device appearance characteristic */
1039 appearance_handle = 0x0008;
1040 bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
1041 atval[0] = ATT_CHAR_PROPER_READ;
1042 att_put_u16(appearance_handle, &atval[1]);
1043 att_put_u16(GATT_CHARAC_APPEARANCE, &atval[3]);
1044 attrib_db_add(0x0007, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
1046 /* GAP service: device appearance attribute */
1047 bt_uuid16_create(&uuid, GATT_CHARAC_APPEARANCE);
1048 att_put_u16(appearance, &atval[0]);
1049 attrib_db_add(appearance_handle, &uuid, ATT_NONE, ATT_NOT_PERMITTED,
1051 gap_sdp_handle = attrib_create_sdp(0x0001, "Generic Access Profile");
1052 if (gap_sdp_handle == 0) {
1053 error("Failed to register GAP service record");
1057 /* GATT service: primary service definition */
1058 bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
1059 att_put_u16(GENERIC_ATTRIB_PROFILE_ID, &atval[0]);
1060 attrib_db_add(0x0010, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
1062 gatt_sdp_handle = attrib_create_sdp(0x0010,
1063 "Generic Attribute Profile");
1064 if (gatt_sdp_handle == 0) {
1065 error("Failed to register GATT service record");
1072 remove_record_from_server(gap_sdp_handle);
1077 int attrib_server_init(void)
1079 GError *gerr = NULL;
1082 l2cap_io = bt_io_listen(BT_IO_L2CAP, NULL, confirm_event,
1084 BT_IO_OPT_SOURCE_BDADDR, BDADDR_ANY,
1085 BT_IO_OPT_PSM, GATT_PSM,
1086 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
1088 if (l2cap_io == NULL) {
1089 error("%s", gerr->message);
1094 if (!register_core_services())
1101 le_io = bt_io_listen(BT_IO_L2CAP, NULL, confirm_event,
1102 &le_io, NULL, &gerr,
1103 BT_IO_OPT_SOURCE_BDADDR, BDADDR_ANY,
1104 BT_IO_OPT_CID, GATT_CID,
1105 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
1107 if (le_io == NULL) {
1108 error("%s", gerr->message);
1110 /* Doesn't have LE support, continue */
1116 g_io_channel_unref(l2cap_io);
1120 g_io_channel_unref(le_io);
1127 void attrib_server_exit(void)
1131 g_slist_foreach(database, (GFunc) g_free, NULL);
1132 g_slist_free(database);
1135 g_io_channel_unref(l2cap_io);
1136 g_io_channel_shutdown(l2cap_io, FALSE, NULL);
1140 g_io_channel_unref(le_io);
1141 g_io_channel_shutdown(le_io, FALSE, NULL);
1144 for (l = clients; l; l = l->next) {
1145 struct gatt_channel *channel = l->data;
1147 g_slist_free(channel->notify);
1148 g_slist_free(channel->indicate);
1149 g_slist_foreach(channel->configs, (GFunc) g_free, NULL);
1150 g_slist_free(channel->configs);
1152 g_attrib_unref(channel->attrib);
1156 g_slist_free(clients);
1158 if (gatt_sdp_handle)
1159 remove_record_from_server(gatt_sdp_handle);
1162 remove_record_from_server(gap_sdp_handle);
1165 uint32_t attrib_create_sdp(uint16_t handle, const char *name)
1167 sdp_record_t *record;
1168 struct attribute *a;
1170 uuid_t svc, gap_uuid;
1172 a = find_primary_range(handle, &end);
1178 sdp_uuid16_create(&svc, att_get_u16(a->data));
1179 else if (a->len == 16)
1180 sdp_uuid128_create(&svc, a->data);
1184 record = server_record_new(&svc, handle, end);
1189 sdp_set_info_attr(record, name, "BlueZ", NULL);
1191 sdp_uuid16_create(&gap_uuid, GENERIC_ACCESS_PROFILE_ID);
1192 if (sdp_uuid_cmp(&svc, &gap_uuid) == 0) {
1193 sdp_set_url_attr(record, "http://www.bluez.org/",
1194 "http://www.bluez.org/",
1195 "http://www.bluez.org/");
1198 if (add_record_to_server(BDADDR_ANY, record) < 0)
1199 sdp_record_free(record);
1201 return record->handle;
1206 void attrib_free_sdp(uint32_t sdp_handle)
1208 remove_record_from_server(sdp_handle);
1211 struct attribute *attrib_db_add(uint16_t handle, bt_uuid_t *uuid, int read_reqs,
1212 int write_reqs, const uint8_t *value, int len)
1214 struct attribute *a;
1216 /* FIXME: handle conflicts */
1218 a = g_malloc0(sizeof(struct attribute) + len);
1220 memcpy(&a->uuid, uuid, sizeof(bt_uuid_t));
1221 a->read_reqs = read_reqs;
1222 a->write_reqs = write_reqs;
1224 memcpy(a->data, value, len);
1226 database = g_slist_insert_sorted(database, a, attribute_cmp);
1231 int attrib_db_update(uint16_t handle, bt_uuid_t *uuid, const uint8_t *value,
1234 struct attribute *a;
1238 l = g_slist_find_custom(database, GUINT_TO_POINTER(h), handle_cmp);
1242 a = g_try_realloc(l->data, sizeof(struct attribute) + len);
1248 if (uuid != &a->uuid)
1249 memcpy(&a->uuid, uuid, sizeof(bt_uuid_t));
1251 memcpy(a->data, value, len);
1253 attrib_notify_clients(a);
1258 int attrib_db_del(uint16_t handle)
1260 struct attribute *a;
1264 l = g_slist_find_custom(database, GUINT_TO_POINTER(h), handle_cmp);
1269 database = g_slist_remove(database, a);
1275 int attrib_gap_set(uint16_t uuid, const uint8_t *value, int len)
1280 /* FIXME: Missing Privacy and Reconnection Address */
1282 bt_uuid16_create(&u16, uuid);
1285 case GATT_CHARAC_DEVICE_NAME:
1286 handle = name_handle;
1288 case GATT_CHARAC_APPEARANCE:
1289 handle = appearance_handle;
1295 return attrib_db_update(handle, &u16, value, len);