1 /*
2 * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <stdio.h>
7 #include <string.h>
8 #include "esp_log.h"
9 #include "esp_hci_transport.h"
10 #include "esp_hci_internal.h"
11 #include "esp_bt.h"
12
13 typedef struct hci_transport_env
14 {
15 hci_transport_host_recv_fn *host_recv_cb;
16 hci_driver_ops_t *driver_ops;
17 } hci_transport_env_t;
18
19 static hci_transport_env_t s_hci_transport_env;
20
21 /* Functions for packets Rx. */
22 static int
hci_transport_controller_packet_rx(hci_driver_data_type_t data_type,uint8_t * data)23 hci_transport_controller_packet_rx(hci_driver_data_type_t data_type, uint8_t *data)
24 {
25 if (data_type == HCI_DRIVER_TYPE_CMD) {
26 r_ble_hci_trans_hs_cmd_tx(data);
27 }
28
29 if (data_type == HCI_DRIVER_TYPE_ACL) {
30 r_ble_hci_trans_hs_acl_tx((struct os_mbuf *) data);
31 }
32 return 0;
33 }
34
35 static int
hci_transport_host_packet_rx(hci_driver_data_type_t data_type,uint8_t * data,uint32_t length)36 hci_transport_host_packet_rx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length)
37 {
38 if (!s_hci_transport_env.host_recv_cb) {
39 return -1;
40 }
41 return s_hci_transport_env.host_recv_cb((hci_trans_pkt_ind_t)data_type, data, length);
42 }
43
44 static int
hci_transport_packet_rx(hci_driver_data_type_t data_type,uint8_t * data,uint32_t length,hci_driver_direction_t dir)45 hci_transport_packet_rx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length,
46 hci_driver_direction_t dir)
47 {
48 int rc;
49 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
50 return -1;
51 }
52
53 if (dir == HCI_DRIVER_DIR_C2H) {
54 rc = hci_transport_host_packet_rx(data_type, data, length);
55 } else {
56 rc = hci_transport_controller_packet_rx(data_type, data);
57 }
58
59 return rc;
60 }
61
62 /* Functions for controller Tx. */
63 static int
hci_transport_controller_tx_dummy(void * data,void * arg)64 hci_transport_controller_tx_dummy(void *data, void *arg)
65 {
66 return -1;
67 }
68
69 static int
hci_transport_controller_evt_tx(uint8_t * hci_ev,void * arg)70 hci_transport_controller_evt_tx(uint8_t *hci_ev, void *arg)
71 {
72 uint32_t len;
73
74 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
75 r_ble_hci_trans_buf_free(hci_ev);
76 return -1;
77 }
78
79 len = hci_ev[1] + 2;
80 return s_hci_transport_env.driver_ops->hci_driver_tx(HCI_DRIVER_TYPE_EVT, hci_ev, len,
81 HCI_DRIVER_DIR_C2H);
82 }
83
84 static int
hci_transport_controller_acl_tx(struct os_mbuf * om,void * arg)85 hci_transport_controller_acl_tx(struct os_mbuf *om, void *arg)
86 {
87 uint16_t len;
88 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
89 os_mbuf_free_chain(om);
90 return -1;
91 }
92
93 len = OS_MBUF_PKTHDR(om)->omp_len;
94 return s_hci_transport_env.driver_ops->hci_driver_tx(HCI_DRIVER_TYPE_ACL, (uint8_t *)om, len,
95 HCI_DRIVER_DIR_C2H);
96 }
97
98 /* Functions for host Tx. */
99 int
hci_transport_host_cmd_tx(uint8_t * data,uint32_t length)100 hci_transport_host_cmd_tx(uint8_t *data, uint32_t length)
101 {
102 return s_hci_transport_env.driver_ops->hci_driver_tx(HCI_DRIVER_TYPE_CMD, data, length,
103 HCI_DRIVER_DIR_H2C);
104 }
105
106 int
hci_transport_host_acl_tx(uint8_t * data,uint32_t length)107 hci_transport_host_acl_tx(uint8_t *data, uint32_t length)
108 {
109 return s_hci_transport_env.driver_ops->hci_driver_tx(HCI_DRIVER_TYPE_ACL, data, length,
110 HCI_DRIVER_DIR_H2C);
111 }
112
113 int
hci_transport_host_callback_register(hci_transport_host_recv_fn * callback)114 hci_transport_host_callback_register(hci_transport_host_recv_fn *callback)
115 {
116 s_hci_transport_env.host_recv_cb = callback;
117 return 0;
118 }
119
120 int
hci_transport_init(uint8_t hci_transport_mode)121 hci_transport_init(uint8_t hci_transport_mode)
122 {
123 int rc;
124 hci_driver_ops_t *ops;
125
126 memset(&s_hci_transport_env, 0, sizeof(hci_transport_env_t));
127
128 switch(hci_transport_mode) {
129 #if CONFIG_BT_LE_HCI_INTERFACE_USE_RAM
130 case HCI_TRANSPORT_VHCI:
131 ops = &hci_driver_vhci_ops;
132 break;
133 #endif // CONFIG_BT_LE_HCI_INTERFACE_USE_RAM
134 #if CONFIG_BT_LE_HCI_INTERFACE_USE_UART
135 #if CONFIG_BT_LE_UART_HCI_DMA_MODE
136 case HCI_TRANSPORT_UART_UHCI:
137 ops = &hci_driver_uart_dma_ops;
138 break;
139 #else
140 case HCI_TRANSPORT_UART_NO_DMA:
141 ops = &hci_driver_uart_ops;
142 break;
143 #endif // CONFIG_BT_LE_UART_HCI_DMA_MODE
144 #endif // CONFIG_BT_LE_HCI_INTERFACE_USE_UART
145 default:
146 assert(0);
147 }
148
149 rc = ops->hci_driver_init(hci_transport_packet_rx);
150 if (rc) {
151 goto error;
152 }
153
154 s_hci_transport_env.driver_ops = ops;
155 r_ble_hci_trans_cfg_hs(hci_transport_controller_evt_tx, NULL, hci_transport_controller_acl_tx, NULL);
156
157 return 0;
158
159 error:
160 hci_transport_deinit();
161 return rc;
162 }
163
164 void
hci_transport_deinit(void)165 hci_transport_deinit(void)
166 {
167 hci_driver_ops_t *ops;
168
169 r_ble_hci_trans_cfg_hs((esp_hci_internal_rx_cmd_fn *)hci_transport_controller_tx_dummy, NULL,
170 (esp_hci_internal_rx_acl_fn *)hci_transport_controller_tx_dummy, NULL);
171
172 ops = s_hci_transport_env.driver_ops;
173 if (ops) {
174 ops->hci_driver_deinit();
175 }
176 memset(&s_hci_transport_env, 0, sizeof(hci_transport_env_t));
177 }
178