1# SMP (Simple Management Protocol) Protocol Notes
2
3The `mcumgr` SMP server and `mcumgr-cli` SMP client tool ([source](https://github.com/apache/mynewt-mcumgr-cli))
4use a custom protocol to send commands and responses between the server and client using a
5variety of transports (currently TTY serial or BLE).
6
7The protocol isn't fully documented but the following information has been inferred
8from the source code available on Github and using the `-l DEBUG` flag when
9executing commands.
10
11## Source Code
12
13**SMP** is based on the earlier **NMP**, which is part of [Apache Mynewt](https://mynewt.apache.org/).
14
15The golang source for the original **newtmgr** is [available here](https://github.com/apache/mynewt-newtmgr),
16and can be used to provide some insight into how data is exchanged between the
17utility and the device under test.
18
19This repository (`mynewt-mcumgr`) implements an SMP server in **C**,
20and a new command-line SMP client called **mcumgr** was created at
21[apache/mynewt-mcumgr-cli](https://github.com/apache/mynewt-mcumgr-cli).
22
23## SMP Frame Format
24
25### Endianness
26
27Frames are normally serialized as **Big Endian** when dealing with values > 8 bits. This is
28mandatory in NMP, but the SMP implementation does add support for **Little Endian** as an
29option at the struct level, as shown below.
30
31### Frame Header
32
33Frames in SMP have the following header format:
34
35```
36struct mgmt_hdr {
37#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
38    uint8_t  nh_op:3;           /* MGMT_OP_[...] */
39    uint8_t  _res1:5;
40#endif
41#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
42    uint8_t  _res1:5;
43    uint8_t  nh_op:3;           /* MGMT_OP_[...] */
44#endif
45    uint8_t  nh_flags;          /* Reserved for future flags */
46    uint16_t nh_len;            /* Length of the payload */
47    uint16_t nh_group;          /* MGMT_GROUP_ID_[...] */
48    uint8_t  nh_seq;            /* Sequence number */
49    uint8_t  nh_id;             /* Message ID within group */
50};
51```
52
53The NMP/newtmgr [go source](https://github.com/apache/mynewt-newtmgr/blob/master/nmxact/nmp/nmp.go) is as follows,
54without the option to select endianness:
55
56```
57type NmpHdr struct {
58	Op    uint8 /* 3 bits of opcode */
59	Flags uint8
60	Len   uint16
61	Group uint16
62	Seq   uint8
63	Id    uint8
64}
65```
66
67`nh_op` (or `Op` in newtmgr) can be one of the following values:
68
69```
70/** Opcodes; encoded in first byte of header. */
71#define MGMT_OP_READ            0
72#define MGMT_OP_READ_RSP        1
73#define MGMT_OP_WRITE           2
74#define MGMT_OP_WRITE_RSP       3
75```
76
77- **`op`**: The operation code
78- **`Flags`**: TBD
79- **`Len`**:  The payload len when `Data` is present
80- **`Group`**: Commands are organized into groups. Groups are defined
81  [here](https://github.com/apache/mynewt-mcumgr/blob/master/mgmt/include/mgmt/mgmt.h).
82- **`Seq`**: TBD
83- **`Id`**: The command ID to send. Commands in the default `Group` are defined
84  [here](https://github.com/apache/mynewt-mcumgr/blob/master/mgmt/include/mgmt/mgmt.h).
85
86SMP header (Little Endian)
87
88```
89 0                   1                   2                   3
90 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
91+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
92|  OP |   Res.  |      Flags    |             Length            |
93+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
94|            Group ID           |    Sequence   |   Command ID  |
95+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
96```
97
98#### `Data` Payload
99
100If `nh_len` (`Len` in nmp) is non-zero, the `nh_len` byte payload (referred to as **`Data`** in this document) immediately follows the frame header.
101
102### Example Packets
103
104The following example commands show how the different fields work:
105
106#### Simple Read Request: `taskstats`
107
108The following example corresponds to the `taskstats` command ([source](https://github.com/apache/mynewt-mcumgr/blob/master/cmd/os_mgmt/include/os_mgmt/os_mgmt.h)), and
109can be seen by running `mcumgr -l DEBUG -c serial taskstats`:
110
111```
112Op:    0  # NMGR_OP_READ
113Flags: 0
114Len:   0  # No payload present
115Group: 0  # 0x00 = NMGR_GROUP_ID_DEFAULT
116Seq:   0
117Id:    2  # 0x02 in group 0x00 = OS_MGMT_ID_TASKSTAT
118Data:  [] # No payload (len = 0 above)
119```
120
121When serialized this will be sent as `0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02`.
122
123If this was sent using the serial port, you would get the following request and response:
124
125```
126$ mcumgr -l DEBUG -c serial taskstats
1272016/11/11 12:45:44 [DEBUG] Writing newtmgr request &{Op:0 Flags:0 Len:0 Group:0 Seq:0 Id:2 Data:[]}
1282016/11/11 12:45:44 [DEBUG] Serializing request &{Op:0 Flags:0 Len:0 Group:0 Seq:0 Id:2 Data:[]} into buffer [0 0 0 0 0 0 0 2]
1292016/11/11 12:45:44 [DEBUG] Tx packet dump:
13000000000  00 00 00 00 00 00 00 02                           |........|
131
1322016/11/11 12:45:44 [DEBUG] Writing [6 9] to data channel
1332016/11/11 12:45:44 [DEBUG] Writing [65 65 111 65 65 65 65 65 65 65 65 65 65 105 66 67] to data channel
1342016/11/11 12:45:44 [DEBUG] Writing [10] to data channel
1352016/11/11 12:45:44 [DEBUG] Reading [6 9 65 65 111 65 65 65 65 65 65 65 65 65 65 105 66 67] from data channel
1362016/11/11 12:45:44 [DEBUG] Rx packet dump:
13700000000  00 00 00 00 00 00 00 02                           |........|
138
1392016/11/11 12:45:44 [DEBUG] Deserialized response &{Op:0 Flags:0 Len:0 Group:0 Seq:0 Id:2 Data:[]}
1402016/11/11 12:45:44 [DEBUG] Reading [13] from data channel
1412016/11/11 12:45:44 [DEBUG] Reading [6 9 65 90 119 66 65 81 71 83 65 65 65 65 65 114 57 105 99 109 77 65 90 88 82 104 99 50 116 122 118 50 82 112 90 71 120 108 118 50 82 119 99 109 108 118 71 80 57 106 100 71 108 107 65 71 86 122 100 71 70 48 90 81 70 109 99 51 82 114 100 88 78 108 71 66 108 109 99 51 82 114 99 50 108 54 71 69 66 109 89 51 78 51 89 50 53 48 71 103 65 85 102 109 112 110 99 110 86 117 100 71 108 116 90 82 111 65 69 53 120 80 98 71 120 104 99 51 82 102] from data channel
1422016/11/11 12:45:44 [DEBUG] Reading [4 20 89 50 104 108 89 50 116 112 98 103 66 115 98 109 86 52 100 70 57 106 97 71 86 106 97 50 108 117 65 80 57 109 89 109 120 108 88 50 120 115 118 50 82 119 99 109 108 118 65 71 78 48 97 87 81 66 90 88 78 48 89 88 82 108 65 109 90 122 100 71 116 49 99 50 85 89 79 109 90 122 100 71 116 122 97 88 111 89 85 71 90 106 99 51 100 106 98 110 81 90 54 112 120 110 99 110 86 117 100 71 108 116 90 82 107 74 82 87 120 115 89 88 78 48 88 50 78 111] from data channel
1432016/11/11 12:45:44 [DEBUG] Reading [4 20 90 87 78 114 97 87 52 65 98 71 53 108 101 72 82 102 89 50 104 108 89 50 116 112 98 103 68 47 98 109 74 115 90 88 86 104 99 110 82 102 89 110 74 112 90 71 100 108 118 50 82 119 99 109 108 118 66 87 78 48 97 87 81 67 90 88 78 48 89 88 82 108 65 87 90 122 100 71 116 49 99 50 85 89 72 50 90 122 100 71 116 122 97 88 111 90 65 81 66 109 89 51 78 51 89 50 53 48 71 103 65 84 113 89 78 110 99 110 86 117 100 71 108 116 90 81 66 115] from data channel
1442016/11/11 12:45:44 [DEBUG] Reading [4 20 98 71 70 122 100 70 57 106 97 71 86 106 97 50 108 117 65 71 120 117 90 88 104 48 88 50 78 111 90 87 78 114 97 87 52 65 47 50 100 105 98 71 86 119 99 110 66 111 118 50 82 119 99 109 108 118 65 87 78 48 97 87 81 68 90 88 78 48 89 88 82 108 65 87 90 122 100 71 116 49 99 50 85 89 48 50 90 122 100 71 116 122 97 88 111 90 65 86 66 109 89 51 78 51 89 50 53 48 71 81 113 68 90 51 74 49 98 110 82 112 98 87 85 69 98 71 120 104] from data channel
1452016/11/11 12:45:44 [DEBUG] Reading [4 20 99 51 82 102 89 50 104 108 89 50 116 112 98 103 66 115 98 109 86 52 100 70 57 106 97 71 86 106 97 50 108 117 65 80 47 47 47 56 85 88] from data channel
1462016/11/11 12:45:44 [DEBUG] Rx packet dump:
14700000000  01 01 01 92 00 00 00 02  bf 62 72 63 00 65 74 61  |.........brc.eta|
14800000010  73 6b 73 bf 64 69 64 6c  65 bf 64 70 72 69 6f 18  |sks.didle.dprio.|
14900000020  ff 63 74 69 64 00 65 73  74 61 74 65 01 66 73 74  |.ctid.estate.fst|
15000000030  6b 75 73 65 18 19 66 73  74 6b 73 69 7a 18 40 66  |kuse..fstksiz.@f|
15100000040  63 73 77 63 6e 74 1a 00  14 7e 6a 67 72 75 6e 74  |cswcnt...~jgrunt|
15200000050  69 6d 65 1a 00 13 9c 4f  6c 6c 61 73 74 5f 63 68  |ime....Ollast_ch|
15300000060  65 63 6b 69 6e 00 6c 6e  65 78 74 5f 63 68 65 63  |eckin.lnext_chec|
15400000070  6b 69 6e 00 ff 66 62 6c  65 5f 6c 6c bf 64 70 72  |kin..fble_ll.dpr|
15500000080  69 6f 00 63 74 69 64 01  65 73 74 61 74 65 02 66  |io.ctid.estate.f|
15600000090  73 74 6b 75 73 65 18 3a  66 73 74 6b 73 69 7a 18  |stkuse.:fstksiz.|
157000000a0  50 66 63 73 77 63 6e 74  19 ea 9c 67 72 75 6e 74  |Pfcswcnt...grunt|
158000000b0  69 6d 65 19 09 45 6c 6c  61 73 74 5f 63 68 65 63  |ime..Ellast_chec|
159000000c0  6b 69 6e 00 6c 6e 65 78  74 5f 63 68 65 63 6b 69  |kin.lnext_checki|
160000000d0  6e 00 ff 6e 62 6c 65 75  61 72 74 5f 62 72 69 64  |n..nbleuart_brid|
161000000e0  67 65 bf 64 70 72 69 6f  05 63 74 69 64 02 65 73  |ge.dprio.ctid.es|
162000000f0  74 61 74 65 01 66 73 74  6b 75 73 65 18 1f 66 73  |tate.fstkuse..fs|
16300000100  74 6b 73 69 7a 19 01 00  66 63 73 77 63 6e 74 1a  |tksiz...fcswcnt.|
16400000110  00 13 a9 83 67 72 75 6e  74 69 6d 65 00 6c 6c 61  |....gruntime.lla|
16500000120  73 74 5f 63 68 65 63 6b  69 6e 00 6c 6e 65 78 74  |st_checkin.lnext|
16600000130  5f 63 68 65 63 6b 69 6e  00 ff 67 62 6c 65 70 72  |_checkin..gblepr|
16700000140  70 68 bf 64 70 72 69 6f  01 63 74 69 64 03 65 73  |ph.dprio.ctid.es|
16800000150  74 61 74 65 01 66 73 74  6b 75 73 65 18 d3 66 73  |tate.fstkuse..fs|
16900000160  74 6b 73 69 7a 19 01 50  66 63 73 77 63 6e 74 19  |tksiz..Pfcswcnt.|
17000000170  0a 83 67 72 75 6e 74 69  6d 65 04 6c 6c 61 73 74  |..gruntime.llast|
17100000180  5f 63 68 65 63 6b 69 6e  00 6c 6e 65 78 74 5f 63  |_checkin.lnext_c|
17200000190  68 65 63 6b 69 6e 00 ff  ff ff                    |heckin....|
173
1742016/11/11 12:45:44 [DEBUG] Deserialized response &{Op:1 Flags:1 Len:402 Group:0 Seq:0 Id:2 Data:[191 98 114 99 0 101 116 97 115 107 115 191 100 105 100 108 101 191 100 112 114 105 111 24 255 99 116 105 100 0 101 115 116 97 116 101 1 102 115 116 107 117 115 101 24 25 102 115 116 107 115 105 122 24 64 102 99 115 119 99 110 116 26 0 20 126 106 103 114 117 110 116 105 109 101 26 0 19 156 79 108 108 97 115 116 95 99 104 101 99 107 105 110 0 108 110 101 120 116 95 99 104 101 99 107 105 110 0 255 102 98 108 101 95 108 108 191 100 112 114 105 111 0 99 116 105 100 1 101 115 116 97 116 101 2 102 115 116 107 117 115 101 24 58 102 115 116 107 115 105 122 24 80 102 99 115 119 99 110 116 25 234 156 103 114 117 110 116 105 109 101 25 9 69 108 108 97 115 116 95 99 104 101 99 107 105 110 0 108 110 101 120 116 95 99 104 101 99 107 105 110 0 255 110 98 108 101 117 97 114 116 95 98 114 105 100 103 101 191 100 112 114 105 111 5 99 116 105 100 2 101 115 116 97 116 101 1 102 115 116 107 117 115 101 24 31 102 115 116 107 115 105 122 25 1 0 102 99 115 119 99 110 116 26 0 19 169 131 103 114 117 110 116 105 109 101 0 108 108 97 115 116 95 99 104 101 99 107 105 110 0 108 110 101 120 116 95 99 104 101 99 107 105 110 0 255 103 98 108 101 112 114 112 104 191 100 112 114 105 111 1 99 116 105 100 3 101 115 116 97 116 101 1 102 115 116 107 117 115 101 24 211 102 115 116 107 115 105 122 25 1 80 102 99 115 119 99 110 116 25 10 131 103 114 117 110 116 105 109 101 4 108 108 97 115 116 95 99 104 101 99 107 105 110 0 108 110 101 120 116 95 99 104 101 99 107 105 110 0 255 255 255]}
175Return Code = 0
176      task pri tid  runtime      csw    stksz   stkuse last_checkin next_checkin
177  bleuart_bridge   5   2        0  1288579      256       31        0        0
178   bleprph   1   3        4     2691      336      211        0        0
179      idle 255   0  1285199  1343082       64       25        0        0
180    ble_ll   0   1     2373    60060       80       58        0        0
181```
182
183#### Group Read Request: `image list`
184
185The following command lists images on the device and uses commands from `Group`
1860x01 (`MGMT_GROUP_ID_IMAGE`), and was generated with `$ mcumgr -l DEBUG -c serial image list`:
187
188> See [img_mgmt](https://github.com/apache/mynewt-mcumgr/tree/master/cmd/img_mgmt)
189for a full list of commands in the IMAGE `Group`.
190
191```
192$ mcumgr -l DEBUG -c serial image list
1932016/11/11 12:25:51 [DEBUG] Writing newtmgr request &{Op:0 Flags:0 Len:0 Group:1 Seq:0 Id:0 Data:[]}
1942016/11/11 12:25:51 [DEBUG] Serializing request &{Op:0 Flags:0 Len:0 Group:1 Seq:0 Id:0 Data:[]} into buffer [0 0 0 0 0 1 0 0]
1952016/11/11 12:25:51 [DEBUG] Tx packet dump:
19600000000  00 00 00 00 00 01 00 00                           |........|
197
1982016/11/11 12:25:51 [DEBUG] Writing [6 9] to data channel
1992016/11/11 12:25:51 [DEBUG] Writing [65 65 111 65 65 65 65 65 65 65 69 65 65 68 99 119] to data channel
2002016/11/11 12:25:51 [DEBUG] Writing [10] to data channel
2012016/11/11 12:25:51 [DEBUG] Reading [6 9 65 65 111 65 65 65 65 65 65 65 69 65 65 68 99 119] from data channel
2022016/11/11 12:25:51 [DEBUG] Rx packet dump:
20300000000  00 00 00 00 00 01 00 00                           |........|
204
2052016/11/11 12:25:51 [DEBUG] Deserialized response &{Op:0 Flags:0 Len:0 Group:1 Seq:0 Id:0 Data:[]}
2062016/11/11 12:25:51 [DEBUG] Reading [13] from data channel
2072016/11/11 12:25:51 [DEBUG] Reading [6 9 65 73 85 66 65 81 66 55 65 65 69 65 65 76 57 109 97 87 49 104 90 50 86 122 110 55 57 107 99 50 120 118 100 65 66 110 100 109 86 121 99 50 108 118 98 109 85 119 76 106 77 117 77 71 82 111 89 88 78 111 87 67 68 83 84 76 77 70 69 49 81 88 75 55 85 81 110 53 121 48 114 110 104 104 50 87 49 113 47 102 120 71 50 48 103 115 54 121 48 48 113 75 101 79 48 71 104 105 98 50 57 48 89 87 74 115 90 102 86 110 99 71 86 117 90 71 108 117] from data channel
2082016/11/11 12:25:51 [DEBUG] Reading [4 20 90 47 82 112 89 50 57 117 90 109 108 121 98 87 86 107 57 87 90 104 89 51 82 112 100 109 88 49 47 47 57 114 99 51 66 115 97 88 82 84 100 71 70 48 100 88 77 65 47 49 78 116] from data channel
2092016/11/11 12:25:51 [DEBUG] Rx packet dump:
21000000000  01 01 00 7b 00 01 00 00  bf 66 69 6d 61 67 65 73  |...{.....fimages|
21100000010  9f bf 64 73 6c 6f 74 00  67 76 65 72 73 69 6f 6e  |..dslot.gversion|
21200000020  65 30 2e 33 2e 30 64 68  61 73 68 58 20 d2 4c b3  |e0.3.0dhashX .L.|
21300000030  05 13 54 17 2b b5 10 9f  9c b4 ae 78 61 d9 6d 6a  |..T.+......xa.mj|
21400000040  fd fc 46 db 48 2c eb 2d  34 a8 a7 8e d0 68 62 6f  |..F.H,.-4....hbo|
21500000050  6f 74 61 62 6c 65 f5 67  70 65 6e 64 69 6e 67 f4  |otable.gpending.|
21600000060  69 63 6f 6e 66 69 72 6d  65 64 f5 66 61 63 74 69  |iconfirmed.facti|
21700000070  76 65 f5 ff ff 6b 73 70  6c 69 74 53 74 61 74 75  |ve...ksplitStatu|
21800000080  73 00 ff                                          |s..|
219
2202016/11/11 12:25:51 [DEBUG] Deserialized response &{Op:1 Flags:1 Len:123 Group:1 Seq:0 Id:0 Data:[191 102 105 109 97 103 101 115 159 191 100 115 108 111 116 0 103 118 101 114 115 105 111 110 101 48 46 51 46 48 100 104 97 115 104 88 32 210 76 179 5 19 84 23 43 181 16 159 156 180 174 120 97 217 109 106 253 252 70 219 72 44 235 45 52 168 167 142 208 104 98 111 111 116 97 98 108 101 245 103 112 101 110 100 105 110 103 244 105 99 111 110 102 105 114 109 101 100 245 102 97 99 116 105 118 101 245 255 255 107 115 112 108 105 116 83 116 97 116 117 115 0 255]}
221Images:
222 slot=0
223    version: 0.3.0
224    bootable: true
225    flags: active confirmed
226    hash: d24cb3051354172bb5109f9cb4ae7861d96d6afdfc46db482ceb2d34a8a78ed0
227Split status: N/A
228```
229
230When serialised this will be sent as `0x00 0x00 0x00 0x00 0x00 0x01 0x00 0x00`.
231
232## Transports
233
234### Mcumgr/Newtmgr SMP Client Over Serial
235
236`mcumgr` or `newtmgr` can be used over TTY serial with the following parameters
237to connect to a SMP server running on the target device:
238
239- Baud Rate: 115200
240- HW Flow Control: None
241
242### Mcumgr/Newtmgr SMP Client Over BLE
243
244`mcumgr` or `newtmgr` can be used over BLE with the following GATT service and
245characteristic UUIDs to connect to a SMP server running on the target device:
246
247- **Service UUID**: `8D53DC1D-1DB7-4CD3-868B-8A527460AA84`
248- **Characteristic UUID**: `DA2E7828-FBCE-4E01-AE9E-261174997C48`
249
250The  "SMP" GATT service consists of one **write no-rsp characteristic**
251for SMP requests: a single-byte characteristic that
252can only accepts write-without-response commands. The contents of
253each write command contains an SMP request.
254
255SMP responses are sent back in the form of unsolicited notifications
256from the same characteristic.
257