-
Notifications
You must be signed in to change notification settings - Fork 7k
/
main.c
209 lines (188 loc) · 7.12 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
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
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include "esp_log.h"
#include "nvs_flash.h"
/* BLE */
#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 "periodic_sync.h"
#include "host/ble_gap.h"
static const char *tag = "NimBLE_BLE_PERIODIC_SYNC";
static int synced = 0;
static int periodic_sync_gap_event(struct ble_gap_event *event, void *arg);
void ble_store_config_init(void);
static void
periodic_sync_scan(void)
{
uint8_t own_addr_type;
struct ble_gap_disc_params disc_params;
int rc;
/* Figure out address to use while advertising (no privacy for now) */
rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
return;
}
/* Tell the controller to filter duplicates; we don't want to process
* repeated advertisements from the same device.
*/
disc_params.filter_duplicates = 0;
/**
* Perform a passive scan. I.e., don't send follow-up scan requests to
* each advertiser.
*/
disc_params.passive = 1;
/* Use defaults for the rest of the parameters. */
disc_params.itvl = 0;
disc_params.window = 0;
disc_params.filter_policy = 0;
disc_params.limited = 0;
rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params,
periodic_sync_gap_event, NULL);
if (rc != 0) {
MODLOG_DFLT(ERROR, "Error initiating GAP discovery procedure; rc=%d\n",
rc);
}
}
void print_periodic_sync_data(struct ble_gap_event *event)
{
MODLOG_DFLT(DEBUG, "status : %d\nperiodic_sync_handle : %d\nsid : %d\n", event->periodic_sync.status, event->periodic_sync.sync_handle, event->periodic_sync.sid);
MODLOG_DFLT(DEBUG, "adv addr : ");
for (int i = 0; i < 6; i++) {
MODLOG_DFLT(DEBUG, "%d ", event->periodic_sync.adv_addr.val[i]);
}
MODLOG_DFLT(DEBUG, "\nadv_phy : %s\n", event->periodic_sync.adv_phy == 1 ? "1m" : (event->periodic_sync.adv_phy == 2 ? "2m" : "coded"));
MODLOG_DFLT(DEBUG, "per_adv_ival : %d\n", event->periodic_sync.per_adv_ival);
MODLOG_DFLT(DEBUG, "adv_clk_accuracy : %d\n", event->periodic_sync.adv_clk_accuracy);
}
void print_periodic_adv_data(struct ble_gap_event *event)
{
MODLOG_DFLT(DEBUG, "sync_handle : %d\n", event->periodic_report.sync_handle);
MODLOG_DFLT(DEBUG, "tx_power : %d\n", event->periodic_report.tx_power);
MODLOG_DFLT(DEBUG, "rssi : %d\n", event->periodic_report.rssi);
MODLOG_DFLT(DEBUG, "data_status : %d\n", event->periodic_report.data_status);
MODLOG_DFLT(DEBUG, "data_length : %d\n", event->periodic_report.data_length);
MODLOG_DFLT(DEBUG, "data : ");
for (int i = 0; i < event->periodic_report.data_length; i++) {
MODLOG_DFLT(DEBUG, "%c", ((char *)event->periodic_report.data)[i]);
}
MODLOG_DFLT(DEBUG, "\n");
}
void print_periodic_sync_lost_data(struct ble_gap_event *event)
{
MODLOG_DFLT(DEBUG, "sync_handle : %d\n", event->periodic_sync_lost.sync_handle);
MODLOG_DFLT(DEBUG, "reason : %s\n", event->periodic_sync_lost.reason == 13 ? "timeout" : (event->periodic_sync_lost.reason == 14 ? "terminated locally" : "Unknown reason"));
}
/**
* The nimble host executes this callback when a GAP event occurs. The
* application associates a GAP event callback with each connection that is
* established. periodic_sync uses the same callback for all connections.
*
* @param event The event being signalled.
* @param arg Application-specified argument; unused by
* periodic_sync.
*
* @return 0 if the application successfully handled the
* event; nonzero on failure. The semantics
* of the return code is specific to the
* particular GAP event being signalled.
*/
static int
periodic_sync_gap_event(struct ble_gap_event *event, void *arg)
{
switch (event->type) {
#if CONFIG_EXAMPLE_EXTENDED_ADV
case BLE_GAP_EVENT_EXT_DISC:
/* An advertisment report was received during GAP discovery. */
struct ble_gap_ext_disc_desc *disc = ((struct ble_gap_ext_disc_desc *)(&event->disc));
if (disc->sid == 2 && synced == 0) {
synced++;
const ble_addr_t addr;
uint8_t adv_sid;
struct ble_gap_periodic_sync_params params;
int rc;
memcpy((void *)&addr, (void *)&disc->addr, sizeof(disc->addr));
memcpy(&adv_sid, &disc->sid, sizeof(disc->sid));
params.skip = 10;
params.sync_timeout = 1000;
rc = ble_gap_periodic_adv_sync_create(&addr, adv_sid, ¶ms, periodic_sync_gap_event, NULL);
assert(rc == 0);
}
return 0;
case BLE_GAP_EVENT_PERIODIC_REPORT:
MODLOG_DFLT(INFO, "Periodic adv report event: \n");
print_periodic_adv_data(event);
return 0;
case BLE_GAP_EVENT_PERIODIC_SYNC_LOST:
MODLOG_DFLT(INFO, "Periodic sync lost\n");
print_periodic_sync_lost_data(event);
synced = 0;
return 0;
case BLE_GAP_EVENT_PERIODIC_SYNC:
MODLOG_DFLT(INFO, "Periodic sync event : \n");
print_periodic_sync_data(event);
return 0;
#endif
default:
return 0;
}
}
static void
periodic_sync_on_reset(int reason)
{
MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason);
}
static void
periodic_sync_on_sync(void)
{
int rc;
/* Make sure we have proper identity address set (public preferred) */
rc = ble_hs_util_ensure_addr(0);
assert(rc == 0);
/* Begin scanning for a peripheral to connect to. */
periodic_sync_scan();
}
void periodic_sync_host_task(void *param)
{
ESP_LOGI(tag, "BLE Host Task Started");
/* This function will return only when nimble_port_stop() is executed */
nimble_port_run();
nimble_port_freertos_deinit();
}
void
app_main(void)
{
int rc;
/* Initialize NVS — it is used to store PHY calibration data */
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;
}
/* Configure the host. */
ble_hs_cfg.reset_cb = periodic_sync_on_reset;
ble_hs_cfg.sync_cb = periodic_sync_on_sync;
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
/* Initialize data structures to track connected peers. */
rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64);
assert(rc == 0);
/* Set the default device name. */
rc = ble_svc_gap_device_name_set("nimble_periodic_sync");
assert(rc == 0);
/* XXX Need to have template for store */
ble_store_config_init();
nimble_port_freertos_init(periodic_sync_host_task);
}