]> granicus.if.org Git - esp-idf/blob - components/bt/bluedroid/hci/hci_hal_h4.c
Merge branch 'refactor/btdm_spp_client_demo' into 'master'
[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 "bt_defs.h"
20 #include "bt_trace.h"
21 #include "bt_types.h"
22 #include "buffer_allocator.h"
23 #include "fixed_queue.h"
24 #include "hci_hal.h"
25 #include "hci_internals.h"
26 #include "hci_layer.h"
27 #include "thread.h"
28 #include "esp_bt.h"
29
30 #define HCI_HAL_SERIAL_BUFFER_SIZE 1026
31 #define HCI_BLE_EVENT 0x3e
32 #define PACKET_TYPE_TO_INBOUND_INDEX(type) ((type) - 2)
33 #define PACKET_TYPE_TO_INDEX(type) ((type) - 1)
34
35
36 static const uint8_t preamble_sizes[] = {
37     HCI_COMMAND_PREAMBLE_SIZE,
38     HCI_ACL_PREAMBLE_SIZE,
39     HCI_SCO_PREAMBLE_SIZE,
40     HCI_EVENT_PREAMBLE_SIZE
41 };
42
43 static const uint16_t outbound_event_types[] = {
44     MSG_HC_TO_STACK_HCI_ERR,
45     MSG_HC_TO_STACK_HCI_ACL,
46     MSG_HC_TO_STACK_HCI_SCO,
47     MSG_HC_TO_STACK_HCI_EVT
48 };
49
50 typedef struct {
51     const allocator_t *allocator;
52     size_t buffer_size;
53     fixed_queue_t *rx_q;
54 } hci_hal_env_t;
55
56
57 static hci_hal_env_t hci_hal_env;
58 static const hci_hal_t interface;
59 static const hci_hal_callbacks_t *callbacks;
60 static const esp_vhci_host_callback_t vhci_host_cb;
61
62 static xTaskHandle xHciH4TaskHandle;
63 static xQueueHandle xHciH4Queue;
64
65 static void host_send_pkt_available_cb(void);
66 static int host_recv_pkt_cb(uint8_t *data, uint16_t len);
67
68 static void hci_hal_h4_rx_handler(void *arg);
69 static void event_uart_has_bytes(fixed_queue_t *queue);
70
71
72 static void hci_hal_env_init(
73     size_t buffer_size,
74     size_t max_buffer_count)
75 {
76     assert(buffer_size > 0);
77     assert(max_buffer_count > 0);
78
79     hci_hal_env.allocator = buffer_allocator_get_interface();
80     hci_hal_env.buffer_size = buffer_size;
81
82     hci_hal_env.rx_q = fixed_queue_new(max_buffer_count);
83     if (hci_hal_env.rx_q) {
84         fixed_queue_register_dequeue(hci_hal_env.rx_q, event_uart_has_bytes);
85     } else {
86         LOG_ERROR("%s unable to create rx queue.\n", __func__);
87     }
88
89     return;
90 }
91
92 static void hci_hal_env_deinit(void)
93 {
94     fixed_queue_free(hci_hal_env.rx_q, hci_hal_env.allocator->free);
95 }
96
97 static bool hal_open(const hci_hal_callbacks_t *upper_callbacks)
98 {
99     assert(upper_callbacks != NULL);
100     callbacks = upper_callbacks;
101
102     hci_hal_env_init(HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX);
103
104     xHciH4Queue = xQueueCreate(HCI_H4_QUEUE_LEN, sizeof(BtTaskEvt_t));
105     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);
106
107     //register vhci host cb
108     esp_vhci_host_register_callback(&vhci_host_cb);
109
110
111     return true;
112 }
113
114 static void hal_close()
115 {
116     hci_hal_env_deinit();
117
118     /* delete task and queue */
119     vTaskDelete(xHciH4TaskHandle);
120     vQueueDelete(xHciH4Queue);
121 }
122
123 /**
124  * Function: transmit_data -TX data to low-layer
125  * It is ported from Bluedroid source code, so it is not
126  * needed to use write() to send data.
127  * TODO: Just use firmware API to send data.
128  */
129 static uint16_t transmit_data(serial_data_type_t type,
130                               uint8_t *data, uint16_t length)
131 {
132     uint8_t previous_byte;
133
134     assert(data != NULL);
135     assert(length > 0);
136
137     if (type < DATA_TYPE_COMMAND || type > DATA_TYPE_SCO) {
138         LOG_ERROR("%s invalid data type: %d", __func__, type);
139         return 0;
140     }
141
142     // Write the signal byte right before the data
143     --data;
144     previous_byte = *data;
145     *(data) = type;
146     ++length;
147
148     BTTRC_DUMP_BUFFER("Transmit Pkt", data, length);
149
150     // TX Data to target
151     esp_vhci_host_send_packet(data, length);
152
153     // Be nice and restore the old value of that byte
154     *(data) = previous_byte;
155
156     return length - 1;
157 }
158
159 // Internal functions
160 static void hci_hal_h4_rx_handler(void *arg)
161 {
162     BtTaskEvt_t e;
163
164     for (;;) {
165         if (pdTRUE == xQueueReceive(xHciH4Queue, &e, (portTickType)portMAX_DELAY)) {
166             if (e.sig == SIG_HCI_HAL_RECV_PACKET) {
167                 fixed_queue_process(hci_hal_env.rx_q);
168             }
169         }
170     }
171 }
172
173 task_post_status_t hci_hal_h4_task_post(task_post_t timeout)
174 {
175     BtTaskEvt_t evt;
176
177     evt.sig = SIG_HCI_HAL_RECV_PACKET;
178     evt.par = 0;
179
180     if (xQueueSend(xHciH4Queue, &evt, timeout) != pdTRUE) {
181         LOG_ERROR("xHciH4Queue failed\n");
182         return TASK_POST_SUCCESS;
183     }
184
185     return TASK_POST_FAIL;
186 }
187
188 static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet)
189 {
190     uint8_t type, hdr_size;
191     uint16_t length;
192     uint8_t *stream = packet->data + packet->offset;
193
194     if (!packet) {
195         return;
196     }
197     STREAM_TO_UINT8(type, stream);
198     packet->offset++;
199     packet->len--;
200     if (type == HCI_BLE_EVENT) {
201         uint8_t len = 0;
202         STREAM_TO_UINT8(len, stream);
203         LOG_ERROR("Workround stream corrupted during LE SCAN: pkt_len=%d ble_event_len=%d\n",
204                   packet->len, len);
205         hci_hal_env.allocator->free(packet);
206         return;
207     }
208     if (type < DATA_TYPE_ACL || type > DATA_TYPE_EVENT) {
209         LOG_ERROR("%s Unknown HCI message type. Dropping this byte 0x%x,"
210                   " min %x, max %x\n", __func__, type,
211                   DATA_TYPE_ACL, DATA_TYPE_EVENT);
212         hci_hal_env.allocator->free(packet);
213         return;
214     }
215     hdr_size = preamble_sizes[type - 1];
216     if (packet->len < hdr_size) {
217         LOG_ERROR("Wrong packet length type=%d pkt_len=%d hdr_len=%d",
218                   type, packet->len, hdr_size);
219         hci_hal_env.allocator->free(packet);
220         return;
221     }
222     if (type == DATA_TYPE_ACL) {
223         stream += hdr_size - 2;
224         STREAM_TO_UINT16(length, stream);
225     } else {
226         stream += hdr_size - 1;
227         STREAM_TO_UINT8(length, stream);
228     }
229
230     if ((length + hdr_size) != packet->len) {
231         LOG_ERROR("Wrong packet length type=%d hdr_len=%d pd_len=%d "
232                   "pkt_len=%d", type, hdr_size, length, packet->len);
233         hci_hal_env.allocator->free(packet);
234         return;
235     }
236
237     packet->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)];
238     callbacks->packet_ready(packet);
239 }
240
241 static void event_uart_has_bytes(fixed_queue_t *queue)
242 {
243     BT_HDR *packet;
244     while (!fixed_queue_is_empty(queue)) {
245         packet = fixed_queue_dequeue(queue);
246         hci_hal_h4_hdl_rx_packet(packet);
247     }
248 }
249
250 static void host_send_pkt_available_cb(void)
251 {
252     //Controller rx cache buffer is ready for receiving new host packet
253     //Just Call Host main thread task to process pending packets.
254     hci_host_task_post(TASK_POST_BLOCKING);
255 }
256
257 static int host_recv_pkt_cb(uint8_t *data, uint16_t len)
258 {
259     //Target has packet to host, malloc new buffer for packet
260     BT_HDR *pkt;
261     size_t pkt_size;
262
263     pkt_size = BT_HDR_SIZE + len;
264     pkt = (BT_HDR *)hci_hal_env.allocator->alloc(pkt_size);
265     if (!pkt) {
266         LOG_ERROR("%s couldn't aquire memory for inbound data buffer.\n", __func__);
267         return -1;
268     }
269     pkt->offset = 0;
270     pkt->len = len;
271     pkt->layer_specific = 0;
272     memcpy(pkt->data, data, len);
273     fixed_queue_enqueue(hci_hal_env.rx_q, pkt);
274     hci_hal_h4_task_post(TASK_POST_BLOCKING);
275
276     BTTRC_DUMP_BUFFER("Recv Pkt", pkt->data, len);
277
278     return 0;
279 }
280
281 static const esp_vhci_host_callback_t vhci_host_cb = {
282     .notify_host_send_available = host_send_pkt_available_cb,
283     .notify_host_recv = host_recv_pkt_cb,
284 };
285
286 static const hci_hal_t interface = {
287     hal_open,
288     hal_close,
289     transmit_data,
290 };
291
292 const hci_hal_t *hci_hal_h4_get_interface()
293 {
294     return &interface;
295 }
296