summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/gsmd/event.h1
-rw-r--r--include/gsmd/usock.h10
-rw-r--r--include/libgsmd/event.h12
-rw-r--r--include/libgsmd/libgsmd.h35
-rw-r--r--src/gsmd/gsmd.h2
-rw-r--r--src/gsmd/unsolicited.c13
-rw-r--r--src/gsmd/usock.c54
-rw-r--r--src/libgsmd/Makefile.am2
-rw-r--r--src/libgsmd/lgsm_internals.h6
-rw-r--r--src/libgsmd/libgsmd.c62
-rw-r--r--src/libgsmd/libgsmd_event.c57
-rw-r--r--src/libgsmd/libgsmd_passthrough.c37
-rw-r--r--src/libgsmd/libgsmd_voicecall.c50
-rw-r--r--src/util/Makefile.am2
-rw-r--r--src/util/event.c38
-rw-r--r--src/util/event.h2
-rw-r--r--src/util/libgsmd-tool.c13
-rw-r--r--src/util/pin.c39
-rw-r--r--src/util/pin.h2
-rw-r--r--src/util/shell.c56
20 files changed, 416 insertions, 77 deletions
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 <gsmd/event.h>
/* 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 <sys/types.h>
#include <errno.h>
+#include <gsmd/usock.h>
+
/* 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 <gsmd/usock.h>
-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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <libgsmd/voicecall.h>
+#include <libgsmd/event.h>
+
+#include <gsmd/usock.h>
+#include <gsmd/event.h>
+
+#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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
#include <libgsmd/voicecall.h>
#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 <stdio.h>
+#include <string.h>
+
+#include <libgsmd/libgsmd.h>
+#include <libgsmd/event.h>
+
+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 <libgsmd/libgsmd.h>
+#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 <stdio.h>
+#include <string.h>
+
+#include <libgsmd/libgsmd.h>
+#include <libgsmd/event.h>
+
+#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 <stdio.h>
#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
#include <libgsmd/libgsmd.h>
#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);
}
}
personal git repositories of Harald Welte. Your mileage may vary