blob: a2c23c2bf476b5287df78dba5802d1459eab7b3a [file] [log] [blame]
/*
* Copyright Runtime.io 2018. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Utility functions used by the UART and shell mcumgr transports.
*
* Mcumgr packets sent over serial are fragmented into frames of 128 bytes or
* fewer.
*
* The initial frame in a packet has the following format:
* offset 0: 0x06 0x09
* === Begin base64 encoding ===
* offset 2: {16-bit packet-length}
* offset ?: {body}
* offset ?: {crc16} (if final frame)
* === End base64 encoding ===
* offset ?: 0x0a (newline)
*
* All subsequent frames have the following format:
* offset 0: 0x04 0x14
* === Begin base64 encoding ===
* offset 2: {body}
* offset ?: {crc16} (if final frame)
* === End base64 encoding ===
* offset ?: 0x0a (newline)
*
* All integers are represented in big-endian. The packet fields are described
* below:
*
* | Field | Description |
* | -------------- | ------------------------------------------------------- |
* | 0x06 0x09 | Byte pair indicating the start of a packet. |
* | 0x04 0x14 | Byte pair indicating the start of a continuation frame. |
* | Packet length | The combined total length of the *unencoded* body. |
* | Body | The actual SMP data (i.e., 8-byte header and CBOR |
* | | key-value map). |
* | CRC16 | A CRC16 of the *unencoded* body of the entire packet. |
* | | This field is only present in the final frame of a |
* | | packet. |
* | Newline | A 0x0a byte; terminates a frame. |
*
* The packet is fully received when {packet-length} bytes of body has been
* received.
*
* ## CRC details
*
* The CRC16 should be calculated with the following parameters:
*
* | Field | Value |
* | ------------- | ------------- |
* | Polynomial | 0x1021 |
* | Initial Value | 0 |
*/
#ifndef H_MGMT_SERIAL_
#define H_MGMT_SERIAL_
#include <zephyr/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MCUMGR_SERIAL_HDR_PKT 0x0609
#define MCUMGR_SERIAL_HDR_FRAG 0x0414
#define MCUMGR_SERIAL_MAX_FRAME 128
#define MCUMGR_SERIAL_HDR_PKT_1 (MCUMGR_SERIAL_HDR_PKT >> 8)
#define MCUMGR_SERIAL_HDR_PKT_2 (MCUMGR_SERIAL_HDR_PKT & 0xff)
#define MCUMGR_SERIAL_HDR_FRAG_1 (MCUMGR_SERIAL_HDR_FRAG >> 8)
#define MCUMGR_SERIAL_HDR_FRAG_2 (MCUMGR_SERIAL_HDR_FRAG & 0xff)
/**
* @brief Maintains state for an incoming mcumgr request packet.
*/
struct mcumgr_serial_rx_ctxt {
/* Contains the partially- or fully-received mcumgr request. Data
* stored in this buffer has already been base64-decoded.
*/
struct net_buf *nb;
/* Length of full packet, as read from header. */
u16_t pkt_len;
};
/** @typedef mcumgr_serial_tx_cb
* @brief Transmits a chunk of raw response data.
*
* @param data The data to transmit.
* @param len The number of bytes to transmit.
* @param arg An optional argument.
*
* @return 0 on success; negative error code on failure.
*/
typedef int (*mcumgr_serial_tx_cb)(const void *data, int len, void *arg);
/**
* @brief Processes an mcumgr request fragment received over a serial
* transport.
*
* Processes an mcumgr request fragment received over a serial transport. If
* the fragment is the end of a valid mcumgr request, this function returns a
* net_buf containing the decoded request. It is the caller's responsibility
* to free the net_buf after it has been processed.
*
* @param rx_ctxt The receive context associated with the serial
* transport being used.
* @param frag The incoming fragment to process.
* @param frag_len The length of the fragment, in bytes.
*
* @return A net_buf containing the decoded request if a
* complete and valid request has been
* received.
* NULL if the packet is incomplete or invalid.
*/
struct net_buf *mcumgr_serial_process_frag(
struct mcumgr_serial_rx_ctxt *rx_ctxt,
const u8_t *frag, int frag_len);
/**
* @brief Encodes and transmits an mcumgr packet over serial.
*
* @param data The mcumgr packet data to send.
* @param len The length of the unencoded mcumgr packet.
* @param cb A callback used to transmit raw bytes.
* @param arg An optional argument to pass to the callback.
*
* @return 0 on success; negative error code on failure.
*/
int mcumgr_serial_tx_pkt(const u8_t *data, int len, mcumgr_serial_tx_cb cb,
void *arg);
#ifdef __cplusplus
}
#endif
#endif