1 /* Copyright (c) 2023 Nordic Semiconductor ASA
2 * SPDX-License-Identifier: Apache-2.0
3 */
4
5 #include <zephyr/kernel.h>
6 #include <zephyr/sys/__assert.h>
7 #include <zephyr/sys/time_units.h>
8 #include <zephyr/toolchain/common.h>
9 #include <errno.h>
10 #include <stddef.h>
11 #include <string.h>
12
13 #include <zephyr/kernel.h>
14 #include <zephyr/arch/cpu.h>
15 #include <zephyr/sys/byteorder.h>
16 #include <zephyr/logging/log.h>
17 #include <zephyr/sys/util.h>
18
19 #include <zephyr/device.h>
20 #include <zephyr/init.h>
21 #include <zephyr/drivers/uart.h>
22
23 #include <zephyr/usb/usb_device.h>
24
25 #include <zephyr/net_buf.h>
26 #include <zephyr/bluetooth/bluetooth.h>
27 #include <zephyr/bluetooth/l2cap.h>
28 #include <zephyr/bluetooth/hci.h>
29 #include <zephyr/bluetooth/buf.h>
30 #include <zephyr/bluetooth/hci_raw.h>
31
32 LOG_MODULE_REGISTER(hci_uart_async, LOG_LEVEL_DBG);
33
34 static const struct device *const hci_uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_c2h_uart));
35
36 static K_THREAD_STACK_DEFINE(h2c_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE);
37 static struct k_thread h2c_thread;
38
39 struct k_poll_signal uart_h2c_rx_sig;
40 struct k_poll_signal uart_c2h_tx_sig;
41
42 static K_FIFO_DEFINE(c2h_queue);
43
44 /** Send raw data on c2h UART.
45 *
46 * Blocks until completion. Not thread-safe.
47 *
48 * @retval 0 on success
49 * @retval -EBUSY Another transmission is in progress. This a
50 * thread-safety violation.
51 * @retval -errno @ref uart_tx error.
52 */
uart_c2h_tx(const uint8_t * data,size_t size)53 static int uart_c2h_tx(const uint8_t *data, size_t size)
54 {
55 int err;
56 struct k_poll_signal *sig = &uart_c2h_tx_sig;
57 struct k_poll_event done[] = {
58 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, sig),
59 };
60
61 k_poll_signal_reset(sig);
62 err = uart_tx(hci_uart_dev, data, size, SYS_FOREVER_US);
63
64 if (err) {
65 LOG_ERR("uart c2h tx: err %d", err);
66 return err;
67 }
68
69 err = k_poll(done, ARRAY_SIZE(done), K_FOREVER);
70 __ASSERT_NO_MSG(err == 0);
71
72 return 0;
73 }
74
75 /* Function expects that type is validated and only CMD, ISO or ACL will be used. */
hci_payload_size(const uint8_t * hdr_buf,uint8_t h4_type)76 static uint32_t hci_payload_size(const uint8_t *hdr_buf, uint8_t h4_type)
77 {
78 switch (h4_type) {
79 case BT_HCI_H4_CMD:
80 return ((const struct bt_hci_cmd_hdr *)hdr_buf)->param_len;
81 case BT_HCI_H4_ACL:
82 return sys_le16_to_cpu(((const struct bt_hci_acl_hdr *)hdr_buf)->len);
83 case BT_HCI_H4_ISO:
84 return bt_iso_hdr_len(
85 sys_le16_to_cpu(((const struct bt_hci_iso_hdr *)hdr_buf)->len));
86 default:
87 LOG_ERR("Invalid type: %u", h4_type);
88 return 0;
89 }
90 }
91
hci_hdr_size(uint8_t h4_type)92 static uint8_t hci_hdr_size(uint8_t h4_type)
93 {
94 switch (h4_type) {
95 case BT_HCI_H4_CMD:
96 return sizeof(struct bt_hci_cmd_hdr);
97 case BT_HCI_H4_ACL:
98 return sizeof(struct bt_hci_acl_hdr);
99 case BT_HCI_H4_ISO:
100 return sizeof(struct bt_hci_iso_hdr);
101 default:
102 LOG_ERR("Unexpected h4 type: %u", h4_type);
103 return 0;
104 }
105 }
106
107 /** Send raw data on c2h UART.
108 *
109 * Blocks until either @p size has been received or special UART
110 * condition occurs on the UART RX line, like an UART break or parity
111 * error.
112 *
113 * Not thread-safe.
114 *
115 * @retval 0 on success
116 * @retval -EBUSY Another transmission is in progress. This a
117 * thread-safety violation.
118 * @retval -errno @ref uart_rx_enable error.
119 * @retval +stop_reason Special condition @ref uart_rx_stop_reason.
120 */
uart_h2c_rx(uint8_t * dst,size_t size)121 static int uart_h2c_rx(uint8_t *dst, size_t size)
122 {
123 int err;
124 struct k_poll_signal *sig = &uart_h2c_rx_sig;
125 struct k_poll_event done[] = {
126 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, sig),
127 };
128
129 k_poll_signal_reset(sig);
130 err = uart_rx_enable(hci_uart_dev, dst, size, SYS_FOREVER_US);
131
132 if (err) {
133 LOG_ERR("uart h2c rx: err %d", err);
134 return err;
135 }
136
137 k_poll(done, ARRAY_SIZE(done), K_FOREVER);
138 return sig->result;
139 }
140
141 /** Inject a HCI EVT Hardware error into the c2h packet stream.
142 *
143 * This uses `bt_recv`, just as if the controller is sending the error.
144 */
send_hw_error(void)145 static void send_hw_error(void)
146 {
147 const uint8_t err_code = 0;
148 const uint8_t hci_evt_hw_err[] = {BT_HCI_EVT_HARDWARE_ERROR,
149 sizeof(struct bt_hci_evt_hardware_error), err_code};
150
151 struct net_buf *buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
152
153 net_buf_add_u8(buf, BT_HCI_H4_EVT);
154 net_buf_add_mem(buf, hci_evt_hw_err, sizeof(hci_evt_hw_err));
155
156 /* Inject the message into the c2h queue. */
157 k_fifo_put(&c2h_queue, buf);
158
159 /* The c2h thread will send the message at some point. The host
160 * will receive it and reset the controller.
161 */
162 }
163
recover_sync_by_reset_pattern(void)164 static void recover_sync_by_reset_pattern(void)
165 {
166 /* { BT_HCI_H4_CMD, le_16(HCI_CMD_OP_RESET), len=0 } */
167 const uint8_t h4_cmd_reset[] = {0x01, 0x03, 0x0C, 0x00};
168 const uint32_t reset_pattern = sys_get_be32(h4_cmd_reset);
169 int err;
170 struct net_buf *h2c_cmd_reset;
171 uint32_t shift_register = 0;
172
173 LOG_DBG("Looking for reset pattern");
174
175 while (shift_register != reset_pattern) {
176 uint8_t read_byte;
177
178 uart_h2c_rx(&read_byte, sizeof(uint8_t));
179 LOG_DBG("h2c: 0x%02x", read_byte);
180 shift_register = (shift_register * 0x100) + read_byte;
181 }
182
183 LOG_DBG("Pattern found");
184 h2c_cmd_reset = bt_buf_get_tx(BT_BUF_H4, K_FOREVER, h4_cmd_reset, sizeof(h4_cmd_reset));
185 LOG_DBG("Fowarding reset");
186
187 err = bt_send(h2c_cmd_reset);
188 __ASSERT(!err, "Failed to send reset: %d", err);
189 }
190
h2c_h4_transport(void)191 static void h2c_h4_transport(void)
192 {
193 /* When entering this function, the h2c stream should be
194 * 'synchronized'. I.e. The stream should be at a H4 packet
195 * boundary.
196 *
197 * This function returns to signal a desynchronization.
198 * When this happens, the caller should resynchronize before
199 * entering this function again. It's up to the caller to decide
200 * how to resynchronize.
201 */
202
203 for (;;) {
204 int err;
205 struct net_buf *buf;
206 uint8_t h4_type;
207 uint8_t hdr_size;
208 uint8_t *hdr_buf;
209 uint16_t payload_size;
210
211 LOG_DBG("h2c: listening");
212
213 /* Read H4 type. */
214 err = uart_h2c_rx(&h4_type, sizeof(uint8_t));
215
216 if (err) {
217 return;
218 }
219 LOG_DBG("h2c: h4_type %d", h4_type);
220
221 /* Allocate buf. */
222 buf = bt_buf_get_tx(BT_BUF_H4, K_FOREVER, &h4_type, sizeof(h4_type));
223 LOG_DBG("h2c: buf %p", buf);
224
225 if (!buf) {
226 /* `h4_type` was invalid. */
227 __ASSERT_NO_MSG(hci_hdr_size(h4_type) == 0);
228
229 LOG_WRN("bt_buf_get_tx failed h4_type %d", h4_type);
230 return;
231 }
232
233 /* Read HCI header. */
234 hdr_size = hci_hdr_size(h4_type);
235 hdr_buf = net_buf_add(buf, hdr_size);
236
237 err = uart_h2c_rx(hdr_buf, hdr_size);
238 if (err) {
239 net_buf_unref(buf);
240 return;
241 }
242 LOG_HEXDUMP_DBG(hdr_buf, hdr_size, "h2c: hci hdr");
243
244 /* Read HCI payload. */
245 payload_size = hci_payload_size(hdr_buf, h4_type);
246
247 LOG_DBG("h2c: payload_size %u", payload_size);
248
249 if (payload_size == 0) {
250 /* Done, dont rx zero bytes */
251 } else if (payload_size <= net_buf_tailroom(buf)) {
252 uint8_t *payload_dst = net_buf_add(buf, payload_size);
253
254 err = uart_h2c_rx(payload_dst, payload_size);
255 if (err) {
256 net_buf_unref(buf);
257 return;
258 }
259 LOG_HEXDUMP_DBG(payload_dst, payload_size, "h2c: hci payload");
260 } else {
261 /* Discard oversize packet. */
262 uint8_t *discard_dst;
263 uint16_t discard_size;
264
265 LOG_WRN("h2c: Discarding oversize h4_type %d payload_size %d.", h4_type,
266 payload_size);
267
268 /* Reset `buf` so all of it is available. */
269 net_buf_reset(buf);
270 discard_dst = net_buf_tail(buf);
271 discard_size = net_buf_max_len(buf);
272
273 while (payload_size) {
274 uint16_t read_size = MIN(payload_size, discard_size);
275
276 err = uart_h2c_rx(discard_dst, read_size);
277 if (err) {
278 net_buf_unref(buf);
279 return;
280 }
281
282 payload_size -= read_size;
283 }
284
285 net_buf_unref(buf);
286 buf = NULL;
287 }
288
289 LOG_DBG("h2c: packet done");
290
291 /* Route buf to Controller. */
292 if (buf) {
293 err = bt_send(buf);
294 if (err) {
295 /* This is not a transport error. */
296 LOG_ERR("bt_send err %d", err);
297 net_buf_unref(buf);
298 buf = NULL;
299 }
300 }
301
302 k_yield();
303 }
304 }
305
h2c_thread_entry(void * p1,void * p2,void * p3)306 static void h2c_thread_entry(void *p1, void *p2, void *p3)
307 {
308 k_thread_name_set(k_current_get(), "HCI TX (h2c)");
309
310 for (;;) {
311 LOG_DBG("Synchronized");
312 h2c_h4_transport();
313 LOG_WRN("Desynchronized");
314 send_hw_error();
315 recover_sync_by_reset_pattern();
316 }
317 }
318
callback(const struct device * dev,struct uart_event * evt,void * user_data)319 void callback(const struct device *dev, struct uart_event *evt, void *user_data)
320 {
321 ARG_UNUSED(user_data);
322
323 if (evt->type == UART_RX_DISABLED) {
324 (void)k_poll_signal_raise(&uart_h2c_rx_sig, 0);
325 } else if (evt->type == UART_RX_STOPPED) {
326 (void)k_poll_signal_raise(&uart_h2c_rx_sig, evt->data.rx_stop.reason);
327 } else if (evt->type == UART_TX_DONE) {
328 (void)k_poll_signal_raise(&uart_c2h_tx_sig, 0);
329 }
330 }
331
hci_uart_init(void)332 static int hci_uart_init(void)
333 {
334 int err;
335
336 k_poll_signal_init(&uart_h2c_rx_sig);
337 k_poll_signal_init(&uart_c2h_tx_sig);
338
339 LOG_DBG("");
340
341 if (!device_is_ready(hci_uart_dev)) {
342 LOG_ERR("HCI UART %s is not ready", hci_uart_dev->name);
343 return -EINVAL;
344 }
345
346 BUILD_ASSERT(IS_ENABLED(CONFIG_UART_ASYNC_API));
347 err = uart_callback_set(hci_uart_dev, callback, NULL);
348
349 /* Note: Asserts if CONFIG_UART_ASYNC_API is not enabled for `hci_uart_dev`. */
350 __ASSERT(!err, "err %d", err);
351
352 return 0;
353 }
354
355 SYS_INIT(hci_uart_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
356
357 const struct {
358 uint8_t h4;
359 struct bt_hci_evt_hdr hdr;
360 struct bt_hci_evt_cmd_complete cc;
361 } __packed cc_evt = {
362 .h4 = BT_HCI_H4_EVT,
363 .hdr = {.evt = BT_HCI_EVT_CMD_COMPLETE, .len = sizeof(struct bt_hci_evt_cmd_complete)},
364 .cc = {.ncmd = 1, .opcode = sys_cpu_to_le16(BT_OP_NOP)},
365 };
366
c2h_thread_entry(void)367 static void c2h_thread_entry(void)
368 {
369 k_thread_name_set(k_current_get(), "HCI RX (c2h)");
370
371 if (IS_ENABLED(CONFIG_BT_WAIT_NOP)) {
372 uart_c2h_tx((char *)&cc_evt, sizeof(cc_evt));
373 }
374
375 for (;;) {
376 struct net_buf *buf;
377
378 buf = k_fifo_get(&c2h_queue, K_FOREVER);
379 uart_c2h_tx(buf->data, buf->len);
380 net_buf_unref(buf);
381 }
382 }
383
hci_uart_main(void)384 void hci_uart_main(void)
385 {
386 int err;
387
388 err = bt_enable_raw(&c2h_queue);
389 __ASSERT_NO_MSG(!err);
390
391 /* TX thread. */
392 k_thread_create(&h2c_thread, h2c_thread_stack, K_THREAD_STACK_SIZEOF(h2c_thread_stack),
393 h2c_thread_entry, NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
394
395 /* Reuse current thread as RX thread. */
396 c2h_thread_entry();
397 }
398