Dawn Framework 1.0
Universal data acquisition framework for embedded systems
adv.cxx
1// dawn/src/proto/nimble/adv.cxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#include "dawn/proto/nimble/adv.hxx"
7
8#include <cstring>
9
10#include "nimble/nimble_port.h"
11
12using namespace dawn;
13
16
17static struct ble_npl_callout g_adv_retry_callout;
18static bool g_adv_retry_inited = false;
19
20void CProtoNimbleAdv::advRetryCb(struct ble_npl_event *ev)
21{
22 (void)ev;
23
24 if (ble_gap_adv_active())
25 {
26 return;
27 }
28
29 CProtoNimbleAdv::startAdvertise();
30}
31
32void CProtoNimbleAdv::scheduleAdvRetry()
33{
34 if (!g_adv_retry_inited)
35 {
36 ble_npl_callout_init(
37 &g_adv_retry_callout, nimble_port_get_dflt_eventq(), CProtoNimbleAdv::advRetryCb, nullptr);
38 g_adv_retry_inited = true;
39 }
40
41 ble_npl_callout_reset(&g_adv_retry_callout, ble_npl_time_ms_to_ticks32(ADV_RETRY_MS));
42}
43
44void CProtoNimbleAdv::startAdvertise()
45{
46 struct ble_gap_adv_params advp;
47 int ret;
48
49 printf("advertise\n");
50
51 CProtoNimbleAdv::updateAd();
52
53 std::memset(&advp, 0, sizeof advp);
54 advp.conn_mode = BLE_GAP_CONN_MODE_UND;
55 advp.disc_mode = BLE_GAP_DISC_MODE_GEN;
56 ret = ble_gap_adv_start(CProtoNimbleAdv::ownAddrType,
57 nullptr,
58 BLE_HS_FOREVER,
59 &advp,
60 CProtoNimbleAdv::gapEventCb,
61 nullptr);
62 if (ret != 0)
63 {
64 // A failure here can be transient (e.g. a disconnect racing in-flight
65 // notification traffic, with connection resources not yet reclaimed).
66 // Giving up would leave the device unreachable until reboot, so keep
67 // retrying until advertising is up again.
68 DAWNERR(
69 "ble_gap_adv_start failed: %d, retry in %u ms\n", ret, static_cast<unsigned>(ADV_RETRY_MS));
70 CProtoNimbleAdv::scheduleAdvRetry();
71 }
72}
73
74void CProtoNimbleAdv::setGapName(const char *name, uint8_t len)
75{
76 size_t copy;
77
78 if (name == nullptr)
79 {
80 DAWNERR("NULL GAP name pointer\n");
81 return;
82 }
83
84 copy = (len > GAPNAME_MAX) ? GAPNAME_MAX : len;
85 std::memcpy(CProtoNimbleAdv::gapName, name, copy);
86 CProtoNimbleAdv::gapName[copy] = '\0';
87}
88
89void CProtoNimbleAdv::putAd(uint8_t type,
90 uint8_t ad_len,
91 const void *ad,
92 uint8_t *buf,
93 uint8_t *len)
94{
95 buf[(*len)++] = ad_len + 1;
96 buf[(*len)++] = type;
97
98 std::memcpy(&buf[*len], ad, ad_len);
99
100 *len += ad_len;
101}
102
103void CProtoNimbleAdv::updateAd()
104{
105 uint8_t ad_flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
106 uint8_t ad_len = 0;
107 uint8_t ad[BLE_HS_ADV_MAX_SZ];
108 size_t gap_len = strnlen(CProtoNimbleAdv::gapName, GAPNAME_MAX);
109
110 CProtoNimbleAdv::putAd(BLE_HS_ADV_TYPE_FLAGS, 1, &ad_flags, ad, &ad_len);
111 CProtoNimbleAdv::putAd(BLE_HS_ADV_TYPE_COMP_NAME, gap_len, CProtoNimbleAdv::gapName, ad, &ad_len);
112
113 ble_gap_adv_set_data(ad, ad_len);
114}
115
116void CProtoNimbleAdv::requestConnParams(uint16_t conn_handle)
117{
118 // Opt-in: CONN_ITVL_MIN == 0 leaves the negotiated interval untouched.
119 if (CONN_ITVL_MIN == 0)
120 {
121 return;
122 }
123
124 struct ble_gap_upd_params params;
125 std::memset(&params, 0, sizeof params);
126 params.itvl_min = CONN_ITVL_MIN;
127 params.itvl_max = (CONN_ITVL_MAX >= CONN_ITVL_MIN) ? CONN_ITVL_MAX : CONN_ITVL_MIN;
128 params.latency = 0;
129 params.supervision_timeout = 400; // 4 s (units of 10 ms)
130
131 int ret = ble_gap_update_params(conn_handle, &params);
132 if (ret != 0)
133 {
134 DAWNERR("ble_gap_update_params failed: %d\n", ret);
135 }
136}
137
138int CProtoNimbleAdv::gapEventCb(struct ble_gap_event *event, void *arg)
139{
140 switch (event->type)
141 {
142 case BLE_GAP_EVENT_CONNECT:
143 {
144 if (event->connect.status)
145 {
146 CProtoNimbleAdv::startAdvertise();
147 }
148 else
149 {
150 CProtoNimbleAdv::requestConnParams(event->connect.conn_handle);
151 }
152 break;
153 }
154
155 case BLE_GAP_EVENT_DISCONNECT:
156 {
157 DAWNINFO("disconected reason=%d\n", event->disconnect.reason);
158 CProtoNimbleAdv::startAdvertise();
159 break;
160 }
161 }
162
163 return 0;
164}
static uint16_t CONN_ITVL_MIN
Preferred connection interval (units of 1.25ms); 0 leaves it untouched.
Definition adv.hxx:29
static size_t GAPNAME_MAX
Max GAP device name length (excluding null).
Definition adv.hxx:24
static char gapName[GAPNAME_MAX+1]
GAP device name visible during BLE discovery.
Definition adv.hxx:33
static uint8_t ownAddrType
BLE device address type (random/static/public).
Definition adv.hxx:32
Out-of-tree user-extension hooks for Dawn.
Definition bindable.hxx:13