diff options
author | laforge <laforge@99fdad57-331a-0410-800a-d7fa5415bdb3> | 2006-10-23 20:28:37 +0000 |
---|---|---|
committer | laforge <laforge@99fdad57-331a-0410-800a-d7fa5415bdb3> | 2006-10-23 20:28:37 +0000 |
commit | cbffc8d64707828b045b679e8db0269ae362ffcf (patch) | |
tree | 9ba71c11b92600548581af9d582a2c1feb18473f /src/libgsmd | |
parent | 7fe163099476937a14dd7a0714de542f7f94f665 (diff) |
more gsmd/libgsm implementation
git-svn-id: http://svn.openmoko.org/trunk/src/target/gsm@114 99fdad57-331a-0410-800a-d7fa5415bdb3
Diffstat (limited to 'src/libgsmd')
-rw-r--r-- | src/libgsmd/Makefile.am | 2 | ||||
-rw-r--r-- | src/libgsmd/lgsm_internals.h | 6 | ||||
-rw-r--r-- | src/libgsmd/libgsmd.c | 62 | ||||
-rw-r--r-- | src/libgsmd/libgsmd_event.c | 57 | ||||
-rw-r--r-- | src/libgsmd/libgsmd_passthrough.c | 37 | ||||
-rw-r--r-- | src/libgsmd/libgsmd_voicecall.c | 50 |
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); } |