changeset 352:02d6c8469535

fcup-smdump implemented, compiles
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 05 Feb 2018 08:47:45 +0000
parents f0e9bb28b4d6
children 3bcc56883b17
files .hgignore uptools/atcmd/Makefile uptools/atcmd/resp_parse.c uptools/atcmd/resp_parse.h uptools/atcmd/smdump.c
diffstat 5 files changed, 221 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- 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$
--- 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}
--- /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 <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#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;
+}
--- /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
--- /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 <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#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);
+}