From cc190488ee34571c1d53fc748d4b4cc0ab71123c Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 21 Jan 2016 12:05:08 +0200 Subject: [PATCH] Bluetooth: nble: Add basic RPC transmit code Refactored Johan Hedberg's code adding initial transmit logic. Change-Id: I44b0166c281d526fbd12b895b5777486c7392260 Signed-off-by: Andrei Emeltchenko --- drivers/nble/uart.c | 93 ++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/drivers/nble/uart.c b/drivers/nble/uart.c index 47c98d3aedd..c4a19721fce 100644 --- a/drivers/nble/uart.c +++ b/drivers/nble/uart.c @@ -36,6 +36,8 @@ static struct nano_fifo rx; static NET_BUF_POOL(rx_pool, NBLE_IPC_COUNT, NBLE_BUF_SIZE, &rx, NULL, 0); +static struct nano_fifo tx; +static NET_BUF_POOL(tx_pool, NBLE_IPC_COUNT, NBLE_BUF_SIZE, &tx, NULL, 0); enum { STATUS_TX_IDLE = 0, @@ -85,6 +87,56 @@ static struct ipc_uart ipc; static struct device *nble_dev; +uint8_t *rpc_alloc_cb(uint16_t length) +{ + struct net_buf *buf; + + BT_DBG("length %u", length); + + buf = net_buf_get(&tx, 0); + if (!buf) { + BT_ERR("Unable to get tx buffer"); + return NULL; + } + + if (length > net_buf_tailroom(buf)) { + BT_ERR("Too big tx buffer requested"); + net_buf_unref(buf); + return NULL; + } + + return buf->__buf; +} + +static void poll_out(const void *buf, size_t length) +{ + const uint8_t *ptr = buf; + + while (length--) { + uart_poll_out(nble_dev, *ptr++); + } +} + +void rpc_transmit_cb(uint8_t *p_buf, uint16_t length) +{ + struct net_buf *buf = CONTAINER_OF(p_buf, struct net_buf, __buf); + struct ipc_uart_header hdr; + + BT_DBG("p_buf %p length %u", p_buf, length); + + hdr.len = length; + hdr.channel = 0; + hdr.src_cpu_id = 0; + + /* Send header */ + poll_out(&hdr, sizeof(hdr)); + + /* Send data */ + poll_out(buf->data, buf->len); + + net_buf_unref(buf); +} + static void uart_frame_recv(uint16_t len, uint8_t *p_data) { BT_DBG("rcv: len: %d data len %d src %d channel %d", @@ -250,46 +302,6 @@ void ipc_uart_close_channel(int channel_id) ipc.uart_enabled = 0; } -static void uart_poll_bytes(uint8_t *buf, size_t len) -{ - while (len--) { - uart_poll_out(nble_dev, *buf++); - } -} - -int ipc_uart_ns16550_send_pdu(struct device *dev, void *handle, int len, - void *p_data) -{ - struct ipc_uart_channels *chan = (struct ipc_uart_channels *)handle; - struct ipc_uart_header hdr; - - if (ipc.tx_state == STATUS_TX_BUSY) { - return IPC_UART_TX_BUSY; - } - - /* It is eventually possible to be in DONE state - * (sending last bytes of previous message), - * so we move immediately to BUSY and configure the next frame - */ - - /* FIXME: needed? */ - ipc.tx_state = STATUS_TX_BUSY; - - /* Using polling for transmit */ - - /* Send header */ - hdr.len = len; - hdr.channel = chan->index; - hdr.src_cpu_id = 0; - - uart_poll_bytes((uint8_t *)&hdr, sizeof(hdr)); - - /* Send data */ - uart_poll_bytes(p_data, len); - - return IPC_UART_ERROR_OK; -} - void ipc_uart_ns16550_set_tx_cb(struct device *dev, void (*cb)(bool, void*), void *param) { @@ -362,6 +374,7 @@ static int _bt_nble_init(struct device *unused) } net_buf_pool_init(rx_pool); + net_buf_pool_init(tx_pool); nble_dev->driver_data = &info; ipc_uart_ns16550_init(nble_dev);