You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2015/12/24 01:45:50 UTC

incubator-mynewt-larva git commit: GATT server

Repository: incubator-mynewt-larva
Updated Branches:
  refs/heads/master ba4a7ed2b -> cc55da90a


GATT server


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/commit/cc55da90
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/cc55da90
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/cc55da90

Branch: refs/heads/master
Commit: cc55da90aa35933dd456a4f2038fb69e31779fff
Parents: ba4a7ed
Author: Christopher Collins <cc...@gmail.com>
Authored: Wed Dec 23 16:45:23 2015 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Wed Dec 23 16:45:23 2015 -0800

----------------------------------------------------------------------
 net/nimble/host/include/host/ble_gatt.h |  11 +-
 net/nimble/host/src/ble_gatts.c         | 190 +++++++++++++++++++++++++--
 2 files changed, 185 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/cc55da90/net/nimble/host/include/host/ble_gatt.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/ble_gatt.h b/net/nimble/host/include/host/ble_gatt.h
index 665b138..fbba391 100644
--- a/net/nimble/host/include/host/ble_gatt.h
+++ b/net/nimble/host/include/host/ble_gatt.h
@@ -72,15 +72,18 @@ int ble_gatt_exchange_mtu(uint16_t conn_handle);
 int ble_gatt_init(void);
 
 /*** @server. */
-struct ble_gatt_desc_def {
+struct ble_gatt_dsc_def {
     uint8_t *uuid128;
+    uint8_t att_flags;
     ble_att_svr_access_fn *access_cb;
+    void *arg;
 };
 
-struct ble_gatt_char_def {
-    uint8_t properties;
+struct ble_gatt_chr_def {
     uint8_t *uuid128;
     ble_att_svr_access_fn *access_cb;
+    struct ble_gatt_dsc_def *descriptors;
+    uint8_t properties;
 };
 
 #define BLE_GATT_SVC_TYPE_END       0
@@ -91,7 +94,7 @@ struct ble_gatt_svc_def {
     uint8_t type;
     uint8_t *uuid128;
     struct ble_gatt_svc_def **includes; /* Terminated with null. */
-    struct ble_gatt_char_def *characteristics;
+    struct ble_gatt_chr_def *characteristics;
 };
 
 int ble_gatt_register_services(const struct ble_gatt_svc_def *svcs);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/cc55da90/net/nimble/host/src/ble_gatts.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gatts.c b/net/nimble/host/src/ble_gatts.c
index 3c71ba1..48e0921 100644
--- a/net/nimble/host/src/ble_gatts.c
+++ b/net/nimble/host/src/ble_gatts.c
@@ -16,14 +16,21 @@
 
 #include <stddef.h>
 #include <assert.h>
+#include <string.h>
+#include "nimble/ble.h"
+#include "host/ble_hs_uuid.h"
 #include "ble_hs_priv.h"
 #include "ble_gatt_priv.h"
 
+#define BLE_GATTS_INCLUDE_SZ    6
+#define BLE_GATTS_CHR_MAX_SZ    19
+
 #define BLE_GATTS_MAX_SERVICES  32 /* XXX: Make this configurable. */
 
 struct ble_gatts_svc_entry {
     const struct ble_gatt_svc_def *svc;
-    uint16_t handle;    /* 0 means unregistered. */
+    uint16_t handle;            /* 0 means unregistered. */
+    uint16_t end_group_handle;
 };
 
 static struct ble_gatts_svc_entry
@@ -46,23 +53,92 @@ ble_gatts_svc_access(uint16_t handle_id, uint8_t *uuid128, uint8_t op,
 }
 
 static int
-ble_gatts_service_includes_satisfied(const struct ble_gatt_svc_def *svc)
+ble_gatts_inc_access(uint16_t handle_id, uint8_t *uuid128, uint8_t op,
+                         union ble_att_svr_access_ctxt *ctxt, void *arg)
+{
+    static uint8_t buf[BLE_GATTS_INCLUDE_SZ];
+
+    const struct ble_gatts_svc_entry *entry;
+    uint16_t uuid16;
+
+    assert(op == BLE_ATT_ACCESS_OP_READ);
+
+    entry = arg;
+
+    htole16(buf + 0, entry->handle);
+    htole16(buf + 2, entry->end_group_handle);
+
+    /* Only include the service UUID if it has a 16-bit representation. */
+    uuid16 = ble_hs_uuid_16bit(entry->svc->uuid128);
+    if (uuid16 != 0) {
+        htole16(buf + 4, uuid16);
+        ctxt->ahc_read.attr_len = 6;
+    } else {
+        ctxt->ahc_read.attr_len = 4;
+    }
+    ctxt->ahc_read.attr_data = buf;
+
+    return 0;
+}
+
+static int
+ble_gatts_chr_access(uint16_t handle_id, uint8_t *uuid128, uint8_t op,
+                     union ble_att_svr_access_ctxt *ctxt, void *arg)
+{
+    static uint8_t buf[BLE_GATTS_CHR_MAX_SZ];
+    const struct ble_gatt_chr_def *chr;
+    uint16_t uuid16;
+
+    assert(op == BLE_ATT_ACCESS_OP_READ);
+
+    chr = arg;
+
+    buf[0] = chr->properties;
+
+    /* The value attribute is always immediately after the declaration. */
+    htole16(buf + 1, handle_id + 1);
+
+    uuid16 = ble_hs_uuid_16bit(chr->uuid128);
+    if (uuid16 != 0) {
+        htole16(buf + 3, uuid16);
+        ctxt->ahc_read.attr_len = 5;
+    } else {
+        memcpy(buf + 3, chr->uuid128, 16);
+        ctxt->ahc_read.attr_len = 19;
+    }
+
+    return 0;
+}
+
+static int
+ble_gatts_find_svc(const struct ble_gatt_svc_def *svc)
 {
-    const struct ble_gatt_svc_def *incl;
     int i;
 
+    for (i = 0; i < ble_gatts_num_svc_entries; i++) {
+        if (ble_gatts_svc_entries[i].svc == svc) {
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+static int
+ble_gatts_svc_incs_satisfied(const struct ble_gatt_svc_def *svc)
+{
+    const struct ble_gatt_svc_def *incl;
+    int idx;
+
     if (svc->includes == NULL) {
         /* No included services. */
         return 1;
     }
 
     for (incl = *svc->includes; incl != NULL; incl++) {
-        for (i = 0; i < ble_gatts_num_svc_entries; i++) {
-            if (ble_gatts_svc_entries[i].handle == 0) {
-                return 0;
-            } else {
-                break;
-            }
+        idx = ble_gatts_find_svc(incl);
+        if (idx == -1) {
+            return 0;
         }
     }
 
@@ -70,12 +146,78 @@ ble_gatts_service_includes_satisfied(const struct ble_gatt_svc_def *svc)
 }
 
 static int
-ble_gatts_register_service(const struct ble_gatt_svc_def *svc,
+ble_gatts_register_inc(struct ble_gatts_svc_entry *entry)
+{
+    uint16_t handle;
+    int rc;
+
+    assert(entry->handle != 0);
+    assert(entry->end_group_handle != 0);
+
+    rc = ble_att_svr_register(entry->svc->uuid128, HA_FLAG_PERM_READ,
+                              &handle, ble_gatts_inc_access, entry);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
+
+static int
+ble_gatts_register_dsc(const struct ble_gatt_dsc_def *dsc)
+{
+    uint16_t handle;
+    int rc;
+
+    rc = ble_att_svr_register(dsc->uuid128, dsc->att_flags, &handle,
+                              dsc->access_cb, (void *)dsc->arg);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+
+}
+
+static int
+ble_gatts_register_characteristic(const struct ble_gatt_chr_def *chr)
+{
+    struct ble_gatt_dsc_def *dsc;
+    uint16_t handle;
+    int rc;
+
+    /* Register characteristic declaration attribute (cast away const on
+     * callback arg).
+     */
+    rc = ble_att_svr_register(chr->uuid128, HA_FLAG_PERM_READ, &handle,
+                              ble_gatts_chr_access, (void *)chr);
+    if (rc != 0) {
+        return rc;
+    }
+
+    /* Register each descriptor. */
+    if (chr->descriptors != NULL) {
+        for (dsc = chr->descriptors; dsc->uuid128 != NULL; dsc++) {
+            rc = ble_gatts_register_dsc(dsc);
+            if (rc != 0) {
+                return rc;
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int
+ble_gatts_register_svc(const struct ble_gatt_svc_def *svc,
                            uint16_t *out_handle)
 {
+    const struct ble_gatt_svc_def *incl;
+    const struct ble_gatt_chr_def *chr;
+    int idx;
     int rc;
 
-    if (!ble_gatts_service_includes_satisfied(svc)) {
+    if (!ble_gatts_svc_incs_satisfied(svc)) {
         return BLE_HS_EAGAIN;
     }
 
@@ -88,6 +230,30 @@ ble_gatts_register_service(const struct ble_gatt_svc_def *svc,
         return rc;
     }
 
+    /* Register each include. */
+    if (svc->includes != NULL) {
+        for (incl = *svc->includes; incl != NULL; incl++) {
+            idx = ble_gatts_find_svc(incl);
+            assert(idx != -1);
+
+            rc = ble_gatts_register_inc(ble_gatts_svc_entries + idx);
+            if (rc != 0) {
+                return rc;
+            }
+        }
+    }
+
+    /* Register each characteristic. */
+    if (svc->characteristics != NULL) {
+        for (chr = svc->characteristics; chr->uuid128 != NULL; chr++) {
+            rc = ble_gatts_register_characteristic(chr);
+            if (rc != 0) {
+                return rc;
+            }
+        }
+
+    }
+
     return 0;
 }
 
@@ -104,7 +270,7 @@ ble_gatts_register_round(int *out_num_registered)
         entry = ble_gatts_svc_entries + i;
 
         if (entry->handle == 0) {
-            rc = ble_gatts_register_service(entry->svc, &handle);
+            rc = ble_gatts_register_svc(entry->svc, &handle);
             switch (rc) {
             case 0:
                 /* Service successfully registered. */