diff options
author | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2011-04-11 15:24:03 -0300 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@nokia.com> | 2011-04-14 20:09:21 +0300 |
commit | 612d0207646064f309edd564a69d30b42de9e26f (patch) | |
tree | 56d2d1c5660ebc05ace211f79f02f99c82c4ac72 /attrib/gatt.c | |
parent | 839adcd63d7e02b814b7ba7b9ad18220ff862760 (diff) | |
download | bluez-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.c | 78 |
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; +} |