Line data Source code
1 1 : /** @file
2 : * @brief Bluetooth data buffer API
3 : */
4 :
5 : /*
6 : * Copyright (c) 2016 Intel Corporation
7 : *
8 : * SPDX-License-Identifier: Apache-2.0
9 : */
10 :
11 : #ifndef ZEPHYR_INCLUDE_BLUETOOTH_BUF_H_
12 : #define ZEPHYR_INCLUDE_BLUETOOTH_BUF_H_
13 :
14 : /**
15 : * @brief Data buffers
16 : * @defgroup bt_buf Data buffers
17 : * @ingroup bluetooth
18 : * @{
19 : */
20 :
21 : #include <stddef.h>
22 : #include <stdint.h>
23 :
24 : #include <zephyr/autoconf.h>
25 : #include <zephyr/bluetooth/hci.h>
26 : #include <zephyr/bluetooth/hci_types.h>
27 : #include <zephyr/net_buf.h>
28 : #include <zephyr/sys/util.h>
29 : #include <zephyr/sys/util_macro.h>
30 : #include <zephyr/sys_clock.h>
31 : #include <zephyr/toolchain.h>
32 :
33 : #ifdef __cplusplus
34 : extern "C" {
35 : #endif
36 :
37 : /** Possible types of buffers passed around the Bluetooth stack in a form of bitmask. */
38 1 : enum bt_buf_type {
39 : /** Unknown/invalid packet type, used for error checking */
40 : BT_BUF_TYPE_NONE = 0,
41 : /** HCI command */
42 : BT_BUF_CMD = BIT(0),
43 : /** HCI event */
44 : BT_BUF_EVT = BIT(1),
45 : /** Outgoing ACL data */
46 : BT_BUF_ACL_OUT = BIT(2),
47 : /** Incoming ACL data */
48 : BT_BUF_ACL_IN = BIT(3),
49 : /** Outgoing ISO data */
50 : BT_BUF_ISO_OUT = BIT(4),
51 : /** Incoming ISO data */
52 : BT_BUF_ISO_IN = BIT(5),
53 : };
54 :
55 : /** Direction of HCI packets. Only used for mapping H:4 to BT_BUF_* values. */
56 1 : enum bt_buf_dir {
57 : /** Packet from the controller to the host */
58 : BT_BUF_IN,
59 : /** Packet from the host to the controller */
60 : BT_BUF_OUT,
61 : };
62 :
63 : /** Convert from bt_buf_type to H:4 type.
64 : *
65 : * @param type The bt_buf_type to convert
66 : * @return The H:4 type
67 : */
68 1 : static inline uint8_t bt_buf_type_to_h4(enum bt_buf_type type)
69 : {
70 : switch (type) {
71 : case BT_BUF_CMD:
72 : return BT_HCI_H4_CMD;
73 : case BT_BUF_ACL_IN:
74 : case BT_BUF_ACL_OUT:
75 : return BT_HCI_H4_ACL;
76 : case BT_BUF_ISO_IN:
77 : case BT_BUF_ISO_OUT:
78 : return BT_HCI_H4_ISO;
79 : case BT_BUF_EVT:
80 : return BT_HCI_H4_EVT;
81 : default:
82 : __ASSERT_NO_MSG(false);
83 : return 0;
84 : }
85 : }
86 :
87 : /** Convert from H:4 type to bt_buf_type.
88 : *
89 : * @param h4_type The H:4 type to convert
90 : * @param dir The direction of the packet
91 : * @return The bt_buf_type
92 : */
93 1 : static inline enum bt_buf_type bt_buf_type_from_h4(uint8_t h4_type, enum bt_buf_dir dir)
94 : {
95 : switch (h4_type) {
96 : case BT_HCI_H4_CMD:
97 : return BT_BUF_CMD;
98 : case BT_HCI_H4_ACL:
99 : return dir == BT_BUF_OUT ? BT_BUF_ACL_OUT : BT_BUF_ACL_IN;
100 : case BT_HCI_H4_EVT:
101 : return BT_BUF_EVT;
102 : case BT_HCI_H4_ISO:
103 : return dir == BT_BUF_OUT ? BT_BUF_ISO_OUT : BT_BUF_ISO_IN;
104 : default:
105 : return BT_BUF_TYPE_NONE;
106 : }
107 : }
108 :
109 : /* Headroom reserved in buffers, primarily for HCI transport encoding purposes */
110 0 : #define BT_BUF_RESERVE 1
111 :
112 : /** Helper to include reserved HCI data in buffer calculations */
113 1 : #define BT_BUF_SIZE(size) (BT_BUF_RESERVE + (size))
114 :
115 : /** Helper to calculate needed buffer size for HCI ACL packets */
116 1 : #define BT_BUF_ACL_SIZE(size) BT_BUF_SIZE(BT_HCI_ACL_HDR_SIZE + (size))
117 :
118 : /** Helper to calculate needed buffer size for HCI Event packets. */
119 1 : #define BT_BUF_EVT_SIZE(size) BT_BUF_SIZE(BT_HCI_EVT_HDR_SIZE + (size))
120 :
121 : /** Helper to calculate needed buffer size for HCI Command packets. */
122 1 : #define BT_BUF_CMD_SIZE(size) BT_BUF_SIZE(BT_HCI_CMD_HDR_SIZE + (size))
123 :
124 : /** Helper to calculate needed buffer size for HCI ISO packets. */
125 1 : #define BT_BUF_ISO_SIZE(size) BT_BUF_SIZE(BT_HCI_ISO_HDR_SIZE + \
126 : BT_HCI_ISO_SDU_TS_HDR_SIZE + \
127 : (size))
128 :
129 : /** Data size needed for HCI ACL RX buffers */
130 1 : #define BT_BUF_ACL_RX_SIZE BT_BUF_ACL_SIZE(CONFIG_BT_BUF_ACL_RX_SIZE)
131 :
132 : /** Data size needed for HCI Event RX buffers */
133 1 : #define BT_BUF_EVT_RX_SIZE BT_BUF_EVT_SIZE(CONFIG_BT_BUF_EVT_RX_SIZE)
134 :
135 : #if defined(CONFIG_BT_ISO)
136 : #define BT_BUF_ISO_RX_SIZE BT_BUF_ISO_SIZE(CONFIG_BT_ISO_RX_MTU)
137 : #define BT_BUF_ISO_RX_COUNT CONFIG_BT_ISO_RX_BUF_COUNT
138 : #else
139 0 : #define BT_BUF_ISO_RX_SIZE 0
140 0 : #define BT_BUF_ISO_RX_COUNT 0
141 : #endif /* CONFIG_BT_ISO */
142 :
143 : /* see Core Spec v6.0 vol.4 part E 7.4.5 */
144 0 : #define BT_BUF_ACL_RX_COUNT_MAX 65535
145 :
146 : #if defined(CONFIG_BT_CONN) && defined(CONFIG_BT_HCI_HOST)
147 : /* The host needs more ACL buffers than maximum ACL links. This is because of
148 : * the way we re-assemble ACL packets into L2CAP PDUs.
149 : *
150 : * We keep around the first buffer (that comes from the driver) to do
151 : * re-assembly into, and if all links are re-assembling, there will be no buffer
152 : * available for the HCI driver to allocate from.
153 : *
154 : * TODO: When CONFIG_BT_BUF_ACL_RX_COUNT is removed,
155 : * remove the MAX and only keep the 1.
156 : */
157 : #define BT_BUF_ACL_RX_COUNT_EXTRA CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA
158 : #define BT_BUF_ACL_RX_COUNT (MAX(CONFIG_BT_BUF_ACL_RX_COUNT, 1) + BT_BUF_ACL_RX_COUNT_EXTRA)
159 : #else
160 0 : #define BT_BUF_ACL_RX_COUNT_EXTRA 0
161 0 : #define BT_BUF_ACL_RX_COUNT 0
162 : #endif /* CONFIG_BT_CONN && CONFIG_BT_HCI_HOST */
163 :
164 : #if defined(CONFIG_BT_BUF_ACL_RX_COUNT) && CONFIG_BT_BUF_ACL_RX_COUNT > 0
165 : #warning "CONFIG_BT_BUF_ACL_RX_COUNT is deprecated, see Zephyr 4.1 migration guide"
166 : #endif /* CONFIG_BT_BUF_ACL_RX_COUNT && CONFIG_BT_BUF_ACL_RX_COUNT > 0 */
167 :
168 : BUILD_ASSERT(BT_BUF_ACL_RX_COUNT <= BT_BUF_ACL_RX_COUNT_MAX,
169 : "Maximum number of ACL RX buffer is 65535, reduce CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA");
170 :
171 : /** Data size needed for HCI ACL, HCI ISO or Event RX buffers */
172 1 : #define BT_BUF_RX_SIZE (MAX(MAX(BT_BUF_ACL_RX_SIZE, BT_BUF_EVT_RX_SIZE), \
173 : BT_BUF_ISO_RX_SIZE))
174 :
175 : /* Controller can generate up to CONFIG_BT_BUF_ACL_TX_COUNT number of unique HCI Number of Completed
176 : * Packets events.
177 : */
178 : BUILD_ASSERT(CONFIG_BT_BUF_EVT_RX_COUNT > CONFIG_BT_BUF_ACL_TX_COUNT,
179 : "Increase Event RX buffer count to be greater than ACL TX buffer count");
180 :
181 : /** Buffer count needed for HCI ACL or HCI ISO plus Event RX buffers */
182 1 : #define BT_BUF_RX_COUNT (CONFIG_BT_BUF_EVT_RX_COUNT + \
183 : MAX(BT_BUF_ACL_RX_COUNT, BT_BUF_ISO_RX_COUNT))
184 :
185 : /** Data size needed for HCI Command buffers. */
186 1 : #define BT_BUF_CMD_TX_SIZE BT_BUF_CMD_SIZE(CONFIG_BT_BUF_CMD_TX_SIZE)
187 :
188 : /** Allocate a buffer for incoming data
189 : *
190 : * This will set the buffer type so it doesn't need to be explicitly encoded into the buffer.
191 : *
192 : * @param type Type of buffer. Only BT_BUF_EVT, BT_BUF_ACL_IN and BT_BUF_ISO_IN
193 : * are allowed.
194 : * @param timeout Non-negative waiting period to obtain a buffer or one of the
195 : * special values K_NO_WAIT and K_FOREVER.
196 : * @return A new buffer.
197 : */
198 1 : struct net_buf *bt_buf_get_rx(enum bt_buf_type type, k_timeout_t timeout);
199 :
200 : /** A callback to notify about freed buffer in the incoming data pool.
201 : *
202 : * This callback is called when a buffer of a given type is freed and can be requested through the
203 : * @ref bt_buf_get_rx function. However, this callback is called from the context of the buffer
204 : * freeing operation and must not attempt to allocate a new buffer from the same pool.
205 : *
206 : * @warning When this callback is called, the scheduler is locked and the callee must not perform
207 : * any action that makes the current thread unready. This callback must only be used for very
208 : * short non-blocking operation (e.g. submitting a work item).
209 : *
210 : * @param type_mask A bit mask of buffer types that have been freed.
211 : */
212 1 : typedef void (*bt_buf_rx_freed_cb_t)(enum bt_buf_type type_mask);
213 :
214 : /** Set the callback to notify about freed buffer in the incoming data pool.
215 : *
216 : * @param cb Callback to notify about freed buffer in the incoming data pool. If NULL, the callback
217 : * is disabled.
218 : */
219 1 : void bt_buf_rx_freed_cb_set(bt_buf_rx_freed_cb_t cb);
220 :
221 : /** Allocate a buffer for outgoing data
222 : *
223 : * This will set the buffer type so it doesn't need to be explicitly encoded into the buffer.
224 : *
225 : * @param type Type of buffer. BT_BUF_CMD or BT_BUF_ACL_OUT.
226 : * @param timeout Non-negative waiting period to obtain a buffer or one of the
227 : * special values K_NO_WAIT and K_FOREVER.
228 : * @param data Initial data to append to buffer. This is optional and can be NULL.
229 : * @param size Initial data size.
230 : * @return A new buffer.
231 : */
232 1 : struct net_buf *bt_buf_get_tx(enum bt_buf_type type, k_timeout_t timeout,
233 : const void *data, size_t size);
234 :
235 : /** Allocate a buffer for an HCI Event
236 : *
237 : * This will set the buffer type so it doesn't need to be explicitly encoded into the buffer.
238 : *
239 : * @param evt HCI event code
240 : * @param discardable Whether the driver considers the event discardable.
241 : * @param timeout Non-negative waiting period to obtain a buffer or one of
242 : * the special values K_NO_WAIT and K_FOREVER.
243 : * @return A new buffer.
244 : */
245 1 : struct net_buf *bt_buf_get_evt(uint8_t evt, bool discardable, k_timeout_t timeout);
246 :
247 : /** Set the buffer type. The type is encoded as an H:4 byte prefix as part of
248 : * the payload itself.
249 : *
250 : * @param buf Bluetooth buffer
251 : * @param type The BT_* type to set the buffer to
252 : */
253 1 : static inline void __deprecated bt_buf_set_type(struct net_buf *buf, enum bt_buf_type type)
254 : {
255 : __ASSERT_NO_MSG(net_buf_headroom(buf) >= 1);
256 : net_buf_push_u8(buf, bt_buf_type_to_h4(type));
257 : }
258 :
259 :
260 : /** Get the buffer type. This pulls the H:4 byte prefix from the payload, which means
261 : * that the call can be done only once per buffer.
262 : *
263 : * @param buf Bluetooth buffer
264 : *
265 : * @return The BT_* type to of the buffer
266 : */
267 1 : static inline enum bt_buf_type __deprecated bt_buf_get_type(struct net_buf *buf)
268 : {
269 : /* We have to assume the direction since the H:4 type doesn't tell us
270 : * if the buffer is incoming or outgoing. The common use case of this API is for outgoing
271 : * buffers, so we assume that.
272 : */
273 : return bt_buf_type_from_h4(net_buf_pull_u8(buf), BT_BUF_OUT);
274 : }
275 :
276 : /**
277 : * @}
278 : */
279 :
280 : #ifdef __cplusplus
281 : }
282 : #endif
283 :
284 : #endif /* ZEPHYR_INCLUDE_BLUETOOTH_BUF_H_ */
|