17static size_t finalize(uint8_t *buf,
const char *mnemonic,
size_t payload_len)
19 buf[0] = (uint8_t)(payload_len >> 24);
20 buf[1] = (uint8_t)(payload_len >> 16);
21 buf[2] = (uint8_t)(payload_len >> 8);
22 buf[3] = (uint8_t)(payload_len);
23 memcpy(buf + 4, mnemonic, PC_LSV2_MNEMONIC_LEN);
24 return PC_LSV2_HEADER_LEN + payload_len;
29static bool append_cstr_nul(uint8_t *buf,
size_t cap,
size_t *pos,
const char *src)
32 for (
const char *s = src; *s !=
'\0'; ++s)
38 buf[p++] = (uint8_t)*s;
49size_t pc_lsv2_build(uint8_t *buf,
size_t cap,
const char *mnemonic,
const uint8_t *payload,
size_t payload_len)
51 if (!buf || !mnemonic || cap < PC_LSV2_HEADER_LEN)
55 if (payload_len && !payload)
59 if ((uint64_t)payload_len > 0xFFFFFFFFULL)
63 if (payload_len > cap - PC_LSV2_HEADER_LEN)
69 memcpy(buf + PC_LSV2_HEADER_LEN, payload, payload_len);
71 return finalize(buf, mnemonic, payload_len);
74bool pc_lsv2_parse(
const uint8_t *buf,
size_t len, Lsv2Telegram *out,
size_t *consumed)
80 memset(out->mnemonic, 0, PC_LSV2_MNEMONIC_LEN);
81 out->payload =
nullptr;
84 if (!buf || len < PC_LSV2_HEADER_LEN)
89 uint32_t plen = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | (uint32_t)buf[3];
90 size_t total = (size_t)PC_LSV2_HEADER_LEN + plen;
96 memcpy(out->mnemonic, buf + 4, PC_LSV2_MNEMONIC_LEN);
97 out->payload = plen ? buf + PC_LSV2_HEADER_LEN :
nullptr;
98 out->payload_len = plen;
106bool pc_lsv2_is(
const Lsv2Telegram *t,
const char *mnemonic4)
108 return t && mnemonic4 && memcmp(t->mnemonic, mnemonic4, PC_LSV2_MNEMONIC_LEN) == 0;
111size_t pc_lsv2_build_login(uint8_t *buf,
size_t cap,
const char *login,
const char *password)
113 if (!buf || !login || cap < PC_LSV2_HEADER_LEN)
117 size_t pos = PC_LSV2_HEADER_LEN;
118 if (!append_cstr_nul(buf, cap, &pos, login))
122 if (password && !append_cstr_nul(buf, cap, &pos, password))
126 return finalize(buf, PC_LSV2_CMD_LOGIN, pos - PC_LSV2_HEADER_LEN);
129size_t pc_lsv2_build_logout(uint8_t *buf,
size_t cap,
const char *login)
131 if (!buf || cap < PC_LSV2_HEADER_LEN)
135 size_t pos = PC_LSV2_HEADER_LEN;
136 if (login && *login !=
'\0' && !append_cstr_nul(buf, cap, &pos, login))
140 return finalize(buf, PC_LSV2_CMD_LOGOUT, pos - PC_LSV2_HEADER_LEN);
143size_t pc_lsv2_build_filename(uint8_t *buf,
size_t cap,
const char *mnemonic,
const char *filename)
145 if (!buf || !mnemonic || !filename || cap < PC_LSV2_HEADER_LEN)
149 size_t pos = PC_LSV2_HEADER_LEN;
150 if (!append_cstr_nul(buf, cap, &pos, filename))
154 return finalize(buf, mnemonic, pos - PC_LSV2_HEADER_LEN);
157size_t pc_lsv2_build_run_info(uint8_t *buf,
size_t cap, uint16_t info_code)
159 if (!buf || cap < PC_LSV2_HEADER_LEN + 2)
163 buf[PC_LSV2_HEADER_LEN] = (uint8_t)(info_code >> 8);
164 buf[PC_LSV2_HEADER_LEN + 1] = (uint8_t)(info_code);
165 return finalize(buf, PC_LSV2_CMD_RUN_INFO, 2);
168bool pc_lsv2_is_ok(
const Lsv2Telegram *t)
170 return pc_lsv2_is(t, PC_LSV2_RSP_OK);
173bool pc_lsv2_is_error(
const Lsv2Telegram *t)
175 return pc_lsv2_is(t, PC_LSV2_RSP_ERROR) || pc_lsv2_is(t, PC_LSV2_RSP_XFER_ERR);
178bool pc_lsv2_error(
const Lsv2Telegram *t, uint8_t *err_class, uint8_t *err_code)
180 if (!pc_lsv2_is_error(t) || t->payload_len != 2 || !t->payload)
186 *err_class = t->payload[0];
190 *err_code = t->payload[1];
Heidenhain LSV/2 telegram codec (PC_ENABLE_LSV2) - a zero-heap codec for the LSV/2 protocol Heidenhai...