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,87 @@ 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: log_d (" BLE_GAP_EVENT_ADV_COMPLETE" ); break ;
152
+ default : break ;
153
+ }
154
+ return 0 ;
155
+ }
156
+ #endif
64
157
158
+ /* **************************************************************************
159
+ * Forward declarations *
160
+ ***************************************************************************/
161
+ static bool _init_gap (const char *name);
162
+ static bool _stop_gap ();
163
+ static bool _update_advertising (const char *name);
164
+
165
+ /* **************************************************************************
166
+ * Initialization functions *
167
+ ***************************************************************************/
65
168
static bool _init_gap (const char *name) {
169
+ if (_ble_initialized) {
170
+ log_d (" BLE already initialized, skipping" );
171
+ return true ;
172
+ }
173
+
174
+ #if defined(CONFIG_BLUEDROID_ENABLED)
66
175
if (!btStarted () && !btStart ()) {
67
176
log_e (" btStart failed" );
68
177
return false ;
@@ -92,16 +201,178 @@ static bool _init_gap(const char *name) {
92
201
log_e (" gap_register_callback failed" );
93
202
return false ;
94
203
}
204
+ _ble_initialized = true ;
95
205
return true ;
206
+ #elif defined(CONFIG_NIMBLE_ENABLED)
207
+ #if defined(CONFIG_ESP_HOSTED_ENABLE_BT_NIMBLE)
208
+ // Initialize esp-hosted transport for BLE HCI when explicitly enabled
209
+ if (!hostedInitBLE ()) {
210
+ log_e (" Failed to initialize ESP-Hosted for BLE" );
211
+ return false ;
212
+ }
213
+ #endif
214
+
215
+ esp_err_t errRc = nimble_port_init ();
216
+ if (errRc != ESP_OK) {
217
+ log_e (" nimble_port_init: rc=%d" , errRc);
218
+ return false ;
219
+ }
220
+
221
+ // Configure NimBLE host
222
+ ble_hs_cfg.reset_cb = _nimble_on_reset;
223
+ ble_hs_cfg.sync_cb = _nimble_on_sync;
224
+ ble_hs_cfg.sm_io_cap = BLE_HS_IO_NO_INPUT_OUTPUT;
225
+ ble_hs_cfg.sm_bonding = 0 ;
226
+ ble_hs_cfg.sm_mitm = 0 ;
227
+ ble_hs_cfg.sm_sc = 1 ;
228
+
229
+ // Set device name
230
+ errRc = ble_svc_gap_device_name_set (name);
231
+ if (errRc != ESP_OK) {
232
+ log_e (" ble_svc_gap_device_name_set: rc=%d" , errRc);
233
+ return false ;
234
+ }
235
+
236
+ // Configure advertising data
237
+ memset (&_nimble_adv_fields, 0 , sizeof (_nimble_adv_fields));
238
+ _nimble_adv_fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
239
+ _nimble_adv_fields.name = (uint8_t *)name;
240
+ _nimble_adv_fields.name_len = strlen (name);
241
+ _nimble_adv_fields.name_is_complete = 1 ;
242
+ _nimble_adv_fields.tx_pwr_lvl_is_present = 1 ;
243
+
244
+ // Initialize store configuration
245
+ ble_store_config_init ();
246
+
247
+ // Start the host task
248
+ nimble_port_freertos_init (_nimble_host_task);
249
+
250
+ // Wait for sync
251
+ int sync_timeout = 1000 ; // 10 seconds timeout
252
+ while (!_nimble_synced && sync_timeout > 0 ) {
253
+ vTaskDelay (pdMS_TO_TICKS (10 ));
254
+ sync_timeout--;
255
+ }
256
+
257
+ if (!_nimble_synced) {
258
+ log_e (" NimBLE sync timeout" );
259
+ return false ;
260
+ }
261
+
262
+ // Set advertising data
263
+ errRc = ble_gap_adv_set_fields (&_nimble_adv_fields);
264
+ if (errRc != ESP_OK) {
265
+ log_e (" ble_gap_adv_set_fields: rc=%d" , errRc);
266
+ return false ;
267
+ }
268
+
269
+ // Start advertising
270
+ errRc = ble_gap_adv_start (BLE_OWN_ADDR_PUBLIC, NULL , BLE_HS_FOREVER, &_nimble_adv_params, _nimble_gap_event, NULL );
271
+ if (errRc != ESP_OK) {
272
+ log_e (" ble_gap_adv_start: rc=%d" , errRc);
273
+ return false ;
274
+ }
275
+
276
+ _ble_initialized = true ;
277
+ return true ;
278
+ #else
279
+ log_e (" No BLE stack enabled" );
280
+ return false ;
281
+ #endif
96
282
}
97
283
98
284
static bool _stop_gap () {
285
+ if (!_ble_initialized) {
286
+ log_d (" BLE not initialized, nothing to stop" );
287
+ return true ;
288
+ }
289
+
290
+ #if defined(CONFIG_BLUEDROID_ENABLED)
99
291
if (btStarted ()) {
100
292
esp_bluedroid_disable ();
101
293
esp_bluedroid_deinit ();
102
294
btStop ();
103
295
}
296
+ _ble_initialized = false ;
297
+ return true ;
298
+ #elif defined(CONFIG_NIMBLE_ENABLED)
299
+ // Stop advertising
300
+ ble_gap_adv_stop ();
301
+
302
+ // Stop NimBLE
303
+ int rc = nimble_port_stop ();
304
+ if (rc != ESP_OK) {
305
+ log_e (" nimble_port_stop: rc=%d" , rc);
306
+ }
307
+
308
+ nimble_port_deinit ();
309
+ _nimble_synced = false ;
310
+ _ble_initialized = false ;
311
+
104
312
return true ;
313
+ #else
314
+ return true ;
315
+ #endif
316
+ }
317
+
318
+ static bool _update_advertising (const char *name) {
319
+ if (!_ble_initialized) {
320
+ log_e (" BLE not initialized" );
321
+ return false ;
322
+ }
323
+
324
+ #if defined(CONFIG_BLUEDROID_ENABLED)
325
+ // Stop current advertising
326
+ esp_ble_gap_stop_advertising ();
327
+
328
+ // Set new device name
329
+ if (esp_ble_gap_set_device_name (name)) {
330
+ log_e (" gap_set_device_name failed" );
331
+ return false ;
332
+ }
333
+
334
+ // Restart advertising with new name
335
+ if (esp_ble_gap_config_adv_data (&_adv_config)) {
336
+ log_e (" gap_config_adv_data failed" );
337
+ return false ;
338
+ }
339
+
340
+ return true ;
341
+ #elif defined(CONFIG_NIMBLE_ENABLED)
342
+ // Stop current advertising
343
+ ble_gap_adv_stop ();
344
+
345
+ // Set new device name
346
+ int errRc = ble_svc_gap_device_name_set (name);
347
+ if (errRc != ESP_OK) {
348
+ log_e (" ble_svc_gap_device_name_set: rc=%d" , errRc);
349
+ return false ;
350
+ }
351
+
352
+ // Update advertising fields with new name
353
+ _nimble_adv_fields.name = (uint8_t *)name;
354
+ _nimble_adv_fields.name_len = strlen (name);
355
+ _nimble_adv_fields.name_is_complete = 1 ;
356
+
357
+ // Set new advertising data
358
+ errRc = ble_gap_adv_set_fields (&_nimble_adv_fields);
359
+ if (errRc != ESP_OK) {
360
+ log_e (" ble_gap_adv_set_fields: rc=%d" , errRc);
361
+ return false ;
362
+ }
363
+
364
+ // Restart advertising
365
+ errRc = ble_gap_adv_start (BLE_OWN_ADDR_PUBLIC, NULL , BLE_HS_FOREVER, &_nimble_adv_params, _nimble_gap_event, NULL );
366
+ if (errRc != ESP_OK) {
367
+ log_e (" ble_gap_adv_start: rc=%d" , errRc);
368
+ return false ;
369
+ }
370
+
371
+ return true ;
372
+ #else
373
+ log_e (" No BLE stack enabled" );
374
+ return false ;
375
+ #endif
105
376
}
106
377
107
378
/*
@@ -121,11 +392,18 @@ bool SimpleBLE::begin(String localName) {
121
392
if (localName.length ()) {
122
393
local_name = localName;
123
394
}
395
+
396
+ // If already initialized, just update advertising data
397
+ if (_ble_initialized) {
398
+ return _update_advertising (local_name.c_str ());
399
+ }
400
+
124
401
return _init_gap (local_name.c_str ());
125
402
}
126
403
127
404
void SimpleBLE::end () {
128
405
_stop_gap ();
129
406
}
130
407
131
- #endif
408
+ #endif // CONFIG_BLUEDROID_ENABLED || CONFIG_NIMBLE_ENABLED
409
+ #endif // SOC_BLE_SUPPORTED || CONFIG_ESP_HOSTED_ENABLE_BT_NIMBLE
0 commit comments