You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
4.2 KiB
165 lines
4.2 KiB
|
3 months ago
|
#include "app_cmd_parser.h"
|
||
|
|
#include <string.h>
|
||
|
|
#include <ctype.h>
|
||
|
|
|
||
|
|
static int find_payload_pos(const char *line)
|
||
|
|
{
|
||
|
|
const char *p = strchr(line, ':');
|
||
|
|
if (!p) return -1;
|
||
|
|
return (int)(p - line + 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
static uint8_t hex_nibble(char c)
|
||
|
|
{
|
||
|
|
c = (char)toupper((unsigned char)c);
|
||
|
|
|
||
|
|
if (c >= '0' && c <= '9') return (uint8_t)(c - '0');
|
||
|
|
if (c >= 'A' && c <= 'F') return (uint8_t)(10 + (c - 'A'));
|
||
|
|
|
||
|
|
return 0xFFu;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int hex_pair_to_u8(char hi, char lo, uint8_t *out)
|
||
|
|
{
|
||
|
|
uint8_t h;
|
||
|
|
uint8_t l;
|
||
|
|
|
||
|
|
if (!out) return 0;
|
||
|
|
|
||
|
|
h = hex_nibble(hi);
|
||
|
|
l = hex_nibble(lo);
|
||
|
|
|
||
|
|
if (h == 0xFFu || l == 0xFFu) return 0;
|
||
|
|
|
||
|
|
*out = (uint8_t)((h << 4) | l);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
int app_cmd_parse_line(app_cmd_src_t src, const char *line, app_job_t *job)
|
||
|
|
{
|
||
|
|
int payload_pos;
|
||
|
|
int len;
|
||
|
|
int pos;
|
||
|
|
unsigned int k;
|
||
|
|
|
||
|
|
if (!line || !job) return 0;
|
||
|
|
|
||
|
|
memset(job, 0, sizeof(*job));
|
||
|
|
job->src = src;
|
||
|
|
job->check_on = 1u;
|
||
|
|
|
||
|
|
strncpy(job->line, line, sizeof(job->line) - 1);
|
||
|
|
job->line[sizeof(job->line) - 1] = '\0';
|
||
|
|
|
||
|
|
len = (int)strlen(line);
|
||
|
|
|
||
|
|
/* x? ?? ? ?? local exec */
|
||
|
|
if (line[0] != 'x' && line[0] != 'X') {
|
||
|
|
job->type = APP_JOB_LOCAL_EXEC;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
payload_pos = find_payload_pos(line);
|
||
|
|
if (payload_pos < 0) {
|
||
|
|
job->type = APP_JOB_FORWARD_LINE;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ?? ?? ??: xNNc_...:payload */
|
||
|
|
if (len < payload_pos) return 0;
|
||
|
|
if (!isdigit((unsigned char)line[1]) || !isdigit((unsigned char)line[2])) return 0;
|
||
|
|
|
||
|
|
job->addr = (uint8_t)((line[1] - '0') * 10 + (line[2] - '0'));
|
||
|
|
job->mode = (char)toupper((unsigned char)line[3]);
|
||
|
|
|
||
|
|
/* ?? CAL? ?? */
|
||
|
|
if (job->mode != 'C') return 0;
|
||
|
|
|
||
|
|
/* xNNc_001101:... ?? channel = 001 */
|
||
|
|
if (payload_pos >= 8 &&
|
||
|
|
isdigit((unsigned char)line[5]) &&
|
||
|
|
isdigit((unsigned char)line[6]) &&
|
||
|
|
isdigit((unsigned char)line[7])) {
|
||
|
|
job->channel = (uint8_t)((line[5] - '0') * 100 +
|
||
|
|
(line[6] - '0') * 10 +
|
||
|
|
(line[7] - '0'));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ?? ??? */
|
||
|
|
if (payload_pos >= 11) {
|
||
|
|
job->hash_on = (uint8_t)(line[8] == '1');
|
||
|
|
job->anaout_on = (uint8_t)(line[9] == '1');
|
||
|
|
job->check_on = (uint8_t)(line[10] == '1');
|
||
|
|
}
|
||
|
|
|
||
|
|
pos = payload_pos;
|
||
|
|
if (pos + 1 >= len) return 0;
|
||
|
|
|
||
|
|
/* ow / owt */
|
||
|
|
if ((line[pos] == 'o' || line[pos] == 'O') &&
|
||
|
|
(line[pos + 1] == 'w' || line[pos + 1] == 'W')) {
|
||
|
|
job->type = APP_JOB_PROTO_OW;
|
||
|
|
pos += 2;
|
||
|
|
|
||
|
|
if (pos < len && (line[pos] == 't' || line[pos] == 'T')) {
|
||
|
|
job->proto = APP_PROTO_OWIT;
|
||
|
|
pos++;
|
||
|
|
} else {
|
||
|
|
job->proto = APP_PROTO_OWIW;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/* or */
|
||
|
|
else if ((line[pos] == 'o' || line[pos] == 'O') &&
|
||
|
|
(line[pos + 1] == 'r' || line[pos + 1] == 'R')) {
|
||
|
|
job->type = APP_JOB_PROTO_OR;
|
||
|
|
job->proto = APP_PROTO_OWIR;
|
||
|
|
pos += 2;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
job->type = APP_JOB_FORWARD_LINE;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (pos < len && (line[pos] == '_' || line[pos] == ':')) pos++;
|
||
|
|
|
||
|
|
if (pos + 1 >= len) return 0;
|
||
|
|
if (!hex_pair_to_u8(line[pos], line[pos + 1], &job->id)) return 0;
|
||
|
|
pos += 2;
|
||
|
|
|
||
|
|
if (pos + 2 >= len ||
|
||
|
|
!isdigit((unsigned char)line[pos]) ||
|
||
|
|
!isdigit((unsigned char)line[pos + 1]) ||
|
||
|
|
!isdigit((unsigned char)line[pos + 2])) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
job->len = (uint16_t)(100 * (line[pos] - '0') +
|
||
|
|
10 * (line[pos + 1] - '0') +
|
||
|
|
(line[pos + 2] - '0'));
|
||
|
|
pos += 3;
|
||
|
|
|
||
|
|
if (job->type == APP_JOB_PROTO_OW) {
|
||
|
|
if (job->len == 0u || job->len > APP_JOB_PAYLOAD_MAX) return 0;
|
||
|
|
if (pos + ((int)job->len * 2) > len) return 0;
|
||
|
|
|
||
|
|
for (k = 0; k < job->len; k++) {
|
||
|
|
if (!hex_pair_to_u8(line[pos + (int)(2 * k)],
|
||
|
|
line[pos + (int)(2 * k + 1)],
|
||
|
|
&job->payload[k])) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pos += (int)job->len * 2;
|
||
|
|
|
||
|
|
/* payload ?? ?? ??? ??? ?? */
|
||
|
|
if (pos != len) return 0;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
/* OR(read)? ??? ?? payload? ??? ? */
|
||
|
|
if (job->len == 0u || job->len > APP_JOB_PAYLOAD_MAX) return 0;
|
||
|
|
if (pos != len) return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
return 1;
|
||
|
|
}
|