1 /*
2    This example code is in the Public Domain (or CC0 licensed, at your option.)
3 
4    Unless required by applicable law or agreed to in writing, this
5    software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
6    CONDITIONS OF ANY KIND, either express or implied.
7 */
8 
9 /****************************************************************************
10 *
11 * This demo showcases BLE GATT server. It can send adv data, be connected by client.
12 * Run the gatt_client demo, the client demo will automatically connect to the gatt_server demo.
13 * Client demo will enable gatt_server's notify after connection. The two devices will then exchange
14 * data.
15 *
16 ****************************************************************************/
17 
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include "freertos/FreeRTOS.h"
23 #include "freertos/task.h"
24 #include "freertos/event_groups.h"
25 #include "esp_system.h"
26 #include "esp_log.h"
27 #include "nvs_flash.h"
28 #include "esp_bt.h"
29 
30 #include "esp_gap_ble_api.h"
31 #include "esp_gatts_api.h"
32 #include "esp_bt_defs.h"
33 #include "esp_bt_main.h"
34 #include "esp_gatt_common_api.h"
35 
36 #include "sdkconfig.h"
37 
38 #include "freertos/semphr.h"
39 
40 #define LOG_TAG "MULTI_ADV_DEMO"
41 
42 #define FUNC_SEND_WAIT_SEM(func, sem) do {\
43         esp_err_t __err_rc = (func);\
44         if (__err_rc != ESP_OK) { \
45             ESP_LOGE(LOG_TAG, "%s, message send fail, error = %d", __func__, __err_rc); \
46         } \
47         xSemaphoreTake(sem, portMAX_DELAY); \
48 } while(0);
49 
50 static SemaphoreHandle_t test_sem = NULL;
51 
52 uint8_t addr_1m[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x01};
53 uint8_t addr_2m[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x02};
54 uint8_t addr_legacy[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x03};
55 uint8_t addr_coded[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x04};
56 
57 esp_ble_gap_ext_adv_params_t ext_adv_params_1M = {
58     .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE,
59     .interval_min = 0x30,
60     .interval_max = 0x30,
61     .channel_map = ADV_CHNL_ALL,
62     .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
63     .primary_phy = ESP_BLE_GAP_PHY_1M,
64     .max_skip = 0,
65     .secondary_phy = ESP_BLE_GAP_PHY_1M,
66     .sid = 0,
67     .scan_req_notif = false,
68     .own_addr_type = BLE_ADDR_TYPE_RANDOM,
69 };
70 
71 esp_ble_gap_ext_adv_params_t ext_adv_params_2M = {
72     .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE,
73     .interval_min = 0x40,
74     .interval_max = 0x40,
75     .channel_map = ADV_CHNL_ALL,
76     .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
77     .primary_phy = ESP_BLE_GAP_PHY_1M,
78     .max_skip = 0,
79     .secondary_phy = ESP_BLE_GAP_PHY_2M,
80     .sid = 1,
81     .scan_req_notif = false,
82     .own_addr_type = BLE_ADDR_TYPE_RANDOM,
83 };
84 
85 esp_ble_gap_ext_adv_params_t legacy_adv_params = {
86     .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_IND,
87     .interval_min = 0x45,
88     .interval_max = 0x45,
89     .channel_map = ADV_CHNL_ALL,
90     .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
91     .primary_phy = ESP_BLE_GAP_PHY_1M,
92     .max_skip = 0,
93     .secondary_phy = ESP_BLE_GAP_PHY_1M,
94     .sid = 2,
95     .scan_req_notif = false,
96     .own_addr_type = BLE_ADDR_TYPE_RANDOM,
97 };
98 
99 esp_ble_gap_ext_adv_params_t ext_adv_params_coded = {
100     .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE,
101     .interval_min = 0x50,
102     .interval_max = 0x50,
103     .channel_map = ADV_CHNL_ALL,
104     .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
105     .primary_phy = ESP_BLE_GAP_PHY_1M,
106     .max_skip = 0,
107     .secondary_phy = ESP_BLE_GAP_PHY_CODED,
108     .sid = 3,
109     .scan_req_notif = false,
110     .own_addr_type = BLE_ADDR_TYPE_RANDOM,
111 };
112 
113 static uint8_t raw_adv_data_1m[] = {
114         0x02, 0x01, 0x06,
115         0x02, 0x0a, 0xeb,
116         0x11, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A',
117         'D', 'V', '_', '1', 'M'
118 };
119 
120 static uint8_t raw_scan_rsp_data_2m[] = {
121         0x02, 0x01, 0x06,
122         0x02, 0x0a, 0xeb,
123         0x11, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A',
124         'D', 'V', '_', '2', 'M'
125 };
126 
127 static uint8_t legacy_adv_data[] = {
128         0x02, 0x01, 0x06,
129         0x02, 0x0a, 0xeb,
130         0x14, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A',
131         'D', 'V', '_', 'C', 'O', 'D', 'E', 'D'
132 };
133 
134 static uint8_t legacy_scan_rsp_data[] = {
135         0x02, 0x01, 0x06,
136         0x02, 0x0a, 0xeb,
137         0x15, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A',
138         'D', 'V', '_', 'L', 'E', 'G', 'A', 'C', 'Y'
139 };
140 
141 static uint8_t raw_scan_rsp_data_coded[] = {
142         0x02, 0x01, 0x06,
143         0x02, 0x0a, 0xeb,
144         0x14, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A',
145         'D', 'V', '_', 'C', 'O', 'D', 'E', 'D'
146 };
147 
148 static esp_ble_gap_ext_adv_t ext_adv[4] = {
149     // instance, duration, peroid
150     [0] = {0, 0, 0},
151     [1] = {1, 0, 0},
152     [2] = {2, 0, 0},
153     [3] = {3, 0, 0},
154 };
155 
gap_event_handler(esp_gap_ble_cb_event_t event,esp_ble_gap_cb_param_t * param)156 static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
157 {
158     switch (event) {
159     case ESP_GAP_BLE_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT:
160         xSemaphoreGive(test_sem);
161         ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT, status %d", param->ext_adv_set_rand_addr.status);
162         break;
163     case ESP_GAP_BLE_EXT_ADV_SET_PARAMS_COMPLETE_EVT:
164         xSemaphoreGive(test_sem);
165         ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_ADV_SET_PARAMS_COMPLETE_EVT, status %d", param->ext_adv_set_params.status);
166         break;
167     case ESP_GAP_BLE_EXT_ADV_DATA_SET_COMPLETE_EVT:
168         xSemaphoreGive(test_sem);
169         ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_ADV_DATA_SET_COMPLETE_EVT, status %d", param->ext_adv_data_set.status);
170         break;
171     case ESP_GAP_BLE_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT:
172         xSemaphoreGive(test_sem);
173         ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT, status %d", param->scan_rsp_set.status);
174         break;
175     case ESP_GAP_BLE_EXT_ADV_START_COMPLETE_EVT:
176         xSemaphoreGive(test_sem);
177         ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_ADV_START_COMPLETE_EVT, status %d", param->ext_adv_start.status);
178         break;
179     case ESP_GAP_BLE_EXT_ADV_STOP_COMPLETE_EVT:
180         xSemaphoreGive(test_sem);
181         ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_ADV_STOP_COMPLETE_EVT, status %d", param->ext_adv_stop.status);
182         break;
183     default:
184         break;
185     }
186 }
187 
app_main(void)188 void app_main(void)
189 {
190     esp_err_t ret;
191 
192     // Initialize NVS.
193     ret = nvs_flash_init();
194     if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
195         ESP_ERROR_CHECK(nvs_flash_erase());
196         ret = nvs_flash_init();
197     }
198     ESP_ERROR_CHECK( ret );
199 
200     ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));
201 
202     esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
203     ret = esp_bt_controller_init(&bt_cfg);
204     if (ret) {
205         ESP_LOGE(LOG_TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(ret));
206         return;
207     }
208 
209     ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
210     if (ret) {
211         ESP_LOGE(LOG_TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(ret));
212         return;
213     }
214     ret = esp_bluedroid_init();
215     if (ret) {
216         ESP_LOGE(LOG_TAG, "%s init bluetooth failed: %s\n", __func__, esp_err_to_name(ret));
217         return;
218     }
219     ret = esp_bluedroid_enable();
220     if (ret) {
221         ESP_LOGE(LOG_TAG, "%s enable bluetooth failed: %s\n", __func__, esp_err_to_name(ret));
222         return;
223     }
224     ret = esp_ble_gap_register_callback(gap_event_handler);
225     if (ret){
226         ESP_LOGE(LOG_TAG, "gap register error, error code = %x", ret);
227         return;
228     }
229 
230     vTaskDelay(200 / portTICK_PERIOD_MS);
231 
232     test_sem = xSemaphoreCreateBinary();
233     // 1M phy extend adv, Connectable advertising
234     FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_set_params(0, &ext_adv_params_1M), test_sem);
235     FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_set_rand_addr(0, addr_1m), test_sem);
236     FUNC_SEND_WAIT_SEM(esp_ble_gap_config_ext_adv_data_raw(0, sizeof(raw_adv_data_1m), &raw_adv_data_1m[0]), test_sem);
237 
238     // 2M phy extend adv, Scannable advertising
239     FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_set_params(1, &ext_adv_params_2M), test_sem);
240     FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_set_rand_addr(1, addr_2m), test_sem);
241     FUNC_SEND_WAIT_SEM(esp_ble_gap_config_ext_scan_rsp_data_raw(1, sizeof(raw_scan_rsp_data_2m), raw_scan_rsp_data_2m), test_sem);
242 
243     // 1M phy legacy adv, ADV_IND
244     FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_set_params(2, &legacy_adv_params), test_sem);
245     FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_set_rand_addr(2, addr_legacy), test_sem);
246     FUNC_SEND_WAIT_SEM(esp_ble_gap_config_ext_adv_data_raw(2, sizeof(legacy_adv_data), &legacy_adv_data[0]), test_sem);
247     FUNC_SEND_WAIT_SEM(esp_ble_gap_config_ext_scan_rsp_data_raw(2, sizeof(legacy_scan_rsp_data), &legacy_scan_rsp_data[0]), test_sem);
248 
249     // coded phy extend adv, Connectable advertising
250     FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_set_params(3, &ext_adv_params_coded), test_sem);
251     FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_set_rand_addr(3, addr_coded), test_sem);
252     FUNC_SEND_WAIT_SEM(esp_ble_gap_config_ext_scan_rsp_data_raw(3, sizeof(raw_scan_rsp_data_coded), &raw_scan_rsp_data_coded[0]), test_sem);
253 
254     // start all adv
255     FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_start(4, &ext_adv[0]), test_sem);
256 
257     return;
258 }
259