|
17 | 17 | #include "mgmt/serial.h" |
18 | 18 | #include "mgmt/buf.h" |
19 | 19 | #include "mgmt/smp.h" |
20 | | - |
21 | | -struct device; |
| 20 | +#include "mgmt/smp_shell.h" |
22 | 21 |
|
23 | 22 | static struct zephyr_smp_transport smp_shell_transport; |
24 | 23 |
|
25 | 24 | static struct mcumgr_serial_rx_ctxt smp_shell_rx_ctxt; |
26 | 25 |
|
27 | | -/** |
28 | | - * Processes a single line (i.e., a single SMP frame) |
29 | | - */ |
30 | | -static int smp_shell_rx_line(const char *line, void *arg) |
| 26 | +/** SMP mcumgr frame fragments. */ |
| 27 | +enum smp_shell_esc_mcumgr { |
| 28 | + ESC_MCUMGR_PKT_1, |
| 29 | + ESC_MCUMGR_PKT_2, |
| 30 | + ESC_MCUMGR_FRAG_1, |
| 31 | + ESC_MCUMGR_FRAG_2, |
| 32 | +}; |
| 33 | + |
| 34 | +/** These states indicate whether an mcumgr frame is being received. */ |
| 35 | +enum smp_shell_mcumgr_state { |
| 36 | + SMP_SHELL_MCUMGR_STATE_NONE, |
| 37 | + SMP_SHELL_MCUMGR_STATE_HEADER, |
| 38 | + SMP_SHELL_MCUMGR_STATE_PAYLOAD |
| 39 | +}; |
| 40 | + |
| 41 | +static int read_mcumgr_byte(struct smp_shell_data *data, u8_t byte) |
| 42 | +{ |
| 43 | + bool frag_1; |
| 44 | + bool frag_2; |
| 45 | + bool pkt_1; |
| 46 | + bool pkt_2; |
| 47 | + |
| 48 | + pkt_1 = atomic_test_bit(&data->esc_state, ESC_MCUMGR_PKT_1); |
| 49 | + pkt_2 = atomic_test_bit(&data->esc_state, ESC_MCUMGR_PKT_2); |
| 50 | + frag_1 = atomic_test_bit(&data->esc_state, ESC_MCUMGR_FRAG_1); |
| 51 | + frag_2 = atomic_test_bit(&data->esc_state, ESC_MCUMGR_FRAG_2); |
| 52 | + |
| 53 | + if (pkt_2 || frag_2) { |
| 54 | + /* Already fully framed. */ |
| 55 | + return SMP_SHELL_MCUMGR_STATE_PAYLOAD; |
| 56 | + } |
| 57 | + |
| 58 | + if (pkt_1) { |
| 59 | + if (byte == MCUMGR_SERIAL_HDR_PKT_2) { |
| 60 | + /* Final framing byte received. */ |
| 61 | + atomic_set_bit(&data->esc_state, ESC_MCUMGR_PKT_2); |
| 62 | + return SMP_SHELL_MCUMGR_STATE_PAYLOAD; |
| 63 | + } |
| 64 | + } else if (frag_1) { |
| 65 | + if (byte == MCUMGR_SERIAL_HDR_FRAG_2) { |
| 66 | + /* Final framing byte received. */ |
| 67 | + atomic_set_bit(&data->esc_state, ESC_MCUMGR_FRAG_2); |
| 68 | + return SMP_SHELL_MCUMGR_STATE_PAYLOAD; |
| 69 | + } |
| 70 | + } else { |
| 71 | + if (byte == MCUMGR_SERIAL_HDR_PKT_1) { |
| 72 | + /* First framing byte received. */ |
| 73 | + atomic_set_bit(&data->esc_state, ESC_MCUMGR_PKT_1); |
| 74 | + return SMP_SHELL_MCUMGR_STATE_HEADER; |
| 75 | + } else if (byte == MCUMGR_SERIAL_HDR_FRAG_1) { |
| 76 | + /* First framing byte received. */ |
| 77 | + atomic_set_bit(&data->esc_state, ESC_MCUMGR_FRAG_1); |
| 78 | + return SMP_SHELL_MCUMGR_STATE_HEADER; |
| 79 | + } |
| 80 | + } |
| 81 | + |
| 82 | + /* Non-mcumgr byte received. */ |
| 83 | + return SMP_SHELL_MCUMGR_STATE_NONE; |
| 84 | +} |
| 85 | + |
| 86 | +bool smp_shell_rx_byte(struct smp_shell_data *data, uint8_t byte) |
31 | 87 | { |
32 | | - struct net_buf *nb; |
33 | | - int line_len; |
| 88 | + int mcumgr_state; |
34 | 89 |
|
35 | | - /* Strip the trailing newline. */ |
36 | | - line_len = strlen(line) - 1; |
| 90 | + mcumgr_state = read_mcumgr_byte(data, byte); |
| 91 | + if (mcumgr_state == SMP_SHELL_MCUMGR_STATE_NONE) { |
| 92 | + /* Not an mcumgr command; let the shell process the byte. */ |
| 93 | + return false; |
| 94 | + } |
37 | 95 |
|
38 | | - nb = mcumgr_serial_process_frag(&smp_shell_rx_ctxt, line, line_len); |
39 | | - if (nb != NULL) { |
40 | | - zephyr_smp_rx_req(&smp_shell_transport, nb); |
| 96 | + /* |
| 97 | + * The received byte is part of an mcumgr command. Process the byte |
| 98 | + * and return true to indicate that shell should ignore it. |
| 99 | + */ |
| 100 | + if (data->cur + data->end < sizeof(data->mcumgr_buff) - 1) { |
| 101 | + data->mcumgr_buff[data->cur++] = byte; |
| 102 | + } |
| 103 | + if (mcumgr_state == SMP_SHELL_MCUMGR_STATE_PAYLOAD && byte == '\n') { |
| 104 | + data->mcumgr_buff[data->cur + data->end] = '\0'; |
| 105 | + data->cmd_rdy = true; |
| 106 | + atomic_clear_bit(&data->esc_state, ESC_MCUMGR_PKT_1); |
| 107 | + atomic_clear_bit(&data->esc_state, ESC_MCUMGR_PKT_2); |
| 108 | + atomic_clear_bit(&data->esc_state, ESC_MCUMGR_FRAG_1); |
| 109 | + atomic_clear_bit(&data->esc_state, ESC_MCUMGR_FRAG_2); |
| 110 | + data->cur = 0U; |
| 111 | + data->end = 0U; |
41 | 112 | } |
42 | 113 |
|
43 | | - return 0; |
| 114 | + return true; |
| 115 | +} |
| 116 | + |
| 117 | +void smp_shell_process(struct smp_shell_data *data) |
| 118 | +{ |
| 119 | + if (data->cmd_rdy) { |
| 120 | + data->cmd_rdy = false; |
| 121 | + struct net_buf *nb; |
| 122 | + int line_len; |
| 123 | + |
| 124 | + /* Strip the trailing newline. */ |
| 125 | + line_len = strlen(data->mcumgr_buff) - 1; |
| 126 | + |
| 127 | + nb = mcumgr_serial_process_frag(&smp_shell_rx_ctxt, |
| 128 | + data->mcumgr_buff, |
| 129 | + line_len); |
| 130 | + if (nb != NULL) { |
| 131 | + zephyr_smp_rx_req(&smp_shell_transport, nb); |
| 132 | + } |
| 133 | + } |
44 | 134 | } |
45 | 135 |
|
46 | 136 | static u16_t smp_shell_get_mtu(const struct net_buf *nb) |
@@ -72,7 +162,6 @@ static int smp_shell_init(struct device *dev) |
72 | 162 |
|
73 | 163 | zephyr_smp_transport_init(&smp_shell_transport, smp_shell_tx_pkt, |
74 | 164 | smp_shell_get_mtu, NULL, NULL); |
75 | | - shell_register_mcumgr_handler(smp_shell_rx_line, NULL); |
76 | 165 |
|
77 | 166 | return 0; |
78 | 167 | } |
|
0 commit comments