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