From 457c6293505e37da59a8af0338dd8688ba8acf13 Mon Sep 17 00:00:00 2001 From: laforge Date: Mon, 23 Oct 2006 21:55:39 +0000 Subject: first working revision of gsmd, libgsmd and libgsmd-tool git-svn-id: http://svn.openmoko.org/trunk/src/target/gsm@115 99fdad57-331a-0410-800a-d7fa5415bdb3 --- include/gsmd/usock.h | 9 +++++++ include/libgsmd/misc.h | 4 +++ src/gsmd/atcmd.c | 11 ++++++++- src/gsmd/gsmd.c | 30 ++++++++-------------- src/gsmd/usock.c | 48 ++++++++++++++++++++++++++++++++++- src/libgsmd/Makefile.am | 2 +- src/util/Makefile.am | 2 +- src/util/atcmd.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ src/util/atcmd.h | 2 ++ src/util/event.c | 27 +++++++++++++++++++- src/util/libgsmd-tool.c | 11 ++++++++- src/util/pin.c | 2 +- src/util/shell.c | 44 ++++++++++++++++++++++++++++++--- src/util/shell.h | 2 ++ 14 files changed, 229 insertions(+), 31 deletions(-) create mode 100644 src/util/atcmd.c create mode 100644 src/util/atcmd.h create mode 100644 src/util/shell.h diff --git a/include/gsmd/usock.h b/include/gsmd/usock.h index f5d26ae..2eaa6cf 100644 --- a/include/gsmd/usock.h +++ b/include/gsmd/usock.h @@ -46,6 +46,15 @@ enum gsmd_msg_pin_type { GSMD_PIN_INPUT = 1, }; +enum gsmd_msg_phone { + GSMD_PHONE_POWERUP = 1, + GSMD_PHONE_POWERDOWN = 2, +}; + +enum gsmd_msg_network { + GSMD_NETWORK_REGISTER = 1, +}; + /* Length from 3GPP TS 04.08, Clause 10.5.4.7 */ #define GSMD_ADDR_MAXLEN 32 diff --git a/include/libgsmd/misc.h b/include/libgsmd/misc.h index e191ce6..95e219d 100644 --- a/include/libgsmd/misc.h +++ b/include/libgsmd/misc.h @@ -8,6 +8,8 @@ #include +extern int lgsm_phone_power(struct lgsm_handle *lh, int power); + enum lgsm_netreg_state { LGSM_NETREG_ST_NOTREG = 0, LGSM_NETREG_ST_REG_HOME = 1, @@ -21,6 +23,8 @@ enum lgsm_netreg_state { extern int lgsm_get_netreg_state(struct lgsm_handle *lh, enum lgsm_netreg_state *state); +extern int lgsm_netreg_register(struct lgsm_handle *lh, int oper); + enum lgsm_info_type { LGSM_INFO_TYPE_NONE = 0, LGSM_INFO_TYPE_MANUF = 1, diff --git a/src/gsmd/atcmd.c b/src/gsmd/atcmd.c index 2647192..53120f4 100644 --- a/src/gsmd/atcmd.c +++ b/src/gsmd/atcmd.c @@ -156,6 +156,11 @@ static int ml_parse(const char *buf, int len, void *ctx) DEBUGP("buf=`%s'(%d)\n", buf, len); + if (!strcmp(buf, "AT-Command Interpreter ready")) { + gsmd_initsettings(g); + return 0; + } + /* 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); @@ -248,13 +253,15 @@ static int ml_parse(const char *buf, int len, void *ctx) /* FIXME: handling of those special commands in response to * ATD / ATA */ - if (!strncmp(buf, "NO CARRIER", 10)) { + if (!strncmp(buf, "NO CARRIER", 11)) { /* Part of Case 'D' */ + final = 1; goto final_cb; } if (!strncmp(buf, "BUSY", 4)) { /* Part of Case 'D' */ + final = 1; goto final_cb; } } @@ -388,6 +395,8 @@ struct gsmd_atcmd *atcmd_fill(const char *cmd, int rlen, /* submit an atcmd in the global queue of pending atcmds */ int atcmd_submit(struct gsmd *g, struct gsmd_atcmd *cmd) { + DEBUGP("submitting command `%s'\n", cmd->buf); + llist_add_tail(&cmd->list, &g->pending_atcmds); g->gfd_uart.when |= GSMD_FD_WRITE; diff --git a/src/gsmd/gsmd.c b/src/gsmd/gsmd.c index c8a3b3f..9595d4b 100644 --- a/src/gsmd/gsmd.c +++ b/src/gsmd/gsmd.c @@ -26,32 +26,24 @@ static int gsmd_test_atcb(struct gsmd_atcmd *cmd, void *ctx, char *resp) return 0; } -static int gsmd_test(struct gsmd *gsmd) +static int gsmd_simplecmd(struct gsmd *gsmd, char *cmdtxt) { struct gsmd_atcmd *cmd; - cmd = atcmd_fill("AT+CRC?", 255, &gsmd_test_atcb, NULL, 0); - return atcmd_submit(gsmd, cmd); -} - -static int atcmd_test(struct gsmd *gsmd) -{ - struct gsmd_atcmd *cmd; - cmd = atcmd_fill("ATE0", 255, &gsmd_test_atcb, NULL, 0); + cmd = atcmd_fill(cmdtxt, strlen(cmdtxt)+1, &gsmd_test_atcb, NULL, 0); + if (!cmd) + return -ENOMEM; + return atcmd_submit(gsmd, cmd); } -static int gsmd_initsettings(struct gsmd *gsmd) +int gsmd_initsettings(struct gsmd *gsmd) { int rc; - struct gsmd_atcmd *cmd; - - cmd = atcmd_fill("ATV1", 255, &gsmd_test_atcb, NULL, 0); - rc = atcmd_submit(gsmd, cmd); - if (rc < 0) - return rc; + + rc |= gsmd_simplecmd(gsmd, "ATE0V1"); + rc |= gsmd_simplecmd(gsmd, "AT+CRC=1;+CREG=2;+CMEE=1;+CLIP=1;+COLP=1;+CTZR=1;+CFUN=1"); - cmd = atcmd_fill("+CRC=1;+CREG=2;+CMEE=2;+CLIP=1;+COLP=1;+CTZR=1", 255, &gsmd_test_atcb, NULL, 0); - return atcmd_submit(gsmd, cmd); + return rc; } struct bdrt { @@ -207,8 +199,6 @@ int main(int argc, char **argv) setsid(); } - atcmd_test(&g); - gsmd_test(&g); gsmd_initsettings(&g); while (1) { diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c index 93e9751..76be1aa 100644 --- a/src/gsmd/usock.c +++ b/src/gsmd/usock.c @@ -88,7 +88,7 @@ static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, case GSMD_VOICECALL_DIAL: if (len < sizeof(*gph) + sizeof(*ga)) return -EINVAL; - ga = (struct gsmd_addr *) (void *)gph + sizeof(*gph); + ga = (struct gsmd_addr *) ((void *)gph + sizeof(*gph)); ga->number[GSMD_ADDR_MAXLEN] = '\0'; cmd = atcmd_fill("ATD", 5 + strlen(ga->number), &usock_cmd_cb, gu, gph->id); @@ -145,11 +145,57 @@ static int usock_rcv_pin(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, return atcmd_submit(gu->gsmd, cmd); } +static int usock_rcv_phone(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, + int len) +{ + struct gsmd_atcmd *cmd; + + switch (gph->msg_subtype) { + case GSMD_PHONE_POWERUP: + cmd = atcmd_fill("AT+CFUN=1", 9+1, + &null_cmd_cb, gu, 0); + break; + + case GSMD_PHONE_POWERDOWN: + cmd = atcmd_fill("AT+CFUN=0", 9+1, + &null_cmd_cb, gu, 0); + break; + default: + return -EINVAL; + } + if (!cmd) + return -ENOMEM; + + return atcmd_submit(gu->gsmd, cmd); +} + +static int usock_rcv_network(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, + int len) +{ + struct gsmd_atcmd *cmd; + + switch (gph->msg_subtype) { + case GSMD_NETWORK_REGISTER: + cmd = atcmd_fill("AT+COPS", 9+1, + &null_cmd_cb, gu, 0); + break; + default: + return -EINVAL; + } + if (!cmd) + return -ENOMEM; + + return atcmd_submit(gu->gsmd, cmd); +} + + static usock_msg_handler *pcmd_type_handlers[__NUM_GSMD_MSGS] = { [GSMD_MSG_PASSTHROUGH] = &usock_rcv_passthrough, [GSMD_MSG_EVENT] = &usock_rcv_event, [GSMD_MSG_VOICECALL] = &usock_rcv_voicecall, [GSMD_MSG_PIN] = &usock_rcv_pin, + [GSMD_MSG_PHONE] = &usock_rcv_phone, + [GSMD_MSG_NETWORK] = &usock_rcv_network, }; static int usock_rcv_pcmd(struct gsmd_user *gu, char *buf, int len) diff --git a/src/libgsmd/Makefile.am b/src/libgsmd/Makefile.am index 640f42a..08233d3 100644 --- a/src/libgsmd/Makefile.am +++ b/src/libgsmd/Makefile.am @@ -5,5 +5,5 @@ AM_CFLAGS = -std=gnu99 lib_LTLIBRARIES = libgsmd.la libgsmd_la_LDFLAGS = -Wc,-nostartfiles -version-info $(LIBVERSION) -libgsmd_la_SOURCES = libgsmd.c libgsmd_input.c libgsmd_voicecall.c libgsmd_passthrough.c libgsmd_event.c +libgsmd_la_SOURCES = libgsmd.c libgsmd_input.c libgsmd_voicecall.c libgsmd_passthrough.c libgsmd_event.c libgsmd_phone.c libgsmd_network.c diff --git a/src/util/Makefile.am b/src/util/Makefile.am index aee83ca..fb17c85 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -3,7 +3,7 @@ AM_CFLAGS = -std=gnu99 bin_PROGRAMS = libgsmd-tool -libgsmd_tool_SOURCES = libgsmd-tool.c shell.c event.c pin.c +libgsmd_tool_SOURCES = libgsmd-tool.c shell.c event.c pin.c atcmd.c libgsmd_tool_LDADD = ../libgsmd/libgsmd.la libgsmd_tool_LDFLAGS = -dynamic diff --git a/src/util/atcmd.c b/src/util/atcmd.c new file mode 100644 index 0000000..6cf9aa7 --- /dev/null +++ b/src/util/atcmd.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include + +#include + +#define STDIN_BUF_SIZE 1024 + +/* this is the handler for receiving passthrough responses */ +static int pt_msghandler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh) +{ + char *payload = (char *)gmh + sizeof(*gmh); + printf("RSTR=`%s'\n", payload); +} + +int atcmd_main(struct lgsm_handle *lgsmh) +{ + int rc; + char buf[STDIN_BUF_SIZE+1]; + char rbuf[STDIN_BUF_SIZE+1]; + int rlen = sizeof(rbuf); + fd_set readset; + + lgsm_register_handler(lgsmh, GSMD_MSG_PASSTHROUGH, &pt_msghandler); + + FD_ZERO(&readset); + + while (1) { + fd_set readset; + int gsm_fd = lgsm_fd(lgsmh); + FD_SET(0, &readset); + FD_SET(gsm_fd, &readset); + + rc = select(gsm_fd+1, &readset, NULL, NULL, NULL); + if (rc <= 0) + break; + if (FD_ISSET(gsm_fd, &readset)) { + /* we've received something on the gsmd socket, pass it + * on to the library */ + rc = read(gsm_fd, buf, sizeof(buf)); + if (rc <= 0) { + printf("ERROR reding from gsm_fd\n"); + break; + } + rc = lgsm_handle_packet(lgsmh, buf, rc); + } + if (FD_ISSET(0, &readset)) { + /* we've received something on stdin. send it as passthrough + * to gsmd */ + rc = fscanf(stdin, "%s", buf); + if (rc == EOF) { + printf("EOF\n"); + return -1; + } + if (rc <= 0) { + printf("NULL\n"); + continue; + } + printf("STR=`%s'\n", buf); + } + /* this is a synchronous call for a passthrough command */ + lgsm_passthrough(lgsmh, buf, rbuf, &rlen); + printf("RSTR=`%s'\n", rbuf); + } +} diff --git a/src/util/atcmd.h b/src/util/atcmd.h new file mode 100644 index 0000000..3a385ae --- /dev/null +++ b/src/util/atcmd.h @@ -0,0 +1,2 @@ + +extern int atcmd_main(struct lgsm_handle *lgsmh); diff --git a/src/util/event.c b/src/util/event.c index 601ea9a..0f09d47 100644 --- a/src/util/event.c +++ b/src/util/event.c @@ -20,7 +20,32 @@ static int clip_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata static int netreg_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux) { - printf("EVENT: Netreg\n"); + printf("EVENT: Netreg "); + + switch (aux->u.netreg.state) { + case 0: + printf("not searching for network "); + break; + case 1: + printf("registered (home network) "); + break; + case 2: + printf("searching for network "); + break; + case 3: + printf("registration denied "); + break; + case 5: + printf("registered (roaming) "); + break; + } + + if (aux->u.netreg.lac) + printf("LocationAreaCode=0x%04X ", aux->u.netreg.lac); + if (aux->u.netreg.ci) + printf("CellID=0x%04X ", aux->u.netreg.ci); + + printf("\n"); return 0; } diff --git a/src/util/libgsmd-tool.c b/src/util/libgsmd-tool.c index 8d4674c..42a8e7c 100644 --- a/src/util/libgsmd-tool.c +++ b/src/util/libgsmd-tool.c @@ -10,6 +10,8 @@ #include "pin.h" #include "event.h" +#include "shell.h" +#include "atcmd.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) @@ -22,12 +24,14 @@ enum mode_enum { MODE_NONE, MODE_SHELL, MODE_EVENTLOG, + MODE_ATCMD, }; static char *modes[] = { [MODE_NONE] = "", [MODE_SHELL] = "shell", [MODE_EVENTLOG] = "eventlog", + [MODE_ATCMD] = "atcmd", }; static int parse_mode(char *modestr) @@ -56,7 +60,9 @@ static void help(void) printf("Usage:\n" "\t-h\t--help\tPrint this Help message\n" "\t-V\t--version\tPrint version number\n" - "\t-v\t--verbose\tBe more verbose\n"); + "\t-v\t--verbose\tBe more verbose\n" + "\t-m\t--mode\tSet mode {passthrough,atcmd}\n" + ); } int main(int argc, char **argv) @@ -107,6 +113,9 @@ int main(int argc, char **argv) event_init(lgsmh); switch (mode) { + case MODE_ATCMD: + atcmd_main(lgsmh); + break; case MODE_SHELL: shell_main(lgsmh); break; diff --git a/src/util/pin.c b/src/util/pin.c index b855e53..c51bd81 100644 --- a/src/util/pin.c +++ b/src/util/pin.c @@ -22,7 +22,7 @@ static int pin_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata } else { do { printf("Please enter PIN: "); - rc = fscanf(stdin, "%32s\n", &pinbuf); + rc = fscanf(stdin, "%32s", &pinbuf); } while (rc < 1); return lgsm_pin(lh, pinbuf); diff --git a/src/util/shell.c b/src/util/shell.c index 77f0c57..2875758 100644 --- a/src/util/shell.c +++ b/src/util/shell.c @@ -4,6 +4,8 @@ #include #include +#include +#include #define STDIN_BUF_SIZE 1024 @@ -14,6 +16,17 @@ static int pt_msghandler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh) printf("RSTR=`%s'\n", payload); } +static int shell_help(void) +{ + printf( "\tA\tAnswer incoming call\n" + "\tD\tDial outgoing number\n" + "\tH\tHangup call\n" + "\tO\tPower On\n" + "\to\tPower Off\n" + "\tR\tRegister Netowrk\n" + ); +} + int shell_main(struct lgsm_handle *lgsmh) { int rc; @@ -48,6 +61,7 @@ int shell_main(struct lgsm_handle *lgsmh) if (FD_ISSET(0, &readset)) { /* we've received something on stdin. send it as passthrough * to gsmd */ + printf("# "); rc = fscanf(stdin, "%s", buf); if (rc == EOF) { printf("EOF\n"); @@ -57,10 +71,32 @@ int shell_main(struct lgsm_handle *lgsmh) printf("NULL\n"); continue; } - printf("STR=`%s'\n", buf); + if (!strcmp(buf, "h")) { + shell_help(); + } else if (!strcmp(buf, "?")) { + shell_help(); + } else if (!strcmp(buf, "H")) { + printf("Hangup\n"); + lgsm_voice_hangup(lgsmh); + } else if (buf[0] == 'D') { + struct lgsm_addr addr; + printf("Dial %s\n", buf+1); + addr.type = 129; + strncpy(addr.addr, buf+1, sizeof(addr.addr)-1); + addr.addr[sizeof(addr.addr)-1] = '\0'; + lgsm_voice_out_init(lgsmh, &addr); + } else if (!strcmp(buf, "A")) { + printf("Answer\n"); + lgsm_voice_in_accept(lgsmh); + } else if (!strcmp(buf, "O")) { + lgsm_phone_power(lgsmh, 1); + } else if (!strcmp(buf, "o")) { + lgsm_phone_power(lgsmh, 0); + } else if (!strcmp(buf, "R")) { + lgsm_netreg_register(lgsmh, 0); + } else { + printf("Unknown command `%s'\n", buf); + } } - /* this is a synchronous call for a passthrough command */ - lgsm_passthrough(lgsmh, buf, rbuf, &rlen); - printf("RSTR=`%s'\n", rbuf); } } diff --git a/src/util/shell.h b/src/util/shell.h new file mode 100644 index 0000000..d383de9 --- /dev/null +++ b/src/util/shell.h @@ -0,0 +1,2 @@ + +extern int shell_main(struct lgsm_handle *lgsmh); -- cgit v1.2.3