You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ja...@apache.org on 2020/03/19 12:03:28 UTC
[mynewt-documentation] branch master updated: Fixed BLE Peripheral
Project - Characteristic Access
This is an automated email from the ASF dual-hosted git repository.
janc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-documentation.git
The following commit(s) were added to refs/heads/master by this push:
new 2b5a015 Fixed BLE Peripheral Project - Characteristic Access
2b5a015 is described below
commit 2b5a01588ec7b87a343e58cc281f9a1c297d0cad
Author: Krzysztof Kopyściński <kr...@codecoup.pl>
AuthorDate: Wed Mar 18 13:21:13 2020 +0100
Fixed BLE Peripheral Project - Characteristic Access
- Tutorial accomodated to changes from commit 8fe77a4
- Functions updated to current version of mynewt-nimble/apps/bleprph
- Edited table contents to fit rest of changes
- Tutorial text changes commenting new syntax
- Tutorial text deletions commenting removed/swapped code snippets
- bleprph is part of nimble, not core
---
.../ble/bleprph/bleprph-sections/bleprph-app.rst | 2 +-
.../bleprph-sections/bleprph-chr-access.rst | 248 +++++++++------------
docs/tutorials/ble/bleprph/bleprph.rst | 2 +-
3 files changed, 106 insertions(+), 146 deletions(-)
diff --git a/docs/tutorials/ble/bleprph/bleprph-sections/bleprph-app.rst b/docs/tutorials/ble/bleprph/bleprph-sections/bleprph-app.rst
index 9ded59d..4bd8498 100644
--- a/docs/tutorials/ble/bleprph/bleprph-sections/bleprph-app.rst
+++ b/docs/tutorials/ble/bleprph/bleprph-sections/bleprph-app.rst
@@ -34,7 +34,7 @@ Peripheral
$ newt target set myperiph bsp=@apache-mynewt-core/hw/bsp/nrf52dk
Target targets/myperiph successfully set target.bsp to @apache-mynewt-core/hw/bsp/nrf52dk
$ newt target set myperiph app=@apache-mynewt-core/apps/bleprph
- Target targets/myperiph successfully set target.app to @apache-mynewt-core/apps/bleprph
+ Target targets/myperiph successfully set target.app to @apache-mynewt-nimble/apps/bleprph
$ newt target set myperiph build_profile=optimized
Target targets/myperiph successfully set target.build_profile to optimized
$ newt build myperiph
diff --git a/docs/tutorials/ble/bleprph/bleprph-sections/bleprph-chr-access.rst b/docs/tutorials/ble/bleprph/bleprph-sections/bleprph-chr-access.rst
index 0e34078..b2beacf 100644
--- a/docs/tutorials/ble/bleprph/bleprph-sections/bleprph-chr-access.rst
+++ b/docs/tutorials/ble/bleprph/bleprph-sections/bleprph-chr-access.rst
@@ -23,19 +23,20 @@ few characteristics in this service.
static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
{
- /*** Service: GAP. */
+ /*** Service: Security test. */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
- .uuid128 = BLE_UUID16(BLE_GAP_SVC_UUID16),
+ .uuid = &gatt_svr_svc_sec_test_uuid.u,
.characteristics = (struct ble_gatt_chr_def[]) { {
- /*** Characteristic: Device Name. */
- .uuid128 = BLE_UUID16(BLE_GAP_CHR_UUID16_DEVICE_NAME),
- .access_cb = gatt_svr_chr_access_gap,
- .flags = BLE_GATT_CHR_F_READ,
+ /*** Characteristic: Random number generator. */
+ .uuid = &gatt_svr_chr_sec_test_rand_uuid.u,
+ .access_cb = gatt_svr_chr_access_sec_test,
+ .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
}, {
- /*** Characteristic: Appearance. */
- .uuid128 = BLE_UUID16(BLE_GAP_CHR_UUID16_APPEARANCE),
- .access_cb = gatt_svr_chr_access_gap,
- .flags = BLE_GATT_CHR_F_READ,
+ /*** Characteristic: Static value. */
+ .uuid = gatt_svr_chr_sec_test_static_uuid.u,
+ .access_cb = gatt_svr_chr_access_sec_test,
+ .flags = BLE_GATT_CHR_F_READ |
+ BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC,
}, {
// [...]
@@ -48,55 +49,55 @@ characteristics use:
.. code:: c
static int
- gatt_svr_chr_access_gap(uint16_t conn_handle, uint16_t attr_handle, uint8_t op,
- union ble_gatt_access_ctxt *ctxt, void *arg)
+ gatt_svr_chr_access_sec_test(uint16_t conn_handle, uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt,
+ void *arg)
{
- uint16_t uuid16;
-
- uuid16 = ble_uuid_128_to_16(ctxt->chr_access.chr->uuid128);
- assert(uuid16 != 0);
-
- switch (uuid16) {
- case BLE_GAP_CHR_UUID16_DEVICE_NAME:
- assert(op == BLE_GATT_ACCESS_OP_READ_CHR);
- ctxt->chr_access.data = (void *)bleprph_device_name;
- ctxt->chr_access.len = strlen(bleprph_device_name);
- break;
-
- case BLE_GAP_CHR_UUID16_APPEARANCE:
- assert(op == BLE_GATT_ACCESS_OP_READ_CHR);
- ctxt->chr_access.data = (void *)&bleprph_appearance;
- ctxt->chr_access.len = sizeof bleprph_appearance;
- break;
-
- case BLE_GAP_CHR_UUID16_PERIPH_PRIV_FLAG:
- assert(op == BLE_GATT_ACCESS_OP_READ_CHR);
- ctxt->chr_access.data = (void *)&bleprph_privacy_flag;
- ctxt->chr_access.len = sizeof bleprph_privacy_flag;
- break;
-
- case BLE_GAP_CHR_UUID16_RECONNECT_ADDR:
- assert(op == BLE_GATT_ACCESS_OP_WRITE_CHR);
- if (ctxt->chr_access.len != sizeof bleprph_reconnect_addr) {
- return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
+ const ble_uuid_t *uuid;
+ int rand_num;
+ int rc;
+
+ uuid = ctxt->chr->uuid;
+
+ /* Determine which characteristic is being accessed by examining its
+ * 128-bit UUID.
+ */
+
+ if (ble_uuid_cmp(uuid, &gatt_svr_chr_sec_test_rand_uuid.u) == 0) {
+ assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
+
+ /* Respond with a 32-bit random number. */
+ rand_num = rand();
+ rc = os_mbuf_append(ctxt->om, &rand_num, sizeof rand_num);
+ return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+ }
+
+ if (ble_uuid_cmp(uuid, &gatt_svr_chr_sec_test_static_uuid.u) == 0) {
+ switch (ctxt->op) {
+ case BLE_GATT_ACCESS_OP_READ_CHR:
+ rc = os_mbuf_append(ctxt->om, &gatt_svr_sec_test_static_val,
+ sizeof gatt_svr_sec_test_static_val);
+ return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+
+ case BLE_GATT_ACCESS_OP_WRITE_CHR:
+ rc = gatt_svr_chr_write(ctxt->om,
+ sizeof gatt_svr_sec_test_static_val,
+ sizeof gatt_svr_sec_test_static_val,
+ &gatt_svr_sec_test_static_val, NULL);
+ return rc;
+
+ default:
+ assert(0);
+ return BLE_ATT_ERR_UNLIKELY;
}
- memcpy(bleprph_reconnect_addr, ctxt->chr_access.data,
- sizeof bleprph_reconnect_addr);
- break;
-
- case BLE_GAP_CHR_UUID16_PERIPH_PREF_CONN_PARAMS:
- assert(op == BLE_GATT_ACCESS_OP_READ_CHR);
- ctxt->chr_access.data = (void *)&bleprph_pref_conn_params;
- ctxt->chr_access.len = sizeof bleprph_pref_conn_params;
- break;
-
- default:
- assert(0);
- break;
}
- return 0;
- }
+ /* Unknown characteristic; the nimble stack should not have called this
+ * function.
+ */
+ assert(0);
+ return BLE_ATT_ERR_UNLIKELY;
+}
After you've taken a moment to examine the structure of this function,
let's explore some details.
@@ -107,8 +108,8 @@ Function signature
.. code:: c
static int
- gatt_svr_chr_access_gap(uint16_t conn_handle, uint16_t attr_handle, uint8_t op,
- union ble_gatt_access_ctxt *ctxt, void *arg)
+ gatt_svr_chr_access_sec_test(uint16_t conn_handle, uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt, void *arg)
A characteristic access function always takes this same set of
parameters and always returns an int. The parameters to this function
@@ -141,17 +142,6 @@ type are documented below.
| | | a UUID |
| | | lookup. |
+----------------+--------------+------------+
-| op | Indicates | Valid |
-| | whether this | values |
-| | is a read or | are:\ *BLE |
-| | write | \_GATT\_AC |
-| | operation | CESS\_OP\_ |
-| | | READ\_CHR* |
-| | | \ \ *BLE\_ |
-| | | GATT\_ACCE |
-| | | SS\_OP\_WR |
-| | | ITE\_CHR* |
-+----------------+--------------+------------+
| ctxt | Contains the | For |
| | characterist | characteri |
| | ic | stic |
@@ -181,18 +171,11 @@ Determine characteristic being accessed
.. code:: c
- {
- uint16_t uuid16;
-
- uuid16 = ble_uuid_128_to_16(ctxt->chr_access.chr->uuid128);
- assert(uuid16 != 0);
-
- switch (uuid16) {
- // [...]
+ ble_uuid_cmp(uuid, &gatt_svr_chr_sec_test_rand_uuid.u)
-This function uses the UUID to determine which characteristic is being
-accessed. There are two alternative methods *bleprph* could have used to
-accomplish this task:
+The function compares UUID with UUIDs of characteristic - if it fits,
+characteristic is being accessed. There are two alternative methods *bleprph*
+could have used to accomplish this task:
- Map characteristics to ATT handles during service registration; use
the *attr\_handle* parameter as a key into this table during
@@ -200,87 +183,64 @@ accomplish this task:
- Implement a dedicated function for each characteristic; each function
inherently knows which characteristic it corresponds to.
-All the GAP service characteristics have 16-bit UUIDs, so this function
-uses the *ble\_uuid\_128\_to\_16()* function to convert the 128-bit UUID
-to its corresponding 16-bit UUID. This conversion function returns the
-corresponding 16-bit UUID on success, or 0 on failure. Success is
-asserted here to ensure the NimBLE stack is doing its job properly; the
-stack should only call this function for accesses to characteristics
-that it is registered with, and all GAP service characteristics have
-valid 16-bit UUIDs.
-
Read access
^^^^^^^^^^^
.. code:: c
- case BLE_GAP_CHR_UUID16_DEVICE_NAME:
- assert(op == BLE_GATT_ACCESS_OP_READ_CHR);
- ctxt->chr_access.data = (void *)bleprph_device_name;
- ctxt->chr_access.len = strlen(bleprph_device_name);
- break;
+ case BLE_GATT_ACCESS_OP_READ_CHR:
+ rc = os_mbuf_append(ctxt->om, &gatt_svr_sec_test_static_val,
+ sizeof gatt_svr_sec_test_static_val);
+ return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+
-This code excerpt handles read accesses to the device name
-characteristic. The *assert()* here is another case of making sure the
+This code excerpt handles read accesses to the device characteristic.
+*ctxt->om* is chained memory buffer that for reads is being populated
+with characteristic data. Returned value is either 0 for success or
+*BLE_ATT_ERR_INSUFFICIENT_RES* if failed. The check makes sure the
NimBLE stack is doing its job; this characteristic was registered as
read-only, so the stack should have prevented write accesses.
-To fulfill a characteristic read request, the application needs to
-assign the *ctxt->chr\_access.data* field to point to the attribute data
-to respond with, and fill the *ctxt->chr\_access.len* field with the
-length of the attribute data. *bleprph* stores the device name in
-read-only memory as follows:
-
-.. code:: c
-
- const char *bleprph_device_name = "nimble-bleprph";
-
-The cast to pointer-to-void is a necessary annoyance to remove the
-*const* qualifier from the device name variable. You will need to "cast
-away const" whenever you respond to read requests with read-only data.
-
-It is not shown in the above snippet, but this function ultimately
-returns 0. By returning 0, *bleprph* indicates that the characteristic
-data in *ctxt->chr\_access* is valid and that NimBLE should include it
-in its response to the peer.
-
-**A word of warning:** The attribute data that *ctxt->chr\_access.data*
-points to must remain valid after the access function returns, as the
-NimBLE stack needs to use it to form a GATT read response. In other
-words, you must not allocate the characteristic value data on the stack
-of the access function. Two characteristic accesses never occur at the
-same time, so it is OK to use the same memory for repeated accesses.
-
Write access
^^^^^^^^^^^^
.. code:: c
+
+ static int
+ gatt_svr_chr_write(struct os_mbuf *om, uint16_t min_len, uint16_t max_len,
+ void *dst, uint16_t *len)
+ {
+ uint16_t om_len;
+ int rc;
- case BLE_GAP_CHR_UUID16_RECONNECT_ADDR:
- assert(op == BLE_GATT_ACCESS_OP_WRITE_CHR);
- if (ctxt->chr_access.len != sizeof bleprph_reconnect_addr) {
- return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
- }
- memcpy(bleprph_reconnect_addr, ctxt->chr_access.data,
- sizeof bleprph_reconnect_addr);
- break;
+ om_len = OS_MBUF_PKTLEN(om);
+ if (om_len < min_len || om_len > max_len) {
+ return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
+ }
-This code excerpt handles writes to the reconnect address
-characteristic. This characteristic was registered as write-only, so the
-*assert()* here is just a safety precaution to ensure the NimBLE stack
+ rc = ble_hs_mbuf_to_flat(om, dst, max_len, len);
+ if (rc != 0) {
+ return BLE_ATT_ERR_UNLIKELY;
+ }
+
+ return 0;
+ }
+ // [...]
+ case BLE_GATT_ACCESS_OP_WRITE_CHR:
+ rc = gatt_svr_chr_write(ctxt->om,
+ sizeof gatt_svr_sec_test_static_val,
+ sizeof gatt_svr_sec_test_static_val,
+ &gatt_svr_sec_test_static_val, NULL);
+ return rc;
+
+This code excerpt handles writes to the Static value
+characteristic. This characteristic was registered as read-write, so the
+*return rc* here is just a safety precaution to ensure the NimBLE stack
is doing its job.
-For writes, the roles of the *ctxt->chr\_access.data* and
-*ctxt->chr\_access.len* fields are the reverse of the read case. The
-NimBLE stack uses these fields to indicate the data written by the peer.
+Data is written to the *ctxt->om* buffer from *gatt_svr_sec_test_static_val*
+by ``ble_hs_mbuf_to_flat()`` function. If length of written data greater or
+smaller than length of *gatt_svr_sec_test_static_val*, function return error.
Many characteristics have strict length requirements for write
-operations. This characteristic has such a restriction; if the written
-data is not a 48-bit BR address, the application tells NimBLE to respond
-with an invalid attribute value length error.
-
-For writes, the *ctxt->chr\_access.data* pointer is only valid for the
-duration of the access function. If the application needs to save the
-written data, it should store it elsewhere before the function returns.
-In this case, *bleprph* stores the specified address in a global
-variable called *bleprph\_reconnect\_addr*.
+operations.
\ No newline at end of file
diff --git a/docs/tutorials/ble/bleprph/bleprph.rst b/docs/tutorials/ble/bleprph/bleprph.rst
index 0295535..84b37aa 100644
--- a/docs/tutorials/ble/bleprph/bleprph.rst
+++ b/docs/tutorials/ble/bleprph/bleprph.rst
@@ -20,7 +20,7 @@ Introduction
Overview
^^^^^^^^
-*bleprph* is an example app included in the apache-mynewt-core
+*bleprph* is an example app included in the apache-mynewt-nimble
repository. This app implements a simple BLE peripheral with the
following properties: