Lines Matching +full:uart +full:- +full:dev

1 /* h4.c - H:4 UART based Bluetooth driver */
4 * Copyright (c) 2015-2016 Intel Corporation
6 * SPDX-License-Identifier: Apache-2.0
16 #include <zephyr/drivers/uart.h>
67 const struct device *uart; member
73 static inline void h4_get_type(const struct device *dev) in h4_get_type() argument
75 const struct h4_config *cfg = dev->config; in h4_get_type()
76 struct h4_data *h4 = dev->data; in h4_get_type()
79 if (uart_fifo_read(cfg->uart, &h4->rx.type, 1) != 1) { in h4_get_type()
81 h4->rx.type = BT_HCI_H4_NONE; in h4_get_type()
85 switch (h4->rx.type) { in h4_get_type()
87 h4->rx.remaining = sizeof(h4->rx.evt); in h4_get_type()
88 h4->rx.hdr_len = h4->rx.remaining; in h4_get_type()
91 h4->rx.remaining = sizeof(h4->rx.acl); in h4_get_type()
92 h4->rx.hdr_len = h4->rx.remaining; in h4_get_type()
96 h4->rx.remaining = sizeof(h4->rx.iso); in h4_get_type()
97 h4->rx.hdr_len = h4->rx.remaining; in h4_get_type()
102 LOG_ERR("Unknown H:4 type 0x%02x", h4->rx.type); in h4_get_type()
103 h4->rx.type = BT_HCI_H4_NONE; in h4_get_type()
107 static void h4_read_hdr(const struct device *dev) in h4_read_hdr() argument
109 const struct h4_config *cfg = dev->config; in h4_read_hdr()
110 struct h4_data *h4 = dev->data; in h4_read_hdr()
111 int bytes_read = h4->rx.hdr_len - h4->rx.remaining; in h4_read_hdr()
114 ret = uart_fifo_read(cfg->uart, h4->rx.hdr + bytes_read, h4->rx.remaining); in h4_read_hdr()
116 LOG_ERR("Unable to read from UART (ret %d)", ret); in h4_read_hdr()
118 h4->rx.remaining -= ret; in h4_read_hdr()
122 static inline void get_acl_hdr(const struct device *dev) in get_acl_hdr() argument
124 struct h4_data *h4 = dev->data; in get_acl_hdr()
126 h4_read_hdr(dev); in get_acl_hdr()
128 if (!h4->rx.remaining) { in get_acl_hdr()
129 struct bt_hci_acl_hdr *hdr = &h4->rx.acl; in get_acl_hdr()
131 h4->rx.remaining = sys_le16_to_cpu(hdr->len); in get_acl_hdr()
132 LOG_DBG("Got ACL header. Payload %u bytes", h4->rx.remaining); in get_acl_hdr()
133 h4->rx.have_hdr = true; in get_acl_hdr()
137 static inline void get_iso_hdr(const struct device *dev) in get_iso_hdr() argument
139 struct h4_data *h4 = dev->data; in get_iso_hdr()
141 h4_read_hdr(dev); in get_iso_hdr()
143 if (!h4->rx.remaining) { in get_iso_hdr()
144 struct bt_hci_iso_hdr *hdr = &h4->rx.iso; in get_iso_hdr()
146 h4->rx.remaining = bt_iso_hdr_len(sys_le16_to_cpu(hdr->len)); in get_iso_hdr()
147 LOG_DBG("Got ISO header. Payload %u bytes", h4->rx.remaining); in get_iso_hdr()
148 h4->rx.have_hdr = true; in get_iso_hdr()
152 static inline void get_evt_hdr(const struct device *dev) in get_evt_hdr() argument
154 struct h4_data *h4 = dev->data; in get_evt_hdr()
156 struct bt_hci_evt_hdr *hdr = &h4->rx.evt; in get_evt_hdr()
158 h4_read_hdr(dev); in get_evt_hdr()
160 if (h4->rx.hdr_len == sizeof(*hdr) && h4->rx.remaining < sizeof(*hdr)) { in get_evt_hdr()
161 switch (h4->rx.evt.evt) { in get_evt_hdr()
163 h4->rx.remaining++; in get_evt_hdr()
164 h4->rx.hdr_len++; in get_evt_hdr()
169 h4->rx.discardable = true; in get_evt_hdr()
175 if (!h4->rx.remaining) { in get_evt_hdr()
176 if (h4->rx.evt.evt == BT_HCI_EVT_LE_META_EVENT && in get_evt_hdr()
177 (h4->rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_ADVERTISING_REPORT)) { in get_evt_hdr()
179 h4->rx.discardable = true; in get_evt_hdr()
182 h4->rx.remaining = hdr->len - (h4->rx.hdr_len - sizeof(*hdr)); in get_evt_hdr()
183 LOG_DBG("Got event header. Payload %u bytes", hdr->len); in get_evt_hdr()
184 h4->rx.have_hdr = true; in get_evt_hdr()
191 net_buf_add_mem(h4->rx.buf, h4->rx.hdr, h4->rx.hdr_len); in copy_hdr()
196 h4->rx.type = BT_HCI_H4_NONE; in reset_rx()
197 h4->rx.remaining = 0U; in reset_rx()
198 h4->rx.have_hdr = false; in reset_rx()
199 h4->rx.hdr_len = 0U; in reset_rx()
200 h4->rx.discardable = false; in reset_rx()
205 LOG_DBG("type 0x%02x, evt 0x%02x", h4->rx.type, h4->rx.evt.evt); in get_rx()
207 switch (h4->rx.type) { in get_rx()
209 return bt_buf_get_evt(h4->rx.evt.evt, h4->rx.discardable, timeout); in get_rx()
223 const struct device *dev = p1; in rx_thread() local
224 const struct h4_config *cfg = dev->config; in rx_thread()
225 struct h4_data *h4 = dev->data; in rx_thread()
234 LOG_DBG("rx.buf %p", h4->rx.buf); in rx_thread()
240 if (h4->rx.have_hdr && !h4->rx.buf) { in rx_thread()
241 h4->rx.buf = get_rx(h4, K_FOREVER); in rx_thread()
242 LOG_DBG("Got rx.buf %p", h4->rx.buf); in rx_thread()
243 if (h4->rx.remaining > net_buf_tailroom(h4->rx.buf)) { in rx_thread()
245 h4->rx.discard = h4->rx.remaining; in rx_thread()
253 uart_irq_rx_enable(cfg->uart); in rx_thread()
255 buf = k_fifo_get(&h4->rx.fifo, K_FOREVER); in rx_thread()
257 uart_irq_rx_enable(cfg->uart); in rx_thread()
260 h4->recv(dev, buf); in rx_thread()
268 uart_irq_rx_disable(cfg->uart); in rx_thread()
269 buf = k_fifo_get(&h4->rx.fifo, K_NO_WAIT); in rx_thread()
274 static size_t h4_discard(const struct device *uart, size_t len) in h4_discard() argument
279 err = uart_fifo_read(uart, buf, MIN(len, sizeof(buf))); in h4_discard()
281 LOG_ERR("Unable to read from UART (err %d)", err); in h4_discard()
288 static inline void read_payload(const struct device *dev) in read_payload() argument
290 const struct h4_config *cfg = dev->config; in read_payload()
291 struct h4_data *h4 = dev->data; in read_payload()
295 if (!h4->rx.buf) { in read_payload()
298 h4->rx.buf = get_rx(h4, K_NO_WAIT); in read_payload()
299 if (!h4->rx.buf) { in read_payload()
300 if (h4->rx.discardable) { in read_payload()
301 LOG_WRN("Discarding event 0x%02x", h4->rx.evt.evt); in read_payload()
302 h4->rx.discard = h4->rx.remaining; in read_payload()
308 uart_irq_rx_disable(cfg->uart); in read_payload()
312 LOG_DBG("Allocated rx.buf %p", h4->rx.buf); in read_payload()
314 buf_tailroom = net_buf_tailroom(h4->rx.buf); in read_payload()
315 if (buf_tailroom < h4->rx.remaining) { in read_payload()
316 LOG_ERR("Not enough space in buffer %u/%zu", h4->rx.remaining, in read_payload()
318 h4->rx.discard = h4->rx.remaining; in read_payload()
326 read = uart_fifo_read(cfg->uart, net_buf_tail(h4->rx.buf), h4->rx.remaining); in read_payload()
328 LOG_ERR("Failed to read UART (err %d)", read); in read_payload()
332 net_buf_add(h4->rx.buf, read); in read_payload()
333 h4->rx.remaining -= read; in read_payload()
335 LOG_DBG("got %d bytes, remaining %u", read, h4->rx.remaining); in read_payload()
336 LOG_DBG("Payload (len %u): %s", h4->rx.buf->len, in read_payload()
337 bt_hex(h4->rx.buf->data, h4->rx.buf->len)); in read_payload()
339 if (h4->rx.remaining) { in read_payload()
343 buf = h4->rx.buf; in read_payload()
344 h4->rx.buf = NULL; in read_payload()
346 if (h4->rx.type == BT_HCI_H4_EVT) { in read_payload()
355 k_fifo_put(&h4->rx.fifo, buf); in read_payload()
358 static inline void read_header(const struct device *dev) in read_header() argument
360 struct h4_data *h4 = dev->data; in read_header()
362 switch (h4->rx.type) { in read_header()
364 h4_get_type(dev); in read_header()
367 get_evt_hdr(dev); in read_header()
370 get_acl_hdr(dev); in read_header()
374 get_iso_hdr(dev); in read_header()
383 if (h4->rx.have_hdr && h4->rx.buf) { in read_header()
384 if (h4->rx.remaining > net_buf_tailroom(h4->rx.buf)) { in read_header()
386 h4->rx.discard = h4->rx.remaining; in read_header()
394 static inline void process_tx(const struct device *dev) in process_tx() argument
396 const struct h4_config *cfg = dev->config; in process_tx()
397 struct h4_data *h4 = dev->data; in process_tx()
400 if (!h4->tx.buf) { in process_tx()
401 h4->tx.buf = k_fifo_get(&h4->tx.fifo, K_NO_WAIT); in process_tx()
402 if (!h4->tx.buf) { in process_tx()
404 uart_irq_tx_disable(cfg->uart); in process_tx()
409 if (!h4->tx.type) { in process_tx()
410 switch (bt_buf_get_type(h4->tx.buf)) { in process_tx()
412 h4->tx.type = BT_HCI_H4_ACL; in process_tx()
415 h4->tx.type = BT_HCI_H4_CMD; in process_tx()
419 h4->tx.type = BT_HCI_H4_ISO; in process_tx()
428 bytes = uart_fifo_fill(cfg->uart, &h4->tx.type, 1); in process_tx()
431 h4->tx.type = BT_HCI_H4_NONE; in process_tx()
436 bytes = uart_fifo_fill(cfg->uart, h4->tx.buf->data, h4->tx.buf->len); in process_tx()
438 LOG_ERR("Unable to write to UART (err %d)", bytes); in process_tx()
440 net_buf_pull(h4->tx.buf, bytes); in process_tx()
443 if (h4->tx.buf->len) { in process_tx()
448 h4->tx.type = BT_HCI_H4_NONE; in process_tx()
449 net_buf_unref(h4->tx.buf); in process_tx()
450 h4->tx.buf = k_fifo_get(&h4->tx.fifo, K_NO_WAIT); in process_tx()
451 if (!h4->tx.buf) { in process_tx()
452 uart_irq_tx_disable(cfg->uart); in process_tx()
456 static inline void process_rx(const struct device *dev) in process_rx() argument
458 const struct h4_config *cfg = dev->config; in process_rx()
459 struct h4_data *h4 = dev->data; in process_rx()
462 h4->rx.remaining, h4->rx.discard, h4->rx.have_hdr, h4->rx.buf, in process_rx()
463 h4->rx.buf ? h4->rx.buf->len : 0); in process_rx()
465 if (h4->rx.discard) { in process_rx()
466 h4->rx.discard -= h4_discard(cfg->uart, h4->rx.discard); in process_rx()
470 if (h4->rx.have_hdr) { in process_rx()
471 read_payload(dev); in process_rx()
473 read_header(dev); in process_rx()
477 static void bt_uart_isr(const struct device *uart, void *user_data) in bt_uart_isr() argument
479 struct device *dev = user_data; in bt_uart_isr() local
481 while (uart_irq_update(uart) && uart_irq_is_pending(uart)) { in bt_uart_isr()
482 if (uart_irq_tx_ready(uart)) { in bt_uart_isr()
483 process_tx(dev); in bt_uart_isr()
486 if (uart_irq_rx_ready(uart)) { in bt_uart_isr()
487 process_rx(dev); in bt_uart_isr()
492 static int h4_send(const struct device *dev, struct net_buf *buf) in h4_send() argument
494 const struct h4_config *cfg = dev->config; in h4_send()
495 struct h4_data *h4 = dev->data; in h4_send()
497 LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); in h4_send()
499 k_fifo_put(&h4->tx.fifo, buf); in h4_send()
500 uart_irq_tx_enable(cfg->uart); in h4_send()
507 * @param dev The device structure for the bus connecting to the IC
511 int __weak bt_hci_transport_setup(const struct device *uart) in bt_hci_transport_setup() argument
513 h4_discard(uart, 32); in bt_hci_transport_setup()
517 static int h4_open(const struct device *dev, bt_hci_recv_t recv) in h4_open() argument
519 const struct h4_config *cfg = dev->config; in h4_open()
520 struct h4_data *h4 = dev->data; in h4_open()
526 uart_irq_rx_disable(cfg->uart); in h4_open()
527 uart_irq_tx_disable(cfg->uart); in h4_open()
529 ret = bt_hci_transport_setup(cfg->uart); in h4_open()
531 return -EIO; in h4_open()
534 h4->recv = recv; in h4_open()
536 uart_irq_callback_user_data_set(cfg->uart, bt_uart_isr, (void *)dev); in h4_open()
538 tid = k_thread_create(cfg->rx_thread, cfg->rx_thread_stack, in h4_open()
539 cfg->rx_thread_stack_size, in h4_open()
540 rx_thread, (void *)dev, NULL, NULL, in h4_open()
549 static int h4_setup(const struct device *dev, const struct bt_hci_setup_params *params) in h4_setup() argument
551 const struct h4_config *cfg = dev->config; in h4_setup()
556 * This function executes vendor-specific commands sequence to in h4_setup()
558 * bt_h4_vnd_setup function must be implemented in vendor-specific HCI in h4_setup()
561 extern int bt_h4_vnd_setup(const struct device *dev); in h4_setup()
563 return bt_h4_vnd_setup(cfg->uart); in h4_setup()
579 .uart = DEVICE_DT_GET(DT_INST_PARENT(inst)), \