1 /*
2  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef H_HCI_TRANSPORT_
8 #define H_HCI_TRANSPORT_
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 #include <inttypes.h>
15 #include "os/os_mempool.h"
16 
17 #define BLE_HCI_TRANS_CMD_SZ        260
18 /*** Type of buffers for holding commands and events. */
19 /**
20  * Controller-to-host event buffers.  Events have one of two priorities:
21  * o Low-priority   (BLE_HCI_TRANS_BUF_EVT_LO)
22  * o High-priority  (BLE_HCI_TRANS_BUF_EVT_HI)
23  *
24  * Low-priority event buffers are only used for advertising reports.  If there
25  * are no free low-priority event buffers, then an incoming advertising report
26  * will get dropped.
27  *
28  * High-priority event buffers are for everything except advertising reports.
29  * If there are no free high-priority event buffers, a request to allocate one
30  * will try to allocate a low-priority buffer instead.
31  *
32  * If you want all events to be given equal treatment, then you should allocate
33  * low-priority events only.
34  *
35  * Event priorities solve the problem of critical events getting dropped due to
36  * a flood of advertising reports.  This solution is likely temporary: when
37  * HCI flow control is added, event priorities may become obsolete.
38  *
39  * Not all transports distinguish between low and high priority events.  If the
40  * transport does not have separate settings for low and high buffer counts,
41  * then it treats all events with equal priority.
42  */
43 #define BLE_HCI_TRANS_BUF_EVT_LO    1
44 #define BLE_HCI_TRANS_BUF_EVT_HI    2
45 
46 /* Host-to-controller command. */
47 #define BLE_HCI_TRANS_BUF_CMD       3
48 
49 /** Callback function types; executed when HCI packets are received. */
50 typedef int ble_hci_trans_rx_cmd_fn(uint8_t *cmd, void *arg);
51 typedef int ble_hci_trans_rx_acl_fn(struct os_mbuf *om, void *arg);
52 
53 #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
54 #define ble_transport_alloc_cmd() ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD)
55 #define ble_transport_alloc_event(X) ble_hci_trans_buf_alloc(X ? BLE_HCI_TRANS_BUF_EVT_LO : BLE_HCI_TRANS_BUF_EVT_HI)
56 #define ble_transport_free ble_hci_trans_buf_free
57 
58 struct ble_hci_trans_funcs_t {
59     int(*_ble_hci_trans_hs_acl_tx)(struct os_mbuf *om);
60     int(*_ble_hci_trans_hs_cmd_tx)(uint8_t *cmd);
61     int(*_ble_hci_trans_ll_acl_tx)(struct os_mbuf *om);
62     int(*_ble_hci_trans_ll_evt_tx)(uint8_t *hci_ev);
63     int(*_ble_hci_trans_reset)(void);
64     int(*_ble_hci_trans_set_acl_free_cb)(os_mempool_put_fn *cb, void *arg);
65 };
66 
67 extern struct ble_hci_trans_funcs_t *ble_hci_trans_funcs_ptr;
68 
69 /**
70  * Sends an HCI event from the controller to the host.
71  *
72  * @param cmd                   The HCI event to send.  This buffer must be
73  *                                  allocated via ble_hci_trans_buf_alloc().
74  *
75  * @return                      0 on success;
76  *                              A BLE_ERR_[...] error code on failure.
77  */
78 extern int r_ble_hci_trans_ll_evt_tx(uint8_t *hci_ev);
79 #define ble_hci_trans_ll_evt_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_evt_tx
80 
81 /**
82  * Sends ACL data from controller to host.
83  *
84  * @param om                    The ACL data packet to send.
85  *
86  * @return                      0 on success;
87  *                              A BLE_ERR_[...] error code on failure.
88  */
89 extern int r_ble_hci_trans_ll_acl_tx(struct os_mbuf *om);
90 #define ble_hci_trans_ll_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_acl_tx
91 
92 /**
93  * Sends an HCI command from the host to the controller.
94  *
95  * @param cmd                   The HCI command to send.  This buffer must be
96  *                                  allocated via ble_hci_trans_buf_alloc().
97  *
98  * @return                      0 on success;
99  *                              A BLE_ERR_[...] error code on failure.
100  */
101 extern int r_ble_hci_trans_hs_cmd_tx(uint8_t *cmd);
102 #define ble_hci_trans_hs_cmd_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_cmd_tx
103 
104 /**
105  * Sends ACL data from host to controller.
106  *
107  * @param om                    The ACL data packet to send.
108  *
109  * @return                      0 on success;
110  *                              A BLE_ERR_[...] error code on failure.
111  */
112 extern int r_ble_hci_trans_hs_acl_tx(struct os_mbuf *om);
113 #define ble_hci_trans_hs_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_acl_tx
114 
115 /**
116  * Allocates a flat buffer of the specified type.
117  *
118  * @param type                  The type of buffer to allocate; one of the
119  *                                  BLE_HCI_TRANS_BUF_[...] constants.
120  *
121  * @return                      The allocated buffer on success;
122  *                              NULL on buffer exhaustion.
123  */
124 extern uint8_t *r_ble_hci_trans_buf_alloc(int type);
125 #define ble_hci_trans_buf_alloc r_ble_hci_trans_buf_alloc
126 
127 /**
128  * Frees the specified flat buffer.  The buffer must have been allocated via
129  * ble_hci_trans_buf_alloc().
130  *
131  * @param buf                   The buffer to free.
132  */
133 extern void r_ble_hci_trans_buf_free(uint8_t *buf);
134 #define ble_hci_trans_buf_free r_ble_hci_trans_buf_free
135 
136 /**
137  * Configures a callback to get executed whenever an ACL data packet is freed.
138  * The function is called immediately before the free occurs.
139  *
140  * @param cb                    The callback to configure.
141  * @param arg                   An optional argument to pass to the callback.
142  *
143  * @return                      0 on success;
144  *                              BLE_ERR_UNSUPPORTED if the transport does not
145  *                                  support this operation.
146  */
147 extern int r_ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg);
148 #define ble_hci_trans_set_acl_free_cb ble_hci_trans_funcs_ptr->_ble_hci_trans_set_acl_free_cb
149 
150 /**
151  * Configures the HCI transport to operate with a controller.  The transport
152  * will execute specified callbacks upon receiving HCI packets from the host.
153  *
154  * @param cmd_cb                The callback to execute upon receiving an HCI
155  *                                  command.
156  * @param cmd_arg               Optional argument to pass to the command
157  *                                  callback.
158  * @param acl_cb                The callback to execute upon receiving ACL
159  *                                  data.
160  * @param acl_arg               Optional argument to pass to the ACL
161  *                                  callback.
162  */
163 extern void r_ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb,
164                                    void *cmd_arg,
165                                    ble_hci_trans_rx_acl_fn *acl_cb,
166                                    void *acl_arg);
167 #define ble_hci_trans_cfg_ll r_ble_hci_trans_cfg_ll
168 
169 /**
170  * Configures the HCI transport to operate with a host.  The transport will
171  * execute specified callbacks upon receiving HCI packets from the controller.
172  *
173  * @param evt_cb                The callback to execute upon receiving an HCI
174  *                                  event.
175  * @param evt_arg               Optional argument to pass to the event
176  *                                  callback.
177  * @param acl_cb                The callback to execute upon receiving ACL
178  *                                  data.
179  * @param acl_arg               Optional argument to pass to the ACL
180  *                                  callback.
181  */
182 extern void r_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb,
183                                    void *evt_arg,
184                                    ble_hci_trans_rx_acl_fn *acl_cb,
185                                    void *acl_arg);
186 #define ble_hci_trans_cfg_hs r_ble_hci_trans_cfg_hs
187 
188 /**
189  * Resets the HCI module to a clean state.  Frees all buffers and reinitializes
190  * the underlying transport.
191  *
192  * @return                      0 on success;
193  *                              A BLE_ERR_[...] error code on failure.
194  */
195 extern int r_ble_hci_trans_reset(void);
196 #define ble_hci_trans_reset ble_hci_trans_funcs_ptr->_ble_hci_trans_reset
197 
198 void esp_ble_hci_trans_init(uint8_t);
199 
200 #else
201 /**
202  * Sends an HCI event from the controller to the host.
203  *
204  * @param cmd                   The HCI event to send.  This buffer must be
205  *                                  allocated via ble_hci_trans_buf_alloc().
206  *
207  * @return                      0 on success;
208  *                              A BLE_ERR_[...] error code on failure.
209  */
210 int ble_hci_trans_ll_evt_tx(uint8_t *hci_ev);
211 
212 /**
213  * Sends ACL data from controller to host.
214  *
215  * @param om                    The ACL data packet to send.
216  *
217  * @return                      0 on success;
218  *                              A BLE_ERR_[...] error code on failure.
219  */
220 int ble_hci_trans_ll_acl_tx(struct os_mbuf *om);
221 
222 /**
223  * Sends an HCI command from the host to the controller.
224  *
225  * @param cmd                   The HCI command to send.  This buffer must be
226  *                                  allocated via ble_hci_trans_buf_alloc().
227  *
228  * @return                      0 on success;
229  *                              A BLE_ERR_[...] error code on failure.
230  */
231 int ble_hci_trans_hs_cmd_tx(uint8_t *cmd);
232 
233 /**
234  * Sends ACL data from host to controller.
235  *
236  * @param om                    The ACL data packet to send.
237  *
238  * @return                      0 on success;
239  *                              A BLE_ERR_[...] error code on failure.
240  */
241 int ble_hci_trans_hs_acl_tx(struct os_mbuf *om);
242 
243 /**
244  * Allocates a flat buffer of the specified type.
245  *
246  * @param type                  The type of buffer to allocate; one of the
247  *                                  BLE_HCI_TRANS_BUF_[...] constants.
248  *
249  * @return                      The allocated buffer on success;
250  *                              NULL on buffer exhaustion.
251  */
252 int esp_ble_hci_trans_hs_cmd_tx(uint8_t *cmd);
253 
254 /**
255  * Sends ACL data from host to controller.
256  *
257  * @param om                    The ACL data packet to send.
258  *
259  * @return                      0 on success;
260  *                              A BLE_ERR_[...] error code on failure.
261  */
262 int esp_ble_hci_trans_hs_acl_tx(struct os_mbuf *om);
263 
264 /**
265  * Allocates a flat buffer of the specified type.
266  *
267  * @param type                  The type of buffer to allocate; one of the
268  *                                  BLE_HCI_TRANS_BUF_[...] constants.
269  *
270  * @return                      The allocated buffer on success;
271  *                              NULL on buffer exhaustion.
272  */
273 uint8_t *esp_ble_hci_trans_buf_alloc(int type);
274 
275 /**
276  * Frees the specified flat buffer.  The buffer must have been allocated via
277  * ble_hci_trans_buf_alloc().
278  *
279  * @param buf                   The buffer to free.
280  */
281 void esp_ble_hci_trans_buf_free(uint8_t *buf);
282 
283 /**
284  * Configures the HCI transport to operate with a host.  The transport will
285  * execute specified callbacks upon receiving HCI packets from the controller.
286  *
287  * @param evt_cb                The callback to execute upon receiving an HCI
288  *                                  event.
289  * @param evt_arg               Optional argument to pass to the event
290  *                                  callback.
291  * @param acl_cb                The callback to execute upon receiving ACL
292  *                                  data.
293  * @param acl_arg               Optional argument to pass to the ACL
294  *                                  callback.
295  */
296 void esp_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb,
297                               void *evt_arg,
298                               ble_hci_trans_rx_acl_fn *acl_cb,
299                               void *acl_arg);
300 
301 /**
302  * Resets the HCI module to a clean state.  Frees all buffers and reinitializes
303  * the underlying transport.
304  *
305  * @return                      0 on success;
306  *                              A BLE_ERR_[...] error code on failure.
307  */
308 int esp_ble_hci_trans_reset(void);
309 #endif
310 
311 #ifdef __cplusplus
312 }
313 #endif
314 
315 #endif /* H_HCI_TRANSPORT_ */
316