summaryrefslogtreecommitdiff
path: root/src/libgsmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libgsmd')
-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
6 files changed, 188 insertions, 26 deletions
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);
}
personal git repositories of Harald Welte. Your mileage may vary