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