summaryrefslogtreecommitdiff
path: root/src/gsmd/atcmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gsmd/atcmd.c')
-rw-r--r--src/gsmd/atcmd.c65
1 files changed, 57 insertions, 8 deletions
diff --git a/src/gsmd/atcmd.c b/src/gsmd/atcmd.c
index f482eb2..ed061e2 100644
--- a/src/gsmd/atcmd.c
+++ b/src/gsmd/atcmd.c
@@ -3,10 +3,13 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <termios.h>
#include <sys/types.h>
#include <common/linux_list.h>
+#include <gsmd/ts0707.h>
+
#include "gsmd.h"
#include "atcmd.h"
#include "unsolicited.h"
@@ -44,8 +47,10 @@ static inline int llparse_append(struct llparser *llp, char byte)
if (llp->cur < llp->buf + llp->len) {
*(llp->cur++) = byte;
return 0;
- } else
+ } else {
+ printf("llp->cur too big!!!\n");
return -EFBIG;
+ }
}
static int llparse_byte(struct llparser *llp, char byte)
@@ -121,6 +126,12 @@ static int llparse_string(struct llparser *llp, char *buf, unsigned int len)
return 0;
}
+static int llparse_init(struct llparser *llp)
+{
+ llp->state = LLPARSE_STATE_IDLE;
+ return 0;
+}
+
/* mid-level parser */
static int parse_final_result(const char *res)
@@ -143,6 +154,7 @@ static int ml_parse(const char *buf, int len, void *ctx)
/* responses come in order, so first response has to be for first
* command we sent, i.e. first entry in list */
cmd = llist_entry(g->busy_atcmds.next, struct gsmd_atcmd, list);
+ cmd->resp = buf;
if (buf[0] == '+') {
/* an extended response */
@@ -214,33 +226,40 @@ static int ml_parse(const char *buf, int len, void *ctx)
}
final_cb:
+ if (cmd->ret != 0)
+ generate_event_from_cme(g, cmd->ret);
if (final) {
/* remove from list of currently executing cmds */
llist_del(&cmd->list);
- if (cmd->cb) {
+ /* if we're finished with current commands, but still have pending
+ * commands: we want to WRITE again */
+ if (llist_empty(&g->busy_atcmds) && !llist_empty(&g->pending_atcmds))
+ g->gfd_uart.when |= GSMD_FD_WRITE;
+
+ if (!cmd->cb) {
fprintf(stderr, "command without cb!!!\n");
return -EINVAL;
}
return cmd->cb(cmd, cmd->ctx);
-
}
return 0;
-}
+}
/* callback to be called if [virtual] UART has some data for us */
static int atcmd_select_cb(int fd, unsigned int what, void *data)
{
- int len;
+ int len, rc;
static char rxbuf[1024];
struct gsmd *g = data;
if (what & GSMD_FD_READ) {
+ memset(rxbuf, 0, sizeof(rxbuf));
while ((len = read(fd, rxbuf, sizeof(rxbuf)))) {
- int rc;
-
if (len < 0) {
+ if (errno == EAGAIN)
+ return 0;
DEBUGP("ERROR reading from fd %u: %d (%s)\n", fd, len,
strerror(errno));
return len;
@@ -257,7 +276,8 @@ static int atcmd_select_cb(int fd, unsigned int what, void *data)
if (what & GSMD_FD_WRITE) {
struct gsmd_atcmd *pos, *pos2;
llist_for_each_entry_safe(pos, pos2, &g->pending_atcmds, list) {
- int rc = write(fd, pos->buf, strlen(pos->buf));
+ len = strlen(pos->buf);
+ rc = write(fd, pos->buf, strlen(pos->buf));
if (rc == 0) {
DEBUGP("write returns 0, aborting\n");
break;
@@ -270,13 +290,24 @@ static int atcmd_select_cb(int fd, unsigned int what, void *data)
fprintf(stderr, "short write!!! FIXME!\n");
exit(3);
}
+ write(fd, "\r", 1);
/* success: remove from global list of to-be-sent atcmds */
llist_del(&pos->list);
/* append to global list of executing atcmds */
llist_add_tail(&pos->list, &g->busy_atcmds);
+
+ /* we only send one cmd at the moment */
+ g->gfd_uart.when &= ~GSMD_FD_WRITE;
+ break;
}
}
+#if 0
+ if (llist_empty(&g->pending_atcmds))
+ g->gfd_uart.when &= ~GSMD_FD_WRITE;
+#endif
+
+
return 0;
}
@@ -314,6 +345,18 @@ int atcmd_submit(struct gsmd *g, struct gsmd_atcmd *cmd)
return 0;
}
+void atcmd_drain(int fd)
+{
+ int rc;
+ struct termios t;
+ rc = tcflush(fd, TCIOFLUSH);
+ rc = tcgetattr(fd, &t);
+ printf("c_iflag = 0x%08x, c_oflag = 0x%08x, c_cflag = 0x%08x, c_lflag = 0x%08x\n",
+ t.c_iflag, t.c_oflag, t.c_cflag, t.c_lflag);
+ t.c_iflag = t.c_oflag = 0;
+ rc = tcsetattr(fd, TCSANOW, &t);
+}
+
/* init atcmd parser */
int atcmd_init(struct gsmd *g, int sockfd)
{
@@ -322,7 +365,13 @@ int atcmd_init(struct gsmd *g, int sockfd)
g->gfd_uart.data = g;
g->gfd_uart.cb = &atcmd_select_cb;
+ INIT_LLIST_HEAD(&g->pending_atcmds);
+ INIT_LLIST_HEAD(&g->busy_atcmds);
+
+ llparse_init (&g->llp);
+
g->llp.cur = g->llp.buf;
+ g->llp.len = sizeof(g->llp.buf);
g->llp.cb = &ml_parse;
g->llp.ctx = g;
g->llp.flags = LGSM_ATCMD_F_EXTENDED;
personal git repositories of Harald Welte. Your mileage may vary