1 /*
2  * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <string.h>
7 #include <stdio.h>
8 #include "os/os_mbuf.h"
9 #include "esp_hci_transport.h"
10 #include "esp_hci_internal.h"
11 #include "esp_hci_driver.h"
12 #include "esp_bt.h"
13 
14 typedef struct {
15     hci_driver_forward_fn *forward_cb;
16     const esp_vhci_host_callback_t *host_recv_cb;
17 } hci_driver_vhci_env_t;
18 
19 static hci_driver_vhci_env_t s_hci_driver_vhci_env;
20 
21 static int
hci_driver_vhci_controller_tx(hci_driver_data_type_t data_type,uint8_t * data,uint32_t length)22 hci_driver_vhci_controller_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length)
23 {
24     int rc;
25     uint16_t buf_len = 0;
26     uint8_t *buf = NULL;
27     struct os_mbuf *om;
28 
29     if (data_type == HCI_DRIVER_TYPE_ACL) {
30         om = (struct os_mbuf *)data;
31         buf_len = length + 1;
32         buf = malloc(buf_len);
33         /* TODO: If there is no memory, should handle it in the controller. */
34         assert(buf);
35         buf[0] = HCI_DRIVER_TYPE_ACL;
36         os_mbuf_copydata(om, 0, length, &buf[1]);
37         os_mbuf_free_chain(om);
38     } else if (data_type == HCI_DRIVER_TYPE_EVT) {
39         buf_len = length + 1;
40         buf = malloc(buf_len);
41         /* TODO: If there is no memory, should handle it in the controller. */
42         assert(buf != NULL);
43         buf[0] = HCI_DRIVER_TYPE_EVT;
44         memcpy(&buf[1], data, length);
45         r_ble_hci_trans_buf_free(data);
46     }
47 
48     rc = s_hci_driver_vhci_env.forward_cb(data_type, buf, buf_len, HCI_DRIVER_DIR_C2H);
49     free(buf);
50 
51     return rc;
52 }
53 
54 static int
hci_driver_vhci_host_tx(hci_driver_data_type_t data_type,uint8_t * data,uint32_t length)55 hci_driver_vhci_host_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length)
56 {
57     uint8_t *cmd;
58     struct os_mbuf *om;
59 
60     if (data_type == HCI_DRIVER_TYPE_ACL) {
61         om = os_msys_get_pkthdr(length, ESP_HCI_INTERNAL_ACL_MBUF_LEADINGSPCAE);
62         assert(om);
63         assert(os_mbuf_append(om, &data[1], length - 1) == 0);
64         data = (uint8_t *)om;
65     } else if (data_type == HCI_DRIVER_TYPE_CMD) {
66         cmd = r_ble_hci_trans_buf_alloc(ESP_HCI_INTERNAL_BUF_CMD);
67         assert(cmd);
68         memcpy(cmd, data + 1, length - 1);
69         data = cmd;
70     }
71 
72     return s_hci_driver_vhci_env.forward_cb(data_type, data, length, HCI_DRIVER_DIR_H2C);
73 }
74 
75 static int
hci_driver_vhci_tx(hci_driver_data_type_t data_type,uint8_t * data,uint32_t length,hci_driver_direction_t dir)76 hci_driver_vhci_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length,
77                    hci_driver_direction_t dir)
78 {
79     int rc;
80 
81     if (dir == HCI_DRIVER_DIR_C2H) {
82         rc = hci_driver_vhci_controller_tx(data_type, data, length);
83     } else {
84         rc = hci_driver_vhci_host_tx(data_type, data, length);
85     }
86     return rc;
87 }
88 
89 static int
hci_driver_vhci_init(hci_driver_forward_fn * cb)90 hci_driver_vhci_init(hci_driver_forward_fn *cb)
91 {
92     memset(&s_hci_driver_vhci_env, 0, sizeof(hci_driver_vhci_env_t));
93     s_hci_driver_vhci_env.forward_cb = cb;
94     return 0;
95 }
96 
97 static void
hci_driver_vhci_deinit(void)98 hci_driver_vhci_deinit(void)
99 {
100     memset(&s_hci_driver_vhci_env, 0, sizeof(hci_driver_vhci_env_t));
101 }
102 
103 hci_driver_ops_t hci_driver_vhci_ops = {
104     .hci_driver_tx = hci_driver_vhci_tx,
105     .hci_driver_init = hci_driver_vhci_init,
106     .hci_driver_deinit = hci_driver_vhci_deinit,
107 };
108 
109 /* Special APIs declared in the `esp_bt.h'. */
110 static int
hci_driver_vhci_host_recv_cb(hci_trans_pkt_ind_t type,uint8_t * data,uint16_t len)111 hci_driver_vhci_host_recv_cb(hci_trans_pkt_ind_t type, uint8_t *data, uint16_t len)
112 {
113     static const esp_vhci_host_callback_t *host_recv_cb;
114 
115     host_recv_cb = s_hci_driver_vhci_env.host_recv_cb;
116     if (host_recv_cb) {
117         return host_recv_cb->notify_host_recv(data, len);
118     }
119 
120     return -1;
121 }
122 
123 esp_err_t
esp_vhci_host_register_callback(const esp_vhci_host_callback_t * callback)124 esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback)
125 {
126     if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
127         return ESP_FAIL;
128     }
129 
130     s_hci_driver_vhci_env.host_recv_cb = callback;
131     if(hci_transport_host_callback_register(hci_driver_vhci_host_recv_cb)) {
132         s_hci_driver_vhci_env.host_recv_cb = NULL;
133         return ESP_FAIL;
134     }
135 
136     return ESP_OK;
137 }
138 
139 void
esp_vhci_host_send_packet(uint8_t * data,uint16_t len)140 esp_vhci_host_send_packet(uint8_t *data, uint16_t len)
141 {
142     if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
143         return;
144     }
145 
146     hci_driver_vhci_tx(data[0], data, len, HCI_DRIVER_DIR_H2C);
147 }
148 
149 bool
esp_vhci_host_check_send_available(void)150 esp_vhci_host_check_send_available(void)
151 {
152     return true;
153 }
154