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