You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ad...@apache.org on 2016/08/10 00:10:43 UTC

[5/6] incubator-mynewt-site git commit: Additions to ble app documentation by ccollins476ad. This closes #110.

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/bdf51006/develop/mkdocs/search_index.json
----------------------------------------------------------------------
diff --git a/develop/mkdocs/search_index.json b/develop/mkdocs/search_index.json
index 606acad..a0e1f71 100644
--- a/develop/mkdocs/search_index.json
+++ b/develop/mkdocs/search_index.json
@@ -1467,7 +1467,7 @@
         }, 
         {
             "location": "/os/tutorials/bleprph/bleprph-intro/", 
-            "text": "BLE Peripheral Project\n\n\nIntroduction\n\n\n\n\nOverview\n\n\nbleprph\n is an example app included in the apache-mynewt-core repository.  This app implements a simple BLE peripheral with the following properties:\n\n\n\n\nSupports three services: GAP, GATT, and alert notification service (ANS).\n\n\nSupports a single concurrent connection.\n\n\nAutomatically advertises connectability when not connected to a central device.\n\n\n\n\nThis tutorial aims to provide a guided tour through the \nbleprph\n app source\ncode.  This document builds on some concepts described elsewhere in the Apache\nMynewt documentation.  Before proceeding with this tutorial, you might want to\nfamiliarize yourself with the following pages:\n\n\n\n\nCreate Your First Mynewt Project\n\n\nNimBLE Stack Initialization\n\n\n\n\n\n\nServices, Characteristics, Descriptors\n\n\nA BLE peripheral interfaces with other BLE devices by exposing \nservices\n,\n\ncharacteristics\n, and \ndescriptors\n.
   All three of these entities are\nimplemented at a lower layer via \nattributes\n.  If you are not familiar with\nthese concepts, you will probably want to check out this\n\noverview\n\nfrom the Bluetooth Developer's site before proceeding.\n\n\nNow let's dig in to some C code.", 
+            "text": "BLE Peripheral Project\n\n\nIntroduction\n\n\n\n\nOverview\n\n\nbleprph\n is an example app included in the apache-mynewt-core repository.  This app implements a simple BLE peripheral with the following properties:\n\n\n\n\nSupports a single concurrent connection.\n\n\nAutomatically advertises connectability when not connected to a central device.\n\n\nSupports pairing and bonding.\n\n\nSupports five services.\n\n\n\n\nThis tutorial aims to provide a guided tour through the \nbleprph\n app source\ncode.  This document builds on some concepts described elsewhere in the Apache\nMynewt documentation.  Before proceeding with this tutorial, you might want to\nfamiliarize yourself with the following pages:\n\n\n\n\nCreate Your First Mynewt Project\n\n\nNimBLE Stack Initialization\n\n\n\n\n\n\nServices, Characteristics, Descriptors\n\n\nA BLE peripheral interfaces with other BLE devices by exposing \nservices\n,\n\ncharacteristics\n, and \ndescriptors\n.  All three of 
 these entities are\nimplemented at a lower layer via \nattributes\n.  If you are not familiar with\nthese concepts, you will probably want to check out this\n\noverview\n\nfrom the Bluetooth Developer's site before proceeding.\n\n\nNow let's dig in to some C code.", 
             "title": "toc"
         }, 
         {
@@ -1482,7 +1482,7 @@
         }, 
         {
             "location": "/os/tutorials/bleprph/bleprph-intro/#overview", 
-            "text": "bleprph  is an example app included in the apache-mynewt-core repository.  This app implements a simple BLE peripheral with the following properties:   Supports three services: GAP, GATT, and alert notification service (ANS).  Supports a single concurrent connection.  Automatically advertises connectability when not connected to a central device.   This tutorial aims to provide a guided tour through the  bleprph  app source\ncode.  This document builds on some concepts described elsewhere in the Apache\nMynewt documentation.  Before proceeding with this tutorial, you might want to\nfamiliarize yourself with the following pages:   Create Your First Mynewt Project  NimBLE Stack Initialization", 
+            "text": "bleprph  is an example app included in the apache-mynewt-core repository.  This app implements a simple BLE peripheral with the following properties:   Supports a single concurrent connection.  Automatically advertises connectability when not connected to a central device.  Supports pairing and bonding.  Supports five services.   This tutorial aims to provide a guided tour through the  bleprph  app source\ncode.  This document builds on some concepts described elsewhere in the Apache\nMynewt documentation.  Before proceeding with this tutorial, you might want to\nfamiliarize yourself with the following pages:   Create Your First Mynewt Project  NimBLE Stack Initialization", 
             "title": "Overview"
         }, 
         {
@@ -1492,7 +1492,7 @@
         }, 
         {
             "location": "/os/tutorials/bleprph/bleprph-svc-reg/", 
-            "text": "BLE Peripheral Project\n\n\nService Registration\n\n\n\n\nAttribute Set\n\n\nThe NimBLE host uses a table-based design for GATT server configuration.  The\nset of supported attributes are expressed as a series of tables that resides in\nyour C code.  When possible, we recommend using a single monolithic table, as\nit results in code that is simpler and less error prone.  Multiple tables\ncan be used if it is impractical for the entire attribute set to live in one\nplace in your code.\n\n\nbleprph\n uses a single attribute table located in the \ngatt_svr.c\n file,\nso let's take a look at that now.  The attribute table is called\n\ngatt_svr_svcs\n; here are the first several lines from this table:\n\n\n\n\nstatic\n \nconst\n \nstruct\n \nble_gatt_svc_def\n \ngatt_svr_svcs\n[] \n=\n {\n    {\n        \n/*** Service: GAP. */\n\n        .\ntype\n               \n=\n \nBLE_GATT_SVC_TYPE_PRIMARY\n,\n        .\nuuid128\n            \n=\n \nBLE_UUID16\n(\nBLE_GAP_SVC_UU
 ID16\n),\n        .\ncharacteristics\n    \n=\n (\nstruct\n \nble_gatt_chr_def\n[]) { {\n            \n/*** Characteristic: Device Name. */\n\n            .\nuuid128\n            \n=\n \nBLE_UUID16\n(\nBLE_GAP_CHR_UUID16_DEVICE_NAME\n),\n            .\naccess_cb\n          \n=\n \ngatt_svr_chr_access_gap\n,\n            .\nflags\n              \n=\n \nBLE_GATT_CHR_F_READ\n,\n        }, {\n            \n/*** Characteristic: Appearance. */\n\n            .\nuuid128\n            \n=\n \nBLE_UUID16\n(\nBLE_GAP_CHR_UUID16_APPEARANCE\n),\n            .\naccess_cb\n          \n=\n \ngatt_svr_chr_access_gap\n,\n            .\nflags\n              \n=\n \nBLE_GATT_CHR_F_READ\n,\n        }, {\n    \n// [...]\n\n\n\n\n\n\n\n\nAs you can see, the table is an array of service definitions (\n\nstruct ble_gatt_svc_def\n).  This code excerpt contains a small part of the\n\nGAP service\n.  The GAP service exposes generic information about a device,\nsuch as its name and appearance.  Support for the 
 GAP service is mandatory for\nall BLE peripherals.  Let's now consider the contents of this table in more\ndetail.\n\n\nA service definition consists of the following fields:\n\n\n\n\n\n\n\n\nField\n\n\nMeaning\n\n\nNotes\n\n\n\n\n\n\n\n\n\n\ntype\n\n\nSpecifies whether this is a primary or secondary service.\n\n\nSecondary services are not very common.  When in doubt, specify \nBLE_GATT_SVC_TYPE_PRIMARY\n for new services.\n\n\n\n\n\n\nuuid128\n\n\nThe 128-bit UUID of this service.\n\n\nIf the service has a 16-bit UUID, you can convert it to its corresponding 128-bit UUID with the \nBLE_UUID16()\n macro.\n\n\n\n\n\n\ncharacteristics\n\n\nThe array of characteristics that belong to this service.\n\n\n\n\n\n\n\n\n\n\n\n\nA service is little more than a container of characteristics; the\ncharacteristics themselves are where the real action happens.  A characteristic\ndefinition consists of the following fields:\n\n\n\n\n\n\n\n\nField\n\n\nMeaning\n\n\nNotes\n\n\n\n\n\n\n\n\n\n\nuuid12
 8\n\n\nThe 128-bit UUID of this characteristic.\n\n\nIf the characteristic has a 16-bit UUID, you can convert it to its corresponding 128-bit UUID with the \nBLE_UUID16()\n macro.\n\n\n\n\n\n\naccess_cb\n\n\nA callback function that gets executed whenever a peer device accesses this characteristic.\n\n\nFor reads:\n this function generates the value that gets sent back to the peer.\nFor writes:\n this function provides the written value as an argument.\n\n\n\n\n\n\nflags\n\n\nIndicates which operations are permitted for this characteristic.  The NimBLE stack responds negatively when a peer attempts an unsupported operation.\n\n\nThe full list of flags can be found under \nble_gatt_chr_flags\n in \nnet/nimble/host/include/host/ble_gatt.h\n.\n\n\n\n\n\n\n\n\nThe access callback is what implements the characteristic's behavior.  Access\ncallbacks are described in detail in the next section:\n\nBLE Peripheral - Characteristic Access\n.\n\n\nThe service definition array and each characte
 ristic definition array is\nterminated with an empty entry, represented with a 0.  The below code listing\nshows the last service in the array, including terminating zeros for the\ncharacteristic array and service array.\n\n\n\n\n    {\n        \n/*** Alert Notification Service. */\n\n        .\ntype\n \n=\n \nBLE_GATT_SVC_TYPE_PRIMARY\n,\n        .\nuuid128\n \n=\n \nBLE_UUID16\n(\nGATT_SVR_SVC_ALERT_UUID\n),\n        .\ncharacteristics\n \n=\n (\nstruct\n \nble_gatt_chr_def\n[]) { {\n            .\nuuid128\n \n=\n \nBLE_UUID16\n(\nGATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID\n),\n            .\naccess_cb\n \n=\n \ngatt_svr_chr_access_alert\n,\n            .\nflags\n \n=\n \nBLE_GATT_CHR_F_READ\n,\n        }, {\n            .\nuuid128\n \n=\n \nBLE_UUID16\n(\nGATT_SVR_CHR_NEW_ALERT\n),\n            .\naccess_cb\n \n=\n \ngatt_svr_chr_access_alert\n,\n            .\nflags\n \n=\n \nBLE_GATT_CHR_F_NOTIFY\n,\n        }, {\n            .\nuuid128\n \n=\n \nBLE_UUID16\n(\nGATT_SVR_CHR_SUP_UNR_AL
 ERT_CAT_UUID\n),\n            .\naccess_cb\n \n=\n \ngatt_svr_chr_access_alert\n,\n            .\nflags\n \n=\n \nBLE_GATT_CHR_F_READ\n,\n        }, {\n            .\nuuid128\n \n=\n \nBLE_UUID16\n(\nGATT_SVR_CHR_UNR_ALERT_STAT_UUID\n),\n            .\naccess_cb\n \n=\n \ngatt_svr_chr_access_alert\n,\n            .\nflags\n \n=\n \nBLE_GATT_CHR_F_NOTIFY\n,\n        }, {\n            .\nuuid128\n \n=\n \nBLE_UUID16\n(\nGATT_SVR_CHR_ALERT_NOT_CTRL_PT\n),\n            .\naccess_cb\n \n=\n \ngatt_svr_chr_access_alert\n,\n            .\nflags\n \n=\n \nBLE_GATT_CHR_F_WRITE\n,\n        }, {\n\n            \n0\n, \n/* No more characteristics in this service. */\n\n\n        } },\n    },\n\n    {\n\n        \n0\n, \n/* No more services. */\n\n\n    },\n\n\n\n\n\n\n\nRegistration function\n\n\nAfter you have created your service table, your app needs to register it with the NimBLE stack.  This is done by calling the following function:\n\n\nint\n\n\nble_gatts_register_svcs\n(\nconst\n \nstru
 ct\n \nble_gatt_svc_def\n \n*svcs\n,\n                        \nble_gatt_register_fn\n \n*cb\n, \nvoid\n \n*cb_arg\n)\n\n\n\n\n\nThe function parameters are documented below.\n\n\n\n\n\n\n\n\nParameter\n\n\nMeaning\n\n\nNotes\n\n\n\n\n\n\n\n\n\n\nsvcs\n\n\nThe table of services to register.\n\n\n\n\n\n\n\n\ncb\n\n\nA callback that gets executed each time a service, characteristic, or descriptor is registered.\n\n\nOptional; pass NULL if you don't want to be notified.\n\n\n\n\n\n\ncb_arg\n\n\nAn argument that gets passed to the callback function on each invocation.\n\n\nOptional; pass NULL if there is no callback or if you don't need a special argument.\n\n\n\n\n\n\n\n\nThe \nble_gatts_register_svcs()\n function returns 0 on success, or a\n\nBLE_HS_E[...]\n error code on failure.\n\n\nMore detailed information about the registration callback function can be found\nin the \nBLE User Guide\n (TBD).\n\n\nThe \nbleprph\n app registers its services as follows:\n\n\n    \nrc\n \n=\n \nble_
 gatts_register_svcs\n(\ngatt_svr_svcs\n, \ngatt_svr_register_cb\n, \nNULL\n);\n    \nassert\n(\nrc\n \n==\n \n0\n);\n\n\n\n\n\n\n\nDescriptors and Included Services\n\n\nYour peripheral can also expose descriptors and included services.  These are\nless common, so they are not covered in this tutorial.  For more information,\nsee the \nBLE User Guide\n.", 
+            "text": "BLE Peripheral Project\n\n\nService Registration\n\n\n\n\nAttribute Set\n\n\nThe NimBLE host uses a table-based design for GATT server configuration.  The\nset of supported attributes are expressed as a series of tables that resides in\nyour C code.\n\n\nbleprph\n supports the following services:\n\n\n\n\nGAP\n\n\nGATT\n\n\nnewtmgr\n\n\nAlert Notification\n\n\nSecurity Test\n\n\n\n\nThe first two services (GAP and GATT) are mandatory services that all BLE peripherals must support.  These are implemented in a separate package which the \nbleprph\n app depends on.  Later, we will see how the \nmain()\n function initializes and registers this package.  Your app will follow the same procedure when using GATT service libraries.\n\n\nThe third service, newtmgr, is vendor-specific service supported by most Mynewt devices.  This service is used for remote configuration, status queries, and firmware updates.  As with GAP and GATT, this service is implemented in a package
  separate from the \nbleprph\n app.\n\n\nThe final two services, \nAlert Notification\n and \nSecurity Test\n, are not implemented in separate libraries.  Rather, these services are specific to the app, so they are implemented the \nbleprph\n app itself.  The attribute table used to express these services is located in the \ngatt_svr.c\n file, so let's take a look at that now.  The attribute table is called \ngatt_svr_svcs\n; here are the first several lines from this table:\n\n\n\n\nstatic\n \nconst\n \nstruct\n \nble_gatt_svc_def\n \ngatt_svr_svcs\n[] \n=\n {\n    {\n        \n/*** Alert Notification Service. */\n\n        .\ntype\n \n=\n \nBLE_GATT_SVC_TYPE_PRIMARY\n,\n        .\nuuid128\n \n=\n \nBLE_UUID16\n(\nGATT_SVR_SVC_ALERT_UUID\n),\n        .\ncharacteristics\n \n=\n (\nstruct\n \nble_gatt_chr_def\n[]) { {\n            .\nuuid128\n \n=\n \nBLE_UUID16\n(\nGATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID\n),\n            .\naccess_cb\n \n=\n \ngatt_svr_chr_access_alert\n,\n            .
 \nflags\n \n=\n \nBLE_GATT_CHR_F_READ\n,\n        }, {\n            .\nuuid128\n \n=\n \nBLE_UUID16\n(\nGATT_SVR_CHR_NEW_ALERT\n),\n            .\naccess_cb\n \n=\n \ngatt_svr_chr_access_alert\n,\n            .\nflags\n \n=\n \nBLE_GATT_CHR_F_NOTIFY\n,\n        }, {\n    \n// [...]\n\n\n\n\n\n\n\n\nAs you can see, the table is an array of service definitions (\n\nstruct ble_gatt_svc_def\n).  This code excerpt contains a small part of the\nAlert Notification service.  Let's now consider the contents of this table in\nmore detail.\n\n\nA service definition consists of the following fields:\n\n\n\n\n\n\n\n\nField\n\n\nMeaning\n\n\nNotes\n\n\n\n\n\n\n\n\n\n\ntype\n\n\nSpecifies whether this is a primary or secondary service.\n\n\nSecondary services are not very common.  When in doubt, specify \nBLE_GATT_SVC_TYPE_PRIMARY\n for new services.\n\n\n\n\n\n\nuuid128\n\n\nThe 128-bit UUID of this service.\n\n\nIf the service has a 16-bit UUID, you can convert it to its corresponding 128-bit UU
 ID with the \nBLE_UUID16()\n macro.\n\n\n\n\n\n\ncharacteristics\n\n\nThe array of characteristics that belong to this service.\n\n\n\n\n\n\n\n\n\n\n\n\nA service is little more than a container of characteristics; the\ncharacteristics themselves are where the real action happens.  A characteristic\ndefinition consists of the following fields:\n\n\n\n\n\n\n\n\nField\n\n\nMeaning\n\n\nNotes\n\n\n\n\n\n\n\n\n\n\nuuid128\n\n\nThe 128-bit UUID of this characteristic.\n\n\nIf the characteristic has a 16-bit UUID, you can convert it to its corresponding 128-bit UUID with the \nBLE_UUID16()\n macro.\n\n\n\n\n\n\naccess_cb\n\n\nA callback function that gets executed whenever a peer device accesses this characteristic.\n\n\nFor reads:\n this function generates the value that gets sent back to the peer.\nFor writes:\n this function receives the written value as an argument.\n\n\n\n\n\n\nflags\n\n\nIndicates which operations are permitted for this characteristic.  The NimBLE stack responds neg
 atively when a peer attempts an unsupported operation.\n\n\nThe full list of flags can be found under \nble_gatt_chr_flags\n in \nnet/nimble/host/include/host/ble_gatt.h\n.\n\n\n\n\n\n\n\n\nA characteristic's access callback implements its behavior.  Access\ncallbacks are described in detail in the next section:\n\nBLE Peripheral - Characteristic Access\n.\n\n\nThe service definition array and each characteristic definition array is\nterminated with an empty entry, represented with a 0.  The below code listing\nshows the last service in the array, including terminating zeros for the\ncharacteristic array and service array.\n\n\n\n\n    {\n        \n/*** Service: Security test. */\n\n        .\ntype\n \n=\n \nBLE_GATT_SVC_TYPE_PRIMARY\n,\n        .\nuuid128\n \n=\n \ngatt_svr_svc_sec_test_uuid\n,\n        .\ncharacteristics\n \n=\n (\nstruct\n \nble_gatt_chr_def\n[]) { {\n            \n/*** Characteristic: Random number generator. */\n\n            .\nuuid128\n \n=\n \ngatt_svr_chr_s
 ec_test_rand_uuid\n,\n            .\naccess_cb\n \n=\n \ngatt_svr_chr_access_sec_test\n,\n            .\nflags\n \n=\n \nBLE_GATT_CHR_F_READ\n \n|\n \nBLE_GATT_CHR_F_READ_ENC\n,\n        }, {\n            \n/*** Characteristic: Static value. */\n\n            .\nuuid128\n \n=\n \ngatt_svr_chr_sec_test_static_uuid\n,\n            .\naccess_cb\n \n=\n \ngatt_svr_chr_access_sec_test\n,\n            .\nflags\n \n=\n \nBLE_GATT_CHR_F_READ\n \n|\n\n                     \nBLE_GATT_CHR_F_WRITE\n \n|\n \nBLE_GATT_CHR_F_WRITE_ENC\n,\n        }, {\n            \n0\n, \n/* No more characteristics in this service. */\n\n        } },\n    },\n\n    {\n        \n0\n, \n/* No more services. */\n\n    },\n\n\n\n\n\n\n\nRegistration function\n\n\nAfter you have created your service table, your app needs to register it with the NimBLE stack.  This is done by calling the \nble_gatts_add_svcs()\n function.  There is a small complication, though.  The NimBLE host needs to allocate sufficient resources up
 front to accommodate all of your peripheral's services.  You can ensure your GATT services are accounted for in the host configuration object by calling the \nble_gatts_count_cfg()\n function.\n\n\nThe \nbleprph\n app registers its services in \ngatt_svr.c\n as follows:\n\n\nint\n\n\ngatt_svr_init\n(\nstruct\n \nble_hs_cfg\n \n*cfg\n)\n{\n    \nint\n \nrc\n;\n\n    \nrc\n \n=\n \nble_gatts_count_cfg\n(\ngatt_svr_svcs\n, \ncfg\n);\n    \nif\n (\nrc\n \n!=\n \n0\n) {\n        \nreturn\n \nrc\n;\n    }\n\n    \nrc\n \n=\n \nble_gatts_add_svcs\n(\ngatt_svr_svcs\n);\n    \nif\n (\nrc\n \n!=\n \n0\n) {\n        \nreturn\n \nrc\n;\n    }\n\n    \nreturn\n \n0\n;\n}\n\n\n\n\n\nYou application will perform the above two-step process for each service definition array that you wish to register.  Libraries that implement GATT services will generally expose an initialization function which does this for you.\n\n\n\n\nDescriptors and Included Services\n\n\nYour peripheral can also expose descript
 ors and included services.  These are\nless common, so they are not covered in this tutorial.  For more information,\nsee the \nBLE User Guide\n.", 
             "title": "Service Registration"
         }, 
         {
@@ -1507,12 +1507,12 @@
         }, 
         {
             "location": "/os/tutorials/bleprph/bleprph-svc-reg/#attribute-set", 
-            "text": "The NimBLE host uses a table-based design for GATT server configuration.  The\nset of supported attributes are expressed as a series of tables that resides in\nyour C code.  When possible, we recommend using a single monolithic table, as\nit results in code that is simpler and less error prone.  Multiple tables\ncan be used if it is impractical for the entire attribute set to live in one\nplace in your code.  bleprph  uses a single attribute table located in the  gatt_svr.c  file,\nso let's take a look at that now.  The attribute table is called gatt_svr_svcs ; here are the first several lines from this table:   static   const   struct   ble_gatt_svc_def   gatt_svr_svcs []  =  {\n    {\n         /*** Service: GAP. */ \n        . type                 =   BLE_GATT_SVC_TYPE_PRIMARY ,\n        . uuid128              =   BLE_UUID16 ( BLE_GAP_SVC_UUID16 ),\n        . characteristics      =  ( struct   ble_gatt_chr_def []) { {\n             /*** Characteristic: Device 
 Name. */ \n            . uuid128              =   BLE_UUID16 ( BLE_GAP_CHR_UUID16_DEVICE_NAME ),\n            . access_cb            =   gatt_svr_chr_access_gap ,\n            . flags                =   BLE_GATT_CHR_F_READ ,\n        }, {\n             /*** Characteristic: Appearance. */ \n            . uuid128              =   BLE_UUID16 ( BLE_GAP_CHR_UUID16_APPEARANCE ),\n            . access_cb            =   gatt_svr_chr_access_gap ,\n            . flags                =   BLE_GATT_CHR_F_READ ,\n        }, {\n     // [...]    As you can see, the table is an array of service definitions ( struct ble_gatt_svc_def ).  This code excerpt contains a small part of the GAP service .  The GAP service exposes generic information about a device,\nsuch as its name and appearance.  Support for the GAP service is mandatory for\nall BLE peripherals.  Let's now consider the contents of this table in more\ndetail.  A service definition consists of the following fields:     Field  Meaning  Notes 
      type  Specifies whether this is a primary or secondary service.  Secondary services are not very common.  When in doubt, specify  BLE_GATT_SVC_TYPE_PRIMARY  for new services.    uuid128  The 128-bit UUID of this service.  If the service has a 16-bit UUID, you can convert it to its corresponding 128-bit UUID with the  BLE_UUID16()  macro.    characteristics  The array of characteristics that belong to this service.       A service is little more than a container of characteristics; the\ncharacteristics themselves are where the real action happens.  A characteristic\ndefinition consists of the following fields:     Field  Meaning  Notes      uuid128  The 128-bit UUID of this characteristic.  If the characteristic has a 16-bit UUID, you can convert it to its corresponding 128-bit UUID with the  BLE_UUID16()  macro.    access_cb  A callback function that gets executed whenever a peer device accesses this characteristic.  For reads:  this function generates the value that gets sent 
 back to the peer. For writes:  this function provides the written value as an argument.    flags  Indicates which operations are permitted for this characteristic.  The NimBLE stack responds negatively when a peer attempts an unsupported operation.  The full list of flags can be found under  ble_gatt_chr_flags  in  net/nimble/host/include/host/ble_gatt.h .     The access callback is what implements the characteristic's behavior.  Access\ncallbacks are described in detail in the next section: BLE Peripheral - Characteristic Access .  The service definition array and each characteristic definition array is\nterminated with an empty entry, represented with a 0.  The below code listing\nshows the last service in the array, including terminating zeros for the\ncharacteristic array and service array.       {\n         /*** Alert Notification Service. */ \n        . type   =   BLE_GATT_SVC_TYPE_PRIMARY ,\n        . uuid128   =   BLE_UUID16 ( GATT_SVR_SVC_ALERT_UUID ),\n        . characteri
 stics   =  ( struct   ble_gatt_chr_def []) { {\n            . uuid128   =   BLE_UUID16 ( GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID ),\n            . access_cb   =   gatt_svr_chr_access_alert ,\n            . flags   =   BLE_GATT_CHR_F_READ ,\n        }, {\n            . uuid128   =   BLE_UUID16 ( GATT_SVR_CHR_NEW_ALERT ),\n            . access_cb   =   gatt_svr_chr_access_alert ,\n            . flags   =   BLE_GATT_CHR_F_NOTIFY ,\n        }, {\n            . uuid128   =   BLE_UUID16 ( GATT_SVR_CHR_SUP_UNR_ALERT_CAT_UUID ),\n            . access_cb   =   gatt_svr_chr_access_alert ,\n            . flags   =   BLE_GATT_CHR_F_READ ,\n        }, {\n            . uuid128   =   BLE_UUID16 ( GATT_SVR_CHR_UNR_ALERT_STAT_UUID ),\n            . access_cb   =   gatt_svr_chr_access_alert ,\n            . flags   =   BLE_GATT_CHR_F_NOTIFY ,\n        }, {\n            . uuid128   =   BLE_UUID16 ( GATT_SVR_CHR_ALERT_NOT_CTRL_PT ),\n            . access_cb   =   gatt_svr_chr_access_alert ,\n            . 
 flags   =   BLE_GATT_CHR_F_WRITE ,\n        }, {              0 ,  /* No more characteristics in this service. */          } },\n    },\n\n    {          0 ,  /* No more services. */      },", 
+            "text": "The NimBLE host uses a table-based design for GATT server configuration.  The\nset of supported attributes are expressed as a series of tables that resides in\nyour C code.  bleprph  supports the following services:   GAP  GATT  newtmgr  Alert Notification  Security Test   The first two services (GAP and GATT) are mandatory services that all BLE peripherals must support.  These are implemented in a separate package which the  bleprph  app depends on.  Later, we will see how the  main()  function initializes and registers this package.  Your app will follow the same procedure when using GATT service libraries.  The third service, newtmgr, is vendor-specific service supported by most Mynewt devices.  This service is used for remote configuration, status queries, and firmware updates.  As with GAP and GATT, this service is implemented in a package separate from the  bleprph  app.  The final two services,  Alert Notification  and  Security Test , are not implemented
  in separate libraries.  Rather, these services are specific to the app, so they are implemented the  bleprph  app itself.  The attribute table used to express these services is located in the  gatt_svr.c  file, so let's take a look at that now.  The attribute table is called  gatt_svr_svcs ; here are the first several lines from this table:   static   const   struct   ble_gatt_svc_def   gatt_svr_svcs []  =  {\n    {\n         /*** Alert Notification Service. */ \n        . type   =   BLE_GATT_SVC_TYPE_PRIMARY ,\n        . uuid128   =   BLE_UUID16 ( GATT_SVR_SVC_ALERT_UUID ),\n        . characteristics   =  ( struct   ble_gatt_chr_def []) { {\n            . uuid128   =   BLE_UUID16 ( GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID ),\n            . access_cb   =   gatt_svr_chr_access_alert ,\n            . flags   =   BLE_GATT_CHR_F_READ ,\n        }, {\n            . uuid128   =   BLE_UUID16 ( GATT_SVR_CHR_NEW_ALERT ),\n            . access_cb   =   gatt_svr_chr_access_alert ,\n            . f
 lags   =   BLE_GATT_CHR_F_NOTIFY ,\n        }, {\n     // [...]    As you can see, the table is an array of service definitions ( struct ble_gatt_svc_def ).  This code excerpt contains a small part of the\nAlert Notification service.  Let's now consider the contents of this table in\nmore detail.  A service definition consists of the following fields:     Field  Meaning  Notes      type  Specifies whether this is a primary or secondary service.  Secondary services are not very common.  When in doubt, specify  BLE_GATT_SVC_TYPE_PRIMARY  for new services.    uuid128  The 128-bit UUID of this service.  If the service has a 16-bit UUID, you can convert it to its corresponding 128-bit UUID with the  BLE_UUID16()  macro.    characteristics  The array of characteristics that belong to this service.       A service is little more than a container of characteristics; the\ncharacteristics themselves are where the real action happens.  A characteristic\ndefinition consists of the following fie
 lds:     Field  Meaning  Notes      uuid128  The 128-bit UUID of this characteristic.  If the characteristic has a 16-bit UUID, you can convert it to its corresponding 128-bit UUID with the  BLE_UUID16()  macro.    access_cb  A callback function that gets executed whenever a peer device accesses this characteristic.  For reads:  this function generates the value that gets sent back to the peer. For writes:  this function receives the written value as an argument.    flags  Indicates which operations are permitted for this characteristic.  The NimBLE stack responds negatively when a peer attempts an unsupported operation.  The full list of flags can be found under  ble_gatt_chr_flags  in  net/nimble/host/include/host/ble_gatt.h .     A characteristic's access callback implements its behavior.  Access\ncallbacks are described in detail in the next section: BLE Peripheral - Characteristic Access .  The service definition array and each characteristic definition array is\nterminated wit
 h an empty entry, represented with a 0.  The below code listing\nshows the last service in the array, including terminating zeros for the\ncharacteristic array and service array.       {\n         /*** Service: Security test. */ \n        . type   =   BLE_GATT_SVC_TYPE_PRIMARY ,\n        . uuid128   =   gatt_svr_svc_sec_test_uuid ,\n        . characteristics   =  ( struct   ble_gatt_chr_def []) { {\n             /*** Characteristic: Random number generator. */ \n            . uuid128   =   gatt_svr_chr_sec_test_rand_uuid ,\n            . access_cb   =   gatt_svr_chr_access_sec_test ,\n            . flags   =   BLE_GATT_CHR_F_READ   |   BLE_GATT_CHR_F_READ_ENC ,\n        }, {\n             /*** Characteristic: Static value. */ \n            . uuid128   =   gatt_svr_chr_sec_test_static_uuid ,\n            . access_cb   =   gatt_svr_chr_access_sec_test ,\n            . flags   =   BLE_GATT_CHR_F_READ   | \n                      BLE_GATT_CHR_F_WRITE   |   BLE_GATT_CHR_F_WRITE_ENC ,\n   
      }, {\n             0 ,  /* No more characteristics in this service. */ \n        } },\n    },\n\n    {\n         0 ,  /* No more services. */ \n    },", 
             "title": "Attribute Set"
         }, 
         {
             "location": "/os/tutorials/bleprph/bleprph-svc-reg/#registration-function", 
-            "text": "After you have created your service table, your app needs to register it with the NimBLE stack.  This is done by calling the following function:  int  ble_gatts_register_svcs ( const   struct   ble_gatt_svc_def   *svcs ,\n                         ble_gatt_register_fn   *cb ,  void   *cb_arg )  The function parameters are documented below.     Parameter  Meaning  Notes      svcs  The table of services to register.     cb  A callback that gets executed each time a service, characteristic, or descriptor is registered.  Optional; pass NULL if you don't want to be notified.    cb_arg  An argument that gets passed to the callback function on each invocation.  Optional; pass NULL if there is no callback or if you don't need a special argument.     The  ble_gatts_register_svcs()  function returns 0 on success, or a BLE_HS_E[...]  error code on failure.  More detailed information about the registration callback function can be found\nin the  BLE User Guide  (TBD).  The  
 bleprph  app registers its services as follows:       rc   =   ble_gatts_register_svcs ( gatt_svr_svcs ,  gatt_svr_register_cb ,  NULL );\n     assert ( rc   ==   0 );", 
+            "text": "After you have created your service table, your app needs to register it with the NimBLE stack.  This is done by calling the  ble_gatts_add_svcs()  function.  There is a small complication, though.  The NimBLE host needs to allocate sufficient resources upfront to accommodate all of your peripheral's services.  You can ensure your GATT services are accounted for in the host configuration object by calling the  ble_gatts_count_cfg()  function.  The  bleprph  app registers its services in  gatt_svr.c  as follows:  int  gatt_svr_init ( struct   ble_hs_cfg   *cfg )\n{\n     int   rc ;\n\n     rc   =   ble_gatts_count_cfg ( gatt_svr_svcs ,  cfg );\n     if  ( rc   !=   0 ) {\n         return   rc ;\n    }\n\n     rc   =   ble_gatts_add_svcs ( gatt_svr_svcs );\n     if  ( rc   !=   0 ) {\n         return   rc ;\n    }\n\n     return   0 ;\n}  You application will perform the above two-step process for each service definition array that you wish to register.  Libraries
  that implement GATT services will generally expose an initialization function which does this for you.", 
             "title": "Registration function"
         }, 
         {
@@ -1522,7 +1522,7 @@
         }, 
         {
             "location": "/os/tutorials/bleprph/bleprph-chr-access/", 
-            "text": "BLE Peripheral Project\n\n\nCharacteristic Access\n\n\n\n\nReview\n\n\nA characteristic's access callback implements its behavior.  Recall that\nservices and characteristics are registered with NimBLE via attribute tables.\nEach characteristic definition in an attribute table contains an \naccess_cb\n\nfield.  The \naccess_cb\n field is an application callback that gets executed\nwhenever a peer device attempts to read or write the characteristic.\n\n\nEarlier in this tutorial, we looked at how \nbleprph\n implements the GAP\nservice.  Let's take another look at how \nbleprph\n specifies the first few\ncharacteristics in this service.\n\n\n\n\nstatic\n \nconst\n \nstruct\n \nble_gatt_svc_def\n \ngatt_svr_svcs\n[] \n=\n {\n    {\n        \n/*** Service: GAP. */\n\n        .\ntype\n               \n=\n \nBLE_GATT_SVC_TYPE_PRIMARY\n,\n        .\nuuid128\n            \n=\n \nBLE_UUID16\n(\nBLE_GAP_SVC_UUID16\n),\n        .\ncharacteristics\n    \n=\n (\nstruct\n \nb
 le_gatt_chr_def\n[]) { {\n            \n/*** Characteristic: Device Name. */\n\n            .\nuuid128\n            \n=\n \nBLE_UUID16\n(\nBLE_GAP_CHR_UUID16_DEVICE_NAME\n),\n            .\naccess_cb\n          \n=\n \ngatt_svr_chr_access_gap\n,\n            .\nflags\n              \n=\n \nBLE_GATT_CHR_F_READ\n,\n        }, {\n            \n/*** Characteristic: Appearance. */\n\n            .\nuuid128\n            \n=\n \nBLE_UUID16\n(\nBLE_GAP_CHR_UUID16_APPEARANCE\n),\n            .\naccess_cb\n          \n=\n \ngatt_svr_chr_access_gap\n,\n            .\nflags\n              \n=\n \nBLE_GATT_CHR_F_READ\n,\n        }, {\n    \n// [...]\n\n\n\n\n\n\nAs you can see, \nbleprph\n uses the same \naccess_cb\n function for all the GAP\nservice characteristics, but the developer could have implemented separate\nfunctions for each characteristic if they preferred.  Here is the \naccess_cb\n\nfunction that the GAP service characteristics use:\n\n\n\n\nstatic\n \nint\n\n\ngatt_svr_chr_access_
 gap\n(\nuint16_t\n \nconn_handle\n, \nuint16_t\n \nattr_handle\n, \nuint8_t\n \nop\n,\n                        \nunion\n \nble_gatt_access_ctxt\n \n*ctxt\n, \nvoid\n \n*arg\n)\n{\n    \nuint16_t\n \nuuid16\n;\n\n    \nuuid16\n \n=\n \nble_uuid_128_to_16\n(\nctxt-\nchr_access\n.\nchr-\nuuid128\n);\n    \nassert\n(\nuuid16\n \n!=\n \n0\n);\n\n    \nswitch\n (\nuuid16\n) {\n    \ncase\n \nBLE_GAP_CHR_UUID16_DEVICE_NAME\n:\n        \nassert\n(\nop\n \n==\n \nBLE_GATT_ACCESS_OP_READ_CHR\n);\n        \nctxt-\nchr_access\n.\ndata\n \n=\n (\nvoid\n \n*\n)\nbleprph_device_name\n;\n        \nctxt-\nchr_access\n.\nlen\n \n=\n \nstrlen\n(\nbleprph_device_name\n);\n        \nbreak\n;\n\n    \ncase\n \nBLE_GAP_CHR_UUID16_APPEARANCE\n:\n        \nassert\n(\nop\n \n==\n \nBLE_GATT_ACCESS_OP_READ_CHR\n);\n        \nctxt-\nchr_access\n.\ndata\n \n=\n (\nvoid\n \n*\n)\nbleprph_appearance\n;\n        \nctxt-\nchr_access\n.\nlen\n \n=\n \nsizeof\n \nbleprph_appearance\n;\n        \nbreak\n;\n\n    \ncas
 e\n \nBLE_GAP_CHR_UUID16_PERIPH_PRIV_FLAG\n:\n        \nassert\n(\nop\n \n==\n \nBLE_GATT_ACCESS_OP_READ_CHR\n);\n        \nctxt-\nchr_access\n.\ndata\n \n=\n (\nvoid\n \n*\n)\nbleprph_privacy_flag\n;\n        \nctxt-\nchr_access\n.\nlen\n \n=\n \nsizeof\n \nbleprph_privacy_flag\n;\n        \nbreak\n;\n\n    \ncase\n \nBLE_GAP_CHR_UUID16_RECONNECT_ADDR\n:\n        \nassert\n(\nop\n \n==\n \nBLE_GATT_ACCESS_OP_WRITE_CHR\n);\n        \nif\n (\nctxt-\nchr_access\n.\nlen\n \n!=\n \nsizeof\n \nbleprph_reconnect_addr\n) {\n            \nreturn\n \nBLE_ATT_ERR_INVALID_ATTR_VALUE_LEN\n;\n        }\n        \nmemcpy\n(\nbleprph_reconnect_addr\n, \nctxt-\nchr_access\n.\ndata\n,\n               \nsizeof\n \nbleprph_reconnect_addr\n);\n        \nbreak\n;\n\n    \ncase\n \nBLE_GAP_CHR_UUID16_PERIPH_PREF_CONN_PARAMS\n:\n        \nassert\n(\nop\n \n==\n \nBLE_GATT_ACCESS_OP_READ_CHR\n);\n        \nctxt-\nchr_access\n.\ndata\n \n=\n (\nvoid\n \n*\n)\nbleprph_pref_conn_params\n;\n        \nctxt-\nch
 r_access\n.\nlen\n \n=\n \nsizeof\n \nbleprph_pref_conn_params\n;\n        \nbreak\n;\n\n    \ndefault\n:\n\n        \nassert\n(\n0\n);\n        \nbreak\n;\n    }\n\n    \nreturn\n \n0\n;\n}\n\n\n\n\n\nAfter you've taken a moment to examine the structure of this function, let's explore some details.\n\n\n\n\nFunction signature\n\n\n\n\nstatic\n \nint\n\n\ngatt_svr_chr_access_gap\n(\nuint16_t\n \nconn_handle\n, \nuint16_t\n \nattr_handle\n, \nuint8_t\n \nop\n,\n                        \nunion\n \nble_gatt_access_ctxt\n \n*ctxt\n, \nvoid\n \n*arg\n)\n\n\n\n\n\nA characteristic access function always takes this same set of parameters and\nalways returns an int.  The parameters to this function type are documented\nbelow.\n\n\n\n\n\n\n\n\n\n\nParameter\n\n\nPurpose\n\n\nNotes\n\n\n\n\n\n\n\n\n\n\nconn_handle\n\n\nIndicates which connection the characteristic access was sent over.\n\n\nUse this value to determine which peer is accessing the characteristic.\n\n\n\n\n\n\nattr_handle\n\n\nT
 he low-level ATT handle of the characteristic value attribute.\n\n\nCan be used to determine which characteristic is being accessed if you don't want to perform a UUID lookup.\n\n\n\n\n\n\nop\n\n\nIndicates whether this is a read or write operation\n\n\nValid values are:\nBLE_GATT_ACCESS_OP_READ_CHR\nBLE_GATT_ACCESS_OP_WRITE_CHR\n\n\n\n\n\n\nctxt\n\n\nContains the characteristic value pointer that the application needs to access.\n\n\nFor characteristic accesses, use the \nctxt-\nchr_access\n member; for descriptor accesses, use the \nctxt-\ndsc_access\n member.\n\n\n\n\n\n\n\n\nThe return value of the access function tells the NimBLE stack how to respond\nto the peer performing the operation.  A value of 0 indicates success.  For\nfailures, the function returns the specific ATT error code that the NimBLE\nstack should respond with.  The ATT error codes are defined in\n\nnet/nimble/host/include/host/ble_att.h\n.\n\n\n\n\nDetermine characteristic being accessed\n\n\n\n\n{\n    \nuint
 16_t\n \nuuid16\n;\n\n    \nuuid16\n \n=\n \nble_uuid_128_to_16\n(\nctxt-\nchr_access\n.\nchr-\nuuid128\n);\n    \nassert\n(\nuuid16\n \n!=\n \n0\n);\n\n    \nswitch\n (\nuuid16\n) {\n        \n// [...]\n\n\n\n\n\n\nThis function uses the UUID to determine which characteristic is being\naccessed.  There are two alternative methods \nbleprph\n could have used to\naccomplish this task:\n\n\n\n\nMap characteristics to ATT handles during service registration; use the \nattr_handle\n parameter as a key into this table during characteristic access.\n\n\nImplement a dedicated function for each characteristic; each function inherently knows which characteristic it corresponds to.\n\n\n\n\nAll the GAP service characteristics have 16-bit UUIDs, so this function uses\nthe \nble_uuid_128_to_16()\n function to convert the 128-bit UUID to its\ncorresponding 16-bit UUID.  This conversion function returns the corresponding\n16-bit UUID on success, or 0 on failure.  Success is asserted here to ensur
 e\nthe NimBLE stack is doing its job properly; the stack should only call this\nfunction for accesses to characteristics that it is registered with, and all\nGAP service characteristics have valid 16-bit UUIDs.\n\n\n\n\nRead access\n\n\n\n\n    \ncase\n \nBLE_GAP_CHR_UUID16_DEVICE_NAME\n:\n        \nassert\n(\nop\n \n==\n \nBLE_GATT_ACCESS_OP_READ_CHR\n);\n        \nctxt-\nchr_access\n.\ndata\n \n=\n (\nvoid\n \n*\n)\nbleprph_device_name\n;\n        \nctxt-\nchr_access\n.\nlen\n \n=\n \nstrlen\n(\nbleprph_device_name\n);\n        \nbreak\n;\n\n\n\n\n\nThis code excerpt handles read accesses to the device name characteristic.  The\n\nassert()\n here is another case of making sure the NimBLE stack is doing its\njob; this characteristic was registered as read-only, so the stack should have\nprevented write accesses.\n\n\nTo fulfill a characteristic read request, the application needs to assign the\n\nctxt-\nchr_access.data\n field to point to the attribute data to respond with,\nand fi
 ll the \nctxt-\nchr_access.len\n field with the length of the attribute data.\n\nbleprph\n stores the device name in read-only memory as follows:\n\n\n\n\nconst\n \nchar\n \n*bleprph_device_name\n \n=\n \nnimble-bleprph\n;\n\n\n\n\n\nThe cast to pointer-to-void is a necessary annoyance to remove the \nconst\n\nqualifier from the device name variable.  You will need to \"cast away const\"\nwhenever you respond to read requests with read-only data.\n\n\nIt is not shown in the above snippet, but this function ultimately returns 0.\nBy returning 0, \nbleprph\n indicates that the characteristic data in\n\nctxt-\nchr_access\n is valid and that NimBLE should include it in its response\nto the peer.\n\n\n\n\nA word of warning:\n The attribute data that \nctxt-\nchr_access.data\n points to\nmust remain valid after the access function returns, as the NimBLE stack needs\nto use it to form a GATT read response.  In other words, you must not\nallocate the characteristic value data on the stack o
 f the access function.\nTwo characteristic accesses never occur at the same time, so it is OK to use\nthe same memory for repeated accesses.\n\n\n\n\nWrite access\n\n\n\n\n    \ncase\n \nBLE_GAP_CHR_UUID16_RECONNECT_ADDR\n:\n        \nassert\n(\nop\n \n==\n \nBLE_GATT_ACCESS_OP_WRITE_CHR\n);\n        \nif\n (\nctxt-\nchr_access\n.\nlen\n \n!=\n \nsizeof\n \nbleprph_reconnect_addr\n) {\n            \nreturn\n \nBLE_ATT_ERR_INVALID_ATTR_VALUE_LEN\n;\n        }\n        \nmemcpy\n(\nbleprph_reconnect_addr\n, \nctxt-\nchr_access\n.\ndata\n,\n               \nsizeof\n \nbleprph_reconnect_addr\n);\n        \nbreak\n;\n\n\n\n\n\nThis code excerpt handles writes to the reconnect address characteristic.  This\ncharacteristic was registered as write-only, so the \nassert()\n here is just a\nsafety precaution to ensure the NimBLE stack is doing its job.\n\n\nFor writes, the roles of the \nctxt-\nchr_access.data\n and \nctxt-\nchr_access.len\n\nfields are the reverse of the read case.  The NimB
 LE stack uses these fields to\nindicate the data written by the peer.\n\n\nMany characteristics have strict length requirements for write operations.\nThis characteristic has such a restriction; if the written data is not a 48-bit\nBR address, the application tells NimBLE to respond with an invalid attribute\nvalue length error.\n\n\nFor writes, the \nctxt-\nchr_access.data\n pointer is only valid for the duration\nof the access function.  If the application needs to save the written data, it\nshould store it elsewhere before the function returns.  In this case, \nbleprph\n\nstores the specified address in a global variable called\n\nbleprph_reconnect_addr\n.", 
+            "text": "BLE Peripheral Project\n\n\nCharacteristic Access\n\n\n\n\nReview\n\n\nA characteristic's access callback implements its behavior.  Recall that\nservices and characteristics are registered with NimBLE via attribute tables.\nEach characteristic definition in an attribute table contains an \naccess_cb\n\nfield.  The \naccess_cb\n field is an application callback that gets executed\nwhenever a peer device attempts to read or write the characteristic.\n\n\nEarlier in this tutorial, we looked at how \nbleprph\n implements the ANS\nservice.  Let's take another look at how \nbleprph\n specifies the first few\ncharacteristics in this service.\n\n\n\n\nstatic\n \nconst\n \nstruct\n \nble_gatt_svc_def\n \ngatt_svr_svcs\n[] \n=\n {\n    {\n        \n/*** Alert Notification Service. */\n\n        .\ntype\n \n=\n \nBLE_GATT_SVC_TYPE_PRIMARY\n,\n        .\nuuid128\n \n=\n \nBLE_UUID16\n(\nGATT_SVR_SVC_ALERT_UUID\n),\n        .\ncharacteristics\n \n=\n (\nstruct\n \nble_gatt_c
 hr_def\n[]) { {\n            .\nuuid128\n \n=\n \nBLE_UUID16\n(\nGATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID\n),\n            .\naccess_cb\n \n=\n \ngatt_svr_chr_access_alert\n,\n            .\nflags\n \n=\n \nBLE_GATT_CHR_F_READ\n,\n        }, {\n            .\nuuid128\n \n=\n \nBLE_UUID16\n(\nGATT_SVR_CHR_NEW_ALERT\n),\n            .\naccess_cb\n \n=\n \ngatt_svr_chr_access_alert\n,\n            .\nflags\n \n=\n \nBLE_GATT_CHR_F_NOTIFY\n,\n        }, {\n    \n// [...]\n\n\n\n\n\n\nAs you can see, \nbleprph\n uses the same \naccess_cb\n function for all the ANS\nservice characteristics, but the developer could have implemented separate\nfunctions for each characteristic if they preferred.  Here is part of the\n\naccess_cb\n function that the ANS service characteristics use:\n\n\n\n\nstatic\n \nint\n\n\ngatt_svr_chr_access_alert\n(\nuint16_t\n \nconn_handle\n, \nuint16_t\n \nattr_handle\n,\n                          \nstruct\n \nble_gatt_access_ctxt\n \n*ctxt\n,\n                          \
 nvoid\n \n*arg\n)\n{\n    \nuint16_t\n \nuuid16\n;\n    \nint\n \nrc\n;\n\n    \nuuid16\n \n=\n \nble_uuid_128_to_16\n(\nctxt-\nchr-\nuuid128\n);\n    \nassert\n(\nuuid16\n \n!=\n \n0\n);\n\n    \nswitch\n (\nuuid16\n) {\n    \ncase\n \nGATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID\n:\n        \nassert\n(\nctxt-\nop\n \n==\n \nBLE_GATT_ACCESS_OP_READ_CHR\n);\n        \nrc\n \n=\n \nos_mbuf_append\n(\nctxt-\nom\n, \ngatt_svr_new_alert_cat\n,\n                            \nsizeof\n \ngatt_svr_new_alert_cat\n);\n        \nreturn\n \nrc\n \n==\n \n0\n \n?\n \n0\n \n:\n \nBLE_ATT_ERR_INSUFFICIENT_RES\n;\n\n    \ncase\n \nGATT_SVR_CHR_UNR_ALERT_STAT_UUID\n:\n        \nif\n (\nctxt-\nop\n \n==\n \nBLE_GATT_ACCESS_OP_WRITE_CHR\n) {\n            \nif\n (\nOS_MBUF_PKTLEN\n(\nctxt-\nom\n) \n!=\n \nsizeof\n \ngatt_svr_unr_alert_stat\n) {\n                \nreturn\n \nBLE_ATT_ERR_INVALID_ATTR_VALUE_LEN\n;\n            }\n\n            \nrc\n \n=\n \nble_hs_mbuf_to_flat\n(\nctxt-\nom\n, \ngatt_svr_unr_aler
 t_stat\n,\n                                     \nsizeof\n \ngatt_svr_unr_alert_stat\n, \nNULL\n);\n            \nif\n (\nrc\n \n!=\n \n0\n) {\n                \nreturn\n \nBLE_ATT_ERR_UNLIKELY\n;\n            }\n\n            \nreturn\n \n0\n;\n\n    \n/* [...] */\n\n\n    \ndefault\n:\n\n        \nassert\n(\n0\n);\n        \nreturn\n \nBLE_ATT_ERR_UNLIKELY\n;\n    }\n}\n\n\n\n\n\nAfter you've taken a moment to examine the structure of this function, let's explore some details.\n\n\n\n\nFunction signature\n\n\nstatic\n \nint\n\n\ngatt_svr_chr_access_alert\n(\nuint16_t\n \nconn_handle\n, \nuint16_t\n \nattr_handle\n,\n                          \nstruct\n \nble_gatt_access_ctxt\n \n*ctxt\n,\n                          \nvoid\n \n*arg\n)\n\n\n\n\n\nA characteristic access function always takes this same set of parameters and\nalways returns an int.  The parameters to this function type are documented\nbelow.\n\n\n\n\n\n\n\n\nParameter\n\n\nPurpose\n\n\nNotes\n\n\n\n\n\n\n\n\n\n\nconn_h
 andle\n\n\nIndicates which connection the characteristic access was sent over.\n\n\nUse this value to determine which peer is accessing the characteristic.\n\n\n\n\n\n\nattr_handle\n\n\nThe low-level ATT handle of the characteristic value attribute.\n\n\nCan be used to determine which characteristic is being accessed if you don't want to perform a UUID lookup.\n\n\n\n\n\n\nop\n\n\nIndicates whether this is a read or write operation\n\n\nValid values are:\nBLE_GATT_ACCESS_OP_READ_CHR\nBLE_GATT_ACCESS_OP_WRITE_CHR\n\n\n\n\n\n\nctxt\n\n\nContains the characteristic value mbuf that the application needs to access.\n\n\nFor characteristic accesses, use the \nctxt-\nchr\n member; for descriptor accesses, use the \nctxt-\ndsc\n member.\n\n\n\n\n\n\n\n\nThe return value of the access function tells the NimBLE stack how to respond\nto the peer performing the operation.  A value of 0 indicates success.  For\nfailures, the function returns the specific \nATT error code\n that the NimBLE\nstack
  should respond with.  \nNote:\n The return code is a formal code, \nnot\n a NimBLE value!\n\n\n\n\nDetermine characteristic being accessed\n\n\n{\n    \nuint16_t\n \nuuid16\n;\n\n    \nuuid16\n \n=\n \nble_uuid_128_to_16\n(\nctxt-\nchr-\nuuid128\n);\n    \nassert\n(\nuuid16\n \n!=\n \n0\n);\n\n    \nswitch\n (\nuuid16\n) {\n        \n// [...]\n\n\n\n\n\n\nThis function uses the UUID to determine which characteristic is being\naccessed.  There are two alternative methods \nbleprph\n could have used to\naccomplish this task:\n\n\n\n\nMap characteristics to ATT handles during service registration; use the \nattr_handle\n parameter as a key into this table during characteristic access.\n\n\nImplement a dedicated function for each characteristic; each function inherently knows which characteristic it corresponds to.\n\n\n\n\nAll the ANS service characteristics have 16-bit UUIDs, so this function uses\nthe \nble_uuid_128_to_16()\n function to convert the 128-bit UUID to its\ncorrespondin
 g 16-bit UUID.  This conversion function returns the corresponding\n16-bit UUID on success, or 0 on failure.  Success is asserted here to ensure\nthe NimBLE stack is doing its job properly; the stack should only call this\nfunction for accesses to characteristics that it is registered with, and all\nANS service characteristics have valid 16-bit UUIDs.\n\n\n\n\nRead access\n\n\n    \ncase\n \nGATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID\n:\n        \nassert\n(\nctxt-\nop\n \n==\n \nBLE_GATT_ACCESS_OP_READ_CHR\n);\n        \nrc\n \n=\n \nos_mbuf_append\n(\nctxt-\nom\n, \ngatt_svr_new_alert_cat\n,\n                            \nsizeof\n \ngatt_svr_new_alert_cat\n);\n        \nreturn\n \nrc\n \n==\n \n0\n \n?\n \n0\n \n:\n \nBLE_ATT_ERR_INSUFFICIENT_RES\n;\n\n\n\n\n\nThis code excerpt handles read accesses to the Supported New Alert Category\ncharacteristic.  The \nassert()\n here is another case of making sure the NimBLE\nstack is doing its job; this characteristic was registered as read-only, 
 so the\nstack should have prevented write accesses.\n\n\nTo fulfill a characteristic read request, the application needs fill a buffer (\nom\n) with the characteristic value.  The NimBLE host will then include the contents of this buffer in its read response.  NimBLE uses \nmbufs\n to exchange data between itself and the application.  To fill an mbuf with data that is available in a contiguous chunk of memory, the \nos_mbuf_append()\n function suffices.  The source of the data, \ngatt_svr_new_alert_cat\n, is is stored in read-only memory as follows:\n\n\n\n\nstatic\n \nconst\n \nuint8_t\n \ngatt_svr_new_alert_cat\n \n=\n \n0x01\n; \n/* Simple alert. */\n\n\n\n\n\n\nIt is not shown in the above snippet, but this function ultimately returns 0.\nBy returning 0, \nbleprph\n indicates that the characteristic data in\n\nctxt-\nom\n is valid and that NimBLE should include it in its response\nto the peer.\n\n\n\n\nWrite access\n\n\nstatic\n \nuint16_t\n \ngatt_svr_unr_alert_stat\n;\n\n\n\n\
 n\n    \ncase\n \nGATT_SVR_CHR_UNR_ALERT_STAT_UUID\n:\n        \nif\n (\nctxt-\nop\n \n==\n \nBLE_GATT_ACCESS_OP_WRITE_CHR\n) {\n            \nif\n (\nOS_MBUF_PKTLEN\n(\nctxt-\nom\n) \n!=\n \nsizeof\n \ngatt_svr_unr_alert_stat\n) {\n                \nreturn\n \nBLE_ATT_ERR_INVALID_ATTR_VALUE_LEN\n;\n            }\n\n            \nrc\n \n=\n \nble_hs_mbuf_to_flat\n(\nctxt-\nom\n, \ngatt_svr_unr_alert_stat\n,\n                                     \nsizeof\n \ngatt_svr_unr_alert_stat\n, \nNULL\n);\n            \nif\n (\nrc\n \n!=\n \n0\n) {\n                \nreturn\n \nBLE_ATT_ERR_UNLIKELY\n;\n            }\n\n            \nreturn\n \n0\n;\n        } \nelse\n \n/* [...] */\n\n\n\n\n\n\nThis code excerpt handles writes to the New Alert characteristic.  For writes,\nthe role of the \nctxt-\nom\n field is the reverse of the read case.  The NimBLE\nstack uses these fields to indicate the data written by the peer.\n\n\nMany characteristics have strict length requirements for write operatio
 ns.\nThis characteristic has such a restriction; if the written data is not a 2-byte\nvalue, the application tells NimBLE to respond with an invalid attribute value\nlength error.\n\n\nbleprph\n copies the data out of the supplied mbuf and writes it to a contiguous chunk of storage (the \ngatt_svr_unr_alert_stat\n variable).  This is accomplished with the \nble_hs_mbuf_to_flat()\n function.  If the application did not have a suitable destination for the data handy, it could have inherited the mbuf from the context object.  This is done by saving a copy of the mbuf pointer, and assigning \nNULL\n to \nctxt-\nom\n.  By assigning \nNULL\n to the mbuf pointer, your application prevents the stack from freeing the mbuf while it is still being used.  Be aware, however, that it is the application's responsibility to free inherited mbufs.", 
             "title": "Characteristic Access"
         }, 
         {
@@ -1537,32 +1537,32 @@
         }, 
         {
             "location": "/os/tutorials/bleprph/bleprph-chr-access/#review", 
-            "text": "A characteristic's access callback implements its behavior.  Recall that\nservices and characteristics are registered with NimBLE via attribute tables.\nEach characteristic definition in an attribute table contains an  access_cb \nfield.  The  access_cb  field is an application callback that gets executed\nwhenever a peer device attempts to read or write the characteristic.  Earlier in this tutorial, we looked at how  bleprph  implements the GAP\nservice.  Let's take another look at how  bleprph  specifies the first few\ncharacteristics in this service.   static   const   struct   ble_gatt_svc_def   gatt_svr_svcs []  =  {\n    {\n         /*** Service: GAP. */ \n        . type                 =   BLE_GATT_SVC_TYPE_PRIMARY ,\n        . uuid128              =   BLE_UUID16 ( BLE_GAP_SVC_UUID16 ),\n        . characteristics      =  ( struct   ble_gatt_chr_def []) { {\n             /*** Characteristic: Device Name. */ \n            . uuid128              =   BLE_UUID
 16 ( BLE_GAP_CHR_UUID16_DEVICE_NAME ),\n            . access_cb            =   gatt_svr_chr_access_gap ,\n            . flags                =   BLE_GATT_CHR_F_READ ,\n        }, {\n             /*** Characteristic: Appearance. */ \n            . uuid128              =   BLE_UUID16 ( BLE_GAP_CHR_UUID16_APPEARANCE ),\n            . access_cb            =   gatt_svr_chr_access_gap ,\n            . flags                =   BLE_GATT_CHR_F_READ ,\n        }, {\n     // [...]   As you can see,  bleprph  uses the same  access_cb  function for all the GAP\nservice characteristics, but the developer could have implemented separate\nfunctions for each characteristic if they preferred.  Here is the  access_cb \nfunction that the GAP service characteristics use:   static   int  gatt_svr_chr_access_gap ( uint16_t   conn_handle ,  uint16_t   attr_handle ,  uint8_t   op ,\n                         union   ble_gatt_access_ctxt   *ctxt ,  void   *arg )\n{\n     uint16_t   uuid16 ;\n\n     uuid16   =
    ble_uuid_128_to_16 ( ctxt- chr_access . chr- uuid128 );\n     assert ( uuid16   !=   0 );\n\n     switch  ( uuid16 ) {\n     case   BLE_GAP_CHR_UUID16_DEVICE_NAME :\n         assert ( op   ==   BLE_GATT_ACCESS_OP_READ_CHR );\n         ctxt- chr_access . data   =  ( void   * ) bleprph_device_name ;\n         ctxt- chr_access . len   =   strlen ( bleprph_device_name );\n         break ;\n\n     case   BLE_GAP_CHR_UUID16_APPEARANCE :\n         assert ( op   ==   BLE_GATT_ACCESS_OP_READ_CHR );\n         ctxt- chr_access . data   =  ( void   * ) bleprph_appearance ;\n         ctxt- chr_access . len   =   sizeof   bleprph_appearance ;\n         break ;\n\n     case   BLE_GAP_CHR_UUID16_PERIPH_PRIV_FLAG :\n         assert ( op   ==   BLE_GATT_ACCESS_OP_READ_CHR );\n         ctxt- chr_access . data   =  ( void   * ) bleprph_privacy_flag ;\n         ctxt- chr_access . len   =   sizeof   bleprph_privacy_flag ;\n         break ;\n\n     case   BLE_GAP_CHR_UUID16_RECONNECT_ADDR :\n         a
 ssert ( op   ==   BLE_GATT_ACCESS_OP_WRITE_CHR );\n         if  ( ctxt- chr_access . len   !=   sizeof   bleprph_reconnect_addr ) {\n             return   BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN ;\n        }\n         memcpy ( bleprph_reconnect_addr ,  ctxt- chr_access . data ,\n                sizeof   bleprph_reconnect_addr );\n         break ;\n\n     case   BLE_GAP_CHR_UUID16_PERIPH_PREF_CONN_PARAMS :\n         assert ( op   ==   BLE_GATT_ACCESS_OP_READ_CHR );\n         ctxt- chr_access . data   =  ( void   * ) bleprph_pref_conn_params ;\n         ctxt- chr_access . len   =   sizeof   bleprph_pref_conn_params ;\n         break ;\n\n     default : \n         assert ( 0 );\n         break ;\n    }\n\n     return   0 ;\n}  After you've taken a moment to examine the structure of this function, let's explore some details.", 
+            "text": "A characteristic's access callback implements its behavior.  Recall that\nservices and characteristics are registered with NimBLE via attribute tables.\nEach characteristic definition in an attribute table contains an  access_cb \nfield.  The  access_cb  field is an application callback that gets executed\nwhenever a peer device attempts to read or write the characteristic.  Earlier in this tutorial, we looked at how  bleprph  implements the ANS\nservice.  Let's take another look at how  bleprph  specifies the first few\ncharacteristics in this service.   static   const   struct   ble_gatt_svc_def   gatt_svr_svcs []  =  {\n    {\n         /*** Alert Notification Service. */ \n        . type   =   BLE_GATT_SVC_TYPE_PRIMARY ,\n        . uuid128   =   BLE_UUID16 ( GATT_SVR_SVC_ALERT_UUID ),\n        . characteristics   =  ( struct   ble_gatt_chr_def []) { {\n            . uuid128   =   BLE_UUID16 ( GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID ),\n            . access_cb   =
    gatt_svr_chr_access_alert ,\n            . flags   =   BLE_GATT_CHR_F_READ ,\n        }, {\n            . uuid128   =   BLE_UUID16 ( GATT_SVR_CHR_NEW_ALERT ),\n            . access_cb   =   gatt_svr_chr_access_alert ,\n            . flags   =   BLE_GATT_CHR_F_NOTIFY ,\n        }, {\n     // [...]   As you can see,  bleprph  uses the same  access_cb  function for all the ANS\nservice characteristics, but the developer could have implemented separate\nfunctions for each characteristic if they preferred.  Here is part of the access_cb  function that the ANS service characteristics use:   static   int  gatt_svr_chr_access_alert ( uint16_t   conn_handle ,  uint16_t   attr_handle ,\n                           struct   ble_gatt_access_ctxt   *ctxt ,\n                           void   *arg )\n{\n     uint16_t   uuid16 ;\n     int   rc ;\n\n     uuid16   =   ble_uuid_128_to_16 ( ctxt- chr- uuid128 );\n     assert ( uuid16   !=   0 );\n\n     switch  ( uuid16 ) {\n     case   GATT_SVR_CHR_
 SUP_NEW_ALERT_CAT_UUID :\n         assert ( ctxt- op   ==   BLE_GATT_ACCESS_OP_READ_CHR );\n         rc   =   os_mbuf_append ( ctxt- om ,  gatt_svr_new_alert_cat ,\n                             sizeof   gatt_svr_new_alert_cat );\n         return   rc   ==   0   ?   0   :   BLE_ATT_ERR_INSUFFICIENT_RES ;\n\n     case   GATT_SVR_CHR_UNR_ALERT_STAT_UUID :\n         if  ( ctxt- op   ==   BLE_GATT_ACCESS_OP_WRITE_CHR ) {\n             if  ( OS_MBUF_PKTLEN ( ctxt- om )  !=   sizeof   gatt_svr_unr_alert_stat ) {\n                 return   BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN ;\n            }\n\n             rc   =   ble_hs_mbuf_to_flat ( ctxt- om ,  gatt_svr_unr_alert_stat ,\n                                      sizeof   gatt_svr_unr_alert_stat ,  NULL );\n             if  ( rc   !=   0 ) {\n                 return   BLE_ATT_ERR_UNLIKELY ;\n            }\n\n             return   0 ;\n\n     /* [...] */ \n\n     default : \n         assert ( 0 );\n         return   BLE_ATT_ERR_UNLIKELY ;\n  
   }\n}  After you've taken a moment to examine the structure of this function, let's explore some details.", 
             "title": "Review"
         }, 
         {
             "location": "/os/tutorials/bleprph/bleprph-chr-access/#function-signature", 
-            "text": "static   int  gatt_svr_chr_access_gap ( uint16_t   conn_handle ,  uint16_t   attr_handle ,  uint8_t   op ,\n                         union   ble_gatt_access_ctxt   *ctxt ,  void   *arg )  A characteristic access function always takes this same set of parameters and\nalways returns an int.  The parameters to this function type are documented\nbelow.      Parameter  Purpose  Notes      conn_handle  Indicates which connection the characteristic access was sent over.  Use this value to determine which peer is accessing the characteristic.    attr_handle  The low-level ATT handle of the characteristic value attribute.  Can be used to determine which characteristic is being accessed if you don't want to perform a UUID lookup.    op  Indicates whether this is a read or write operation  Valid values are: BLE_GATT_ACCESS_OP_READ_CHR BLE_GATT_ACCESS_OP_WRITE_CHR    ctxt  Contains the characteristic value pointer that the application needs to access.  For characteristic ac
 cesses, use the  ctxt- chr_access  member; for descriptor accesses, use the  ctxt- dsc_access  member.     The return value of the access function tells the NimBLE stack how to respond\nto the peer performing the operation.  A value of 0 indicates success.  For\nfailures, the function returns the specific ATT error code that the NimBLE\nstack should respond with.  The ATT error codes are defined in net/nimble/host/include/host/ble_att.h .", 
+            "text": "static   int  gatt_svr_chr_access_alert ( uint16_t   conn_handle ,  uint16_t   attr_handle ,\n                           struct   ble_gatt_access_ctxt   *ctxt ,\n                           void   *arg )  A characteristic access function always takes this same set of parameters and\nalways returns an int.  The parameters to this function type are documented\nbelow.     Parameter  Purpose  Notes      conn_handle  Indicates which connection the characteristic access was sent over.  Use this value to determine which peer is accessing the characteristic.    attr_handle  The low-level ATT handle of the characteristic value attribute.  Can be used to determine which characteristic is being accessed if you don't want to perform a UUID lookup.    op  Indicates whether this is a read or write operation  Valid values are: BLE_GATT_ACCESS_OP_READ_CHR BLE_GATT_ACCESS_OP_WRITE_CHR    ctxt  Contains the characteristic value mbuf that the application needs to access.  For chara
 cteristic accesses, use the  ctxt- chr  member; for descriptor accesses, use the  ctxt- dsc  member.     The return value of the access function tells the NimBLE stack how to respond\nto the peer performing the operation.  A value of 0 indicates success.  For\nfailures, the function returns the specific  ATT error code  that the NimBLE\nstack should respond with.   Note:  The return code is a formal code,  not  a NimBLE value!", 
             "title": "Function signature"
         }, 
         {
             "location": "/os/tutorials/bleprph/bleprph-chr-access/#determine-characteristic-being-accessed", 
-            "text": "{\n     uint16_t   uuid16 ;\n\n     uuid16   =   ble_uuid_128_to_16 ( ctxt- chr_access . chr- uuid128 );\n     assert ( uuid16   !=   0 );\n\n     switch  ( uuid16 ) {\n         // [...]   This function uses the UUID to determine which characteristic is being\naccessed.  There are two alternative methods  bleprph  could have used to\naccomplish this task:   Map characteristics to ATT handles during service registration; use the  attr_handle  parameter as a key into this table during characteristic access.  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\nthe  ble_uuid_128_to_16()  function to convert the 128-bit UUID to its\ncorresponding 16-bit UUID.  This conversion function returns the corresponding\n16-bit UUID on success, or 0 on failure.  Success is asserted here to ensure\nthe NimBLE stack is doing i
 ts job properly; the stack should only call this\nfunction for accesses to characteristics that it is registered with, and all\nGAP service characteristics have valid 16-bit UUIDs.", 
+            "text": "{\n     uint16_t   uuid16 ;\n\n     uuid16   =   ble_uuid_128_to_16 ( ctxt- chr- uuid128 );\n     assert ( uuid16   !=   0 );\n\n     switch  ( uuid16 ) {\n         // [...]   This function uses the UUID to determine which characteristic is being\naccessed.  There are two alternative methods  bleprph  could have used to\naccomplish this task:   Map characteristics to ATT handles during service registration; use the  attr_handle  parameter as a key into this table during characteristic access.  Implement a dedicated function for each characteristic; each function inherently knows which characteristic it corresponds to.   All the ANS service characteristics have 16-bit UUIDs, so this function uses\nthe  ble_uuid_128_to_16()  function to convert the 128-bit UUID to its\ncorresponding 16-bit UUID.  This conversion function returns the corresponding\n16-bit UUID on success, or 0 on failure.  Success is asserted here to ensure\nthe NimBLE stack is doing its job proper
 ly; the stack should only call this\nfunction for accesses to characteristics that it is registered with, and all\nANS service characteristics have valid 16-bit UUIDs.", 
             "title": "Determine characteristic being accessed"
         }, 
         {
             "location": "/os/tutorials/bleprph/bleprph-chr-access/#read-access", 
-            "text": "case   BLE_GAP_CHR_UUID16_DEVICE_NAME :\n         assert ( op   ==   BLE_GATT_ACCESS_OP_READ_CHR );\n         ctxt- chr_access . data   =  ( void   * ) bleprph_device_name ;\n         ctxt- chr_access . len   =   strlen ( bleprph_device_name );\n         break ;  This code excerpt handles read accesses to the device name characteristic.  The assert()  here is another case of making sure the NimBLE stack is doing its\njob; this characteristic was registered as read-only, so the stack should have\nprevented 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,\nand 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:   const   char   *bleprph_device_name   =   nimble-bleprph ;  The cast to pointer-to-void is a necessary annoyance to remove the  const \nqualifier
  from the device name variable.  You will need to \"cast away const\"\nwhenever you respond to read requests with read-only data.  It is not shown in the above snippet, but this function ultimately returns 0.\nBy returning 0,  bleprph  indicates that the characteristic data in ctxt- chr_access  is valid and that NimBLE should include it in its response\nto the peer.   A word of warning:  The attribute data that  ctxt- chr_access.data  points to\nmust remain valid after the access function returns, as the NimBLE stack needs\nto use it to form a GATT read response.  In other words, you must not\nallocate the characteristic value data on the stack of the access function.\nTwo characteristic accesses never occur at the same time, so it is OK to use\nthe same memory for repeated accesses.", 
+            "text": "case   GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID :\n         assert ( ctxt- op   ==   BLE_GATT_ACCESS_OP_READ_CHR );\n         rc   =   os_mbuf_append ( ctxt- om ,  gatt_svr_new_alert_cat ,\n                             sizeof   gatt_svr_new_alert_cat );\n         return   rc   ==   0   ?   0   :   BLE_ATT_ERR_INSUFFICIENT_RES ;  This code excerpt handles read accesses to the Supported New Alert Category\ncharacteristic.  The  assert()  here is another case of making sure the NimBLE\nstack is doing its job; this characteristic was registered as read-only, so the\nstack should have prevented write accesses.  To fulfill a characteristic read request, the application needs fill a buffer ( om ) with the characteristic value.  The NimBLE host will then include the contents of this buffer in its read response.  NimBLE uses  mbufs  to exchange data between itself and the application.  To fill an mbuf with data that is available in a contiguous chunk of memory, the  os_mbuf_a
 ppend()  function suffices.  The source of the data,  gatt_svr_new_alert_cat , is is stored in read-only memory as follows:   static   const   uint8_t   gatt_svr_new_alert_cat   =   0x01 ;  /* Simple alert. */   It is not shown in the above snippet, but this function ultimately returns 0.\nBy returning 0,  bleprph  indicates that the characteristic data in ctxt- om  is valid and that NimBLE should include it in its response\nto the peer.", 
             "title": "Read access"
         }, 
         {
             "location": "/os/tutorials/bleprph/bleprph-chr-access/#write-access", 
-            "text": "case   BLE_GAP_CHR_UUID16_RECONNECT_ADDR :\n         assert ( op   ==   BLE_GATT_ACCESS_OP_WRITE_CHR );\n         if  ( ctxt- chr_access . len   !=   sizeof   bleprph_reconnect_addr ) {\n             return   BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN ;\n        }\n         memcpy ( bleprph_reconnect_addr ,  ctxt- chr_access . data ,\n                sizeof   bleprph_reconnect_addr );\n         break ;  This code excerpt handles writes to the reconnect address characteristic.  This\ncharacteristic was registered as write-only, so the  assert()  here is just a\nsafety 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 \nfields are the reverse of the read case.  The NimBLE stack uses these fields to\nindicate the data written by the peer.  Many characteristics have strict length requirements for write operations.\nThis characteristic has such a restriction; if the written data is not a 48
 -bit\nBR address, the application tells NimBLE to respond with an invalid attribute\nvalue length error.  For writes, the  ctxt- chr_access.data  pointer is only valid for the duration\nof the access function.  If the application needs to save the written data, it\nshould store it elsewhere before the function returns.  In this case,  bleprph \nstores the specified address in a global variable called bleprph_reconnect_addr .", 
+            "text": "static   uint16_t   gatt_svr_unr_alert_stat ;       case   GATT_SVR_CHR_UNR_ALERT_STAT_UUID :\n         if  ( ctxt- op   ==   BLE_GATT_ACCESS_OP_WRITE_CHR ) {\n             if  ( OS_MBUF_PKTLEN ( ctxt- om )  !=   sizeof   gatt_svr_unr_alert_stat ) {\n                 return   BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN ;\n            }\n\n             rc   =   ble_hs_mbuf_to_flat ( ctxt- om ,  gatt_svr_unr_alert_stat ,\n                                      sizeof   gatt_svr_unr_alert_stat ,  NULL );\n             if  ( rc   !=   0 ) {\n                 return   BLE_ATT_ERR_UNLIKELY ;\n            }\n\n             return   0 ;\n        }  else   /* [...] */   This code excerpt handles writes to the New Alert characteristic.  For writes,\nthe role of the  ctxt- om  field is the reverse of the read case.  The NimBLE\nstack uses these fields to indicate the data written by the peer.  Many characteristics have strict length requirements for write operations.\nThis character
 istic has such a restriction; if the written data is not a 2-byte\nvalue, the application tells NimBLE to respond with an invalid attribute value\nlength error.  bleprph  copies the data out of the supplied mbuf and writes it to a contiguous chunk of storage (the  gatt_svr_unr_alert_stat  variable).  This is accomplished with the  ble_hs_mbuf_to_flat()  function.  If the application did not have a suitable destination for the data handy, it could have inherited the mbuf from the context object.  This is done by saving a copy of the mbuf pointer, and assigning  NULL  to  ctxt- om .  By assigning  NULL  to the mbuf pointer, your application prevents the stack from freeing the mbuf while it is still being used.  Be aware, however, that it is the application's responsibility to free inherited mbufs.", 
             "title": "Write access"
         }, 
         {
             "location": "/os/tutorials/bleprph/bleprph-adv/", 
-            "text": "BLE Peripheral Project\n\n\nAdvertising\n\n\n\n\nOverview\n\n\nA peripheral announces its presence to the world by broadcasting\nadvertisements.  An advertisement typically contains additional information\nabout the peripheral sending it, such as the device name and an abbreviated\nlist of supported services.  The presence of this information helps a listening\ncentral to determine whether it is interested in connecting to the peripheral.\nAdvertisements are quite limited in the amount of information they can contain,\nso only the most important information should be included.\n\n\nWhen a listening device receives an advertisement, it can choose to connect to\nthe peripheral, or query the sender for more information.  This second action\nis known as an \nactive scan\n.  A peripheral responds to an active scan with\nsome extra information that it couldn't fit in its advertisement.  This\nadditional information is known as \nscan response data\n.  \nbleprph\n does
  not\nconfigure any scan response data, so this feature is not discussed in the\nremainder of this tutorial.\n\n\nbleprph\n constantly broadcasts advertisements until a central connects to it.\nWhen a connection is terminated, \nbleprph\n resumes advertising.\n\n\nLet's take a look at \nbleprph\n's advertisement code (\nmain.c\n):\n\n\n\n\n/**\n\n\n * Enables advertising with the following parameters:\n\n\n *     o General discoverable mode.\n\n\n *     o Undirected connectable mode.\n\n\n */\n\n\nstatic\n \nvoid\n\n\nbleprph_advertise\n(\nvoid\n)\n{\n    \nstruct\n \nble_hs_adv_fields\n \nfields\n;\n    \nint\n \nrc\n;\n\n    \n/* Set the advertisement data included in our advertisements. */\n\n    \nmemset\n(\nfields\n, \n0\n, \nsizeof\n \nfields\n);\n    \nfields\n.\nname\n \n=\n (\nuint8_t\n \n*\n)\nbleprph_device_name\n;\n    \nfields\n.\nname_len\n \n=\n \nstrlen\n(\nbleprph_device_name\n);\n    \nfields\n.\nname_is_complete\n \n=\n \n1\n;\n    \nrc\n \n=\n \nble_gap_adv_set_f
 ields\n(\nfields\n);\n    \nif\n (\nrc\n \n!=\n \n0\n) {\n        \nBLEPRPH_LOG\n(\nERROR\n, \nerror setting advertisement data; rc=%d\\n\n, \nrc\n);\n        \nreturn\n;\n    }\n\n    \n/* Begin advertising. */\n\n    \nrc\n \n=\n \nble_gap_adv_start\n(\nBLE_GAP_DISC_MODE_GEN\n, \nBLE_GAP_CONN_MODE_UND\n,\n                           \nNULL\n, \n0\n, \nNULL\n, \nbleprph_on_connect\n, \nNULL\n);\n    \nif\n (\nrc\n \n!=\n \n0\n) {\n        \nBLEPRPH_LOG\n(\nERROR\n, \nerror enabling advertisement; rc=%d\\n\n, \nrc\n);\n        \nreturn\n;\n    }\n}\n\n\n\n\n\nNow let's examine this code in detail.\n\n\n\n\nSetting advertisement data\n\n\nA NimBLE peripheral specifies what information to include in its advertisements with the following function:\n\n\n\n\nint\n\n\nble_gap_adv_set_fields\n(\nstruct\n \nble_hs_adv_fields\n \n*adv_fields\n)\n\n\n\n\n\n\n\nThe \nadv_fields\n argument specifies the fields and their contents to include in\nsubsequent advertisements.  The Bluetooth \nCore Spe
 cification\nSupplement\n\ndefines a set of standard fields that can be included in an advertisement; the\nmember variables of the \nstruct ble_hs_adv_fields\n type correspond to these\nstandard fields.  Information that doesn't fit neatly into a standard field\nshould be put in the \nmanufacturing specific data\n field.\n\n\nAs you can see in the above code listing, the \nstruct ble_hs_adv_fields\n\ninstance is allocated on the stack.  It is OK to use the stack for this struct\nand the data it references, as the \nble_gap_adv_set_fields()\n\nfunction makes a copy of all the advertisement data before it returns.\n\nbleprph\n doesn't take full advantange of this; it stores its device name in a\nstatic array.\n\n\nThe code sets three members of the \nstruct ble_hs_adv_fields\n instance:\n\n\n\n\nname\n\n\nname_len\n\n\nname_is_complete\n\n\n\n\nThe first two fields are used to communicate the device's name and are quite\nstraight-forward.  The third field requires some explanation.  Bl
 uetooth\nspecifies two name-related advertisement fields: \nShortened Local Name\n and\n\nComplete Local Name\n.  Setting the \nname_is_complete\n variable to 1 or 0 tells\nNimBLE which of these two fields to include in advertisements.  Some other\nadvertisement fields also correspond to multiple variables in the field struct,\nso it is a good idea to review the \nble_hs_adv_fields\n reference to\nmake sure you get the details right in your app.\n\n\n\n\nBegin advertising\n\n\nAn app starts advertising with the following function:\n\n\n\n\nint\n\n\nble_gap_adv_start\n(\nuint8_t\n \ndiscoverable_mode\n, \nuint8_t\n \nconnectable_mode\n,\n                  \nuint8_t\n \n*peer_addr\n, \nuint8_t\n \npeer_addr_type\n,\n                  \nstruct\n \nhci_adv_params\n \n*adv_params\n,\n                  \nble_gap_conn_fn\n \n*cb\n, \nvoid\n \n*cb_arg\n)\n\n\n\n\n\nThis function allows a lot of flexibility, and it might seem daunting at first\nglance.  \nbleprph\n specifies a simple set of 
 arguments that is appropriate for\nmost peripherals.  When getting started on a typical peripheral, we recommend\nyou use the same arguments as \nbleprph\n, with the exception of the last two\n(\ncb\n and \ncb_arg\n).  These last two arguments will be specific to your app, so\nlet's talk about them.\n\n\ncb\n is a callback function.  It gets executed when a central connects to your\nperipheral after receiving an advertisement.  The \ncb_arg\n argument gets passed\nto the \ncb\n callback.  If your callback doesn't need the \ncb_arg\n parameter,\nyou can do what \nbleprph\n does and pass \nNULL\n.  Once a connection is\nestablished, the \ncb\n callback becomes permanently associated with the\nconnection.  All subsequent events related to the connection are communicated\nto your app via calls to this callback function.  Connection callbacks are an\nimportant part of building a BLE app, and we examine \nbleprph\n's connection\ncallback in detail in the next section of this tutorial.\n\n
 \n\n\nOne final note:\n Your peripheral automatically stops advertising when a central connects to it.  You can immediately resume advertising if you want to allow another central to connect, but you will need to do so explicitly by calling \nble_gap_adv_start()\n again.  Also, be aware NimBLE's default configuration only allows a single connection at a time.  NimBLE supports multiple concurrent connections, but you must configure it to do so first.", 
+            "text": "BLE Peripheral Project\n\n\nAdvertising\n\n\n\n\nOverview\n\n\nA peripheral announces its presence to the world by broadcasting\nadvertisements.  An advertisement typically contains additional information\nabout the peripheral sending it, such as the device name and an abbreviated\nlist of supported services.  The presence of this information helps a listening\ncentral to determine whether it is interested in connecting to the peripheral.\nAdvertisements are quite limited in the amount of information they can contain,\nso only the most important information should be included.\n\n\nWhen a listening device receives an advertisement, it can choose to connect to\nthe peripheral, or query the sender for more information.  This second action\nis known as an \nactive scan\n.  A peripheral responds to an active scan with\nsome extra information that it couldn't fit in its advertisement.  This\nadditional information is known as \nscan response data\n.  \nbleprph\n does
  not\nconfigure any scan response data, so this feature is not discussed in the\nremainder of this tutorial.\n\n\nbleprph\n constantly broadcasts advertisements until a central connects to it.\nWhen a connection is terminated, \nbleprph\n resumes advertising.\n\n\nLet's take a look at \nbleprph\n's advertisement code (\nmain.c\n):\n\n\n\n\n/**\n\n\n * Enables advertising with the following parameters:\n\n\n *     o General discoverable mode.\n\n\n *     o Undirected connectable mode.\n\n\n */\n\n\nstatic\n \nvoid\n\n\nbleprph_advertise\n(\nvoid\n)\n{\n    \nstruct\n \nble_gap_adv_params\n \nadv_params\n;\n    \nstruct\n \nble_hs_adv_fields\n \nfields\n;\n    \nconst\n \nchar\n \n*name\n;\n    \nint\n \nrc\n;\n\n    \n/**\n\n\n     *  Set the advertisement data included in our advertisements:\n\n\n     *     o Flags (indicates advertisement type and other general info).\n\n\n     *     o Advertising tx power.\n\n\n     *     o Device name.\n\n\n     *     o 16-bit service UUIDs (aler
 t notifications).\n\n\n     */\n\n\n    \nmemset\n(\nfields\n, \n0\n, \nsizeof\n \nfields\n);\n\n    \n/* Indicate that the flags field should be included; specify a value of 0\n\n\n     * to instruct the stack to fill the value in for us.\n\n\n     */\n\n    \nfields\n.\nflags_is_present\n \n=\n \n1\n;\n    \nfields\n.\nflags\n \n=\n \n0\n;\n\n    \n/* Indicate that the TX power level field should be included; have the\n\n\n     * stack fill this one automatically as well.  This is done by assiging the\n\n\n     * special value BLE_HS_ADV_TX_PWR_LVL_AUTO.\n\n\n     */\n\n    \nfields\n.\ntx_pwr_lvl_is_present\n \n=\n \n1\n;\n    \nfields\n.\ntx_pwr_lvl\n \n=\n \nBLE_HS_ADV_TX_PWR_LVL_AUTO\n;\n\n    \nname\n \n=\n \nble_svc_gap_device_name\n();\n    \nfields\n.\nname\n \n=\n (\nuint8_t\n \n*\n)\nname\n;\n    \nfields\n.\nname_len\n \n=\n \nstrlen\n(\nname\n);\n    \nfields\n.\nname_is_complete\n \n=\n \n1\n;\n\n    \nfields\n.\nuuids16\n \n=\n (\nuint16_t\n[]){ \nGATT_SVR_SVC_ALERT_
 UUID\n };\n    \nfields\n.\nnum_uuids16\n \n=\n \n1\n;\n    \nfields\n.\nuuids16_is_complete\n \n=\n \n1\n;\n\n    \nrc\n \n=\n \nble_gap_adv_set_fields\n(\nfields\n);\n    \nif\n (\nrc\n \n!=\n \n0\n) {\n        \nBLEPRPH_LOG\n(\nERROR\n, \nerror setting advertisement data; rc=%d\\n\n, \nrc\n);\n        \nreturn\n;\n    }\n\n    \n/* Begin advertising. */\n\n    \nmemset\n(\nadv_params\n, \n0\n, \nsizeof\n \nadv_params\n);\n    \nadv_params\n.\nconn_mode\n \n=\n \nBLE_GAP_CONN_MODE_UND\n;\n    \nadv_params\n.\ndisc_mode\n \n=\n \nBLE_GAP_DISC_MODE_GEN\n;\n    \nrc\n \n=\n \nble_gap_adv_start\n(\nBLE_ADDR_TYPE_PUBLIC\n, \n0\n, \nNULL\n, \nBLE_HS_FOREVER\n,\n                           \nadv_params\n, \nbleprph_gap_event\n, \nNULL\n);\n    \nif\n (\nrc\n \n!=\n \n0\n) {\n        \nBLEPRPH_LOG\n(\nERROR\n, \nerror enabling advertisement; rc=%d\\n\n, \nrc\n);\n        \nreturn\n;\n    }\n}\n\n\n\n\n\nNow let's examine this code in detail.\n\n\n\n\nSetting advertisement data\n\n\nA NimBL
 E peripheral specifies what information to include in its advertisements with the \nble_gap_adv_set_fields()\n function.\n\n\nThe \nfields\n argument specifies the fields and their contents to include in\nsubsequent advertisements.  The Bluetooth \nCore Specification\nSupplement\n\ndefines a set of standard fields that can be included in an advertisement; the\nmember variables of the \nstruct ble_hs_adv_fields\n type correspond to these\nstandard fields.  Information that doesn't fit neatly into a standard field\nshould be put in the \nmanufacturing specific data\n field.\n\n\nAs you can see in the above code listing, the \nstruct ble_hs_adv_fields\n\ninstance is allocated on the stack.  It is OK to use the stack for this struct\nand the data it references, as the \nble_gap_adv_set_fields()\n\nfunction makes a copy of all the advertisement data before it returns.\n\nbleprph\n doesn't take full advantange of this; it stores its device name in a\nstatic array.\n\n\nThe code sets sever
 al members of the \nstruct ble_hs_adv_fields\n instance.  Most\nof them are quite straight-forward.  However, the \nname_is_complete\n field\nrequires some explanation.  Bluetooth specifies two name-related advertisement\nfields: \nShortened Local Name\n and \nComplete Local Name\n.  Setting the\n\nname_is_complete\n variable to 1 or 0 tells NimBLE which of these two fields to\ninclude in advertisements.  Some other advertisement fields also correspond to\nmultiple variables in the field struct, so it is a good idea to review the\n\nble_hs_adv_fields\n reference to make sure you get the details right in your\napp.\n\n\n\n\nBegin advertising\n\n\nAn app starts advertising with\n\nble_gap_adv_start()\n\nfunction.  This function allows a lot of flexibility, and it might seem\ndaunting at first glance.  \nbleprph\n specifies a simple set of arguments that\nis appropriate for most peripherals.  When getting started on a typical\nperipheral, we recommend you use the same arguments as \nbl
 eprph\n, with the\nexception of the last two (\ncb\n and \ncb_arg\n; \nbleprph_gap_event\n and \nNULL\n in\nthis case).  These last two arguments will be specific to your app, so let's\ntalk about them.\n\n\ncb\n is a callback function.  It gets executed when a central connects to your\nperipheral after receiving an advertisement.  The \ncb_arg\n argument gets passed\nto the \ncb\n callback.  If your callback doesn't need the \ncb_arg\n parameter,\nyou can do what \nbleprph\n does and pass \nNULL\n.  Once a connection is\nestablished, the \ncb\n callback becomes permanently associated with the\nconnection.  All subsequent events related to the connection are communicated\nto your app via calls to this callback function.  GAP event callbacks are an\nimportant part of building a BLE app, and we examine \nbleprph\n's connection\ncallback in detail in the next section of this tutorial.\n\n\n\n\nOne final note:\n Your peripheral automatically stops advertising when a\ncentral connects to
  it.  You can immediately resume advertising if you want to\nallow another central to connect, but you will need to do so explicitly by\ncalling \nble_gap_adv_start()\n again.  Also, be aware NimBLE's default\nconfiguration only allows a single connection at a time.  NimBLE supports\nmultiple concurrent connections, but you must configure it to do so first.", 
             "title": "Advertising"
         }, 
         {
@@ -1577,46 +1577,46 @@
         }, 
         {
             "location": "/os/tutorials/bleprph/bleprph-adv/#overview", 
-            "text": "A peripheral announces its presence to the world by broadcasting\nadvertisements.  An advertisement typically contains additional information\nabout the peripheral sending it, such as the device name and an abbreviated\nlist of supported services.  The presence of this information helps a listening\ncentral to determine whether it is interested in connecting to the peripheral.\nAdvertisements are quite limited in the amount of information they can contain,\nso only the most important information should be included.  When a listening device receives an advertisement, it can choose to connect to\nthe peripheral, or query the sender for more information.  This second action\nis known as an  active scan .  A peripheral responds to an active scan with\nsome extra information that it couldn't fit in its advertisement.  This\nadditional information is known as  scan response data .   bleprph  does not\nconfigure any scan response data, so this feature is not discussed 
 in the\nremainder of this tutorial.  bleprph  constantly broadcasts advertisements until a central connects to it.\nWhen a connection is terminated,  bleprph  resumes advertising.  Let's take a look at  bleprph 's advertisement code ( main.c ):   /**   * Enables advertising with the following parameters:   *     o General discoverable mode.   *     o Undirected connectable mode.   */  static   void  bleprph_advertise ( void )\n{\n     struct   ble_hs_adv_fields   fields ;\n     int   rc ;\n\n     /* Set the advertisement data included in our advertisements. */ \n     memset ( fields ,  0 ,  sizeof   fields );\n     fields . name   =  ( uint8_t   * ) bleprph_device_name ;\n     fields . name_len   =   strlen ( bleprph_device_name );\n     fields . name_is_complete   =   1 ;\n     rc   =   ble_gap_adv_set_fields ( fields );\n     if  ( rc   !=   0 ) {\n         BLEPRPH_LOG ( ERROR ,  error setting advertisement data; rc=%d\\n ,  rc );\n         return ;\n    }\n\n     /* Begin adverti
 sing. */ \n     rc   =   ble_gap_adv_start ( BLE_GAP_DISC_MODE_GEN ,  BLE_GAP_CONN_MODE_UND ,\n                            NULL ,  0 ,  NULL ,  bleprph_on_connect ,  NULL );\n     if  ( rc   !=   0 ) {\n         BLEPRPH_LOG ( ERROR ,  error enabling advertisement; rc=%d\\n ,  rc );\n         return ;\n    }\n}  Now let's examine this code in detail.", 
+            "text": "A peripheral announces its presence to the world by broadcasting\nadvertisements.  An advertisement typically contains additional information\nabout the peripheral sending it, such as the device name and an abbreviated\nlist of supported services.  The presence of this information helps a listening\ncentral to determine whether it is interested in connecting to the peripheral.\nAdvertisements are quite limited in the amount of information they can contain,\nso only the most important information should be included.  When a listening device receives an advertisement, it can choose to connect to\nthe peripheral, or query the sender for more information.  This second action\nis known as an 

<TRUNCATED>