diff options
| -rw-r--r-- | include/gsmd/event.h | 1 | ||||
| -rw-r--r-- | include/gsmd/usock.h | 10 | ||||
| -rw-r--r-- | include/libgsmd/event.h | 12 | ||||
| -rw-r--r-- | include/libgsmd/libgsmd.h | 35 | ||||
| -rw-r--r-- | src/gsmd/gsmd.h | 2 | ||||
| -rw-r--r-- | src/gsmd/unsolicited.c | 13 | ||||
| -rw-r--r-- | src/gsmd/usock.c | 54 | ||||
| -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 | ||||
| -rw-r--r-- | src/util/Makefile.am | 2 | ||||
| -rw-r--r-- | src/util/event.c | 38 | ||||
| -rw-r--r-- | src/util/event.h | 2 | ||||
| -rw-r--r-- | src/util/libgsmd-tool.c | 13 | ||||
| -rw-r--r-- | src/util/pin.c | 39 | ||||
| -rw-r--r-- | src/util/pin.h | 2 | ||||
| -rw-r--r-- | src/util/shell.c | 56 | 
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);  	}  }  | 
