1
8
9
10
11
12
13
14
15
16
17
18
19
20
21
25
26
30
31
32
33
34
35
36
40
41
45
49
50
54
55
56
57
58
61
69
70
71
75
76
77
78
85
86
87
88
92
93
98
99
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
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
199
200
201
211
212
213
214
215
216
217
218
222
223
224
225
226
227
228
229
230
231
232
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
257
260
261
262
263
267
270
271
274
275
279
284
285
286
287
291
295
296
309
310
311
312
316
319
320
321
322
323
327
328
329
330
331
332
333
334
340
341
342
343
344
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
368
369
370
371
372
373
374
375
376
377
378
379
380
384
385
386
387
388
389
390
391
392
393
394
398
399
400
401
402
406
407
411
412
416
417
418
419
423
424
425
426
427
428
429
432
433
434
437
438
439
440
441
442
443
444
445
446
/* ... */
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_bt.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "nvs_flash.h"
#include "freertos/queue.h"
#include "bt_hci_common.h"10 includes
static const char *TAG = "BLE_ADV_SCAN";
typedef struct {
char scan_local_name[32];
uint8_t name_len;
}{ ... } ble_scan_local_name_t;
typedef struct {
uint8_t *q_data;
uint16_t q_data_len;
}{ ... } host_rcv_data_t;
static uint8_t hci_cmd_buf[128];
static uint16_t scanned_count = 0;
static QueueHandle_t adv_queue;
static void periodic_timer_callback(void *arg)
{
ESP_LOGI(TAG, "Number of received advertising reports: %d", scanned_count);
}{ ... }
/* ... */
static void controller_rcv_pkt_ready(void)
{
ESP_LOGI(TAG, "controller rcv pkt ready");
}{ ... }
/* ... */
static int host_rcv_pkt(uint8_t *data, uint16_t len)
{
host_rcv_data_t send_data;
uint8_t *data_pkt;
/* ... */
if (data[1] == 0x0e) {
if (data[6] == 0) {
ESP_LOGI(TAG, "Event opcode 0x%02x success.", data[4]);
}{...} else {
ESP_LOGE(TAG, "Event opcode 0x%02x fail with reason: 0x%02x.", data[4], data[6]);
return ESP_FAIL;
}{...}
}{...}
data_pkt = (uint8_t *)malloc(sizeof(uint8_t) * len);
if (data_pkt == NULL) {
ESP_LOGE(TAG, "Malloc data_pkt failed!");
return ESP_FAIL;
}{...}
memcpy(data_pkt, data, len);
send_data.q_data = data_pkt;
send_data.q_data_len = len;
if (xQueueSend(adv_queue, (void *)&send_data, ( TickType_t ) 0) != pdTRUE) {
ESP_LOGD(TAG, "Failed to enqueue advertising report. Queue full.");
/* ... */
free(data_pkt);
}{...}
return ESP_OK;
}{ ... }
static esp_vhci_host_callback_t vhci_host_cb = {
controller_rcv_pkt_ready,
host_rcv_pkt
}{...};
static void hci_cmd_send_reset(void)
{
uint16_t sz = make_cmd_reset (hci_cmd_buf);
esp_vhci_host_send_packet(hci_cmd_buf, sz);
}{ ... }
static void hci_cmd_send_set_evt_mask(void)
{
uint8_t evt_mask[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20};
uint16_t sz = make_cmd_set_evt_mask(hci_cmd_buf, evt_mask);
esp_vhci_host_send_packet(hci_cmd_buf, sz);
}{ ... }
static void hci_cmd_send_ble_scan_params(void)
{
uint8_t scan_type = 0x01;
uint16_t scan_interval = 0x50;
uint16_t scan_window = 0x30;
uint8_t own_addr_type = 0x00;
uint8_t filter_policy = 0x00;
uint16_t sz = make_cmd_ble_set_scan_params(hci_cmd_buf, scan_type, scan_interval, scan_window, own_addr_type, filter_policy);
esp_vhci_host_send_packet(hci_cmd_buf, sz);
}{ ... }
static void hci_cmd_send_ble_scan_start(void)
{
uint8_t scan_enable = 0x01;
uint8_t filter_duplicates = 0x00;
uint16_t sz = make_cmd_ble_set_scan_enable(hci_cmd_buf, scan_enable, filter_duplicates);
esp_vhci_host_send_packet(hci_cmd_buf, sz);
ESP_LOGI(TAG, "BLE Scanning started..");
}{ ... }
static void hci_cmd_send_ble_adv_start(void)
{
uint16_t sz = make_cmd_ble_set_adv_enable (hci_cmd_buf, 1);
esp_vhci_host_send_packet(hci_cmd_buf, sz);
ESP_LOGI(TAG, "BLE Advertising started..");
}{ ... }
static void hci_cmd_send_ble_set_adv_param(void)
{
uint16_t adv_intv_min = 0x100;
uint16_t adv_intv_max = 0x100;
uint8_t adv_type = 0;
uint8_t own_addr_type = 0;
uint8_t peer_addr_type = 0;
uint8_t peer_addr[6] = {0x80, 0x81, 0x82, 0x83, 0x84, 0x85};
uint8_t adv_chn_map = 0x07;
uint8_t adv_filter_policy = 0;
uint16_t sz = make_cmd_ble_set_adv_param(hci_cmd_buf,
adv_intv_min,
adv_intv_max,
adv_type,
own_addr_type,
peer_addr_type,
peer_addr,
adv_chn_map,
adv_filter_policy);
esp_vhci_host_send_packet(hci_cmd_buf, sz);
}{ ... }
static void hci_cmd_send_ble_set_adv_data(void)
{
char *adv_name = "ESP-BLE-1";
uint8_t name_len = (uint8_t)strlen(adv_name);
uint8_t adv_data[31] = {0x02, 0x01, 0x06, 0x0, 0x09};
uint8_t adv_data_len;
adv_data[3] = name_len + 1;
for (int i = 0; i < name_len; i++) {
adv_data[5 + i] = (uint8_t)adv_name[i];
}{...}
adv_data_len = 5 + name_len;
uint16_t sz = make_cmd_ble_set_adv_data(hci_cmd_buf, adv_data_len, (uint8_t *)adv_data);
esp_vhci_host_send_packet(hci_cmd_buf, sz);
ESP_LOGI(TAG, "Starting BLE advertising with name \"%s\"", adv_name);
}{ ... }
static esp_err_t get_local_name (uint8_t *data_msg, uint8_t data_len, ble_scan_local_name_t *scanned_packet)
{
uint8_t curr_ptr = 0, curr_len, curr_type;
while (curr_ptr < data_len) {
curr_len = data_msg[curr_ptr++];
curr_type = data_msg[curr_ptr++];
if (curr_len == 0) {
return ESP_FAIL;
}{...}
if (curr_type == 0x08 || curr_type == 0x09) {
for (uint8_t i = 0; i < curr_len - 1; i += 1) {
scanned_packet->scan_local_name[i] = data_msg[curr_ptr + i];
}{...}
scanned_packet->name_len = curr_len - 1;
return ESP_OK;
}{...} else {
curr_ptr += curr_len - 1;
}{...}
}{...}
return ESP_FAIL;
}{ ... }
void hci_evt_process(void *pvParameters)
{
host_rcv_data_t *rcv_data = (host_rcv_data_t *)malloc(sizeof(host_rcv_data_t));
if (rcv_data == NULL) {
ESP_LOGE(TAG, "Malloc rcv_data failed!");
return;
}{...}
esp_err_t ret;
while (1) {
uint8_t sub_event, num_responses, total_data_len, data_msg_ptr, hci_event_opcode;
uint8_t *queue_data = NULL, *event_type = NULL, *addr_type = NULL, *addr = NULL, *data_len = NULL, *data_msg = NULL;
short int *rssi = NULL;
uint16_t data_ptr;
ble_scan_local_name_t *scanned_name = NULL;
total_data_len = 0;
data_msg_ptr = 0;
if (xQueueReceive(adv_queue, rcv_data, portMAX_DELAY) != pdPASS) {
ESP_LOGE(TAG, "Queue receive error");
}{...} else {
data_ptr = 0;
queue_data = rcv_data->q_data;
hci_event_opcode = queue_data[++data_ptr];
if (hci_event_opcode == LE_META_EVENTS) {
data_ptr += 2;
sub_event = queue_data[data_ptr++];
if (sub_event == HCI_LE_ADV_REPORT) {
scanned_count += 1;
num_responses = queue_data[data_ptr++];
event_type = (uint8_t *)malloc(sizeof(uint8_t) * num_responses);
if (event_type == NULL) {
ESP_LOGE(TAG, "Malloc event_type failed!");
goto reset;
}{...}
for (uint8_t i = 0; i < num_responses; i += 1) {
event_type[i] = queue_data[data_ptr++];
}{...}
addr_type = (uint8_t *)malloc(sizeof(uint8_t) * num_responses);
if (addr_type == NULL) {
ESP_LOGE(TAG, "Malloc addr_type failed!");
goto reset;
}{...}
for (uint8_t i = 0; i < num_responses; i += 1) {
addr_type[i] = queue_data[data_ptr++];
}{...}
/* ... */
addr = (uint8_t *)malloc(sizeof(uint8_t) * 6 * num_responses);
if (addr == NULL) {
ESP_LOGE(TAG, "Malloc addr failed!");
goto reset;
}{...}
for (int i = 0; i < num_responses; i += 1) {
for (int j = 0; j < 6; j += 1) {
addr[(6 * i) + j] = queue_data[data_ptr++];
}{...}
}{...}
data_len = (uint8_t *)malloc(sizeof(uint8_t) * num_responses);
if (data_len == NULL) {
ESP_LOGE(TAG, "Malloc data_len failed!");
goto reset;
}{...}
for (uint8_t i = 0; i < num_responses; i += 1) {
data_len[i] = queue_data[data_ptr];
total_data_len += queue_data[data_ptr++];
}{...}
if (total_data_len != 0) {
data_msg = (uint8_t *)malloc(sizeof(uint8_t) * total_data_len);
if (data_msg == NULL) {
ESP_LOGE(TAG, "Malloc data_msg failed!");
goto reset;
}{...}
for (uint8_t i = 0; i < num_responses; i += 1) {
for (uint8_t j = 0; j < data_len[i]; j += 1) {
data_msg[data_msg_ptr++] = queue_data[data_ptr++];
}{...}
}{...}
}{...}
rssi = (short int *)malloc(sizeof(short int) * num_responses);
if (data_len == NULL) {
ESP_LOGE(TAG, "Malloc rssi failed!");
goto reset;
}{...}
for (uint8_t i = 0; i < num_responses; i += 1) {
rssi[i] = -(0xFF - queue_data[data_ptr++]);
}{...}
data_msg_ptr = 0;
scanned_name = (ble_scan_local_name_t *)malloc(num_responses * sizeof(ble_scan_local_name_t));
if (data_len == NULL) {
ESP_LOGE(TAG, "Malloc scanned_name failed!");
goto reset;
}{...}
for (uint8_t i = 0; i < num_responses; i += 1) {
ret = get_local_name(&data_msg[data_msg_ptr], data_len[i], scanned_name);
if (ret == ESP_OK) {
printf("******** Response %d/%d ********\n", i + 1, num_responses);
printf("Event type: %02x\nAddress type: %02x\nAddress: ", event_type[i], addr_type[i]);
for (int j = 5; j >= 0; j -= 1) {
printf("%02x", addr[(6 * i) + j]);
if (j > 0) {
printf(":");
}{...}
}{...}
printf("\nData length: %d", data_len[i]);
data_msg_ptr += data_len[i];
printf("\nAdvertisement Name: ");
for (int k = 0; k < scanned_name->name_len; k += 1 ) {
printf("%c", scanned_name->scan_local_name[k]);
}{...}
printf("\nRSSI: %ddB\n", rssi[i]);
}{...}
}{...}
reset:
free(scanned_name);
free(rssi);
free(data_msg);
free(data_len);
free(addr);
free(addr_type);
free(event_type);
}{...}
}{...}
#if (CONFIG_LOG_DEFAULT_LEVEL_DEBUG || CONFIG_LOG_DEFAULT_LEVEL_VERBOSE)
printf("Raw Data:");
for (uint8_t j = 0; j < rcv_data->q_data_len; j += 1) {
printf(" %02x", queue_data[j]);
}{...}
printf("\nQueue free size: %d\n", uxQueueSpacesAvailable(adv_queue));/* ... */
#endif
free(queue_data);
}{...}
memset(rcv_data, 0, sizeof(host_rcv_data_t));
}{...}
}{ ... }
void app_main(void)
{
bool continue_commands = 1;
int cmd_cnt = 0;
const esp_timer_create_args_t periodic_timer_args = {
.callback = &periodic_timer_callback,
.name = "periodic"
}{...};
esp_timer_handle_t periodic_timer;
ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, 5000000));
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 );
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
ret = esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
if (ret) {
ESP_LOGI(TAG, "Bluetooth controller release classic bt memory failed: %s", esp_err_to_name(ret));
return;
}{...}
if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) {
ESP_LOGI(TAG, "Bluetooth controller initialize failed: %s", esp_err_to_name(ret));
return;
}{...}
if ((ret = esp_bt_controller_enable(ESP_BT_MODE_BLE)) != ESP_OK) {
ESP_LOGI(TAG, "Bluetooth controller enable failed: %s", esp_err_to_name(ret));
return;
}{...}
adv_queue = xQueueCreate(15, sizeof(host_rcv_data_t));
if (adv_queue == NULL) {
ESP_LOGE(TAG, "Queue creation failed");
return;
}{...}
esp_vhci_host_register_callback(&vhci_host_cb);
while (continue_commands) {
if (continue_commands && esp_vhci_host_check_send_available()) {
switch (cmd_cnt) {
case 0: hci_cmd_send_reset(); ++cmd_cnt; break;
case 1: hci_cmd_send_set_evt_mask(); ++cmd_cnt; break;
...
case 2: hci_cmd_send_ble_set_adv_param(); ++cmd_cnt; break;
case 3: hci_cmd_send_ble_set_adv_data(); ++cmd_cnt; break;
case 4: hci_cmd_send_ble_adv_start(); ++cmd_cnt; break;
...
case 5: hci_cmd_send_ble_scan_params(); ++cmd_cnt; break;
case 6: hci_cmd_send_ble_scan_start(); ++cmd_cnt; break;
default: continue_commands = 0; break;
}{...}
ESP_LOGI(TAG, "BLE Advertise, cmd_sent: %d", cmd_cnt);
}{...}
vTaskDelay(1000 / portTICK_PERIOD_MS);
}{...}
xTaskCreatePinnedToCore(&hci_evt_process, "hci_evt_process", 2048, NULL, 6, NULL, 0);
}{ ... }