1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
27
28
29
30
31
32
33
34
35
36
39
40
47
48
49
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
130
131
132
137
138
139
140
145
146
147
148
149
150
151
152
155
156
157
158
159
163
164
165
166
167
168
169
170
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
226
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
285
286
287
288
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
/* ... */
#include "esp_log.h"
#include "nvs_flash.h"
#include "freertos/FreeRTOSConfig.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include "host/ble_hs.h"
#include "host/util/util.h"
#include "console/console.h"
#include "services/gap/ble_svc_gap.h"
#include "ble_cts_prph.h"
#include "services/cts/ble_svc_cts.h"11 includes
#if CONFIG_EXAMPLE_EXTENDED_ADV
static uint8_t ext_adv_pattern_1[] = {
0x02, 0x01, 0x06,
0x03, 0x03, 0xab, 0xcd,
0x03, 0x03, 0x05, 0x18,
0x12, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'c', 't', 's', '-', 'p', 'r', 'p', 'h', '-', 'e',
}{...};/* ... */
#endif
static const char *tag = "NimBLE_CTS_PRPH";
static const char *device_name = "ble_cts_prph";
static int ble_cts_prph_gap_event(struct ble_gap_event *event, void *arg);
static uint8_t ble_cts_prph_addr_type;
/* ... */
void
print_bytes(const uint8_t *bytes, int len)
{
int i;
for (i = 0; i < len; i++) {
MODLOG_DFLT(INFO, "%s0x%02x", i != 0 ? ":" : "", bytes[i]);
}{...}
}{ ... }
void
print_addr(const void *addr)
{
const uint8_t *u8p;
u8p = addr;
MODLOG_DFLT(INFO, "%02x:%02x:%02x:%02x:%02x:%02x",
u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
}{ ... }
#if CONFIG_EXAMPLE_EXTENDED_ADV
/* ... */
static void
ext_ble_cts_prph_advertise(void)
{
struct ble_gap_ext_adv_params params;
struct os_mbuf *data;
uint8_t instance = 0;
int rc;
if (ble_gap_ext_adv_active(instance)) {
return;
}{...}
memset (¶ms, 0, sizeof(params));
params.connectable = 1;
params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
params.primary_phy = BLE_HCI_LE_PHY_1M;
params.secondary_phy = BLE_HCI_LE_PHY_2M;
params.sid = 1;
params.itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
params.itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
rc = ble_gap_ext_adv_configure(instance, ¶ms, NULL,
ble_cts_prph_gap_event, NULL);
assert (rc == 0);
data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0);
assert(data);
rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1));
assert(rc == 0);
rc = ble_gap_ext_adv_set_data(instance, data);
assert (rc == 0);
rc = ble_gap_ext_adv_start(instance, 0, 0);
assert (rc == 0);
}{...}
/* ... */#else
static void
ble_cts_prph_advertise(void)
{
struct ble_gap_adv_params adv_params;
struct ble_hs_adv_fields fields;
int rc;
/* ... */
memset(&fields, 0, sizeof(fields));
/* ... */
fields.flags = BLE_HS_ADV_F_DISC_GEN |
BLE_HS_ADV_F_BREDR_UNSUP;
/* ... */
fields.tx_pwr_lvl_is_present = 1;
fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
fields.name = (uint8_t *)device_name;
fields.name_len = strlen(device_name);
fields.name_is_complete = 1;
fields.uuids16 = (ble_uuid16_t[]) {
BLE_UUID16_INIT(BLE_SVC_CTS_UUID16)
}{...};
fields.num_uuids16 = 1;
fields.uuids16_is_complete = 1;
rc = ble_gap_adv_set_fields(&fields);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error setting advertisement data; rc=%d\n", rc);
return;
}{...}
memset(&adv_params, 0, sizeof(adv_params));
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
rc = ble_gap_adv_start(ble_cts_prph_addr_type, NULL, BLE_HS_FOREVER,
&adv_params, ble_cts_prph_gap_event, NULL);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error enabling advertisement; rc=%d\n", rc);
return;
}{...}
}{ ... }
#endif/* ... */
static int
ble_cts_prph_gap_event(struct ble_gap_event *event, void *arg)
{
switch (event->type) {
case BLE_GAP_EVENT_LINK_ESTAB:
MODLOG_DFLT(INFO, "connection %s; status=%d\n",
event->link_estab.status == 0 ? "established" : "failed",
event->link_estab.status);
if (event->link_estab.status != 0) {
#if CONFIG_EXAMPLE_EXTENDED_ADV
ext_ble_cts_prph_advertise();
#else
ble_cts_prph_advertise();
#endif
}{...}
break;
...
case BLE_GAP_EVENT_DISCONNECT:
MODLOG_DFLT(INFO, "disconnect; reason=%d\n", event->disconnect.reason);
#if CONFIG_EXAMPLE_EXTENDED_ADV
ext_ble_cts_prph_advertise();
#else
ble_cts_prph_advertise();
#endif
break;
...
case BLE_GAP_EVENT_ADV_COMPLETE:
MODLOG_DFLT(INFO, "adv complete\n");
#if CONFIG_EXAMPLE_EXTENDED_ADV
ext_ble_cts_prph_advertise();
#else
ble_cts_prph_advertise();
#endif
break;
...
case BLE_GAP_EVENT_SUBSCRIBE:
MODLOG_DFLT(INFO, "subscribe event; cur_notify=%d\n value handle; "
"val_handle=%d\n",
event->subscribe.cur_notify, event->subscribe.attr_handle);
break;
...
case BLE_GAP_EVENT_MTU:
MODLOG_DFLT(INFO, "mtu update event; conn_handle=%d mtu=%d\n",
event->mtu.conn_handle,
event->mtu.value);
break;
...
}{...}
return 0;
}{ ... }
static void
ble_cts_prph_on_sync(void)
{
int rc;
rc = ble_hs_id_infer_auto(0, &ble_cts_prph_addr_type);
assert(rc == 0);
uint8_t addr_val[6] = {0};
rc = ble_hs_id_copy_addr(ble_cts_prph_addr_type, addr_val, NULL);
MODLOG_DFLT(INFO, "Device Address: ");
print_addr(addr_val);
MODLOG_DFLT(INFO, "\n");
#if CONFIG_EXAMPLE_EXTENDED_ADV
ext_ble_cts_prph_advertise();
#else
ble_cts_prph_advertise();
#endif
}{ ... }
static void
ble_cts_prph_on_reset(int reason)
{
MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason);
}{ ... }
void ble_cts_prph_host_task(void *param)
{
ESP_LOGI(tag, "BLE Host Task Started");
nimble_port_run();
nimble_port_freertos_deinit();
}{ ... }
void app_main(void)
{
int rc;
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}{...}
ESP_ERROR_CHECK(ret);
ret = nimble_port_init();
if (ret != ESP_OK) {
MODLOG_DFLT(ERROR, "Failed to init nimble %d \n", ret);
return;
}{...}
ble_hs_cfg.sync_cb = ble_cts_prph_on_sync;
ble_hs_cfg.reset_cb = ble_cts_prph_on_reset;
ble_hs_cfg.sm_bonding = 1;
ble_hs_cfg.sm_our_key_dist |= BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID;
ble_hs_cfg.sm_their_key_dist |= BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID;
ble_hs_cfg.sm_sc = 1;
ble_hs_cfg.sm_mitm = 1;
rc = gatt_svr_init();
assert(rc == 0);
rc = ble_svc_gap_device_name_set(device_name);
assert(rc == 0);
nimble_port_freertos_init(ble_cts_prph_host_task);
}{ ... }