From cbffc8d64707828b045b679e8db0269ae362ffcf Mon Sep 17 00:00:00 2001 From: laforge Date: Mon, 23 Oct 2006 20:28:37 +0000 Subject: more gsmd/libgsm implementation git-svn-id: http://svn.openmoko.org/trunk/src/target/gsm@114 99fdad57-331a-0410-800a-d7fa5415bdb3 --- include/gsmd/event.h | 1 + include/gsmd/usock.h | 10 ++----- include/libgsmd/event.h | 12 +++++--- include/libgsmd/libgsmd.h | 35 ++++++++++++++-------- src/gsmd/gsmd.h | 2 +- src/gsmd/unsolicited.c | 13 ++++++-- src/gsmd/usock.c | 54 ++++++++++++++++++++++++++-------- src/libgsmd/Makefile.am | 2 +- src/libgsmd/lgsm_internals.h | 6 ++-- src/libgsmd/libgsmd.c | 62 +++++++++++++++++++++++++++++++++++++++ src/libgsmd/libgsmd_event.c | 57 +++++++++++++++++++++++++++++++++++ src/libgsmd/libgsmd_passthrough.c | 37 ++++++++++++----------- src/libgsmd/libgsmd_voicecall.c | 50 +++++++++++++++++++++++++++---- src/util/Makefile.am | 2 +- src/util/event.c | 38 ++++++++++++++++++++++++ src/util/event.h | 2 ++ src/util/libgsmd-tool.c | 13 +++++++- src/util/pin.c | 39 ++++++++++++++++++++++++ src/util/pin.h | 2 ++ src/util/shell.c | 56 ++++++++++++++++++++++++++++------- 20 files changed, 416 insertions(+), 77 deletions(-) create mode 100644 src/libgsmd/libgsmd_event.c create mode 100644 src/util/event.c create mode 100644 src/util/event.h create mode 100644 src/util/pin.c create mode 100644 src/util/pin.h diff --git a/include/gsmd/event.h b/include/gsmd/event.h index c6f2986..6ae4e02 100644 --- a/include/gsmd/event.h +++ b/include/gsmd/event.h @@ -14,6 +14,7 @@ enum gsmd_events { GSMD_EVT_OUT_COLP = 9, /* Outgoing COLP */ GSMD_EVT_CALL_WAIT = 10, /* Call Waiting */ GSMD_EVT_TIMEZONE = 11, /* Timezone change */ + GSMD_EVT_SUBSCRIPTIONS = 12, /* To which events are we subscribed to */ __NUM_GSMD_EVT }; diff --git a/include/gsmd/usock.h b/include/gsmd/usock.h index eced10e..f5d26ae 100644 --- a/include/gsmd/usock.h +++ b/include/gsmd/usock.h @@ -30,15 +30,10 @@ enum gsmd_passthrough_type { GSMD_PASSTHROUGH_RESP = 2, }; -enum gsmd_event_type { - GSMD_EVENT_NONE = 0, - GSMD_EVENT_SUBSCRIPTIONS= 1, - GSMD_EVENT_HAPPENED = 2, -}; - enum gsmd_msg_voicecall_type { GSMD_VOICECALL_DIAL = 1, GSMD_VOICECALL_HANGUP = 2, + GSMD_VOICECALL_ANSWER = 3, }; /* Handset / MT related commands */ @@ -53,7 +48,7 @@ enum gsmd_msg_pin_type { /* Length from 3GPP TS 04.08, Clause 10.5.4.7 */ -#define GSMD_ADDR_MAXLEN 13 +#define GSMD_ADDR_MAXLEN 32 struct gsmd_addr { u_int8_t type; char number[GSMD_ADDR_MAXLEN+1]; @@ -95,6 +90,7 @@ struct gsmd_msg_hdr { u_int8_t _pad; u_int16_t id; u_int16_t len; + u_int8_t data[]; } __attribute__((packed)); diff --git a/include/libgsmd/event.h b/include/libgsmd/event.h index d7faa9b..e1338f7 100644 --- a/include/libgsmd/event.h +++ b/include/libgsmd/event.h @@ -4,11 +4,15 @@ #include /* Prototype of libgsmd callback handler function */ -typedef int evt_cb_func(struct lgsm_handle *lh, enum gsmd_events evt, - void *user); +typedef int lgsm_evt_handler(struct lgsm_handle *lh, int evt_type, struct gsmd_evt_auxdata *aux); /* Register an event callback handler with libgsmd */ -extern int lgsm_register_evt_cb(struct lgsm_handle *lh, - evt_cb_func *cb, void *user); +extern int lgsm_evt_handler_register(struct lgsm_handle *lh, int evt_type, + lgsm_evt_handler *handler); +extern void lgsm_evt_handler_unregister(struct lgsm_handle *lh, int evt_type); + +extern int lgsm_evt_init(struct lgsm_handle *lh); +extern void lgsm_evt_exit(struct lgsm_handle *lh); + #endif diff --git a/include/libgsmd/libgsmd.h b/include/libgsmd/libgsmd.h index 7ce1a83..a89f4b6 100644 --- a/include/libgsmd/libgsmd.h +++ b/include/libgsmd/libgsmd.h @@ -9,6 +9,8 @@ #include #include +#include + /* Generic Information * * Return value: @@ -28,17 +30,6 @@ /* Opaque data structure, content only known to libgsm implementation */ struct lgsm_handle; -#define LGSMD_DEVICE_GSMD "gsmd" - -/* initialize usage of libgsmd, obtain handle for othe API calls */ -extern struct lgsm_handle *lgsm_init(const char *device); - -/* Terminate usage of libgsmd */ -extern int lgsm_exit(struct lgsm_handle *lh); - -/* Obtain file descriptor (e.g. for select-loop under app control) */ -extern int lgsm_fd(struct lgsm_handle *lh); - /* Refer to GSM 04.08 [8] subclause 10.5.4.7 */ enum lgsm_addr_type { LGSM_ATYPE_ISDN_UNKN = 161, @@ -48,9 +39,29 @@ enum lgsm_addr_type { #define LGSM_ADDR_MAXLEN 31 struct lgsm_addr { + enum lgsm_addr_type type; char addr[LGSM_ADDR_MAXLEN+1]; - enum lgsm_addr_type tyoe; }; +typedef int lgsm_msg_handler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh); + +#define LGSMD_DEVICE_GSMD "gsmd" + +/* initialize usage of libgsmd, obtain handle for othe API calls */ +extern struct lgsm_handle *lgsm_init(const char *device); + +/* Terminate usage of libgsmd */ +extern int lgsm_exit(struct lgsm_handle *lh); + +/* Obtain file descriptor (e.g. for select-loop under app control) */ +extern int lgsm_fd(struct lgsm_handle *lh); + +extern int lgsm_register_handler(struct lgsm_handle *lh, int type, lgsm_msg_handler *handler); +extern void lgsm_unregister_handler(struct lgsm_handle *lh, int type); + +extern int lgsm_passthrough_send(struct lgsm_handle *lh, const char *tx); extern int lgsm_passthrough(struct lgsm_handle *lh, const char *tx, char *rx, unsigned int *rx_len); +extern int lgsm_subscriptions(struct lgsm_handle *lh, u_int32_t subscriptions); + +extern int lgsm_pin(struct lgsm_handle *lh, char *pin); #endif diff --git a/src/gsmd/gsmd.h b/src/gsmd/gsmd.h index 9c3a484..c67e15e 100644 --- a/src/gsmd/gsmd.h +++ b/src/gsmd/gsmd.h @@ -76,7 +76,7 @@ extern int gsmdlog_init(const char *path); /* write a message to the daemons' logfile */ void __gsmd_log(int level, const char *file, int line, const char *function, const char *message, ...); /* macro for logging including filename and line number */ -#define gsmd_log(level, format, args...) \ +#define gsmd_log(level, format, args ...) \ __gsmd_log(level, __FILE__, __LINE__, __FUNCTION__, format, ## args) #define DEBUGP(x, args ...) gsmd_log(GSMD_DEBUG, x, ## args) diff --git a/src/gsmd/unsolicited.c b/src/gsmd/unsolicited.c index 5242042..e97f478 100644 --- a/src/gsmd/unsolicited.c +++ b/src/gsmd/unsolicited.c @@ -217,6 +217,7 @@ static int clip_parse(char *buf, int len, const char *param, if (!comma) return -EINVAL; + if (comma - param > GSMD_ADDR_MAXLEN) return -EINVAL; @@ -308,7 +309,7 @@ static const struct gsmd_unsolicit gsm0707_unsolicit[] = { /* called by midlevel parser if a response seems unsolicited */ int unsolicited_parse(struct gsmd *g, char *buf, int len, const char *param) { - int i; + int i, rc; for (i = 0; i < ARRAY_SIZE(gsm0707_unsolicit); i++) { const char *colon; @@ -316,14 +317,20 @@ int unsolicited_parse(struct gsmd *g, char *buf, int len, const char *param) strlen(gsm0707_unsolicit[i].prefix))) continue; - colon = strchr(buf, ':') + 1; + colon = strchr(buf, ':') + 2; if (colon > buf+len) colon = NULL; - return gsm0707_unsolicit[i].parse(buf, len, colon, g); + rc = gsm0707_unsolicit[i].parse(buf, len, colon, g); + if (rc < 0) + gsmd_log(GSMD_ERROR, "error %d during parse of " + "unsolicied response `%s'\n", rc, buf); + return rc; } /* FIXME: call vendor-specific unsolicited code parser */ + gsmd_log(GSMD_NOTICE, "no parser for unsolicited response `%s'\n", buf); + return -ENOENT; } diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c index b774f74..93e9751 100644 --- a/src/gsmd/usock.c +++ b/src/gsmd/usock.c @@ -30,13 +30,15 @@ void usock_cmd_enqueue(struct gsmd_ucmd *ucmd, struct gsmd_user *gu) static int usock_cmd_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp) { struct gsmd_user *gu = ctx; - struct gsmd_ucmd *ucmd = malloc(sizeof(*ucmd)+cmd->buflen); + int rlen = strlen(resp)+1; + struct gsmd_ucmd *ucmd = malloc(sizeof(*ucmd)+rlen); DEBUGP("entering(cmd=%p, gu=%p)\n", cmd, gu); if (!ucmd) return -ENOMEM; + /* FIXME: pass error values back somehow */ ucmd->hdr.version = GSMD_PROTO_VERSION; ucmd->hdr.msg_type = GSMD_MSG_PASSTHROUGH; ucmd->hdr.msg_subtype = GSMD_PASSTHROUGH_RESP; @@ -70,49 +72,77 @@ static int usock_rcv_event(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int l if (len < sizeof(*gph) + sizeof(u_int32_t)) return -EINVAL; - if (gph->msg_subtype != GSMD_EVENT_SUBSCRIPTIONS) + if (gph->msg_subtype != GSMD_EVT_SUBSCRIPTIONS) return -EINVAL; gu->subscriptions = *evtmask; } -static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len) +static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, + int len) { - struct gsmd_atcmd *cmd; + struct gsmd_atcmd *cmd = NULL; + struct gsmd_addr *ga; switch (gph->msg_subtype) { case GSMD_VOICECALL_DIAL: - /* FIXME */ + if (len < sizeof(*gph) + sizeof(*ga)) + return -EINVAL; + 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); + sprintf(cmd->buf, "ATD%s;", ga->number); + /* FIXME: number type! */ break; case GSMD_VOICECALL_HANGUP: cmd = atcmd_fill("ATH0", 5, &usock_cmd_cb, gu, gph->id); break; + case GSMD_VOICECALL_ANSWER: + cmd = atcmd_fill("ATA", 4, &usock_cmd_cb, gu, gph->id); + break; default: return -EINVAL; } - return 0; + if (cmd) + return atcmd_submit(gu->gsmd, cmd); + else + return 0; } -#define GSMD_PIN_MAXLEN 16 +static int null_cmd_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp) +{ + gsmd_log(GSMD_DEBUG, "null cmd cb\n"); + return 0; +} -static int usock_rcv_pin(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len) +static int usock_rcv_pin(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, + int len) { u_int8_t *pin = (u_int8_t *)gph + sizeof(*gph); int pin_len = len - sizeof(*gph); - char pinbuf[GSMD_PIN_MAXLEN + 11]; /* `AT+CPIN=""\0' */ - - snprintf(pinbuf, sizeof(pinbuf), "AT+CPIN=\"%s\"", pin); + struct gsmd_atcmd *cmd; switch (gph->msg_subtype) { case GSMD_PIN_INPUT: /* FIXME */ break; default: + gsmd_log(GSMD_ERROR, "unknown pin type %u\n", + gph->msg_subtype); return -EINVAL; } - return 0; + cmd = atcmd_fill("AT+CPIN=\"", 9+1+1+strlen(pin), + &null_cmd_cb, gu, 0); + if (!cmd) + return -ENOMEM; + + strcat(cmd->buf, pin); + strcat(cmd->buf, "\""); + + return atcmd_submit(gu->gsmd, cmd); } static usock_msg_handler *pcmd_type_handlers[__NUM_GSMD_MSGS] = { diff --git a/src/libgsmd/Makefile.am b/src/libgsmd/Makefile.am index a718116..640f42a 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_la_SOURCES = libgsmd.c libgsmd_input.c libgsmd_voicecall.c libgsmd_passthrough.c libgsmd_event.c diff --git a/src/libgsmd/lgsm_internals.h b/src/libgsmd/lgsm_internals.h index 0601959..bf1f4a2 100644 --- a/src/libgsmd/lgsm_internals.h +++ b/src/libgsmd/lgsm_internals.h @@ -3,11 +3,13 @@ #include -typedef int lgsm_msg_handler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh); - struct lgsm_handle { int fd; lgsm_msg_handler *handler[__NUM_GSMD_MSGS]; }; +int lgsm_send(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh); +struct gsmd_msg_hdr *lgsm_gmh_fill(int type, int subtype, int payload_len); +#define lgsm_gmh_free(x) free(x) + #endif /* _LGSM_INTERNALS_H */ diff --git a/src/libgsmd/libgsmd.c b/src/libgsmd/libgsmd.c index b916898..7f936e8 100644 --- a/src/libgsmd/libgsmd.c +++ b/src/libgsmd/libgsmd.c @@ -87,6 +87,22 @@ int lgsm_handle_packet(struct lgsm_handle *lh, char *buf, int len) fprintf(stderr, "unable to handle packet type=%u\n", gmh->msg_type); } +int lgsm_register_handler(struct lgsm_handle *lh, int type, lgsm_msg_handler *handler) +{ + if (type >= __NUM_GSMD_MSGS) + return -EINVAL; + + lh->handler[type] = handler; + + return 0; +} + +void lgsm_unregister_handler(struct lgsm_handle *lh, int type) +{ + if (type < __NUM_GSMD_MSGS) + lh->handler[type] = NULL; +} + /* blocking read and processing of packets until packet matching 'id' is found */ int lgsm_blocking_wait_packet(struct lgsm_handle *lh, u_int16_t id, struct gsmd_msg_hdr *gmh, int rlen) @@ -131,6 +147,8 @@ struct lgsm_handle *lgsm_init(const char *device) return NULL; } + lgsm_evt_init(lh); + return lh; } @@ -140,3 +158,47 @@ int lgsm_exit(struct lgsm_handle *lh) return 0; } + + +static u_int16_t next_msg_id; + +int lgsm_send(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh) +{ + gmh->id = next_msg_id++; + return send(lh->fd, (char *) gmh, sizeof(*gmh) + gmh->len, 0); +} + +struct gsmd_msg_hdr *lgsm_gmh_fill(int type, int subtype, int payload_len) +{ + struct gsmd_msg_hdr *gmh = malloc(sizeof(*gmh)+payload_len); + if (!gmh) + return NULL; + + memset(gmh, 0, sizeof(*gmh)); + + gmh->version = GSMD_PROTO_VERSION; + gmh->msg_type = type; + gmh->msg_subtype = subtype; + gmh->len = payload_len; + + return gmh; +} + + +int lgsm_pin(struct lgsm_handle *lh, char *pin) +{ + int rc; + struct gsmd_msg_hdr *gmh; + + gmh = lgsm_gmh_fill(GSMD_MSG_PIN, GSMD_PIN_INPUT, strlen(pin)+1); + if (!gmh) + return -ENOMEM; + + gmh->data[0] = '\0'; + strcat(gmh->data, pin); + + rc = lgsm_send(lh, gmh); + free(gmh); + + return rc; +} diff --git a/src/libgsmd/libgsmd_event.c b/src/libgsmd/libgsmd_event.c new file mode 100644 index 0000000..6e19eff --- /dev/null +++ b/src/libgsmd/libgsmd_event.c @@ -0,0 +1,57 @@ +/* libgsmd event demultiplexer handler */ + +#include +#include +#include + +#include +#include + +#include +#include + +#include "lgsm_internals.h" + +static lgsm_evt_handler *evt_handlers[__NUM_GSMD_EVT]; + +int lgsm_evt_handler_register(struct lgsm_handle *lh, int evt_type, + lgsm_evt_handler *handler) +{ + if (evt_type >= __NUM_GSMD_EVT) + return -EINVAL; + + evt_handlers[evt_type] = handler; + + return 0; +} + +void lgsm_evt_handler_unregister(struct lgsm_handle *lh, int evt_type) +{ + if (evt_type < __NUM_GSMD_EVT) + evt_handlers[evt_type] = NULL; +} + + +static int evt_demux_msghandler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh) +{ + struct gsmd_evt_auxdata *aux = gmh->data; + + if (gmh->len < sizeof(*aux)) + return -EIO; + + if (gmh->msg_type != GSMD_MSG_EVENT || + gmh->msg_subtype >= __NUM_GSMD_EVT) + return -EINVAL; + + return evt_handlers[gmh->msg_subtype](lh, gmh->msg_subtype, aux); +} + +int lgsm_evt_init(struct lgsm_handle *lh) +{ + return lgsm_register_handler(lh, GSMD_MSG_EVENT, &evt_demux_msghandler); +} + +void lgsm_evt_exit(struct lgsm_handle *lh) +{ + lgsm_unregister_handler(lh, GSMD_MSG_EVENT); +} diff --git a/src/libgsmd/libgsmd_passthrough.c b/src/libgsmd/libgsmd_passthrough.c index 66f4a82..5362e4e 100644 --- a/src/libgsmd/libgsmd_passthrough.c +++ b/src/libgsmd/libgsmd_passthrough.c @@ -12,26 +12,15 @@ #include "lgsm_internals.h" -static u_int16_t next_msg_id; - -static int lgsm_send(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh) -{ - gmh->id = next_msg_id++; - return send(lh->fd, (char *) gmh, sizeof(*gmh) + gmh->len, 0); -} - #define PT_BUF_SIZE 1024 static char passthrough_buf[sizeof(struct gsmd_msg_hdr)+PT_BUF_SIZE]; static char passthrough_rbuf[sizeof(struct gsmd_msg_hdr)+PT_BUF_SIZE]; -int lgsm_passthrough(struct lgsm_handle *lh, const char *tx, char *rx, unsigned int *rx_len) +int lgsm_passthrough_send(struct lgsm_handle *lh, const char *tx) { struct gsmd_msg_hdr *gmh = (struct gsmd_msg_hdr *)passthrough_buf; - struct gsmd_msg_hdr *rgmh = (struct gsmd_msg_hdr *)passthrough_rbuf; char *tx_buf = (char *)gmh + sizeof(*gmh); - char *rx_buf = (char *)rgmh + sizeof(*rgmh); int len = strlen(tx); - int rc; if (len > PT_BUF_SIZE) return -EINVAL; @@ -42,13 +31,27 @@ int lgsm_passthrough(struct lgsm_handle *lh, const char *tx, char *rx, unsigned gmh->len = len+1; strcpy(tx_buf, tx); - rc = lgsm_send(lh, gmh); - if (rc < len+sizeof(*gmh)) + if (lgsm_send(lh, gmh) < len+sizeof(*gmh)) + return -EIO; + + return gmh->id; +} + +int lgsm_passthrough(struct lgsm_handle *lh, const char *tx, char *rx, unsigned int *rx_len) +{ + struct gsmd_msg_hdr *rgmh = (struct gsmd_msg_hdr *)passthrough_rbuf; + char *rx_buf = (char *)rgmh + sizeof(*rgmh); + int rc; + + rc = lgsm_passthrough_send(lh, tx); + if (rc < 0) return rc; - /* since we synchronously want to wait for a response, we need to _internally_ loop over - * incoming packets and call the callbacks for intermediate messages (if applicable) */ - rc = lgsm_blocking_wait_packet(lh, gmh->id, passthrough_rbuf, sizeof(passthrough_rbuf)); + /* since we synchronously want to wait for a response, we need to + * _internally_ loop over incoming packets and call the callbacks for + * intermediate messages (if applicable) */ + rc = lgsm_blocking_wait_packet(lh, rc, passthrough_rbuf, + sizeof(passthrough_rbuf)); if (rc <= 0) return rc; diff --git a/src/libgsmd/libgsmd_voicecall.c b/src/libgsmd/libgsmd_voicecall.c index 25c565d..2a1d6e6 100644 --- a/src/libgsmd/libgsmd_voicecall.c +++ b/src/libgsmd/libgsmd_voicecall.c @@ -1,24 +1,62 @@ - +#include +#include +#include #include #include "lgsm_internals.h" +int lgsm_send_simple(struct lgsm_handle *lh, int type, int sub_type) +{ + struct gsmd_msg_hdr *gmh; + int rc; + + gmh = lgsm_gmh_fill(type, sub_type, 0); + if (!gmh) + return -ENOMEM; + rc = lgsm_send(lh, gmh); + if (rc < gmh->len + sizeof(*gmh)) { + lgsm_gmh_free(gmh); + return -EIO; + } + lgsm_gmh_free(gmh); + + return 0; +} int lgsm_voice_out_init(struct lgsm_handle *lh, const struct lgsm_addr *number) { - /* send ATD command */ - return -EINVAL; + struct gsmd_msg_hdr *gmh; + struct gsmd_addr *ga; + int rc; + + gmh = lgsm_gmh_fill(GSMD_MSG_VOICECALL, + GSMD_VOICECALL_DIAL, sizeof(*ga)); + if (!gmh) + return -ENOMEM; + ga = (struct gsmd_addr *) gmh->data; + ga->type = number->type; /* FIXME: is this correct? */ + memcpy(ga->number, number->addr, sizeof(ga->number)); + ga->number[sizeof(ga->number)-1] = '\0'; + + rc = lgsm_send(lh, gmh); + if (rc < gmh->len + sizeof(*gmh)) { + lgsm_gmh_free(gmh); + return -EIO; + } + + lgsm_gmh_free(gmh); + + return 0; } int lgsm_voice_in_accept(struct lgsm_handle *lh) { - return -EINVAL; + return lgsm_send_simple(lh, GSMD_MSG_VOICECALL, GSMD_VOICECALL_ANSWER); } int lgsm_voice_hangup(struct lgsm_handle *lh) { - /* Send ATH0 */ - return -EINVAL; + return lgsm_send_simple(lh, GSMD_MSG_VOICECALL, GSMD_VOICECALL_HANGUP); } diff --git a/src/util/Makefile.am b/src/util/Makefile.am index bec625a..aee83ca 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 +libgsmd_tool_SOURCES = libgsmd-tool.c shell.c event.c pin.c libgsmd_tool_LDADD = ../libgsmd/libgsmd.la libgsmd_tool_LDFLAGS = -dynamic diff --git a/src/util/event.c b/src/util/event.c new file mode 100644 index 0000000..601ea9a --- /dev/null +++ b/src/util/event.c @@ -0,0 +1,38 @@ +#include +#include + +#include +#include + +static int incall_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux) +{ + printf("EVENT: Incoming call type=%u!\n", aux->u.call.type); + + return 0; +} + +static int clip_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux) +{ + printf("EVENT: Incoming call clip=`%s'\n", aux->u.clip.addr.number); + + return 0; +} + +static int netreg_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux) +{ + printf("EVENT: Netreg\n"); + + return 0; +} + +int event_init(struct lgsm_handle *lh) +{ + int rc; + + rc = lgsm_evt_handler_register(lh, GSMD_EVT_IN_CALL, &incall_handler); + rc |= lgsm_evt_handler_register(lh, GSMD_EVT_IN_CLIP, &clip_handler); + rc |= lgsm_evt_handler_register(lh, GSMD_EVT_NETREG, &netreg_handler); + + return rc; +} + diff --git a/src/util/event.h b/src/util/event.h new file mode 100644 index 0000000..6901a2d --- /dev/null +++ b/src/util/event.h @@ -0,0 +1,2 @@ + +extern int event_init(struct lgsm_handle *lh); diff --git a/src/util/libgsmd-tool.c b/src/util/libgsmd-tool.c index e8590c1..8d4674c 100644 --- a/src/util/libgsmd-tool.c +++ b/src/util/libgsmd-tool.c @@ -8,6 +8,9 @@ #include +#include "pin.h" +#include "event.h" + #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif @@ -44,6 +47,7 @@ static struct option opts[] = { { "version", 0, 0, 'V' }, { "verbose", 0, 0, 'v' }, { "mode", 1, 0, 'm' }, + { "pin", 1, 0, 'p' }, { 0, 0, 0, 0 } }; @@ -57,6 +61,7 @@ static void help(void) int main(int argc, char **argv) { + char *pin = NULL; int rc, i, mode; printf("libgsm-tool - (C) 2006 by Harald Welte\n" @@ -64,7 +69,7 @@ int main(int argc, char **argv) while (1) { int c, option_index = 0; - c = getopt_long(argc, argv, "vVhm:", opts, &option_index); + c = getopt_long(argc, argv, "vVhm:p:", opts, &option_index); if (c == -1) break; @@ -86,6 +91,9 @@ int main(int argc, char **argv) exit(2); } break; + case 'p': + pin = optarg; + break; } } @@ -95,6 +103,9 @@ int main(int argc, char **argv) exit(1); } + pin_init(lgsmh, pin); + event_init(lgsmh); + switch (mode) { case MODE_SHELL: shell_main(lgsmh); diff --git a/src/util/pin.c b/src/util/pin.c new file mode 100644 index 0000000..b855e53 --- /dev/null +++ b/src/util/pin.c @@ -0,0 +1,39 @@ +#include +#include + +#include +#include + +#define PIN_SIZE 32 + +static char *pin; +static char pinbuf[PIN_SIZE+1]; + +static int pin_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux) +{ + int rc; + + printf("EVENT: PIN request (type=%u) ", aux->u.pin.type); + + /* FIXME: read pin from STDIN and send it back via lgsm_pin */ + if (aux->u.pin.type == 1 && pin) { + printf("Auto-responding with pin `%s'\n", pin); + lgsm_pin(lh, pin); + } else { + do { + printf("Please enter PIN: "); + rc = fscanf(stdin, "%32s\n", &pinbuf); + } while (rc < 1); + + return lgsm_pin(lh, pinbuf); + } + + return 0; +} + +int pin_init(struct lgsm_handle *lh, const char *pin_preset) +{ + pin = pin_preset; + return lgsm_evt_handler_register(lh, GSMD_EVT_PIN, &pin_handler); +} + diff --git a/src/util/pin.h b/src/util/pin.h new file mode 100644 index 0000000..534e2b4 --- /dev/null +++ b/src/util/pin.h @@ -0,0 +1,2 @@ + +extern int pin_init(struct lgsm_handle *lh, const char *pin_preset); diff --git a/src/util/shell.c b/src/util/shell.c index 3b13bc9..77f0c57 100644 --- a/src/util/shell.c +++ b/src/util/shell.c @@ -1,30 +1,66 @@ #include #include +#include +#include #include #define STDIN_BUF_SIZE 1024 -int shell_main(struct lgsmd_handle *lgsmh) +/* 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 shell_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) { - rc = fscanf(stdin, "%s", buf); - if (rc == EOF) { - printf("EOF\n"); - return -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 (rc <= 0) { - printf("NULL\n"); - continue; + 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); } - 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); } } -- cgit v1.2.3