diff options
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 0b69daf6..360218b0 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; +} |