1 /******************************************************************************
3 * Copyright (C) 2014 Google, Inc.
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
22 #include "buffer_allocator.h"
23 #include "fixed_queue.h"
25 #include "hci_internals.h"
26 #include "hci_layer.h"
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)
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
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
51 const allocator_t *allocator;
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;
62 static xTaskHandle xHciH4TaskHandle;
63 static xQueueHandle xHciH4Queue;
65 static void host_send_pkt_available_cb(void);
66 static int host_recv_pkt_cb(uint8_t *data, uint16_t len);
68 static void hci_hal_h4_rx_handler(void *arg);
69 static void event_uart_has_bytes(fixed_queue_t *queue);
72 static void hci_hal_env_init(
74 size_t max_buffer_count)
76 assert(buffer_size > 0);
77 assert(max_buffer_count > 0);
79 hci_hal_env.allocator = buffer_allocator_get_interface();
80 hci_hal_env.buffer_size = buffer_size;
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);
86 LOG_ERROR("%s unable to create rx queue.\n", __func__);
92 static void hci_hal_env_deinit(void)
94 fixed_queue_free(hci_hal_env.rx_q, hci_hal_env.allocator->free);
97 static bool hal_open(const hci_hal_callbacks_t *upper_callbacks)
99 assert(upper_callbacks != NULL);
100 callbacks = upper_callbacks;
102 hci_hal_env_init(HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX);
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);
107 //register vhci host cb
108 esp_vhci_host_register_callback(&vhci_host_cb);
114 static void hal_close()
116 hci_hal_env_deinit();
118 /* delete task and queue */
119 vTaskDelete(xHciH4TaskHandle);
120 vQueueDelete(xHciH4Queue);
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.
129 static uint16_t transmit_data(serial_data_type_t type,
130 uint8_t *data, uint16_t length)
132 uint8_t previous_byte;
134 assert(data != NULL);
137 if (type < DATA_TYPE_COMMAND || type > DATA_TYPE_SCO) {
138 LOG_ERROR("%s invalid data type: %d", __func__, type);
142 // Write the signal byte right before the data
144 previous_byte = *data;
148 BTTRC_DUMP_BUFFER("Transmit Pkt", data, length);
151 esp_vhci_host_send_packet(data, length);
153 // Be nice and restore the old value of that byte
154 *(data) = previous_byte;
159 // Internal functions
160 static void hci_hal_h4_rx_handler(void *arg)
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);
173 task_post_status_t hci_hal_h4_task_post(task_post_t timeout)
177 evt.sig = SIG_HCI_HAL_RECV_PACKET;
180 if (xQueueSend(xHciH4Queue, &evt, timeout) != pdTRUE) {
181 LOG_ERROR("xHciH4Queue failed\n");
182 return TASK_POST_SUCCESS;
185 return TASK_POST_FAIL;
188 static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet)
190 uint8_t type, hdr_size;
192 uint8_t *stream = packet->data + packet->offset;
197 STREAM_TO_UINT8(type, stream);
200 if (type == HCI_BLE_EVENT) {
202 STREAM_TO_UINT8(len, stream);
203 LOG_ERROR("Workround stream corrupted during LE SCAN: pkt_len=%d ble_event_len=%d\n",
205 hci_hal_env.allocator->free(packet);
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);
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);
222 if (type == DATA_TYPE_ACL) {
223 stream += hdr_size - 2;
224 STREAM_TO_UINT16(length, stream);
226 stream += hdr_size - 1;
227 STREAM_TO_UINT8(length, stream);
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);
237 packet->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)];
238 callbacks->packet_ready(packet);
241 static void event_uart_has_bytes(fixed_queue_t *queue)
244 while (!fixed_queue_is_empty(queue)) {
245 packet = fixed_queue_dequeue(queue);
246 hci_hal_h4_hdl_rx_packet(packet);
250 static void host_send_pkt_available_cb(void)
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);
257 static int host_recv_pkt_cb(uint8_t *data, uint16_t len)
259 //Target has packet to host, malloc new buffer for packet
263 pkt_size = BT_HDR_SIZE + len;
264 pkt = (BT_HDR *)hci_hal_env.allocator->alloc(pkt_size);
266 LOG_ERROR("%s couldn't aquire memory for inbound data buffer.\n", __func__);
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);
276 BTTRC_DUMP_BUFFER("Recv Pkt", pkt->data, len);
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,
286 static const hci_hal_t interface = {
292 const hci_hal_t *hci_hal_h4_get_interface()