summaryrefslogtreecommitdiff
path: root/attrib/gatt.c
diff options
context:
space:
mode:
authorClaudio Takahasi <claudio.takahasi@openbossa.org>2011-04-11 15:24:03 -0300
committerJohan Hedberg <johan.hedberg@nokia.com>2011-04-14 20:09:21 +0300
commit612d0207646064f309edd564a69d30b42de9e26f (patch)
tree56d2d1c5660ebc05ace211f79f02f99c82c4ac72 /attrib/gatt.c
parent839adcd63d7e02b814b7ba7b9ad18220ff862760 (diff)
downloadbluez-612d0207646064f309edd564a69d30b42de9e26f.tar.gz
Register primary services exported over basic rate
This patch registers the object paths for primary services exported through SDP. PSM, start and end handle information are available in the Protocol Descriptor List.
Diffstat (limited to 'attrib/gatt.c')
-rw-r--r--attrib/gatt.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/attrib/gatt.c b/attrib/gatt.c
index 0b69daf60..360218b05 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -23,8 +23,11 @@
*/
#include <stdint.h>
+#include <stdlib.h>
#include <glib.h>
#include <bluetooth/uuid.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
#include "att.h"
#include "gattrib.h"
@@ -575,3 +578,78 @@ guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, uint8_t *value, int vlen,
return g_attrib_send(attrib, 0, ATT_OP_WRITE_CMD, buf, plen, NULL,
user_data, notify);
}
+
+static sdp_data_t *proto_seq_find(sdp_list_t *proto_list)
+{
+ sdp_list_t *list;
+ uuid_t proto;
+
+ sdp_uuid16_create(&proto, ATT_UUID);
+
+ for (list = proto_list; list; list = list->next) {
+ sdp_list_t *p;
+ for (p = list->data; p; p = p->next) {
+ sdp_data_t *seq = p->data;
+ if (seq && seq->dtd == SDP_UUID16 &&
+ sdp_uuid16_cmp(&proto, &seq->val.uuid) == 0)
+ return seq->next;
+ }
+ }
+
+ return NULL;
+}
+
+static gboolean parse_proto_params(sdp_list_t *proto_list, uint16_t *psm,
+ uint16_t *start, uint16_t *end)
+{
+ sdp_data_t *seq1, *seq2;
+
+ if (psm)
+ *psm = sdp_get_proto_port(proto_list, L2CAP_UUID);
+
+ /* Getting start and end handle */
+ seq1 = proto_seq_find(proto_list);
+ if (!seq1 || seq1->dtd != SDP_UINT16)
+ return FALSE;
+
+ seq2 = seq1->next;
+ if (!seq2 || seq2->dtd != SDP_UINT16)
+ return FALSE;
+
+ if (start)
+ *start = seq1->val.uint16;
+
+ if (end)
+ *end = seq2->val.uint16;
+
+ return TRUE;
+}
+
+gboolean gatt_parse_record(const sdp_record_t *rec,
+ uuid_t *prim_uuid, uint16_t *psm,
+ uint16_t *start, uint16_t *end)
+{
+ sdp_list_t *list;
+ uuid_t uuid;
+ gboolean ret;
+
+ if (sdp_get_service_classes(rec, &list) < 0)
+ return FALSE;
+
+ memcpy(&uuid, list->data, sizeof(uuid));
+ sdp_list_free(list, free);
+
+ if (sdp_get_access_protos(rec, &list) < 0)
+ return FALSE;
+
+ ret = parse_proto_params(list, psm, start, end);
+
+ sdp_list_foreach(list, (sdp_list_func_t) sdp_list_free, NULL);
+ sdp_list_free(list, NULL);
+
+ /* FIXME: replace by bt_uuid_t after uuid_t/sdp code cleanup */
+ if (ret && prim_uuid)
+ memcpy(prim_uuid, &uuid, sizeof(uuid_t));
+
+ return ret;
+}