]> granicus.if.org Git - esp-idf/blob - components/bt/bluedroid/hci/hci_hal_h4.c
Component/bt: fix hci_hal_env.rx_q and xHciH4Queue blocking when scanning
[esp-idf] / components / bt / bluedroid / hci / hci_hal_h4.c
1 /******************************************************************************
2  *
3  *  Copyright (C) 2014 Google, Inc.
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 #include <string.h>
19 #include "common/bt_defs.h"
20 #include "common/bt_trace.h"
21 #include "stack/bt_types.h"
22 #include "hci/buffer_allocator.h"
23 #include "osi/fixed_queue.h"
24 #include "hci/hci_hal.h"
25 #include "hci/hci_internals.h"
26 #include "hci/hci_layer.h"
27 #include "osi/thread.h"
28 #include "esp_bt.h"
29
30 #if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
31 #include "l2c_int.h"
32 #include "stack/hcimsgs.h"
33 #endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
34
35 #define HCI_HAL_SERIAL_BUFFER_SIZE 1026
36 #define HCI_BLE_EVENT 0x3e
37 #define PACKET_TYPE_TO_INBOUND_INDEX(type) ((type) - 2)
38 #define PACKET_TYPE_TO_INDEX(type) ((type) - 1)
39 extern bool BTU_check_queue_is_congest(void);
40
41
42 static const uint8_t preamble_sizes[] = {
43     HCI_COMMAND_PREAMBLE_SIZE,
44     HCI_ACL_PREAMBLE_SIZE,
45     HCI_SCO_PREAMBLE_SIZE,
46     HCI_EVENT_PREAMBLE_SIZE
47 };
48
49 static const uint16_t outbound_event_types[] = {
50     MSG_HC_TO_STACK_HCI_ERR,
51     MSG_HC_TO_STACK_HCI_ACL,
52     MSG_HC_TO_STACK_HCI_SCO,
53     MSG_HC_TO_STACK_HCI_EVT
54 };
55
56 typedef struct {
57     const allocator_t *allocator;
58     size_t buffer_size;
59     fixed_queue_t *rx_q;
60 } hci_hal_env_t;
61
62
63 static hci_hal_env_t hci_hal_env;
64 static const hci_hal_t interface;
65 static const hci_hal_callbacks_t *callbacks;
66 static const esp_vhci_host_callback_t vhci_host_cb;
67
68 static xTaskHandle xHciH4TaskHandle;
69 static xQueueHandle xHciH4Queue;
70
71 static void host_send_pkt_available_cb(void);
72 static int host_recv_pkt_cb(uint8_t *data, uint16_t len);
73
74 static void hci_hal_h4_rx_handler(void *arg);
75 static void event_uart_has_bytes(fixed_queue_t *queue);
76
77
78 static void hci_hal_env_init(
79     size_t buffer_size,
80     size_t max_buffer_count)
81 {
82     assert(buffer_size > 0);
83     assert(max_buffer_count > 0);
84
85     hci_hal_env.allocator = buffer_allocator_get_interface();
86     hci_hal_env.buffer_size = buffer_size;
87
88     hci_hal_env.rx_q = fixed_queue_new(max_buffer_count);
89     if (hci_hal_env.rx_q) {
90         fixed_queue_register_dequeue(hci_hal_env.rx_q, event_uart_has_bytes);
91     } else {
92         HCI_TRACE_ERROR("%s unable to create rx queue.\n", __func__);
93     }
94
95     return;
96 }
97
98 static void hci_hal_env_deinit(void)
99 {
100     fixed_queue_free(hci_hal_env.rx_q, hci_hal_env.allocator->free);
101     hci_hal_env.rx_q = NULL;
102 }
103
104 static bool hal_open(const hci_hal_callbacks_t *upper_callbacks)
105 {
106     assert(upper_callbacks != NULL);
107     callbacks = upper_callbacks;
108
109     hci_hal_env_init(HCI_HAL_SERIAL_BUFFER_SIZE, QUEUE_SIZE_MAX);
110
111     xHciH4Queue = xQueueCreate(HCI_H4_QUEUE_LEN, sizeof(BtTaskEvt_t));
112     xTaskCreatePinnedToCore(hci_hal_h4_rx_handler, HCI_H4_TASK_NAME, HCI_H4_TASK_STACK_SIZE, NULL, HCI_H4_TASK_PRIO, &xHciH4TaskHandle, HCI_H4_TASK_PINNED_TO_CORE);
113
114     //register vhci host cb
115     esp_vhci_host_register_callback(&vhci_host_cb);
116
117
118     return true;
119 }
120
121 static void hal_close()
122 {
123     hci_hal_env_deinit();
124
125     /* delete task and queue */
126     vTaskDelete(xHciH4TaskHandle);
127     vQueueDelete(xHciH4Queue);
128 }
129
130 /**
131  * Function: transmit_data -TX data to low-layer
132  * It is ported from Bluedroid source code, so it is not
133  * needed to use write() to send data.
134  * TODO: Just use firmware API to send data.
135  */
136 static uint16_t transmit_data(serial_data_type_t type,
137                               uint8_t *data, uint16_t length)
138 {
139     uint8_t previous_byte;
140
141     assert(data != NULL);
142     assert(length > 0);
143
144     if (type < DATA_TYPE_COMMAND || type > DATA_TYPE_SCO) {
145         HCI_TRACE_ERROR("%s invalid data type: %d", __func__, type);
146         return 0;
147     }
148
149     // Write the signal byte right before the data
150     --data;
151     previous_byte = *data;
152     *(data) = type;
153     ++length;
154
155     BTTRC_DUMP_BUFFER("Transmit Pkt", data, length);
156
157     // TX Data to target
158     esp_vhci_host_send_packet(data, length);
159
160     // Be nice and restore the old value of that byte
161     *(data) = previous_byte;
162
163     return length - 1;
164 }
165
166 // Internal functions
167 static void hci_hal_h4_rx_handler(void *arg)
168 {
169     BtTaskEvt_t e;
170
171     for (;;) {
172         if (pdTRUE == xQueueReceive(xHciH4Queue, &e, (portTickType)portMAX_DELAY)) {
173             if (e.sig == SIG_HCI_HAL_RECV_PACKET) {
174                 fixed_queue_process(hci_hal_env.rx_q);
175
176             }
177         }
178     }
179 }
180
181 task_post_status_t hci_hal_h4_task_post(task_post_t timeout)
182 {
183     BtTaskEvt_t evt;
184
185     evt.sig = SIG_HCI_HAL_RECV_PACKET;
186     evt.par = 0;
187
188     if (xQueueSend(xHciH4Queue, &evt, timeout) != pdTRUE) {
189         return TASK_POST_SUCCESS;
190     }
191
192     return TASK_POST_FAIL;
193 }
194
195 #if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
196 static void hci_packet_complete(BT_HDR *packet){
197     uint8_t type, num_handle;
198     uint16_t handle;
199     uint16_t handles[MAX_L2CAP_LINKS + 4];
200     uint16_t num_packets[MAX_L2CAP_LINKS + 4];
201     uint8_t *stream = packet->data + packet->offset;
202     tL2C_LCB  *p_lcb = NULL;
203
204     STREAM_TO_UINT8(type, stream);
205     if (type == DATA_TYPE_ACL/* || type == DATA_TYPE_SCO*/) {
206         STREAM_TO_UINT16(handle, stream);
207         handle = handle & HCI_DATA_HANDLE_MASK;
208         p_lcb = l2cu_find_lcb_by_handle(handle);
209         if (p_lcb) {
210             p_lcb->completed_packets++;
211         }
212         if (esp_vhci_host_check_send_available()){
213             num_handle = l2cu_find_completed_packets(handles, num_packets);
214             if (num_handle > 0){
215                 btsnd_hcic_host_num_xmitted_pkts (num_handle, handles, num_packets);
216             }
217         } else {
218             //Send HCI_Host_Number_of_Completed_Packets next time.
219         }
220
221     }
222 }
223 #endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
224
225 bool host_recv_adv_packet(BT_HDR *packet)
226 {
227     assert(packet);
228     if(packet->data[0] == DATA_TYPE_EVENT && packet->data[1] == HCI_BLE_EVENT && packet->data[3] ==  HCI_BLE_ADV_PKT_RPT_EVT) {
229         return true;
230     }
231     return false;
232 }
233
234 static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet)
235 {
236     uint8_t type, hdr_size;
237     uint16_t length;
238     uint8_t *stream = packet->data + packet->offset;
239
240     if (!packet) {
241         return;
242     }
243
244 #if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
245     hci_packet_complete(packet);
246 #endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
247
248     STREAM_TO_UINT8(type, stream);
249     packet->offset++;
250     packet->len--;
251     if (type == HCI_BLE_EVENT) {
252         uint8_t len = 0;
253         STREAM_TO_UINT8(len, stream);
254         HCI_TRACE_ERROR("Workround stream corrupted during LE SCAN: pkt_len=%d ble_event_len=%d\n",
255                   packet->len, len);
256         hci_hal_env.allocator->free(packet);
257         return;
258     }
259     if (type < DATA_TYPE_ACL || type > DATA_TYPE_EVENT) {
260         HCI_TRACE_ERROR("%s Unknown HCI message type. Dropping this byte 0x%x,"
261                   " min %x, max %x\n", __func__, type,
262                   DATA_TYPE_ACL, DATA_TYPE_EVENT);
263         hci_hal_env.allocator->free(packet);
264         return;
265     }
266     hdr_size = preamble_sizes[type - 1];
267     if (packet->len < hdr_size) {
268         HCI_TRACE_ERROR("Wrong packet length type=%d pkt_len=%d hdr_len=%d",
269                   type, packet->len, hdr_size);
270         hci_hal_env.allocator->free(packet);
271         return;
272     }
273     if (type == DATA_TYPE_ACL) {
274         stream += hdr_size - 2;
275         STREAM_TO_UINT16(length, stream);
276     } else {
277         stream += hdr_size - 1;
278         STREAM_TO_UINT8(length, stream);
279     }
280
281     if ((length + hdr_size) != packet->len) {
282         HCI_TRACE_ERROR("Wrong packet length type=%d hdr_len=%d pd_len=%d "
283                   "pkt_len=%d", type, hdr_size, length, packet->len);
284         hci_hal_env.allocator->free(packet);
285         return;
286     }
287 #if SCAN_QUEUE_CONGEST_CHECK
288     if(BTU_check_queue_is_congest() && host_recv_adv_packet(packet)) {
289         HCI_TRACE_ERROR("BtuQueue is congested");
290         hci_hal_env.allocator->free(packet);
291         return;
292     }
293 #endif
294
295     packet->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)];
296     callbacks->packet_ready(packet);
297 }
298
299 static void event_uart_has_bytes(fixed_queue_t *queue)
300 {
301     BT_HDR *packet;
302     while (!fixed_queue_is_empty(queue)) {
303         packet = fixed_queue_dequeue(queue);
304         hci_hal_h4_hdl_rx_packet(packet);
305     }
306 }
307
308 static void host_send_pkt_available_cb(void)
309 {
310     //Controller rx cache buffer is ready for receiving new host packet
311     //Just Call Host main thread task to process pending packets.
312     hci_host_task_post(TASK_POST_BLOCKING);
313 }
314
315 static int host_recv_pkt_cb(uint8_t *data, uint16_t len)
316 {
317     //Target has packet to host, malloc new buffer for packet
318     BT_HDR *pkt;
319     size_t pkt_size;
320
321     if (hci_hal_env.rx_q == NULL) {
322         return 0;
323     }
324
325     pkt_size = BT_HDR_SIZE + len;
326     pkt = (BT_HDR *)hci_hal_env.allocator->alloc(pkt_size);
327     if (!pkt) {
328         HCI_TRACE_ERROR("%s couldn't aquire memory for inbound data buffer.\n", __func__);
329         return -1;
330     }
331     pkt->offset = 0;
332     pkt->len = len;
333     pkt->layer_specific = 0;
334     memcpy(pkt->data, data, len);
335     fixed_queue_enqueue(hci_hal_env.rx_q, pkt);
336     hci_hal_h4_task_post(100 / portTICK_PERIOD_MS);
337
338     BTTRC_DUMP_BUFFER("Recv Pkt", pkt->data, len);
339
340     return 0;
341 }
342
343 static const esp_vhci_host_callback_t vhci_host_cb = {
344     .notify_host_send_available = host_send_pkt_available_cb,
345     .notify_host_recv = host_recv_pkt_cb,
346 };
347
348 static const hci_hal_t interface = {
349     hal_open,
350     hal_close,
351     transmit_data,
352 };
353
354 const hci_hal_t *hci_hal_h4_get_interface()
355 {
356     return &interface;
357 }
358