12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
14
15
- #include " sdkconfig.h"
16
15
#include " soc/soc_caps.h"
17
-
18
- #if SOC_BT_SUPPORTED && defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED)
16
+ #include " sdkconfig.h"
17
+ #if defined(SOC_BLE_SUPPORTED) || defined(CONFIG_ESP_HOSTED_ENABLE_BT_NIMBLE)
18
+ #if defined(CONFIG_BLUEDROID_ENABLED) || defined(CONFIG_NIMBLE_ENABLED)
19
19
20
20
#include " SimpleBLE.h"
21
21
#include " esp32-hal-log.h"
22
22
23
+ #if defined(SOC_BLE_SUPPORTED)
23
24
#include " esp_bt.h"
25
+ #endif
26
+
27
+ /* **************************************************************************
28
+ * Bluedroid includes *
29
+ ***************************************************************************/
30
+ #if defined(CONFIG_BLUEDROID_ENABLED)
24
31
#include " esp_gap_ble_api.h"
25
32
#include " esp_gatts_api.h"
26
33
#include " esp_bt_defs.h"
27
34
#include " esp_bt_main.h"
35
+ #endif
36
+
37
+ /* **************************************************************************
38
+ * NimBLE includes *
39
+ ***************************************************************************/
40
+ #if defined(CONFIG_NIMBLE_ENABLED)
41
+ #include < host/ble_gap.h>
42
+ #include < host/ble_hs.h>
43
+ #include < host/ble_store.h>
44
+ #include < store/config/ble_store_config.h>
45
+ #include < services/gap/ble_svc_gap.h>
46
+ #include < nimble/nimble_port.h>
47
+ #include < nimble/nimble_port_freertos.h>
48
+
49
+ #ifdef CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE
50
+ #include < esp_nimble_hci.h>
51
+ #endif
52
+
53
+ // Forward declaration
54
+ extern " C" void ble_store_config_init (void );
55
+ #endif
56
+
57
+ #if defined(CONFIG_ESP_HOSTED_ENABLE_BT_NIMBLE)
58
+ #include " esp32-hal-hosted.h"
59
+ #endif
28
60
61
+ /* **************************************************************************
62
+ * Bluedroid data structures *
63
+ ***************************************************************************/
64
+ #if defined(CONFIG_BLUEDROID_ENABLED)
29
65
static esp_ble_adv_data_t _adv_config = {
30
66
.set_scan_rsp = false ,
31
67
.include_name = true ,
@@ -55,14 +91,90 @@ static esp_ble_adv_params_t _adv_params = {
55
91
.channel_map = ADV_CHNL_ALL,
56
92
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
57
93
};
94
+ #endif
95
+
96
+ /* **************************************************************************
97
+ * NimBLE data structures *
98
+ ***************************************************************************/
99
+ #if defined(CONFIG_NIMBLE_ENABLED)
100
+ static struct ble_hs_adv_fields _nimble_adv_fields;
101
+ static struct ble_gap_adv_params _nimble_adv_params = {
102
+ .conn_mode = BLE_GAP_CONN_MODE_NON,
103
+ .disc_mode = BLE_GAP_DISC_MODE_GEN,
104
+ .itvl_min = 512 ,
105
+ .itvl_max = 1024 ,
106
+ .channel_map = 0 ,
107
+ .filter_policy = 0 ,
108
+ .high_duty_cycle = 0 ,
109
+ };
58
110
111
+ // Global variables for NimBLE synchronization
112
+ static bool _nimble_synced = false ;
113
+ #endif
114
+
115
+ // Global state tracking
116
+ static bool _ble_initialized = false ;
117
+
118
+ /* **************************************************************************
119
+ * Bluedroid callbacks *
120
+ ***************************************************************************/
121
+ #if defined(CONFIG_BLUEDROID_ENABLED)
59
122
static void _on_gap (esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
60
123
if (event == ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT) {
61
124
esp_ble_gap_start_advertising (&_adv_params);
62
125
}
63
126
}
127
+ #endif
128
+
129
+ /* **************************************************************************
130
+ * NimBLE callbacks *
131
+ ***************************************************************************/
132
+ #if defined(CONFIG_NIMBLE_ENABLED)
133
+ static void _nimble_host_task (void *param) {
134
+ // This function will be called to run the BLE host
135
+ nimble_port_run ();
136
+ // Should never reach here unless nimble_port_stop() is called
137
+ nimble_port_freertos_deinit ();
138
+ }
139
+
140
+ static void _nimble_on_reset (int reason) {
141
+ log_i (" NimBLE reset; reason=%d" , reason);
142
+ }
143
+
144
+ static void _nimble_on_sync (void ) {
145
+ log_i (" NimBLE sync complete" );
146
+ _nimble_synced = true ;
147
+ }
148
+
149
+ static int _nimble_gap_event (struct ble_gap_event *event, void *arg) {
150
+ switch (event->type ) {
151
+ case BLE_GAP_EVENT_ADV_COMPLETE:
152
+ log_d (" BLE_GAP_EVENT_ADV_COMPLETE" );
153
+ break ;
154
+ default :
155
+ break ;
156
+ }
157
+ return 0 ;
158
+ }
159
+ #endif
64
160
161
+ /* **************************************************************************
162
+ * Forward declarations *
163
+ ***************************************************************************/
164
+ static bool _init_gap (const char *name);
165
+ static bool _stop_gap ();
166
+ static bool _update_advertising (const char *name);
167
+
168
+ /* **************************************************************************
169
+ * Initialization functions *
170
+ ***************************************************************************/
65
171
static bool _init_gap (const char *name) {
172
+ if (_ble_initialized) {
173
+ log_d (" BLE already initialized, skipping" );
174
+ return true ;
175
+ }
176
+
177
+ #if defined(CONFIG_BLUEDROID_ENABLED)
66
178
if (!btStarted () && !btStart ()) {
67
179
log_e (" btStart failed" );
68
180
return false ;
@@ -92,16 +204,178 @@ static bool _init_gap(const char *name) {
92
204
log_e (" gap_register_callback failed" );
93
205
return false ;
94
206
}
207
+ _ble_initialized = true ;
95
208
return true ;
209
+ #elif defined(CONFIG_NIMBLE_ENABLED)
210
+ #if defined(CONFIG_ESP_HOSTED_ENABLE_BT_NIMBLE)
211
+ // Initialize esp-hosted transport for BLE HCI when explicitly enabled
212
+ if (!hostedInitBLE ()) {
213
+ log_e (" Failed to initialize ESP-Hosted for BLE" );
214
+ return false ;
215
+ }
216
+ #endif
217
+
218
+ esp_err_t errRc = nimble_port_init ();
219
+ if (errRc != ESP_OK) {
220
+ log_e (" nimble_port_init: rc=%d" , errRc);
221
+ return false ;
222
+ }
223
+
224
+ // Configure NimBLE host
225
+ ble_hs_cfg.reset_cb = _nimble_on_reset;
226
+ ble_hs_cfg.sync_cb = _nimble_on_sync;
227
+ ble_hs_cfg.sm_io_cap = BLE_HS_IO_NO_INPUT_OUTPUT;
228
+ ble_hs_cfg.sm_bonding = 0 ;
229
+ ble_hs_cfg.sm_mitm = 0 ;
230
+ ble_hs_cfg.sm_sc = 1 ;
231
+
232
+ // Set device name
233
+ errRc = ble_svc_gap_device_name_set (name);
234
+ if (errRc != ESP_OK) {
235
+ log_e (" ble_svc_gap_device_name_set: rc=%d" , errRc);
236
+ return false ;
237
+ }
238
+
239
+ // Configure advertising data
240
+ memset (&_nimble_adv_fields, 0 , sizeof (_nimble_adv_fields));
241
+ _nimble_adv_fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
242
+ _nimble_adv_fields.name = (uint8_t *)name;
243
+ _nimble_adv_fields.name_len = strlen (name);
244
+ _nimble_adv_fields.name_is_complete = 1 ;
245
+ _nimble_adv_fields.tx_pwr_lvl_is_present = 1 ;
246
+
247
+ // Initialize store configuration
248
+ ble_store_config_init ();
249
+
250
+ // Start the host task
251
+ nimble_port_freertos_init (_nimble_host_task);
252
+
253
+ // Wait for sync
254
+ int sync_timeout = 1000 ; // 10 seconds timeout
255
+ while (!_nimble_synced && sync_timeout > 0 ) {
256
+ vTaskDelay (pdMS_TO_TICKS (10 ));
257
+ sync_timeout--;
258
+ }
259
+
260
+ if (!_nimble_synced) {
261
+ log_e (" NimBLE sync timeout" );
262
+ return false ;
263
+ }
264
+
265
+ // Set advertising data
266
+ errRc = ble_gap_adv_set_fields (&_nimble_adv_fields);
267
+ if (errRc != ESP_OK) {
268
+ log_e (" ble_gap_adv_set_fields: rc=%d" , errRc);
269
+ return false ;
270
+ }
271
+
272
+ // Start advertising
273
+ errRc = ble_gap_adv_start (BLE_OWN_ADDR_PUBLIC, NULL , BLE_HS_FOREVER, &_nimble_adv_params, _nimble_gap_event, NULL );
274
+ if (errRc != ESP_OK) {
275
+ log_e (" ble_gap_adv_start: rc=%d" , errRc);
276
+ return false ;
277
+ }
278
+
279
+ _ble_initialized = true ;
280
+ return true ;
281
+ #else
282
+ log_e (" No BLE stack enabled" );
283
+ return false ;
284
+ #endif
96
285
}
97
286
98
287
static bool _stop_gap () {
288
+ if (!_ble_initialized) {
289
+ log_d (" BLE not initialized, nothing to stop" );
290
+ return true ;
291
+ }
292
+
293
+ #if defined(CONFIG_BLUEDROID_ENABLED)
99
294
if (btStarted ()) {
100
295
esp_bluedroid_disable ();
101
296
esp_bluedroid_deinit ();
102
297
btStop ();
103
298
}
299
+ _ble_initialized = false ;
300
+ return true ;
301
+ #elif defined(CONFIG_NIMBLE_ENABLED)
302
+ // Stop advertising
303
+ ble_gap_adv_stop ();
304
+
305
+ // Stop NimBLE
306
+ int rc = nimble_port_stop ();
307
+ if (rc != ESP_OK) {
308
+ log_e (" nimble_port_stop: rc=%d" , rc);
309
+ }
310
+
311
+ nimble_port_deinit ();
312
+ _nimble_synced = false ;
313
+ _ble_initialized = false ;
314
+
104
315
return true ;
316
+ #else
317
+ return true ;
318
+ #endif
319
+ }
320
+
321
+ static bool _update_advertising (const char *name) {
322
+ if (!_ble_initialized) {
323
+ log_e (" BLE not initialized" );
324
+ return false ;
325
+ }
326
+
327
+ #if defined(CONFIG_BLUEDROID_ENABLED)
328
+ // Stop current advertising
329
+ esp_ble_gap_stop_advertising ();
330
+
331
+ // Set new device name
332
+ if (esp_ble_gap_set_device_name (name)) {
333
+ log_e (" gap_set_device_name failed" );
334
+ return false ;
335
+ }
336
+
337
+ // Restart advertising with new name
338
+ if (esp_ble_gap_config_adv_data (&_adv_config)) {
339
+ log_e (" gap_config_adv_data failed" );
340
+ return false ;
341
+ }
342
+
343
+ return true ;
344
+ #elif defined(CONFIG_NIMBLE_ENABLED)
345
+ // Stop current advertising
346
+ ble_gap_adv_stop ();
347
+
348
+ // Set new device name
349
+ int errRc = ble_svc_gap_device_name_set (name);
350
+ if (errRc != ESP_OK) {
351
+ log_e (" ble_svc_gap_device_name_set: rc=%d" , errRc);
352
+ return false ;
353
+ }
354
+
355
+ // Update advertising fields with new name
356
+ _nimble_adv_fields.name = (uint8_t *)name;
357
+ _nimble_adv_fields.name_len = strlen (name);
358
+ _nimble_adv_fields.name_is_complete = 1 ;
359
+
360
+ // Set new advertising data
361
+ errRc = ble_gap_adv_set_fields (&_nimble_adv_fields);
362
+ if (errRc != ESP_OK) {
363
+ log_e (" ble_gap_adv_set_fields: rc=%d" , errRc);
364
+ return false ;
365
+ }
366
+
367
+ // Restart advertising
368
+ errRc = ble_gap_adv_start (BLE_OWN_ADDR_PUBLIC, NULL , BLE_HS_FOREVER, &_nimble_adv_params, _nimble_gap_event, NULL );
369
+ if (errRc != ESP_OK) {
370
+ log_e (" ble_gap_adv_start: rc=%d" , errRc);
371
+ return false ;
372
+ }
373
+
374
+ return true ;
375
+ #else
376
+ log_e (" No BLE stack enabled" );
377
+ return false ;
378
+ #endif
105
379
}
106
380
107
381
/*
@@ -121,11 +395,18 @@ bool SimpleBLE::begin(String localName) {
121
395
if (localName.length ()) {
122
396
local_name = localName;
123
397
}
398
+
399
+ // If already initialized, just update advertising data
400
+ if (_ble_initialized) {
401
+ return _update_advertising (local_name.c_str ());
402
+ }
403
+
124
404
return _init_gap (local_name.c_str ());
125
405
}
126
406
127
407
void SimpleBLE::end () {
128
408
_stop_gap ();
129
409
}
130
410
131
- #endif
411
+ #endif // CONFIG_BLUEDROID_ENABLED || CONFIG_NIMBLE_ENABLED
412
+ #endif // SOC_BLE_SUPPORTED || CONFIG_ESP_HOSTED_ENABLE_BT_NIMBLE
0 commit comments