1 /* 2 * Copyright Runtime.io 2018. All rights reserved. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /** 8 * @file 9 * @brief Utility functions used by the UART and shell mcumgr transports. 10 * 11 * Mcumgr packets sent over serial are fragmented into frames of 128 bytes or 12 * fewer. 13 * 14 * The initial frame in a packet has the following format: 15 * offset 0: 0x06 0x09 16 * === Begin base64 encoding === 17 * offset 2: {16-bit packet-length} 18 * offset ?: {body} 19 * offset ?: {crc16} (if final frame) 20 * === End base64 encoding === 21 * offset ?: 0x0a (newline) 22 * 23 * All subsequent frames have the following format: 24 * offset 0: 0x04 0x14 25 * === Begin base64 encoding === 26 * offset 2: {body} 27 * offset ?: {crc16} (if final frame) 28 * === End base64 encoding === 29 * offset ?: 0x0a (newline) 30 * 31 * All integers are represented in big-endian. The packet fields are described 32 * below: 33 * 34 * | Field | Description | 35 * | -------------- | ------------------------------------------------------- | 36 * | 0x06 0x09 | Byte pair indicating the start of a packet. | 37 * | 0x04 0x14 | Byte pair indicating the start of a continuation frame. | 38 * | Packet length | The combined total length of the *unencoded* body plus | 39 * | | the final CRC (2 bytes). Length is in Big-Endian format.| 40 * | Body | The actual SMP data (i.e., 8-byte header and CBOR | 41 * | | key-value map). | 42 * | CRC16 | A CRC16 of the *unencoded* body of the entire packet. | 43 * | | This field is only present in the final frame of a | 44 * | | packet. | 45 * | Newline | A 0x0a byte; terminates a frame. | 46 * 47 * The packet is fully received when {packet-length} bytes of body has been 48 * received. 49 * 50 * ## CRC details 51 * 52 * The CRC16 should be calculated with the following parameters: 53 * 54 * | Field | Value | 55 * | ------------- | ------------- | 56 * | Polynomial | 0x1021 | 57 * | Initial Value | 0 | 58 */ 59 60 #ifndef ZEPHYR_INCLUDE_MGMT_SERIAL_H_ 61 #define ZEPHYR_INCLUDE_MGMT_SERIAL_H_ 62 63 #include <zephyr/types.h> 64 65 #ifdef __cplusplus 66 extern "C" { 67 #endif 68 69 #define MCUMGR_SERIAL_HDR_PKT 0x0609 70 #define MCUMGR_SERIAL_HDR_FRAG 0x0414 71 #define MCUMGR_SERIAL_MAX_FRAME 128 72 73 #define MCUMGR_SERIAL_HDR_PKT_1 (MCUMGR_SERIAL_HDR_PKT >> 8) 74 #define MCUMGR_SERIAL_HDR_PKT_2 (MCUMGR_SERIAL_HDR_PKT & 0xff) 75 #define MCUMGR_SERIAL_HDR_FRAG_1 (MCUMGR_SERIAL_HDR_FRAG >> 8) 76 #define MCUMGR_SERIAL_HDR_FRAG_2 (MCUMGR_SERIAL_HDR_FRAG & 0xff) 77 78 /** 79 * @brief Maintains state for an incoming mcumgr request packet. 80 */ 81 struct mcumgr_serial_rx_ctxt { 82 /* Contains the partially- or fully-received mcumgr request. Data 83 * stored in this buffer has already been base64-decoded. 84 */ 85 struct net_buf *nb; 86 87 /* Length of full packet, as read from header. */ 88 uint16_t pkt_len; 89 }; 90 91 /** @typedef mcumgr_serial_tx_cb 92 * @brief Transmits a chunk of raw response data. 93 * 94 * @param data The data to transmit. 95 * @param len The number of bytes to transmit. 96 * @param arg An optional argument. 97 * 98 * @return 0 on success; negative error code on failure. 99 */ 100 typedef int (*mcumgr_serial_tx_cb)(const void *data, int len, void *arg); 101 102 /** 103 * @brief Processes an mcumgr request fragment received over a serial 104 * transport. 105 * 106 * Processes an mcumgr request fragment received over a serial transport. If 107 * the fragment is the end of a valid mcumgr request, this function returns a 108 * net_buf containing the decoded request. It is the caller's responsibility 109 * to free the net_buf after it has been processed. 110 * 111 * @param rx_ctxt The receive context associated with the serial 112 * transport being used. 113 * @param frag The incoming fragment to process. 114 * @param frag_len The length of the fragment, in bytes. 115 * 116 * @return A net_buf containing the decoded request if a 117 * complete and valid request has been 118 * received. 119 * NULL if the packet is incomplete or invalid. 120 */ 121 struct net_buf *mcumgr_serial_process_frag( 122 struct mcumgr_serial_rx_ctxt *rx_ctxt, 123 const uint8_t *frag, int frag_len); 124 125 /** 126 * @brief Encodes and transmits an mcumgr packet over serial. 127 * 128 * @param data The mcumgr packet data to send. 129 * @param len The length of the unencoded mcumgr packet. 130 * @param cb A callback used to transmit raw bytes. 131 * @param arg An optional argument to pass to the callback. 132 * 133 * @return 0 on success; negative error code on failure. 134 */ 135 int mcumgr_serial_tx_pkt(const uint8_t *data, int len, mcumgr_serial_tx_cb cb, 136 void *arg); 137 138 #ifdef __cplusplus 139 } 140 #endif 141 142 #endif 143