blob: 69bc20e09cf3d320f362c95a25c2cf6065ac4564 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- This is broken by doc revisioning.
-->
<link rel="shortcut icon" href="../../../../img/favicon.ico">
<title>Characteristic Access - Apache Mynewt</title>
<link href="../../../../css/bootstrap-3.0.3.min.css" rel="stylesheet">
<link rel="stylesheet" href="../../../../css/highlight.css">
<link href="../../../../css/base.css" rel="stylesheet">
<link href="../../../../css/custom.css" rel="stylesheet">
<link href="../../../../css/v2.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
<script>
(function(i, s, o, g, r, a, m) {
i["GoogleAnalyticsObject"] = r;
(i[r] =
i[r] ||
function() {
(i[r].q = i[r].q || []).push(arguments);
}),
(i[r].l = 1 * new Date());
(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m);
})(window, document, "script", "//www.google-analytics.com/analytics.js", "ga");
ga("create", "UA-72162311-1", "auto");
ga("send", "pageview");
</script>
</head>
<body class="Characteristic Access">
<div class="container">
<div class="row v2-main-banner">
<a class="logo-cell" href="/">
<img class="logo" src="/img/logo.png">
</a>
<div class="tagline-cell">
<h4 class="tagline">An OS to build, deploy and securely manage billions of devices</h4>
</div>
<div class="news-cell">
<div class="well">
<h4>Latest News:</h4> <a href="/download">Apache Mynewt 1.12.0, Apache NimBLE 1.7.0 </a> released (April 4, 2024)
</div>
</div>
</div>
</div>
<nav id="navbar" class="navbar navbar-inverse affix-top" data-spy="affix" data-offset-top="150" role="navigation">
<div class="container">
<!-- Collapsed navigation -->
<div class="navbar-header">
<!-- Expander button -->
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- Expanded navigation -->
<div class="navbar-collapse collapse">
<!-- Main navigation -->
<ul class="nav navbar-nav navbar-right">
<li
class=""
>
<a href="/"><i class="fa fa-home" style="font-size: larger;"></i></a>
</li>
<li
class="important"
>
<a href="/quick-start/">Quick Start</a>
</li>
<li
class=""
>
<a href="/about/">About</a>
</li>
<li
class=""
>
<a href="/talks/">Talks</a>
</li>
<li
class="active"
>
<a href="/documentation/">Documentation</a>
</li>
<li
class=""
>
<a href="/download/">Download</a>
</li>
<li
class=""
>
<a href="/community/">Community</a>
</li>
<li
class=""
>
<a href="/events/">Events</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-md-3 v2-sidebar sidebar-container"><div id="docSidebar" class="hidden-print" role="complementary">
<div class="top">
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../../../../search.html" method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search documentation" />
</div>
</form>
</div>
</div>
<ul class="toc-nav">
<li class="doc-version"><select class="form-control" onchange="if (this.value) window.location.href=this.value">
<option value="/latest">
Version: master
</option>
<option value="/v1_12_0/" >
Version: 1.12.0
</option>
<option value="/v1_11_0/" >
Version: 1.11.0
</option>
<option value="/v1_10_0/" >
Version: 1.10.0
</option>
<option value="/v1_9_0/" >
Version: 1.9.0
</option>
<option value="/v1_8_0/" >
Version: 1.8.0
</option>
<option value="/v1_7_0/" >
Version: 1.7.0
</option>
<option value="/v1_6_0/" >
Version: 1.6.0
</option>
<option value="/v1_5_0/" >
Version: 1.5.0
</option>
<option value="/v1_4_0/" >
Version: 1.4.0
</option>
<option value="/v1_3_0/os/introduction" >
Version: 1.3.0
</option>
<option value="/v1_2_0/os/introduction" >
Version: 1.2.0
</option>
<option value="/v1_1_0/os/introduction" >
Version: 1.1.0
</option>
<option value="/v1_0_0/os/introduction" >
Version: 1.0.0
</option>
<option value="/v0_9_0/os/introduction" selected="selected" >
Version: 0.9.0
</option>
</select></li>
<li ><a href="../../../introduction/">Mynewt Documentation</a>
<ul>
<li ><a href="../../../get_started/get_started/">Basic Setup</a>
</li>
<li >
<a href="../../../get_started/vocabulary/">Concepts</a>
</li>
<li ><a href="../../tutorials/">Tutorials</a>
<ul>
<li><a href="
../../arduino_zero/
">Project Blinky</a>
</li>
<li ><a href="../../repo/add_repos/">Work with repositories</a>
</li>
<li >
<a href="../../unit_test/">Write a Test Suite for a Package</a>
</li>
<li >
<a href="../../air_quality_sensor/">Air-quality Sensor project</a>
</li>
<li >
<a href="../../event_queue/">Add task to manage multiple events</a>
</li>
<li >
<a href="../../project-slinky/">Enable remote comms on sim device</a>
</li>
<li >
<a href="../../project-target-slinky/">Enable remote comms on STM32 board</a>
</li>
<li >
<a href="../../bletiny_project/">BLE app to check stats via console</a>
</li>
<li ><a href="../bleprph-intro/">BLE peripheral project</a>
<ul>
<li >
<a href="../bleprph-svc-reg/">Service Registration</a>
</li>
<li class="active">
<a href="./">Characteristic Access</a>
</li>
<li >
<a href="../bleprph-adv/">Advertising</a>
</li>
<li >
<a href="../bleprph-conn/">Connection Callbacks</a>
</li>
</ul>
</li>
<li >
<a href="../../ibeacon/">BLE iBeacon</a>
</li>
<li >
<a href="../../blehci_project/">BLE HCI interface</a>
</li>
</ul>
</li>
<li ><a href="../../../os_user_guide/">OS User Guide</a>
</li>
<li><a href="
../../../../network/ble/ble_intro/
">BLE User Guide</a>
</li>
<li ><a href="../../../../newt/newt_intro/">Newt Tool Guide</a>
</li>
<li ><a href="../../../../newtmgr/overview/">Newt Manager Guide</a>
</li>
<li >
<a href="../../../../known_issues/">Known Issues</a>
</li>
</ul>
</li>
<li><a href="
../../../../faq/how_to_edit_docs/
">Appendix</a>
</li>
</ul>
</div></div>
<div class="col-md-9" role="main">
<div class="doc-header">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="/documentation/">Docs</a></li>
<li>&raquo; <a href="os/tutorials/bleprph/bleprph-intro/">BLE peripheral project</a></li>
<li>&raquo; <a href="os/tutorials/tutorials/">Tutorials</a></li>
<li>&raquo; <a href="os/introduction/">Mynewt Documentation</a></li>
<li>&raquo; Characteristic Access</li>
</ul>
</div>
</div>
<div class="alert alert-warning">
<p>
Version 0.9.0 is not the most recent version of the Apache Mynewt
documentation. Click <a href="/latest">here</a> to read the latest
version.
</p>
</div>
<h2 id="ble-peripheral-project">BLE Peripheral Project</h2>
<h3 id="characteristic-access">Characteristic Access</h3>
<p><br></p>
<h4 id="review">Review</h4>
<p>A characteristic's access callback implements its behavior. Recall that
services and characteristics are registered with NimBLE via attribute tables.
Each characteristic definition in an attribute table contains an <em>access_cb</em>
field. The <em>access_cb</em> field is an application callback that gets executed
whenever a peer device attempts to read or write the characteristic.</p>
<p>Earlier in this tutorial, we looked at how <em>bleprph</em> implements the GAP
service. Let's take another look at how <em>bleprph</em> specifies the first few
characteristics in this service.</p>
<p><br></p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #A90D91">static</span> <span style="color: #A90D91">const</span> <span style="color: #A90D91">struct</span> <span style="color: #3F6E75">ble_gatt_svc_def</span> <span style="color: #000000">gatt_svr_svcs</span>[] <span style="color: #000000">=</span> {
{
<span style="color: #177500">/*** Service: GAP. */</span>
.<span style="color: #000000">type</span> <span style="color: #000000">=</span> <span style="color: #000000">BLE_GATT_SVC_TYPE_PRIMARY</span>,
.<span style="color: #000000">uuid128</span> <span style="color: #000000">=</span> <span style="color: #000000">BLE_UUID16</span>(<span style="color: #000000">BLE_GAP_SVC_UUID16</span>),
.<span style="color: #000000">characteristics</span> <span style="color: #000000">=</span> (<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">ble_gatt_chr_def</span>[]) { {
<span style="color: #177500">/*** Characteristic: Device Name. */</span>
.<span style="color: #000000">uuid128</span> <span style="color: #000000">=</span> <span style="color: #000000">BLE_UUID16</span>(<span style="color: #000000">BLE_GAP_CHR_UUID16_DEVICE_NAME</span>),
.<span style="color: #000000">access_cb</span> <span style="color: #000000">=</span> <span style="color: #000000">gatt_svr_chr_access_gap</span>,
.<span style="color: #000000">flags</span> <span style="color: #000000">=</span> <span style="color: #000000">BLE_GATT_CHR_F_READ</span>,
}, {
<span style="color: #177500">/*** Characteristic: Appearance. */</span>
.<span style="color: #000000">uuid128</span> <span style="color: #000000">=</span> <span style="color: #000000">BLE_UUID16</span>(<span style="color: #000000">BLE_GAP_CHR_UUID16_APPEARANCE</span>),
.<span style="color: #000000">access_cb</span> <span style="color: #000000">=</span> <span style="color: #000000">gatt_svr_chr_access_gap</span>,
.<span style="color: #000000">flags</span> <span style="color: #000000">=</span> <span style="color: #000000">BLE_GATT_CHR_F_READ</span>,
}, {
<span style="color: #177500">// [...]</span>
</code></pre></div>
<p>As you can see, <em>bleprph</em> uses the same <em>access_cb</em> function for all the GAP
service characteristics, but the developer could have implemented separate
functions for each characteristic if they preferred. Here is the <em>access_cb</em>
function that the GAP service characteristics use:</p>
<p><br></p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #A90D91">static</span> <span style="color: #A90D91">int</span>
<span style="color: #000000">gatt_svr_chr_access_gap</span>(<span style="color: #A90D91">uint16_t</span> <span style="color: #000000">conn_handle</span>, <span style="color: #A90D91">uint16_t</span> <span style="color: #000000">attr_handle</span>, <span style="color: #A90D91">uint8_t</span> <span style="color: #000000">op</span>,
<span style="color: #A90D91">union</span> <span style="color: #3F6E75">ble_gatt_access_ctxt</span> <span style="color: #000000">*ctxt</span>, <span style="color: #A90D91">void</span> <span style="color: #000000">*arg</span>)
{
<span style="color: #A90D91">uint16_t</span> <span style="color: #000000">uuid16</span>;
<span style="color: #000000">uuid16</span> <span style="color: #000000">=</span> <span style="color: #000000">ble_uuid_128_to_16</span>(<span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">chr-&gt;uuid128</span>);
<span style="color: #000000">assert</span>(<span style="color: #000000">uuid16</span> <span style="color: #000000">!=</span> <span style="color: #1C01CE">0</span>);
<span style="color: #A90D91">switch</span> (<span style="color: #000000">uuid16</span>) {
<span style="color: #A90D91">case</span> <span style="color: #000000">BLE_GAP_CHR_UUID16_DEVICE_NAME</span>:
<span style="color: #000000">assert</span>(<span style="color: #000000">op</span> <span style="color: #000000">==</span> <span style="color: #000000">BLE_GATT_ACCESS_OP_READ_CHR</span>);
<span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">data</span> <span style="color: #000000">=</span> (<span style="color: #A90D91">void</span> <span style="color: #000000">*</span>)<span style="color: #000000">bleprph_device_name</span>;
<span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">len</span> <span style="color: #000000">=</span> <span style="color: #000000">strlen</span>(<span style="color: #000000">bleprph_device_name</span>);
<span style="color: #A90D91">break</span>;
<span style="color: #A90D91">case</span> <span style="color: #000000">BLE_GAP_CHR_UUID16_APPEARANCE</span>:
<span style="color: #000000">assert</span>(<span style="color: #000000">op</span> <span style="color: #000000">==</span> <span style="color: #000000">BLE_GATT_ACCESS_OP_READ_CHR</span>);
<span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">data</span> <span style="color: #000000">=</span> (<span style="color: #A90D91">void</span> <span style="color: #000000">*</span>)<span style="color: #000000">&amp;bleprph_appearance</span>;
<span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">len</span> <span style="color: #000000">=</span> <span style="color: #A90D91">sizeof</span> <span style="color: #000000">bleprph_appearance</span>;
<span style="color: #A90D91">break</span>;
<span style="color: #A90D91">case</span> <span style="color: #000000">BLE_GAP_CHR_UUID16_PERIPH_PRIV_FLAG</span>:
<span style="color: #000000">assert</span>(<span style="color: #000000">op</span> <span style="color: #000000">==</span> <span style="color: #000000">BLE_GATT_ACCESS_OP_READ_CHR</span>);
<span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">data</span> <span style="color: #000000">=</span> (<span style="color: #A90D91">void</span> <span style="color: #000000">*</span>)<span style="color: #000000">&amp;bleprph_privacy_flag</span>;
<span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">len</span> <span style="color: #000000">=</span> <span style="color: #A90D91">sizeof</span> <span style="color: #000000">bleprph_privacy_flag</span>;
<span style="color: #A90D91">break</span>;
<span style="color: #A90D91">case</span> <span style="color: #000000">BLE_GAP_CHR_UUID16_RECONNECT_ADDR</span>:
<span style="color: #000000">assert</span>(<span style="color: #000000">op</span> <span style="color: #000000">==</span> <span style="color: #000000">BLE_GATT_ACCESS_OP_WRITE_CHR</span>);
<span style="color: #A90D91">if</span> (<span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">len</span> <span style="color: #000000">!=</span> <span style="color: #A90D91">sizeof</span> <span style="color: #000000">bleprph_reconnect_addr</span>) {
<span style="color: #A90D91">return</span> <span style="color: #000000">BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN</span>;
}
<span style="color: #000000">memcpy</span>(<span style="color: #000000">bleprph_reconnect_addr</span>, <span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">data</span>,
<span style="color: #A90D91">sizeof</span> <span style="color: #000000">bleprph_reconnect_addr</span>);
<span style="color: #A90D91">break</span>;
<span style="color: #A90D91">case</span> <span style="color: #000000">BLE_GAP_CHR_UUID16_PERIPH_PREF_CONN_PARAMS</span>:
<span style="color: #000000">assert</span>(<span style="color: #000000">op</span> <span style="color: #000000">==</span> <span style="color: #000000">BLE_GATT_ACCESS_OP_READ_CHR</span>);
<span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">data</span> <span style="color: #000000">=</span> (<span style="color: #A90D91">void</span> <span style="color: #000000">*</span>)<span style="color: #000000">&amp;bleprph_pref_conn_params</span>;
<span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">len</span> <span style="color: #000000">=</span> <span style="color: #A90D91">sizeof</span> <span style="color: #000000">bleprph_pref_conn_params</span>;
<span style="color: #A90D91">break</span>;
<span style="color: #A90D91">default</span><span style="color: #000000">:</span>
<span style="color: #000000">assert</span>(<span style="color: #1C01CE">0</span>);
<span style="color: #A90D91">break</span>;
}
<span style="color: #A90D91">return</span> <span style="color: #1C01CE">0</span>;
}
</code></pre></div>
<p>After you've taken a moment to examine the structure of this function, let's explore some details.</p>
<p><br></p>
<h4 id="function-signature">Function signature</h4>
<p><br></p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #A90D91">static</span> <span style="color: #A90D91">int</span>
<span style="color: #000000">gatt_svr_chr_access_gap</span>(<span style="color: #A90D91">uint16_t</span> <span style="color: #000000">conn_handle</span>, <span style="color: #A90D91">uint16_t</span> <span style="color: #000000">attr_handle</span>, <span style="color: #A90D91">uint8_t</span> <span style="color: #000000">op</span>,
<span style="color: #A90D91">union</span> <span style="color: #3F6E75">ble_gatt_access_ctxt</span> <span style="color: #000000">*ctxt</span>, <span style="color: #A90D91">void</span> <span style="color: #000000">*arg</span>)
</code></pre></div>
<p>A characteristic access function always takes this same set of parameters and
always returns an int. The parameters to this function type are documented
below.</p>
<p><br></p>
<table>
<thead>
<tr>
<th><strong>Parameter</strong></th>
<th><strong>Purpose</strong></th>
<th><strong>Notes</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>conn_handle</td>
<td>Indicates which connection the characteristic access was sent over.</td>
<td>Use this value to determine which peer is accessing the characteristic.</td>
</tr>
<tr>
<td>attr_handle</td>
<td>The low-level ATT handle of the characteristic value attribute.</td>
<td>Can be used to determine which characteristic is being accessed if you don't want to perform a UUID lookup.</td>
</tr>
<tr>
<td>op</td>
<td>Indicates whether this is a read or write operation</td>
<td>Valid values are:<br><em>BLE_GATT_ACCESS_OP_READ_CHR</em><br><em>BLE_GATT_ACCESS_OP_WRITE_CHR</em></td>
</tr>
<tr>
<td>ctxt</td>
<td>Contains the characteristic value pointer that the application needs to access.</td>
<td>For characteristic accesses, use the <em>ctxt-&gt;chr_access</em> member; for descriptor accesses, use the <em>ctxt-&gt;dsc_access</em> member.</td>
</tr>
</tbody>
</table>
<p>The return value of the access function tells the NimBLE stack how to respond
to the peer performing the operation. A value of 0 indicates success. For
failures, the function returns the specific ATT error code that the NimBLE
stack should respond with. The ATT error codes are defined in
<a href="https://github.com/apache/incubator-mynewt-core/blob/master/net/nimble/host/include/host/ble_att.h">net/nimble/host/include/host/ble_att.h</a>.</p>
<p><br></p>
<h4 id="determine-characteristic-being-accessed">Determine characteristic being accessed</h4>
<p><br></p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>{
<span style="color: #A90D91">uint16_t</span> <span style="color: #000000">uuid16</span>;
<span style="color: #000000">uuid16</span> <span style="color: #000000">=</span> <span style="color: #000000">ble_uuid_128_to_16</span>(<span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">chr-&gt;uuid128</span>);
<span style="color: #000000">assert</span>(<span style="color: #000000">uuid16</span> <span style="color: #000000">!=</span> <span style="color: #1C01CE">0</span>);
<span style="color: #A90D91">switch</span> (<span style="color: #000000">uuid16</span>) {
<span style="color: #177500">// [...]</span>
</code></pre></div>
<p>This function uses the UUID to determine which characteristic is being
accessed. There are two alternative methods <em>bleprph</em> could have used to
accomplish this task:</p>
<ul>
<li>Map characteristics to ATT handles during service registration; use the <em>attr_handle</em> parameter as a key into this table during characteristic access.</li>
<li>Implement a dedicated function for each characteristic; each function inherently knows which characteristic it corresponds to.</li>
</ul>
<p>All the GAP service characteristics have 16-bit UUIDs, so this function uses
the <em>ble_uuid_128_to_16()</em> 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.</p>
<p><br></p>
<h4 id="read-access">Read access</h4>
<p><br></p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code> <span style="color: #A90D91">case</span> <span style="color: #000000">BLE_GAP_CHR_UUID16_DEVICE_NAME</span>:
<span style="color: #000000">assert</span>(<span style="color: #000000">op</span> <span style="color: #000000">==</span> <span style="color: #000000">BLE_GATT_ACCESS_OP_READ_CHR</span>);
<span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">data</span> <span style="color: #000000">=</span> (<span style="color: #A90D91">void</span> <span style="color: #000000">*</span>)<span style="color: #000000">bleprph_device_name</span>;
<span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">len</span> <span style="color: #000000">=</span> <span style="color: #000000">strlen</span>(<span style="color: #000000">bleprph_device_name</span>);
<span style="color: #A90D91">break</span>;
</code></pre></div>
<p>This code excerpt handles read accesses to the device name characteristic. The
<em>assert()</em> here is another case of making sure the NimBLE stack is doing its
job; this characteristic was registered as read-only, so the stack should have
prevented write accesses.</p>
<p>To fulfill a characteristic read request, the application needs to assign the
<em>ctxt-&gt;chr_access.data</em> field to point to the attribute data to respond with,
and fill the <em>ctxt-&gt;chr_access.len</em> field with the length of the attribute data.
<em>bleprph</em> stores the device name in read-only memory as follows:</p>
<p><br></p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #A90D91">const</span> <span style="color: #A90D91">char</span> <span style="color: #000000">*bleprph_device_name</span> <span style="color: #000000">=</span> <span style="color: #C41A16">&quot;nimble-bleprph&quot;</span>;
</code></pre></div>
<p>The cast to pointer-to-void is a necessary annoyance to remove the <em>const</em>
qualifier from the device name variable. You will need to "cast away const"
whenever you respond to read requests with read-only data.</p>
<p>It is not shown in the above snippet, but this function ultimately returns 0.
By returning 0, <em>bleprph</em> indicates that the characteristic data in
<em>ctxt-&gt;chr_access</em> is valid and that NimBLE should include it in its response
to the peer.</p>
<p><br></p>
<p><strong>A word of warning:</strong> The attribute data that <em>ctxt-&gt;chr_access.data</em> 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.</p>
<p><br></p>
<h4 id="write-access">Write access</h4>
<p><br></p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code> <span style="color: #A90D91">case</span> <span style="color: #000000">BLE_GAP_CHR_UUID16_RECONNECT_ADDR</span>:
<span style="color: #000000">assert</span>(<span style="color: #000000">op</span> <span style="color: #000000">==</span> <span style="color: #000000">BLE_GATT_ACCESS_OP_WRITE_CHR</span>);
<span style="color: #A90D91">if</span> (<span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">len</span> <span style="color: #000000">!=</span> <span style="color: #A90D91">sizeof</span> <span style="color: #000000">bleprph_reconnect_addr</span>) {
<span style="color: #A90D91">return</span> <span style="color: #000000">BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN</span>;
}
<span style="color: #000000">memcpy</span>(<span style="color: #000000">bleprph_reconnect_addr</span>, <span style="color: #000000">ctxt-&gt;chr_access</span>.<span style="color: #000000">data</span>,
<span style="color: #A90D91">sizeof</span> <span style="color: #000000">bleprph_reconnect_addr</span>);
<span style="color: #A90D91">break</span>;
</code></pre></div>
<p>This code excerpt handles writes to the reconnect address characteristic. This
characteristic was registered as write-only, so the <em>assert()</em> here is just a
safety precaution to ensure the NimBLE stack is doing its job.</p>
<p>For writes, the roles of the <em>ctxt-&gt;chr_access.data</em> and <em>ctxt-&gt;chr_access.len</em>
fields are the reverse of the read case. The NimBLE stack uses these fields to
indicate the data written by the peer.</p>
<p>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.</p>
<p>For writes, the <em>ctxt-&gt;chr_access.data</em> 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, <em>bleprph</em>
stores the specified address in a global variable called
<em>bleprph_reconnect_addr</em>.</p>
<div class="row">
<ul class="nav nav-pills" style="margin-bottom: 10px">
<li>
</li>
<li class="pull-right">
</li>
</ul>
</div>
<footer class="row">
<div class="col-xs-12">
<p class="copyright">Apache Mynewt (incubating) is available under Apache License, version 2.0.</p>
</div>
<div class="col-xs-12">
<div class="logos">
<a href="https://www.apache.org/">
<img src="/img/asf_logo_wide_small.png" alt="Apache" title="Apache">
</a>
<p>
Copyright © 2015-2021 The Apache Software Foundation.<br>
<small class="footnote">
Apache Mynewt, Mynewt, Apache, the Apache feather logo, and the Apache Mynewt
project logo are either registered trademarks or trademarks of the Apache
Software Foundation in the United States and other countries.
</small>
</p>
<a href="">
<img src="https://www.countit.com/images/add_to_slack.png" alt="Slack Icon" title="Join our Slack Community" />
</a>
</div>
</div>
<a href="https://www.apache.org/licenses/">
<button class="button-footer-asf">
License
</button>
</a>
<a href="https://www.apache.org/foundation/sponsorship.html">
<button class="button-footer-asf">
Sponsorship
</button>
</a>
<a href="https://www.apache.org/foundation/thanks.html">
<button class="button-footer-asf">
Thanks
</button>
</a>
<a href="https://www.apache.org/security/">
<button class="button-footer-asf">
Security
</button>
</a>
<a href="https://apache.org/events/current-event">
<button class="button-footer-asf">
ASF Events
</button>
</a>
</footer>
</div>
</div>
</div>
<script src="../../../../js/jquery-1.10.2.min.js"></script>
<script src="../../../../js/bootstrap-3.0.3.min.js"></script>
<script src="../../../../js/highlight.pack.js"></script>
<script src="../../../../js/base.js"></script>
<script src="../../../../js/custom.js"></script>
<script src="search/main.js"></script>
</body>
</html>