2018-01-18 10:01:52 +08:00
|
|
|
/*
|
|
|
|
* Copyright Runtime.io 2018. All rights reserved.
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** @file
|
|
|
|
* @brief UART transport for the mcumgr SMP protocol.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <zephyr.h>
|
|
|
|
#include <init.h>
|
|
|
|
#include "net/buf.h"
|
|
|
|
#include "console/uart_mcumgr.h"
|
|
|
|
#include "mgmt/mgmt.h"
|
|
|
|
#include <mgmt/serial.h>
|
|
|
|
#include "mgmt/buf.h"
|
|
|
|
#include "mgmt/smp.h"
|
|
|
|
|
|
|
|
struct device;
|
|
|
|
|
|
|
|
static void smp_uart_process_rx_queue(struct k_work *work);
|
|
|
|
|
|
|
|
K_FIFO_DEFINE(smp_uart_rx_fifo);
|
|
|
|
K_WORK_DEFINE(smp_uart_work, smp_uart_process_rx_queue);
|
|
|
|
|
|
|
|
static struct mcumgr_serial_rx_ctxt smp_uart_rx_ctxt;
|
|
|
|
static struct zephyr_smp_transport smp_uart_transport;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Processes a single line (fragment) coming from the mcumgr UART driver.
|
|
|
|
*/
|
|
|
|
static void smp_uart_process_frag(struct uart_mcumgr_rx_buf *rx_buf)
|
|
|
|
{
|
|
|
|
struct net_buf *nb;
|
|
|
|
|
|
|
|
/* Decode the fragment and write the result to the global receive
|
|
|
|
* context.
|
|
|
|
*/
|
|
|
|
nb = mcumgr_serial_process_frag(&smp_uart_rx_ctxt,
|
|
|
|
rx_buf->data, rx_buf->length);
|
|
|
|
|
|
|
|
/* Release the encoded fragment. */
|
|
|
|
uart_mcumgr_free_rx_buf(rx_buf);
|
|
|
|
|
|
|
|
/* If a complete packet has been received, pass it to SMP for
|
|
|
|
* processing.
|
|
|
|
*/
|
|
|
|
if (nb != NULL) {
|
|
|
|
zephyr_smp_rx_req(&smp_uart_transport, nb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void smp_uart_process_rx_queue(struct k_work *work)
|
|
|
|
{
|
|
|
|
struct uart_mcumgr_rx_buf *rx_buf;
|
|
|
|
|
|
|
|
while ((rx_buf = k_fifo_get(&smp_uart_rx_fifo, K_NO_WAIT)) != NULL) {
|
|
|
|
smp_uart_process_frag(rx_buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enqueues a received SMP fragment for later processing. This function
|
|
|
|
* executes in the interrupt context.
|
|
|
|
*/
|
|
|
|
static void smp_uart_rx_frag(struct uart_mcumgr_rx_buf *rx_buf)
|
|
|
|
{
|
|
|
|
k_fifo_put(&smp_uart_rx_fifo, rx_buf);
|
|
|
|
k_work_submit(&smp_uart_work);
|
|
|
|
}
|
|
|
|
|
|
|
|
static u16_t smp_uart_get_mtu(const struct net_buf *nb)
|
|
|
|
{
|
|
|
|
return CONFIG_MCUMGR_SMP_UART_MTU;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int smp_uart_tx_pkt(struct zephyr_smp_transport *zst,
|
|
|
|
struct net_buf *nb)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = uart_mcumgr_send(nb->data, nb->len);
|
|
|
|
mcumgr_buf_free(nb);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int smp_uart_init(struct device *dev)
|
|
|
|
{
|
|
|
|
ARG_UNUSED(dev);
|
|
|
|
|
|
|
|
zephyr_smp_transport_init(&smp_uart_transport, smp_uart_tx_pkt,
|
2018-07-17 01:22:05 +08:00
|
|
|
smp_uart_get_mtu, NULL, NULL);
|
2018-01-18 10:01:52 +08:00
|
|
|
uart_mcumgr_register(smp_uart_rx_frag);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
SYS_INIT(smp_uart_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|