15#if DETWS_ENABLE_THREAD
19bool is_reserved(uint8_t b)
21 return b == 0x7E || b == 0x7D || b == 0x11 || b == 0x13;
25bool put_stuffed(uint8_t *out, uint16_t *p, uint16_t cap, uint8_t b)
31 out[(*p)++] = ThreadHdlc::HDLC_ESCAPE;
32 out[(*p)++] = (uint8_t)(b ^ 0x20);
44uint8_t spinel_pack_uint(uint32_t value, uint8_t *out, uint8_t cap)
53 uint8_t
byte = (uint8_t)(value & 0x7F);
62int spinel_unpack_uint(
const uint8_t *raw, uint8_t len, uint32_t *value)
68 for (uint8_t n = 0; n < len; n++)
71 v |= (uint32_t)(b & 0x7F) << shift;
85uint16_t spinel_command_build(uint8_t header, uint32_t cmd, uint32_t prop,
const uint8_t *value, uint16_t value_len,
86 uint8_t *out, uint16_t cap)
88 if (!out || cap < 1 || (value ==
nullptr && value_len > 0))
92 uint8_t n = spinel_pack_uint(cmd, out + p, (uint8_t)(cap - p));
96 n = spinel_pack_uint(prop, out + p, (uint8_t)(cap > p ? cap - p : 0));
100 if ((uint32_t)p + value_len > cap)
102 for (uint16_t i = 0; i < value_len; i++)
103 out[p + i] = value[i];
104 return (uint16_t)(p + value_len);
107int spinel_command_parse(
const uint8_t *payload, uint16_t len, uint8_t *header, uint32_t *cmd, uint32_t *prop,
108 const uint8_t **value, uint16_t *value_len)
110 if (!payload || len < 1)
113 uint8_t h = payload[p++];
116 int n = spinel_unpack_uint(payload + p, (uint8_t)((len - p) > 255 ? 255 : (len - p)), &c);
120 n = spinel_unpack_uint(payload + p, (uint8_t)((len - p) > 255 ? 255 : (len - p)), &pr);
131 *value = payload + p;
133 *value_len = (uint16_t)(len - p);
137uint16_t spinel_fcs(
const uint8_t *buf, uint16_t len)
139 uint16_t crc = 0xFFFF;
140 for (uint16_t i = 0; i < len; i++)
143 for (uint8_t b = 0; b < 8; b++)
144 crc = (crc & 1) ? (uint16_t)((crc >> 1) ^ 0x8408) : (uint16_t)(crc >> 1);
146 return (uint16_t)(crc ^ 0xFFFF);
149uint16_t spinel_frame_encode(
const uint8_t *payload, uint16_t len, uint8_t *out, uint16_t cap)
153 uint16_t fcs = spinel_fcs(payload, len);
155 for (uint16_t i = 0; i < len; i++)
156 if (!put_stuffed(out, &p, cap, payload[i]))
158 if (!put_stuffed(out, &p, cap, (uint8_t)(fcs & 0xFF)) ||
159 !put_stuffed(out, &p, cap, (uint8_t)(fcs >> 8)))
163 out[p++] = ThreadHdlc::HDLC_FLAG;
167int spinel_frame_decode(
const uint8_t *raw, uint16_t len, uint8_t *payload, uint16_t pay_cap, uint16_t *pay_len)
172 while (flag < len && raw[flag] != ThreadHdlc::HDLC_FLAG)
180 for (uint16_t i = 0; i < flag; i++)
183 if (b == ThreadHdlc::HDLC_ESCAPE)
187 b = (uint8_t)(raw[i] ^ 0x20);
195 uint16_t plen = (uint16_t)(n - 2);
196 uint16_t fcs = spinel_fcs(un, plen);
197 if ((uint16_t)(un[plen] | (un[plen + 1] << 8)) != fcs)
201 for (uint16_t i = 0; i < plen; i++)
205 return (
int)(flag + 1);
#define DETWS_THREAD_MAX_DATA
Max spinel payload bytes carried in one HDLC-lite frame.
Thread spinel / HDLC-lite framing codec (DETWS_ENABLE_THREAD) - OpenThread RCP.