]>
Commit | Line | Data |
---|---|---|
78780d5b | 1 | // Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD |
1af447de MM |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 | // you may not use this file except in compliance with the License. | |
5 | // You may obtain a copy of the License at | |
6 | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | |
8 | // | |
9 | // Unless required by applicable law or agreed to in writing, software | |
10 | // distributed under the License is distributed on an "AS IS" BASIS, | |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 | // See the License for the specific language governing permissions and | |
13 | // limitations under the License. | |
14 | // | |
73a9fa1c | 15 | |
73a9fa1c MM |
16 | #include <stdlib.h> |
17 | #include <stdio.h> | |
18 | #include <string.h> | |
73a9fa1c | 19 | #include "esp_log.h" |
4b054626 | 20 | #include "esp32/rom/lldesc.h" |
21 | #include "sys/queue.h" | |
73a9fa1c | 22 | #include "soc/soc.h" |
3b225d59 AI |
23 | #include "esp_event_loop.h" |
24 | #include "nvs_flash.h" | |
73a9fa1c MM |
25 | #include "sdkconfig.h" |
26 | #include <unistd.h> | |
3b225d59 | 27 | #include "xtensa/core-macros.h" |
98796820 | 28 | #include "esp_private/wifi.h" |
2b8608d0 | 29 | #include "interface.h" |
932e8337 | 30 | #include "esp_wpa.h" |
87bf74d3 | 31 | #include "app_main.h" |
eb1195b9 | 32 | |
2b8608d0 | 33 | #include "freertos/task.h" |
9e0b1a67 | 34 | #include "freertos/queue.h" |
a7e51224 MM |
35 | #ifdef CONFIG_BT_ENABLED |
36 | #include "esp_bt.h" | |
71d37aa1 | 37 | #ifdef CONFIG_BT_HCI_UART |
a7e51224 MM |
38 | #include "driver/uart.h" |
39 | #endif | |
71d37aa1 | 40 | #endif |
219c1878 | 41 | #include "endian.h" |
73a9fa1c | 42 | |
eb1195b9 | 43 | #include <protocomm.h> |
44 | #include "protocomm_pserial.h" | |
45 | #include "slave_commands.h" | |
46 | ||
73a9fa1c | 47 | #define EV_STR(s) "================ "s" ================" |
2b8608d0 | 48 | static const char TAG[] = "NETWORK_ADAPTER"; |
80f6beb4 MM |
49 | |
50 | #if CONFIG_ESP_WLAN_DEBUG | |
272bd470 | 51 | static const char TAG_RX[] = "H -> S"; |
272bd470 | 52 | static const char TAG_TX[] = "S -> H"; |
80f6beb4 MM |
53 | #endif |
54 | ||
55 | #if CONFIG_ESP_SERIAL_DEBUG | |
56 | static const char TAG_RX_S[] = "CONTROL H -> S"; | |
272bd470 | 57 | static const char TAG_TX_S[] = "CONTROL S -> H"; |
80f6beb4 | 58 | #endif |
9e0b1a67 | 59 | |
71d37aa1 | 60 | #ifdef CONFIG_BT_HCI_UART |
a7e51224 MM |
61 | #define BT_TX_PIN 5 |
62 | #define BT_RX_PIN 18 | |
63 | #define BT_RTS_PIN 19 | |
64 | #define BT_CTS_PIN 23 | |
65 | #endif | |
66 | ||
71d37aa1 MM |
67 | #ifdef CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI |
68 | #define VHCI_MAX_TIMEOUT_MS 2000 | |
69 | static SemaphoreHandle_t vhci_send_sem; | |
70 | static void deinitialize_bluetooth(void); | |
71 | static esp_err_t initialise_bluetooth(void); | |
72 | #endif | |
73 | ||
21cafbb1 | 74 | volatile uint8_t action = 0; |
272bd470 MM |
75 | volatile uint8_t datapath = 0; |
76 | volatile uint8_t sta_connected = 0; | |
77 | ||
78 | uint32_t from_wlan_count = 0; | |
79 | uint32_t to_host_count = 0; | |
80 | uint32_t to_host_sent_count = 0; | |
81 | ||
2b8608d0 | 82 | interface_context_t *if_context = NULL; |
f0597120 | 83 | interface_handle_t *if_handle = NULL; |
75946f52 | 84 | |
9e0b1a67 MM |
85 | QueueHandle_t to_host_queue = NULL; |
86 | QueueHandle_t from_host_queue = NULL; | |
80f6beb4 MM |
87 | #define TO_HOST_QUEUE_SIZE 100 |
88 | #define FROM_HOST_QUEUE_SIZE 100 | |
73a9fa1c | 89 | |
eb1195b9 | 90 | static protocomm_t *pc_pserial; |
91 | ||
272bd470 MM |
92 | static struct rx_data { |
93 | uint8_t valid; | |
94 | int len; | |
95 | uint8_t data[1024]; | |
96 | } r; | |
97 | //#define min(x, y) ((x) < (y) ? (x) : (y)) | |
98 | static inline int min(int x, int y) { | |
99 | return (x < y) ? x : y; | |
100 | } | |
101 | ||
71d37aa1 MM |
102 | static uint8_t get_capabilities() |
103 | { | |
104 | uint8_t cap = 0; | |
105 | ||
106 | ESP_LOGI(TAG, "Supported features are:"); | |
472f5245 MM |
107 | #if CONFIG_ESP_SPI_HOST_INTERFACE |
108 | ESP_LOGI(TAG, "- WLAN over SPI"); | |
5e72bc8b MM |
109 | cap |= ESP_WLAN_SPI_SUPPORT; |
110 | #else | |
472f5245 MM |
111 | ESP_LOGI(TAG, "- WLAN over SDIO"); |
112 | cap |= ESP_WLAN_SDIO_SUPPORT; | |
5e72bc8b | 113 | #endif |
71d37aa1 MM |
114 | #ifdef CONFIG_BT_ENABLED |
115 | ESP_LOGI(TAG, "- BT/BLE"); | |
472f5245 MM |
116 | #if CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI |
117 | #if CONFIG_ESP_SPI_HOST_INTERFACE | |
118 | ESP_LOGI(TAG, " - HCI Over SPI"); | |
119 | cap |= ESP_BT_SPI_SUPPORT; | |
120 | #else | |
71d37aa1 MM |
121 | ESP_LOGI(TAG, " - HCI Over SDIO"); |
122 | cap |= ESP_BT_SDIO_SUPPORT; | |
472f5245 | 123 | #endif |
71d37aa1 MM |
124 | #elif CONFIG_BT_HCI_UART |
125 | ESP_LOGI(TAG, " - HCI Over UART"); | |
126 | cap |= ESP_BT_UART_SUPPORT; | |
127 | #endif | |
128 | #if CONFIG_BTDM_CTRL_MODE_BLE_ONLY | |
129 | ESP_LOGI(TAG, " - BLE only"); | |
130 | cap |= ESP_BLE_ONLY_SUPPORT; | |
131 | #elif CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY | |
132 | ESP_LOGI(TAG, " - BR_EDR only"); | |
133 | cap |= ESP_BR_EDR_ONLY_SUPPORT; | |
134 | #elif CONFIG_BTDM_CTRL_MODE_BTDM | |
135 | ESP_LOGI(TAG, " - BT/BLE dual mode"); | |
502e1612 | 136 | cap |= ESP_BLE_ONLY_SUPPORT | ESP_BR_EDR_ONLY_SUPPORT; |
71d37aa1 MM |
137 | #endif |
138 | #endif | |
139 | ||
140 | return cap; | |
141 | } | |
142 | ||
932e8337 | 143 | static void esp_wifi_set_debug_log() |
144 | { | |
145 | /* set WiFi log level and module */ | |
146 | #if CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE | |
147 | uint32_t g_wifi_log_level = WIFI_LOG_INFO; | |
148 | uint32_t g_wifi_log_module = 0; | |
149 | uint32_t g_wifi_log_submodule = 0; | |
150 | #if CONFIG_ESP32_WIFI_DEBUG_LOG_DEBUG | |
151 | g_wifi_log_level = WIFI_LOG_DEBUG; | |
152 | #endif | |
153 | #if CONFIG_ESP32_WIFI_DEBUG_LOG_VERBOSE | |
154 | g_wifi_log_level = WIFI_LOG_VERBOSE; | |
155 | #endif | |
156 | #if CONFIG_ESP32_WIFI_DEBUG_LOG_MODULE_ALL | |
157 | g_wifi_log_module = WIFI_LOG_MODULE_ALL; | |
158 | #endif | |
159 | #if CONFIG_ESP32_WIFI_DEBUG_LOG_MODULE_WIFI | |
160 | g_wifi_log_module = WIFI_LOG_MODULE_WIFI; | |
161 | #endif | |
162 | #if CONFIG_ESP32_WIFI_DEBUG_LOG_MODULE_COEX | |
163 | g_wifi_log_module = WIFI_LOG_MODULE_COEX; | |
164 | #endif | |
165 | #if CONFIG_ESP32_WIFI_DEBUG_LOG_MODULE_MESH | |
166 | g_wifi_log_module = WIFI_LOG_MODULE_MESH; | |
167 | #endif | |
168 | #if CONFIG_ESP32_WIFI_DEBUG_LOG_SUBMODULE_ALL | |
169 | g_wifi_log_submodule |= WIFI_LOG_SUBMODULE_ALL; | |
170 | #endif | |
171 | #if CONFIG_ESP32_WIFI_DEBUG_LOG_SUBMODULE_INIT | |
172 | g_wifi_log_submodule |= WIFI_LOG_SUBMODULE_INIT; | |
173 | #endif | |
174 | #if CONFIG_ESP32_WIFI_DEBUG_LOG_SUBMODULE_IOCTL | |
175 | g_wifi_log_submodule |= WIFI_LOG_SUBMODULE_IOCTL; | |
176 | #endif | |
177 | #if CONFIG_ESP32_WIFI_DEBUG_LOG_SUBMODULE_CONN | |
178 | g_wifi_log_submodule |= WIFI_LOG_SUBMODULE_CONN; | |
179 | #endif | |
180 | #if CONFIG_ESP32_WIFI_DEBUG_LOG_SUBMODULE_SCAN | |
181 | g_wifi_log_submodule |= WIFI_LOG_SUBMODULE_SCAN; | |
182 | #endif | |
183 | esp_wifi_internal_set_log_level(g_wifi_log_level); | |
184 | esp_wifi_internal_set_log_mod(g_wifi_log_module, g_wifi_log_submodule, true); | |
185 | ||
186 | #endif /* CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE*/ | |
187 | ||
188 | } | |
189 | ||
75946f52 MM |
190 | esp_err_t wlan_ap_rx_callback(void *buffer, uint16_t len, void *eb) |
191 | { | |
192 | esp_err_t ret = ESP_OK; | |
f0597120 | 193 | interface_buffer_handle_t buf_handle; |
75946f52 | 194 | |
36ec8c2a | 195 | if (!buffer || !eb || !datapath) { |
75946f52 MM |
196 | if (eb) { |
197 | esp_wifi_internal_free_rx_buffer(eb); | |
198 | } | |
199 | return ESP_OK; | |
200 | } | |
201 | ||
75946f52 | 202 | /* Prepare buffer descriptor */ |
f0597120 | 203 | memset(&buf_handle, 0, sizeof(buf_handle)); |
75946f52 | 204 | |
f0597120 MM |
205 | buf_handle.if_type = ESP_AP_IF; |
206 | buf_handle.if_num = 0; | |
207 | buf_handle.payload_len = len; | |
208 | buf_handle.payload = buffer; | |
209 | buf_handle.wlan_buf_handle = eb; | |
210 | buf_handle.free_buf_handle = esp_wifi_internal_free_rx_buffer; | |
75946f52 | 211 | |
f0597120 | 212 | ret = xQueueSend(to_host_queue, &buf_handle, portMAX_DELAY); |
75946f52 MM |
213 | |
214 | if (ret != pdTRUE) { | |
9e0b1a67 | 215 | ESP_LOGE(TAG, "Slave -> Host: Failed to send buffer\n"); |
75946f52 MM |
216 | goto DONE; |
217 | } | |
218 | ||
219 | return ESP_OK; | |
272bd470 | 220 | |
75946f52 MM |
221 | DONE: |
222 | esp_wifi_internal_free_rx_buffer(eb); | |
223 | return ESP_OK; | |
224 | } | |
225 | ||
226 | esp_err_t wlan_sta_rx_callback(void *buffer, uint16_t len, void *eb) | |
272bd470 MM |
227 | { |
228 | esp_err_t ret = ESP_OK; | |
f0597120 | 229 | interface_buffer_handle_t buf_handle; |
272bd470 | 230 | |
36ec8c2a | 231 | if (!buffer || !eb || !datapath) { |
272bd470 MM |
232 | if (eb) { |
233 | esp_wifi_internal_free_rx_buffer(eb); | |
234 | } | |
235 | return ESP_OK; | |
236 | } | |
237 | ||
36ec8c2a MM |
238 | from_wlan_count++; |
239 | ||
272bd470 | 240 | /* Prepare buffer descriptor */ |
f0597120 | 241 | memset(&buf_handle, 0, sizeof(buf_handle)); |
272bd470 | 242 | |
f0597120 MM |
243 | buf_handle.if_type = ESP_STA_IF; |
244 | buf_handle.if_num = 0; | |
245 | buf_handle.payload_len = len; | |
246 | buf_handle.payload = buffer; | |
247 | buf_handle.wlan_buf_handle = eb; | |
248 | buf_handle.free_buf_handle = esp_wifi_internal_free_rx_buffer; | |
272bd470 | 249 | |
f0597120 | 250 | ret = xQueueSend(to_host_queue, &buf_handle, portMAX_DELAY); |
272bd470 MM |
251 | |
252 | if (ret != pdTRUE) { | |
9e0b1a67 | 253 | ESP_LOGE(TAG, "Slave -> Host: Failed to send buffer\n"); |
272bd470 MM |
254 | goto DONE; |
255 | } | |
256 | ||
257 | return ESP_OK; | |
258 | ||
259 | DONE: | |
260 | esp_wifi_internal_free_rx_buffer(eb); | |
261 | return ESP_OK; | |
262 | } | |
263 | ||
272bd470 | 264 | /* Send data to host */ |
73a9fa1c MM |
265 | void send_task(void* pvParameters) |
266 | { | |
9e0b1a67 | 267 | esp_err_t ret = ESP_OK; |
272bd470 MM |
268 | int t1, t2, t_total = 0; |
269 | int d_total = 0; | |
f0597120 | 270 | interface_buffer_handle_t buf_handle = {0}; |
73a9fa1c | 271 | |
73a9fa1c | 272 | |
272bd470 | 273 | while (1) { |
3b225d59 | 274 | |
f0597120 | 275 | ret = xQueueReceive(to_host_queue, &buf_handle, portMAX_DELAY); |
272bd470 MM |
276 | |
277 | if (datapath) { | |
9e0b1a67 | 278 | if (ret == pdTRUE) { |
272bd470 | 279 | to_host_count++; |
f0597120 | 280 | |
272bd470 MM |
281 | /* Send data */ |
282 | t1 = XTHAL_GET_CCOUNT(); | |
283 | ||
2b8608d0 | 284 | if (if_context && if_context->if_ops && if_context->if_ops->write) { |
f0597120 | 285 | if_context->if_ops->write(if_handle, &buf_handle); |
2b8608d0 | 286 | } |
75946f52 | 287 | |
272bd470 MM |
288 | t2 = XTHAL_GET_CCOUNT(); |
289 | t_total += t2 - t1; | |
f0597120 | 290 | d_total += buf_handle.payload_len; |
272bd470 | 291 | |
80f6beb4 MM |
292 | #if CONFIG_ESP_WLAN_DEBUG |
293 | ESP_LOG_BUFFER_HEXDUMP(TAG_TX, buf_handle.buf, 8, ESP_LOG_INFO); | |
294 | #endif | |
272bd470 | 295 | /* Post processing */ |
f0597120 MM |
296 | if (buf_handle.free_buf_handle) |
297 | buf_handle.free_buf_handle(buf_handle.priv_buffer_handle); | |
272bd470 | 298 | |
272bd470 | 299 | to_host_sent_count++; |
272bd470 MM |
300 | } |
301 | if (t_total) { | |
302 | /* printf("TX complete. Total time spent in tx = %d for %d bytes\n", t_total, d_total);*/ | |
303 | t_total = 0; | |
304 | } | |
305 | ||
306 | } else { | |
9e0b1a67 | 307 | if (ret == pdTRUE) { |
80f6beb4 | 308 | #if CONFIG_ESP_WLAN_DEBUG |
f0597120 | 309 | ESP_LOGD (TAG_TX, "Data path stopped"); |
80f6beb4 | 310 | #endif |
f0597120 MM |
311 | |
312 | /* Post processing */ | |
313 | if (buf_handle.free_buf_handle) | |
314 | buf_handle.free_buf_handle(buf_handle.priv_buffer_handle); | |
272bd470 MM |
315 | } |
316 | ||
272bd470 MM |
317 | sleep(1); |
318 | } | |
319 | } | |
73a9fa1c MM |
320 | } |
321 | ||
71d37aa1 | 322 | void process_rx_task(void* pvParameters) |
272bd470 | 323 | { |
9e0b1a67 | 324 | esp_err_t ret = ESP_OK; |
f0597120 MM |
325 | interface_buffer_handle_t buf_handle = {0}; |
326 | struct esp_payload_header *header; | |
327 | uint8_t *payload; | |
328 | uint16_t payload_len; | |
272bd470 MM |
329 | |
330 | while (1) { | |
f0597120 | 331 | ret = xQueueReceive(from_host_queue, &buf_handle, portMAX_DELAY); |
272bd470 | 332 | |
9e0b1a67 | 333 | if (ret != pdTRUE) { |
272bd470 MM |
334 | continue; |
335 | } | |
336 | ||
f0597120 | 337 | header = (struct esp_payload_header *) buf_handle.payload; |
219c1878 MM |
338 | payload = buf_handle.payload + le16toh(header->offset); |
339 | payload_len = le16toh(header->len); | |
f0597120 | 340 | |
80f6beb4 MM |
341 | #if CONFIG_ESP_WLAN_DEBUG |
342 | ESP_LOG_BUFFER_HEXDUMP(TAG_RX, payload, 8, ESP_LOG_INFO); | |
343 | #endif | |
344 | ||
f0597120 | 345 | if ((buf_handle.if_type == ESP_STA_IF) && sta_connected) { |
2b8608d0 | 346 | /* Forward data to wlan driver */ |
f0597120 MM |
347 | esp_wifi_internal_tx(ESP_IF_WIFI_STA, payload, payload_len); |
348 | } else if (buf_handle.if_type == ESP_AP_IF) { | |
2b8608d0 | 349 | /* Forward data to wlan driver */ |
f0597120 MM |
350 | esp_wifi_internal_tx(ESP_IF_WIFI_AP, payload, payload_len); |
351 | } else if (buf_handle.if_type == ESP_SERIAL_IF) { | |
2b8608d0 | 352 | /* Process AT command*/ |
f0597120 | 353 | memcpy(r.data, payload, min(payload_len, sizeof(r.data))); |
272bd470 | 354 | r.valid = 1; |
f0597120 | 355 | r.len = min(payload_len, sizeof(r.data)); |
80f6beb4 | 356 | #if CONFIG_ESP_SERIAL_DEBUG |
272bd470 | 357 | ESP_LOG_BUFFER_HEXDUMP(TAG_RX_S, r.data, r.len, ESP_LOG_INFO); |
80f6beb4 | 358 | #endif |
eb1195b9 | 359 | protocomm_pserial_data_ready(pc_pserial, r.len); |
71d37aa1 MM |
360 | #ifdef CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI |
361 | } else if (buf_handle.if_type == ESP_HCI_IF) { | |
362 | /* VHCI needs one extra byte at the start of payload */ | |
363 | /* that is accomodated in esp_payload_header */ | |
364 | /* ESP_LOG_BUFFER_HEXDUMP("BT TX", payload, payload_len, ESP_LOG_INFO);*/ | |
365 | payload--; | |
366 | payload_len++; | |
367 | ||
368 | if (!esp_vhci_host_check_send_available()) { | |
369 | ESP_LOGD(TAG, "VHCI not available"); | |
370 | } | |
371 | ||
372 | if (vhci_send_sem) { | |
373 | if (xSemaphoreTake(vhci_send_sem, VHCI_MAX_TIMEOUT_MS) == pdTRUE) { | |
374 | esp_vhci_host_send_packet(payload, payload_len); | |
375 | } else { | |
376 | ESP_LOGI(TAG, "VHCI sem timeout"); | |
377 | } | |
378 | } | |
379 | #endif | |
272bd470 MM |
380 | } |
381 | ||
2b8608d0 | 382 | /* Free buffer handle */ |
f0597120 MM |
383 | if (buf_handle.free_buf_handle) { |
384 | buf_handle.free_buf_handle(buf_handle.priv_buffer_handle); | |
2b8608d0 | 385 | } |
272bd470 | 386 | } |
3b225d59 | 387 | } |
272bd470 MM |
388 | |
389 | /* Get data from host */ | |
73a9fa1c MM |
390 | void recv_task(void* pvParameters) |
391 | { | |
f0597120 | 392 | interface_buffer_handle_t *buf_handle = NULL; |
2b8608d0 | 393 | esp_err_t ret; |
272bd470 MM |
394 | |
395 | for (;;) { | |
396 | ||
a7e51224 MM |
397 | if (!datapath) { |
398 | /* Datapath is not enabled by host yet*/ | |
399 | sleep(1); | |
5e72bc8b | 400 | continue; |
a7e51224 MM |
401 | } |
402 | ||
2b8608d0 MM |
403 | // receive data from transport layer |
404 | if (if_context && if_context->if_ops && if_context->if_ops->read) { | |
f0597120 MM |
405 | buf_handle = if_context->if_ops->read(if_handle); |
406 | if (!buf_handle) { | |
2b8608d0 MM |
407 | continue; |
408 | } | |
272bd470 MM |
409 | } |
410 | ||
f0597120 | 411 | ret = xQueueSend(from_host_queue, buf_handle, portMAX_DELAY); |
9e0b1a67 | 412 | |
f0597120 MM |
413 | if (ret != pdTRUE) { |
414 | ESP_LOGE(TAG, "Host -> Slave: Failed to send buffer\n"); | |
415 | if (buf_handle->free_buf_handle) { | |
416 | buf_handle->free_buf_handle(buf_handle->priv_buffer_handle); | |
272bd470 | 417 | } |
272bd470 | 418 | } |
f0597120 MM |
419 | |
420 | free(buf_handle); | |
73a9fa1c | 421 | } |
73a9fa1c | 422 | } |
272bd470 | 423 | |
71d37aa1 | 424 | static int32_t serial_read_data(uint8_t *data, int32_t len) |
3b225d59 | 425 | { |
1af447de MM |
426 | len = min(len, r.len); |
427 | if (r.valid) { | |
428 | memcpy(data, r.data, len); | |
429 | r.valid = 0; | |
430 | r.len = 0; | |
431 | } else { | |
432 | printf("No data to be read\n"); | |
433 | } | |
434 | return len; | |
3b225d59 | 435 | } |
1af447de | 436 | |
71d37aa1 | 437 | static int32_t serial_write_data(uint8_t* data, int32_t len) |
3b225d59 | 438 | { |
f0597120 | 439 | interface_buffer_handle_t buf_handle = {0}; |
75946f52 | 440 | |
f0597120 MM |
441 | buf_handle.if_type = ESP_SERIAL_IF; |
442 | buf_handle.if_num = 0; | |
443 | buf_handle.payload = data; | |
444 | buf_handle.payload_len = len; | |
445 | ||
2b8608d0 | 446 | if (datapath && if_context && if_context->if_ops && if_context->if_ops->write) |
f0597120 | 447 | if_context->if_ops->write(if_handle, &buf_handle); |
80f6beb4 | 448 | #if CONFIG_ESP_SERIAL_DEBUG |
1af447de | 449 | ESP_LOG_BUFFER_HEXDUMP(TAG_TX_S, data, len, ESP_LOG_INFO); |
80f6beb4 | 450 | #endif |
1af447de | 451 | return len; |
3b225d59 | 452 | } |
1af447de | 453 | |
a7e51224 | 454 | #ifdef CONFIG_BT_ENABLED |
71d37aa1 MM |
455 | |
456 | #ifdef CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI | |
457 | static void controller_rcv_pkt_ready(void) | |
458 | { | |
459 | if (vhci_send_sem) | |
460 | xSemaphoreGive(vhci_send_sem); | |
461 | } | |
462 | ||
463 | static int host_rcv_pkt(uint8_t *data, uint16_t len) | |
464 | { | |
465 | esp_err_t ret = ESP_OK; | |
466 | interface_buffer_handle_t buf_handle; | |
467 | uint8_t *buf = NULL; | |
468 | ||
469 | buf = (uint8_t *) malloc(len); | |
470 | ||
471 | if (!buf) { | |
472 | ESP_LOGE(TAG, "HCI Send packet: memory allocation failed"); | |
473 | return ESP_FAIL; | |
474 | } | |
475 | ||
476 | memcpy(buf, data, len); | |
477 | ||
478 | memset(&buf_handle, 0, sizeof(buf_handle)); | |
479 | /* ESP_LOG_BUFFER_HEXDUMP("BT RX", buf, len, ESP_LOG_INFO);*/ | |
480 | ||
481 | buf_handle.if_type = ESP_HCI_IF; | |
482 | buf_handle.if_num = 0; | |
483 | buf_handle.payload_len = len; | |
484 | buf_handle.payload = buf; | |
485 | buf_handle.wlan_buf_handle = buf; | |
486 | buf_handle.free_buf_handle = free; | |
487 | ||
488 | ret = xQueueSend(to_host_queue, &buf_handle, portMAX_DELAY); | |
489 | ||
490 | if (ret != pdTRUE) { | |
491 | ESP_LOGE(TAG, "HCI send packet: Failed to send buffer\n"); | |
492 | free(buf); | |
493 | return ESP_FAIL; | |
494 | } | |
495 | ||
496 | return 0; | |
497 | } | |
498 | ||
499 | static esp_vhci_host_callback_t vhci_host_cb = { | |
500 | controller_rcv_pkt_ready, | |
501 | host_rcv_pkt | |
502 | }; | |
503 | #endif | |
504 | ||
505 | static esp_err_t initialise_bluetooth(void) | |
a7e51224 MM |
506 | { |
507 | esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); | |
71d37aa1 | 508 | esp_err_t ret = ESP_OK; |
a7e51224 | 509 | |
71d37aa1 | 510 | #ifdef CONFIG_BT_HCI_UART |
a7e51224 MM |
511 | #if CONFIG_BT_HCI_UART_NO == 1 |
512 | periph_module_enable(PERIPH_UART1_MODULE); | |
513 | #elif CONFIG_BT_HCI_UART_NO == 2 | |
514 | periph_module_enable(PERIPH_UART2_MODULE); | |
515 | #endif | |
516 | ||
517 | periph_module_enable(PERIPH_UHCI0_MODULE); | |
518 | ESP_ERROR_CHECK( uart_set_pin(CONFIG_BT_HCI_UART_NO, BT_TX_PIN, | |
519 | BT_RX_PIN, BT_RTS_PIN, BT_CTS_PIN) ); | |
71d37aa1 | 520 | #endif |
a7e51224 MM |
521 | ESP_ERROR_CHECK( esp_bt_controller_init(&bt_cfg) ); |
522 | #ifdef CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY | |
523 | ESP_ERROR_CHECK( esp_bt_controller_enable(ESP_BT_MODE_BLE) ); | |
524 | #elif CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY | |
525 | ESP_ERROR_CHECK( esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT) ); | |
526 | #elif CONFIG_BTDM_CONTROLLER_MODE_BTDM | |
527 | ESP_ERROR_CHECK( esp_bt_controller_enable(ESP_BT_MODE_BTDM) ); | |
528 | #endif | |
71d37aa1 MM |
529 | |
530 | #ifdef CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI | |
531 | ret = esp_vhci_host_register_callback(&vhci_host_cb); | |
532 | ||
533 | if (ret != ESP_OK) { | |
534 | ESP_LOGE(TAG, "Failed to register VHCI callback"); | |
535 | return ret; | |
536 | } | |
537 | ||
538 | vhci_send_sem = xSemaphoreCreateBinary(); | |
539 | if (vhci_send_sem == NULL) { | |
540 | ESP_LOGE(TAG, "Failed to create VHCI send sem"); | |
541 | return ESP_ERR_NO_MEM; | |
542 | } | |
543 | ||
544 | xSemaphoreGive(vhci_send_sem); | |
545 | #endif | |
546 | ||
547 | return ESP_OK; | |
548 | } | |
549 | ||
550 | static void deinitialize_bluetooth(void) | |
551 | { | |
552 | #ifdef CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI | |
553 | if (vhci_send_sem) { | |
554 | /* Dummy take and give sema before deleting it */ | |
555 | xSemaphoreTake(vhci_send_sem, portMAX_DELAY); | |
556 | xSemaphoreGive(vhci_send_sem); | |
557 | vSemaphoreDelete(vhci_send_sem); | |
558 | vhci_send_sem = NULL; | |
559 | } | |
560 | esp_bt_controller_disable(); | |
561 | esp_bt_controller_deinit(); | |
562 | #endif | |
a7e51224 MM |
563 | } |
564 | #endif | |
565 | ||
932e8337 | 566 | static esp_err_t initialise_wifi(void) |
567 | { | |
568 | wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); | |
569 | ESP_ERROR_CHECK(esp_event_loop_create_default()); | |
570 | esp_err_t result = esp_wifi_init_internal(&cfg); | |
571 | if (result != ESP_OK) { | |
572 | ESP_LOGE(TAG,"Init internal failed"); | |
573 | return result; | |
574 | } | |
575 | esp_wifi_set_debug_log(); | |
576 | result = esp_supplicant_init(); | |
577 | if (result != ESP_OK) { | |
578 | ESP_LOGE(TAG, "Failed to init supplicant (0x%x)", result); | |
579 | esp_err_t deinit_ret = esp_wifi_deinit_internal(); | |
580 | if (deinit_ret != ESP_OK) { | |
581 | ESP_LOGE(TAG, "Failed to deinit Wi-Fi internal (0x%x)", deinit_ret); | |
582 | return deinit_ret; | |
583 | } | |
584 | return result; | |
585 | } | |
586 | result = esp_wifi_start(); | |
587 | if (result != ESP_OK) { | |
588 | ESP_LOGI(TAG,"Failed to start WiFi"); | |
589 | return result; | |
590 | } | |
591 | return result; | |
592 | } | |
a7e51224 | 593 | |
87bf74d3 | 594 | int event_handler(uint8_t val) |
2b8608d0 MM |
595 | { |
596 | switch(val) { | |
f0597120 MM |
597 | case ESP_OPEN_DATA_PATH: |
598 | ESP_EARLY_LOGI(TAG, "Start Data Path"); | |
2b8608d0 | 599 | datapath = 1; |
f0597120 | 600 | if_handle->state = ACTIVE; |
2b8608d0 MM |
601 | break; |
602 | ||
f0597120 MM |
603 | case ESP_CLOSE_DATA_PATH: |
604 | ESP_EARLY_LOGI(TAG, "Stop Data Path"); | |
2b8608d0 | 605 | datapath = 0; |
f0597120 | 606 | if_handle->state = DEACTIVE; |
2b8608d0 MM |
607 | break; |
608 | } | |
609 | return 0; | |
610 | } | |
611 | ||
73a9fa1c MM |
612 | void app_main() |
613 | { | |
1af447de | 614 | esp_err_t ret; |
71d37aa1 MM |
615 | uint8_t capa = 0; |
616 | ||
617 | capa = get_capabilities(); | |
1af447de | 618 | |
2b8608d0 MM |
619 | //Initialize NVS |
620 | ret = nvs_flash_init(); | |
73a9fa1c | 621 | |
2b8608d0 MM |
622 | if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { |
623 | ESP_ERROR_CHECK(nvs_flash_erase()); | |
624 | ret = nvs_flash_init(); | |
625 | } | |
73a9fa1c | 626 | |
87bf74d3 | 627 | if_context = interface_insert_driver(event_handler); |
5e72bc8b | 628 | datapath = 1; |
73a9fa1c | 629 | |
2b8608d0 MM |
630 | if (!if_context || !if_context->if_ops) { |
631 | ESP_LOGE(TAG, "Failed to insert driver\n"); | |
632 | return; | |
1af447de | 633 | } |
73a9fa1c | 634 | |
71d37aa1 | 635 | if_handle = if_context->if_ops->init(capa); |
73a9fa1c | 636 | |
f0597120 | 637 | if (!if_handle) { |
2b8608d0 MM |
638 | ESP_LOGE(TAG, "Failed to initialize driver\n"); |
639 | return; | |
640 | } | |
73a9fa1c | 641 | |
80f6beb4 | 642 | to_host_queue = xQueueCreate(TO_HOST_QUEUE_SIZE, sizeof(interface_buffer_handle_t)); |
9e0b1a67 | 643 | assert(to_host_queue != NULL); |
272bd470 | 644 | |
80f6beb4 | 645 | from_host_queue = xQueueCreate(FROM_HOST_QUEUE_SIZE, sizeof(interface_buffer_handle_t)); |
9e0b1a67 | 646 | assert(from_host_queue != NULL); |
272bd470 | 647 | |
1af447de | 648 | ESP_ERROR_CHECK(ret); |
272bd470 | 649 | |
71d37aa1 MM |
650 | xTaskCreate(recv_task , "recv_task" , 4096 , NULL , 18 , NULL); |
651 | xTaskCreate(send_task , "send_task" , 4096 , NULL , 18 , NULL); | |
652 | xTaskCreate(process_rx_task , "process_rx_task" , 4096 , NULL , 18 , NULL); | |
73a9fa1c | 653 | |
1af447de MM |
654 | tcpip_adapter_init(); |
655 | ||
932e8337 | 656 | ESP_ERROR_CHECK(initialise_wifi()); |
657 | ||
eb1195b9 | 658 | pc_pserial = protocomm_new(); |
659 | if (pc_pserial == NULL) { | |
660 | ESP_LOGE(TAG,"Failed to allocate memory for new instance of protocomm "); | |
661 | return; | |
1af447de | 662 | } |
a7e51224 MM |
663 | |
664 | #ifdef CONFIG_BT_ENABLED | |
665 | initialise_bluetooth(); | |
666 | #endif | |
73a9fa1c | 667 | |
eb1195b9 | 668 | if (protocomm_add_endpoint(pc_pserial, "control", data_transfer_handler, NULL) != ESP_OK) { |
669 | ESP_LOGE(TAG, "Failed to add enpoint"); | |
670 | return; | |
671 | } | |
73a9fa1c | 672 | |
71d37aa1 | 673 | protocomm_pserial_start(pc_pserial, serial_write_data, serial_read_data); |
932e8337 | 674 | ESP_LOGI(TAG,"Initial set up done"); |
71d37aa1 | 675 | |
eb1195b9 | 676 | } |