Skip to content

Commit 26d9716

Browse files
jhedbergkartben
authored andcommitted
Bluetooth: HCI: Use H:4 encoding for buffers
Encode the packet type as a H:4 payload prefix for buffers passing to & from HCI drivers. The existing bt_buf_set/get_type functions are deprecated, but kept compatible with the change, except that they can only be called once, since they modify the buffer payload. Signed-off-by: Johan Hedberg <[email protected]>
1 parent 9baa321 commit 26d9716

File tree

17 files changed

+191
-408
lines changed

17 files changed

+191
-408
lines changed

include/zephyr/bluetooth/buf.h

Lines changed: 71 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ extern "C" {
3636

3737
/** Possible types of buffers passed around the Bluetooth stack in a form of bitmask. */
3838
enum bt_buf_type {
39+
/** Invalid value, used for error checking */
40+
BT_BUF_TYPE_INVALID = 0,
3941
/** HCI command */
4042
BT_BUF_CMD = BIT(0),
4143
/** HCI event */
@@ -48,15 +50,60 @@ enum bt_buf_type {
4850
BT_BUF_ISO_OUT = BIT(4),
4951
/** Incoming ISO data */
5052
BT_BUF_ISO_IN = BIT(5),
51-
/** H:4 data */
52-
BT_BUF_H4 = BIT(6),
5353
};
5454

55-
/** @brief This is a base type for bt_buf user data. */
56-
struct bt_buf_data {
57-
uint8_t type;
55+
/** Direction of HCI packets. Only used for mapping H:4 to BT_BUF_* values. */
56+
enum bt_buf_dir {
57+
BT_BUF_IN,
58+
BT_BUF_OUT,
5859
};
5960

61+
/** Convert from bt_buf_type to H:4 type.
62+
*
63+
* @param type The bt_buf_type to convert
64+
* @return The H:4 type
65+
*/
66+
static inline uint8_t bt_buf_type_to_h4(enum bt_buf_type type)
67+
{
68+
switch (type) {
69+
case BT_BUF_CMD:
70+
return BT_HCI_H4_CMD;
71+
case BT_BUF_ACL_IN:
72+
case BT_BUF_ACL_OUT:
73+
return BT_HCI_H4_ACL;
74+
case BT_BUF_ISO_IN:
75+
case BT_BUF_ISO_OUT:
76+
return BT_HCI_H4_ISO;
77+
case BT_BUF_EVT:
78+
return BT_HCI_H4_EVT;
79+
default:
80+
__ASSERT_NO_MSG(false);
81+
return 0;
82+
}
83+
}
84+
85+
/** Convert from H:4 type to bt_buf_type.
86+
*
87+
* @param h4_type The H:4 type to convert
88+
* @param dir The direction of the packet
89+
* @return The bt_buf_type
90+
*/
91+
static inline enum bt_buf_type bt_buf_type_from_h4(uint8_t h4_type, enum bt_buf_dir dir)
92+
{
93+
switch (h4_type) {
94+
case BT_HCI_H4_CMD:
95+
return BT_BUF_CMD;
96+
case BT_HCI_H4_ACL:
97+
return dir == BT_BUF_OUT ? BT_BUF_ACL_OUT : BT_BUF_ACL_IN;
98+
case BT_HCI_H4_EVT:
99+
return BT_BUF_EVT;
100+
case BT_HCI_H4_ISO:
101+
return dir == BT_BUF_OUT ? BT_BUF_ISO_OUT : BT_BUF_ISO_IN;
102+
default:
103+
return BT_BUF_TYPE_INVALID;
104+
}
105+
}
106+
60107
/* Headroom reserved in buffers, primarily for HCI transport encoding purposes */
61108
#define BT_BUF_RESERVE 1
62109

@@ -138,8 +185,7 @@ BUILD_ASSERT(CONFIG_BT_BUF_EVT_RX_COUNT > CONFIG_BT_BUF_ACL_TX_COUNT,
138185

139186
/** Allocate a buffer for incoming data
140187
*
141-
* This will set the buffer type so bt_buf_set_type() does not need to
142-
* be explicitly called.
188+
* This will set the buffer type so it doesn't need to be explicitly encoded into the buffer.
143189
*
144190
* @param type Type of buffer. Only BT_BUF_EVT, BT_BUF_ACL_IN and BT_BUF_ISO_IN
145191
* are allowed.
@@ -172,14 +218,12 @@ void bt_buf_rx_freed_cb_set(bt_buf_rx_freed_cb_t cb);
172218

173219
/** Allocate a buffer for outgoing data
174220
*
175-
* This will set the buffer type so bt_buf_set_type() does not need to
176-
* be explicitly called.
221+
* This will set the buffer type so it doesn't need to be explicitly encoded into the buffer.
177222
*
178-
* @param type Type of buffer. Only BT_BUF_CMD, BT_BUF_ACL_OUT or
179-
* BT_BUF_H4, when operating on H:4 mode, are allowed.
223+
* @param type Type of buffer. BT_BUF_CMD or BT_BUF_ACL_OUT.
180224
* @param timeout Non-negative waiting period to obtain a buffer or one of the
181225
* special values K_NO_WAIT and K_FOREVER.
182-
* @param data Initial data to append to buffer.
226+
* @param data Initial data to append to buffer. This is optional and can be NULL.
183227
* @param size Initial data size.
184228
* @return A new buffer.
185229
*/
@@ -188,8 +232,7 @@ struct net_buf *bt_buf_get_tx(enum bt_buf_type type, k_timeout_t timeout,
188232

189233
/** Allocate a buffer for an HCI Event
190234
*
191-
* This will set the buffer type so bt_buf_set_type() does not need to
192-
* be explicitly called.
235+
* This will set the buffer type so it doesn't need to be explicitly encoded into the buffer.
193236
*
194237
* @param evt HCI event code
195238
* @param discardable Whether the driver considers the event discardable.
@@ -199,26 +242,33 @@ struct net_buf *bt_buf_get_tx(enum bt_buf_type type, k_timeout_t timeout,
199242
*/
200243
struct net_buf *bt_buf_get_evt(uint8_t evt, bool discardable, k_timeout_t timeout);
201244

202-
/** Set the buffer type
245+
/** Set the buffer type. The type is encoded as an H:4 byte prefix as part of
246+
* the payload itself.
203247
*
204248
* @param buf Bluetooth buffer
205249
* @param type The BT_* type to set the buffer to
206250
*/
207-
static inline void bt_buf_set_type(struct net_buf *buf, enum bt_buf_type type)
251+
static inline void __deprecated bt_buf_set_type(struct net_buf *buf, enum bt_buf_type type)
208252
{
209-
((struct bt_buf_data *)net_buf_user_data(buf))->type = type;
253+
__ASSERT_NO_MSG(net_buf_headroom(buf) >= 1);
254+
net_buf_push_u8(buf, bt_buf_type_to_h4(type));
210255
}
211256

212-
/** Get the buffer type
257+
258+
/** Get the buffer type. This pulls the H:4 byte prefix from the payload, which means
259+
* that the call can be done only once per buffer.
213260
*
214261
* @param buf Bluetooth buffer
215262
*
216263
* @return The BT_* type to of the buffer
217264
*/
218-
static inline enum bt_buf_type bt_buf_get_type(struct net_buf *buf)
265+
static inline enum bt_buf_type __deprecated bt_buf_get_type(struct net_buf *buf)
219266
{
220-
return (enum bt_buf_type)((struct bt_buf_data *)net_buf_user_data(buf))
221-
->type;
267+
/* We have to assume the direction since the H:4 type doesn't tell us
268+
* if the buffer is incoming or outgoing. The common use case of this API is for outgoing
269+
* buffers, so we assume that.
270+
*/
271+
return bt_buf_type_from_h4(net_buf_pull_u8(buf), BT_BUF_OUT);
222272
}
223273

224274
/**

include/zephyr/bluetooth/hci_raw.h

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -38,87 +38,6 @@ extern "C" {
3838
*/
3939
int bt_send(struct net_buf *buf);
4040

41-
enum {
42-
/** Passthrough mode
43-
*
44-
* While in this mode the buffers are passed as is between the stack
45-
* and the driver.
46-
*/
47-
BT_HCI_RAW_MODE_PASSTHROUGH = 0x00,
48-
49-
/** H:4 mode
50-
*
51-
* While in this mode H:4 headers will added into the buffers
52-
* according to the buffer type when coming from the stack and will be
53-
* removed and used to set the buffer type.
54-
*/
55-
BT_HCI_RAW_MODE_H4 = 0x01,
56-
};
57-
58-
/** @brief Set Bluetooth RAW channel mode
59-
*
60-
* Set access mode of Bluetooth RAW channel.
61-
*
62-
* @param mode Access mode.
63-
*
64-
* @return Zero on success or (negative) error code otherwise.
65-
*/
66-
int bt_hci_raw_set_mode(uint8_t mode);
67-
68-
/** @brief Get Bluetooth RAW channel mode
69-
*
70-
* Get access mode of Bluetooth RAW channel.
71-
*
72-
* @return Access mode.
73-
*/
74-
uint8_t bt_hci_raw_get_mode(void);
75-
76-
#define BT_HCI_ERR_EXT_HANDLED 0xff
77-
78-
/** Helper macro to define a command extension
79-
*
80-
* @param _op Opcode of the command.
81-
* @param _min_len Minimal length of the command.
82-
* @param _func Handler function to be called.
83-
*/
84-
#define BT_HCI_RAW_CMD_EXT(_op, _min_len, _func) \
85-
{ \
86-
.op = _op, \
87-
.min_len = _min_len, \
88-
.func = _func, \
89-
}
90-
91-
struct bt_hci_raw_cmd_ext {
92-
/** Opcode of the command */
93-
uint16_t op;
94-
95-
/** Minimal length of the command */
96-
size_t min_len;
97-
98-
/** Handler function.
99-
*
100-
* Handler function to be called when a command is intercepted.
101-
*
102-
* @param buf Buffer containing the command.
103-
*
104-
* @return HCI Status code or BT_HCI_ERR_EXT_HANDLED if command has
105-
* been handled already and a response has been sent as oppose to
106-
* BT_HCI_ERR_SUCCESS which just indicates that the command can be
107-
* sent to the controller to be processed.
108-
*/
109-
uint8_t (*func)(struct net_buf *buf);
110-
};
111-
112-
/** @brief Register Bluetooth RAW command extension table
113-
*
114-
* Register Bluetooth RAW channel command extension table, opcodes in this
115-
* table are intercepted to sent to the handler function.
116-
*
117-
* @param cmds Pointer to the command extension table.
118-
* @param size Size of the command extension table.
119-
*/
120-
void bt_hci_raw_cmd_ext_register(struct bt_hci_raw_cmd_ext *cmds, size_t size);
121-
12241
/** @brief Enable Bluetooth RAW channel:
12342
*
12443
* Enable Bluetooth RAW HCI channel.

include/zephyr/drivers/bluetooth.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,8 @@ __subsystem struct bt_hci_driver_api {
114114
*
115115
* @param dev HCI device
116116
* @param recv This is callback through which the HCI driver provides the
117-
* host with data from the controller. The buffer passed to
118-
* the callback will have its type set with bt_buf_set_type().
119-
* The callback is expected to be called from thread context.
117+
* host with data from the controller. The callback is expected
118+
* to be called from thread context.
120119
*
121120
* @return 0 on success or negative POSIX error number on failure.
122121
*/
@@ -151,8 +150,10 @@ static inline int bt_hci_close(const struct device *dev)
151150
/**
152151
* @brief Send HCI buffer to controller.
153152
*
154-
* Send an HCI packet to the controller. The packet type of the buffer
155-
* must be set using bt_buf_set_type().
153+
* Send an HCI packet to the controller. The packet type is encoded as H:4,
154+
* i.e. the UART transport encoding, as a prefix to the actual payload. This means
155+
* that HCI drivers that use H:4 as their native encoding don't need to do any
156+
* special handling of the packet type.
156157
*
157158
* @note This function must only be called from a cooperative thread.
158159
*

samples/bluetooth/hci_ipc/src/main.c

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -225,30 +225,10 @@ static void tx_thread(void *p1, void *p2, void *p3)
225225

226226
static void hci_ipc_send(struct net_buf *buf, bool is_fatal_err)
227227
{
228-
uint8_t pkt_indicator;
229228
uint8_t retries = 0;
230229
int ret;
231230

232-
LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len);
233-
234-
LOG_HEXDUMP_DBG(buf->data, buf->len, "Controller buffer:");
235-
236-
switch (bt_buf_get_type(buf)) {
237-
case BT_BUF_ACL_IN:
238-
pkt_indicator = HCI_IPC_ACL;
239-
break;
240-
case BT_BUF_EVT:
241-
pkt_indicator = HCI_IPC_EVT;
242-
break;
243-
case BT_BUF_ISO_IN:
244-
pkt_indicator = HCI_IPC_ISO;
245-
break;
246-
default:
247-
LOG_ERR("Unknown type %u", bt_buf_get_type(buf));
248-
net_buf_unref(buf);
249-
return;
250-
}
251-
net_buf_push_u8(buf, pkt_indicator);
231+
LOG_DBG("buf %p type %u len %u", buf, buf->data[0], buf->len);
252232

253233
LOG_HEXDUMP_DBG(buf->data, buf->len, "Final HCI buffer:");
254234

samples/bluetooth/hci_spi/src/main.c

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -107,20 +107,7 @@ static inline int spi_send(struct net_buf *buf)
107107
0x00, 0x00, 0x00 };
108108
int ret;
109109

110-
LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len);
111-
112-
switch (bt_buf_get_type(buf)) {
113-
case BT_BUF_ACL_IN:
114-
net_buf_push_u8(buf, HCI_ACL);
115-
break;
116-
case BT_BUF_EVT:
117-
net_buf_push_u8(buf, HCI_EVT);
118-
break;
119-
default:
120-
LOG_ERR("Unknown type %u", bt_buf_get_type(buf));
121-
net_buf_unref(buf);
122-
return -EINVAL;
123-
}
110+
LOG_DBG("buf %p type %u len %u", buf, buf->data[0], buf->len);
124111

125112
if (buf->len > SPI_MAX_MSG_LEN) {
126113
LOG_ERR("TX message too long");
@@ -245,8 +232,7 @@ static void bt_tx_thread(void *p1, void *p2, void *p3)
245232
continue;
246233
}
247234

248-
LOG_DBG("buf %p type %u len %u",
249-
buf, bt_buf_get_type(buf), buf->len);
235+
LOG_DBG("buf %p type %u len %u", buf, buf->data[0], buf->len);
250236

251237
ret = bt_send(buf);
252238
if (ret) {

samples/bluetooth/hci_uart/src/main.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@ static void rx_isr(void)
150150
* interrupt. On failed allocation state machine
151151
* is reset.
152152
*/
153-
buf = bt_buf_get_tx(BT_BUF_H4, K_NO_WAIT,
154-
&type, sizeof(type));
153+
buf = bt_buf_get_tx(bt_buf_type_from_h4(type, BT_BUF_OUT),
154+
K_NO_WAIT, NULL, 0);
155155
if (!buf) {
156156
LOG_ERR("No available command buffers!");
157157
state = ST_IDLE;
@@ -272,8 +272,7 @@ static void tx_thread(void *p1, void *p2, void *p3)
272272

273273
static int h4_send(struct net_buf *buf)
274274
{
275-
LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf),
276-
buf->len);
275+
LOG_DBG("buf %p type %u len %u", buf, buf->data[0], buf->len);
277276

278277
k_fifo_put(&uart_tx_queue, buf);
279278
uart_irq_tx_enable(hci_uart_dev);

samples/bluetooth/hci_uart_3wire/src/main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,8 +479,8 @@ static void bt_uart_isr(const struct device *unused, void *user_data)
479479
case HCI_COMMAND_PKT:
480480
case HCI_ACLDATA_PKT:
481481
case HCI_ISODATA_PKT:
482-
h5.rx_buf = bt_buf_get_tx(BT_BUF_H4, K_NO_WAIT,
483-
&type, sizeof(type));
482+
h5.rx_buf = bt_buf_get_tx(bt_buf_type_from_h4(type, BT_BUF_OUT),
483+
K_NO_WAIT, NULL, 0);
484484
if (!h5.rx_buf) {
485485
LOG_WRN("No available data buffers");
486486
h5_reset_rx();
@@ -565,7 +565,7 @@ static void bt_uart_isr(const struct device *unused, void *user_data)
565565

566566
static int h5_queue(struct net_buf *buf)
567567
{
568-
LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len);
568+
LOG_DBG("buf %p type %u len %u", buf, buf->data[0], buf->len);
569569

570570
k_fifo_put(&h5.tx_queue, buf);
571571

samples/bluetooth/hci_uart_async/src/hci_uart_async.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ static void send_hw_error(void)
150150

151151
struct net_buf *buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
152152

153-
net_buf_add_u8(buf, BT_HCI_H4_EVT);
154153
net_buf_add_mem(buf, hci_evt_hw_err, sizeof(hci_evt_hw_err));
155154

156155
/* Inject the message into the c2h queue. */
@@ -181,7 +180,8 @@ static void recover_sync_by_reset_pattern(void)
181180
}
182181

183182
LOG_DBG("Pattern found");
184-
h2c_cmd_reset = bt_buf_get_tx(BT_BUF_H4, K_FOREVER, h4_cmd_reset, sizeof(h4_cmd_reset));
183+
h2c_cmd_reset = bt_buf_get_tx(BT_BUF_CMD, K_FOREVER,
184+
&h4_cmd_reset[1], sizeof(h4_cmd_reset) - 1);
185185
LOG_DBG("Fowarding reset");
186186

187187
err = bt_send(h2c_cmd_reset);
@@ -219,7 +219,7 @@ static void h2c_h4_transport(void)
219219
LOG_DBG("h2c: h4_type %d", h4_type);
220220

221221
/* Allocate buf. */
222-
buf = bt_buf_get_tx(BT_BUF_H4, K_FOREVER, &h4_type, sizeof(h4_type));
222+
buf = bt_buf_get_tx(bt_buf_type_from_h4(h4_type, BT_BUF_OUT), K_FOREVER, NULL, 0);
223223
LOG_DBG("h2c: buf %p", buf);
224224

225225
if (!buf) {

0 commit comments

Comments
 (0)