diff options
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);  }  | 
