# HG changeset patch # User Mychaela Falconia # Date 1517820465 0 # Node ID 02d6c846953528d9c8fcebc63d467b577f8d373b # Parent f0e9bb28b4d6e826fdd946e6ea0421aee0fc6558 fcup-smdump implemented, compiles diff -r f0e9bb28b4d6 -r 02d6c8469535 .hgignore --- a/.hgignore Sun Feb 04 18:44:41 2018 +0000 +++ b/.hgignore Mon Feb 05 08:47:45 2018 +0000 @@ -61,5 +61,6 @@ ^toolchain/newlib-build/ ^uptools/atcmd/fcup-at$ +^uptools/atcmd/fcup-smdump$ ^uptools/atinterf/fcup-atinterf$ ^uptools/sms-pdu-decode/sms-pdu-decode$ diff -r f0e9bb28b4d6 -r 02d6c8469535 uptools/atcmd/Makefile --- a/uptools/atcmd/Makefile Sun Feb 04 18:44:41 2018 +0000 +++ b/uptools/atcmd/Makefile Mon Feb 05 08:47:45 2018 +0000 @@ -1,17 +1,22 @@ CC= gcc CFLAGS= -O2 -PROGS= fcup-at +PROGS= fcup-at fcup-smdump INSTBIN=/opt/freecalypso/bin LIBCODING= ../libcoding/libcoding.a ATCMD_OBJS= atcmd.o atinterf.o +SMDUMP_OBJS= atinterf.o resp_parse.o smdump.o ${LIBCODING} + all: ${PROGS} fcup-at: ${ATCMD_OBJS} ${CC} ${CFLAGS} -o $@ ${ATCMD_OBJS} +fcup-smdump: ${SMDUMP_OBJS} + ${CC} ${CFLAGS} -o $@ ${SMDUMP_OBJS} + install: ${PROGS} mkdir -p ${INSTBIN} install -c ${PROGS} ${INSTBIN} diff -r f0e9bb28b4d6 -r 02d6c8469535 uptools/atcmd/resp_parse.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uptools/atcmd/resp_parse.c Mon Feb 05 08:47:45 2018 +0000 @@ -0,0 +1,46 @@ +/* + * Parsing of structured responses to AT commands + */ + +#include +#include +#include +#include "resp_parse.h" + +parse_structured_response(start, fields, max_fields) + char *start; + struct resp_field *fields; + int max_fields; +{ + char *cp; + int fieldcnt; + + cp = start; + for (fieldcnt = 0; fieldcnt < max_fields; fieldcnt++) { + if (*cp == '\0') + break; + if (isdigit(*cp)) { + fields[fieldcnt].type = RESP_FIELD_NUMBER; + fields[fieldcnt].num = strtoul(cp, 0, 10); + while (isdigit(*cp)) + cp++; + } else if (*cp == '"') { + cp++; + fields[fieldcnt].type = RESP_FIELD_STRING; + fields[fieldcnt].str = cp; + while (*cp && *cp != '"') + cp++; + if (*cp != '"') + return(-1); + *cp++ = '\0'; + } else if (*cp == ',') + fields[fieldcnt].type = RESP_FIELD_EMPTY; + else + return(-1); + if (*cp == ',') + cp++; + else if (*cp) + return(-1); + } + return fieldcnt; +} diff -r f0e9bb28b4d6 -r 02d6c8469535 uptools/atcmd/resp_parse.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uptools/atcmd/resp_parse.h Mon Feb 05 08:47:45 2018 +0000 @@ -0,0 +1,13 @@ +/* + * Data structures for parsing structured responses to AT commands + */ + +struct resp_field { + int type; + unsigned num; + char *str; +}; + +#define RESP_FIELD_EMPTY 0 +#define RESP_FIELD_NUMBER 1 +#define RESP_FIELD_STRING 2 diff -r f0e9bb28b4d6 -r 02d6c8469535 uptools/atcmd/smdump.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uptools/atcmd/smdump.c Mon Feb 05 08:47:45 2018 +0000 @@ -0,0 +1,155 @@ +/* + * This utility retrieves a dump of all stored SMS records in PDU mode. + */ + +#include +#include +#include +#include +#include +#include +#include "../../rvinterf/include/exitcodes.h" +#include "resp_parse.h" + +extern char at_response[]; + +int pdu_state; +char *msgtype; +u_char pbname_gsm[40]; +unsigned pbname_len, header_len; +u_char pdu_bin[176]; + +validate_pbname_7bit() +{ + unsigned n; + + for (n = 0; n < pbname_len; n++) + if (pbname_gsm[n] & 0x80) + return(-1); + return(0); +} + +cmgl_header() +{ + struct resp_field fields[4]; + int cc; + + /* skip empty lines */ + if (!at_response[1]) + return; + /* if not empty, it MUST be +CMGL */ + if (strncmp(at_response+1, "+CMGL: ", 7)) { + fprintf(stderr, "error: response from target is not +CMGL\n"); + exit(ERROR_TARGET); + } + if (parse_structured_response(at_response+8, fields, 4) != 4) { +malformed: fprintf(stderr, "error: malformed +CMGL response\n"); + exit(ERROR_TARGET); + } + if (fields[0].type != RESP_FIELD_NUMBER || + fields[1].type != RESP_FIELD_NUMBER || + fields[3].type != RESP_FIELD_NUMBER) + goto malformed; + if (fields[2].type != RESP_FIELD_STRING && + fields[2].type != RESP_FIELD_EMPTY) + goto malformed; + /* we'll handle the message number when we add delete after dump */ + switch (fields[1].num) { + case 0: + case 1: + msgtype = "Received"; + break; + case 2: + msgtype = "Stored unsent"; + break; + case 3: + msgtype = "Sent"; + break; + default: + fprintf(stderr, + "error: invalid message status code in +CMGL response\n"); + exit(ERROR_TARGET); + } + if (fields[2].type == RESP_FIELD_STRING) { + cc = decode_hex_line(fields[2].str, pbname_gsm, + sizeof pbname_gsm); + if (cc >= 1) { + pbname_len = cc; + if (validate_pbname_7bit() < 0) + pbname_len = 0; + } else + pbname_len = 0; + } else + pbname_len = 0; + header_len = fields[3].num; + pdu_state = 1; +} + +emit_pb_name() +{ + u_char decoded_name[81]; + + gsm7_to_ascii_or_ext(pbname_gsm, pbname_len, decoded_name, 0, 0, 0, 0); + printf("Phonebook-Name: %s\n", decoded_name); +} + +cmgl_pdu() +{ + int cc; + unsigned sca_len; + + cc = decode_hex_line(at_response+1, pdu_bin, sizeof pdu_bin); + if (cc < 1) { + fprintf(stderr, "error: expected PDU not received\n"); + exit(ERROR_TARGET); + } + sca_len = pdu_bin[0]; + if (1 + sca_len + header_len != cc) { + fprintf(stderr, "error: PDU length mismatch\n"); + exit(ERROR_TARGET); + } + printf("%s message:\n", msgtype); + if (pbname_len) + emit_pb_name(); + puts(at_response+1); + putchar('\n'); + pdu_state = 0; +} + +cmgl_callback() +{ + if (pdu_state) + cmgl_pdu(); + else + cmgl_header(); +} + +main(argc, argv) + char **argv; +{ + int c; + extern int optind; + + while ((c = getopt(argc, argv, "B:np:RX:")) != EOF) + if (!atinterf_cmdline_opt(c)) { + /* error msg already printed */ + exit(ERROR_USAGE); + } + if (argc != optind) { + fprintf(stderr, "usage: %s [options]\n", argv[0]); + exit(ERROR_USAGE); + } + atinterf_init(); + /* put the 07.05 modem in PDU mode */ + atinterf_exec_cmd_needok("AT+CMGF=0", 0, 0); + /* HEX charset for phonebook names */ + atinterf_exec_cmd_needok("AT+CSCS=\"HEX\"", 0, 0); + /* main command */ + atinterf_exec_cmd_needok("AT+CMGL=4", 0, cmgl_callback); + if (pdu_state) { + fprintf(stderr, "error: wrong state at the end of +CMGL\n"); + exit(ERROR_TARGET); + } + /* delete-after-dump will go here */ + exit(0); +}