18size_t len_octets(
size_t len)
23 for (
size_t v = len; v; v >>= 8)
29size_t write_len(uint8_t *p,
size_t len)
37 for (
size_t v = len; v; v >>= 8)
39 p[0] = (uint8_t)(0x80 | nb);
40 for (
size_t i = 0; i < nb; i++)
41 p[1 + i] = (uint8_t)(len >> (8 * (nb - 1 - i)));
46bool tlv(uint8_t *out,
size_t cap,
size_t *n, uint8_t tag,
const uint8_t *val,
size_t val_len)
48 size_t need = 1 + len_octets(val_len) + val_len;
52 *n += write_len(out + *n, val_len);
55 memcpy(out + *n, val, val_len);
62bool ber_int(uint8_t *out,
size_t cap,
size_t *n, uint8_t tag, uint32_t v)
73 for (uint32_t x = v; x; x >>= 8)
74 tmp[t++] = (uint8_t)x;
75 if (tmp[t - 1] & 0x80)
77 for (
size_t i = 0; i < t; i++)
78 buf[k++] = tmp[t - 1 - i];
80 return tlv(out, cap, n, tag, buf, k);
83bool ber_str(uint8_t *out,
size_t cap,
size_t *n, uint8_t tag,
const char *s)
85 return tlv(out, cap, n, tag, (
const uint8_t *)(s ? s :
""), s ? strnlen(s, cap + 1) : 0);
88bool ber_bool(uint8_t *out,
size_t cap,
size_t *n, uint8_t tag,
bool v)
90 uint8_t b = v ? 0xFF : 0x00;
91 return tlv(out, cap, n, tag, &b, 1);
95size_t detws_goose_pdu(
const DetwsGoose *g, uint8_t *out,
size_t cap)
99 const size_t RESERVE = 4;
104 static const uint8_t ZT[8] = {0};
105 bool ok = ber_str(out, cap, &n, 0x80, g->gocb_ref) && ber_int(out, cap, &n, 0x81, g->time_allowed_to_live) &&
106 ber_str(out, cap, &n, 0x82, g->dat_set) && ber_str(out, cap, &n, 0x83, g->go_id) &&
107 tlv(out, cap, &n, 0x84, g->t ? g->t : ZT, 8) && ber_int(out, cap, &n, 0x85, g->st_num) &&
108 ber_int(out, cap, &n, 0x86, g->sq_num) && ber_bool(out, cap, &n, 0x87, g->simulation) &&
109 ber_int(out, cap, &n, 0x88, g->conf_rev) && ber_bool(out, cap, &n, 0x89, g->nds_com) &&
110 ber_int(out, cap, &n, 0x8A, g->num_entries) && tlv(out, cap, &n, 0xAB, g->all_data, g->all_data_len);
114 size_t content_len = n - RESERVE;
115 size_t hdr = 1 + len_octets(content_len);
117 memmove(out + hdr, out + RESERVE, content_len);
119 write_len(out + 1, content_len);
120 return hdr + content_len;
123size_t detws_goose_frame(
const uint8_t *dst,
const uint8_t *src, uint16_t appid,
const DetwsGoose *g, uint8_t *out,
126 if (!dst || !src || !g || !out || cap < 22)
130 memcpy(out + 6, src, 6);
134 out[14] = (uint8_t)(appid >> 8);
135 out[15] = (uint8_t)appid;
141 size_t pdu = detws_goose_pdu(g, out + 22, cap - 22);
144 uint16_t goose_len = (uint16_t)(8 + pdu);
145 out[16] = (uint8_t)(goose_len >> 8);
146 out[17] = (uint8_t)goose_len;
IEC 61850 GOOSE publisher codec (DETWS_ENABLE_GOOSE).