diff options
| -rw-r--r-- | include/gsmd/usock.h | 9 | ||||
| -rw-r--r-- | include/libgsmd/misc.h | 4 | ||||
| -rw-r--r-- | src/gsmd/atcmd.c | 11 | ||||
| -rw-r--r-- | src/gsmd/gsmd.c | 30 | ||||
| -rw-r--r-- | src/gsmd/usock.c | 48 | ||||
| -rw-r--r-- | src/libgsmd/Makefile.am | 2 | ||||
| -rw-r--r-- | src/util/Makefile.am | 2 | ||||
| -rw-r--r-- | src/util/atcmd.c | 66 | ||||
| -rw-r--r-- | src/util/atcmd.h | 2 | ||||
| -rw-r--r-- | src/util/event.c | 27 | ||||
| -rw-r--r-- | src/util/libgsmd-tool.c | 11 | ||||
| -rw-r--r-- | src/util/pin.c | 2 | ||||
| -rw-r--r-- | src/util/shell.c | 44 | ||||
| -rw-r--r-- | src/util/shell.h | 2 | 
14 files changed, 229 insertions, 31 deletions
diff --git a/include/gsmd/usock.h b/include/gsmd/usock.h index f5d26ae..2eaa6cf 100644 --- a/include/gsmd/usock.h +++ b/include/gsmd/usock.h @@ -46,6 +46,15 @@ enum gsmd_msg_pin_type {  	GSMD_PIN_INPUT		= 1,  }; +enum gsmd_msg_phone { +	GSMD_PHONE_POWERUP	= 1, +	GSMD_PHONE_POWERDOWN	= 2, +}; + +enum gsmd_msg_network { +	GSMD_NETWORK_REGISTER	= 1, +}; +  /* Length from 3GPP TS 04.08, Clause 10.5.4.7 */  #define GSMD_ADDR_MAXLEN	32 diff --git a/include/libgsmd/misc.h b/include/libgsmd/misc.h index e191ce6..95e219d 100644 --- a/include/libgsmd/misc.h +++ b/include/libgsmd/misc.h @@ -8,6 +8,8 @@  #include <libgsmd/libgsmd.h> +extern int lgsm_phone_power(struct lgsm_handle *lh, int power); +  enum lgsm_netreg_state {  	LGSM_NETREG_ST_NOTREG		= 0,  	LGSM_NETREG_ST_REG_HOME		= 1, @@ -21,6 +23,8 @@ enum lgsm_netreg_state {  extern int lgsm_get_netreg_state(struct lgsm_handle *lh,  				 enum lgsm_netreg_state *state); +extern int lgsm_netreg_register(struct lgsm_handle *lh, int oper); +  enum lgsm_info_type {  	LGSM_INFO_TYPE_NONE		= 0,  	LGSM_INFO_TYPE_MANUF		= 1, diff --git a/src/gsmd/atcmd.c b/src/gsmd/atcmd.c index 2647192..53120f4 100644 --- a/src/gsmd/atcmd.c +++ b/src/gsmd/atcmd.c @@ -156,6 +156,11 @@ static int ml_parse(const char *buf, int len, void *ctx)  	DEBUGP("buf=`%s'(%d)\n", buf, len); +	if (!strcmp(buf, "AT-Command Interpreter ready")) { +		gsmd_initsettings(g); +		return 0; +	} +  	/* responses come in order, so first response has to be for first  	 * command we sent, i.e. first entry in list */  	cmd = llist_entry(g->busy_atcmds.next, struct gsmd_atcmd, list); @@ -248,13 +253,15 @@ static int ml_parse(const char *buf, int len, void *ctx)  		/* FIXME: handling of those special commands in response to  		 * ATD / ATA */ -		if (!strncmp(buf, "NO CARRIER", 10)) { +		if (!strncmp(buf, "NO CARRIER", 11)) {  			/* Part of Case 'D' */ +			final = 1;  			goto final_cb;  		}  		if (!strncmp(buf, "BUSY", 4)) {  			/* Part of Case 'D' */ +			final = 1;  			goto final_cb;  		}  	} @@ -388,6 +395,8 @@ struct gsmd_atcmd *atcmd_fill(const char *cmd, int rlen,  /* submit an atcmd in the global queue of pending atcmds */  int atcmd_submit(struct gsmd *g, struct gsmd_atcmd *cmd)  { +	DEBUGP("submitting command `%s'\n", cmd->buf); +  	llist_add_tail(&cmd->list, &g->pending_atcmds);  	g->gfd_uart.when |= GSMD_FD_WRITE; diff --git a/src/gsmd/gsmd.c b/src/gsmd/gsmd.c index c8a3b3f..9595d4b 100644 --- a/src/gsmd/gsmd.c +++ b/src/gsmd/gsmd.c @@ -26,32 +26,24 @@ static int gsmd_test_atcb(struct gsmd_atcmd *cmd, void *ctx, char *resp)  	return 0;  } -static int gsmd_test(struct gsmd *gsmd) +static int gsmd_simplecmd(struct gsmd *gsmd, char *cmdtxt)  {  	struct gsmd_atcmd *cmd; -	cmd = atcmd_fill("AT+CRC?", 255, &gsmd_test_atcb, NULL, 0); -	return atcmd_submit(gsmd, cmd); -} - -static int atcmd_test(struct gsmd *gsmd) -{ -	struct gsmd_atcmd *cmd; -	cmd = atcmd_fill("ATE0", 255, &gsmd_test_atcb, NULL, 0); +	cmd = atcmd_fill(cmdtxt, strlen(cmdtxt)+1, &gsmd_test_atcb, NULL, 0); +	if (!cmd) +		return -ENOMEM; +	  	return atcmd_submit(gsmd, cmd);  } -static int gsmd_initsettings(struct gsmd *gsmd) +int gsmd_initsettings(struct gsmd *gsmd)  {  	int rc; -	struct gsmd_atcmd *cmd; - -	cmd = atcmd_fill("ATV1", 255, &gsmd_test_atcb, NULL, 0); -	rc = atcmd_submit(gsmd, cmd); -	if (rc < 0) -		return rc; +	 +	rc |= gsmd_simplecmd(gsmd, "ATE0V1"); +	rc |= gsmd_simplecmd(gsmd, "AT+CRC=1;+CREG=2;+CMEE=1;+CLIP=1;+COLP=1;+CTZR=1;+CFUN=1"); -	cmd = atcmd_fill("+CRC=1;+CREG=2;+CMEE=2;+CLIP=1;+COLP=1;+CTZR=1", 255, &gsmd_test_atcb, NULL, 0); -	return atcmd_submit(gsmd, cmd); +	return rc;  }  struct bdrt { @@ -207,8 +199,6 @@ int main(int argc, char **argv)  		setsid();  	} -	atcmd_test(&g); -	gsmd_test(&g);  	gsmd_initsettings(&g);  	while (1) { diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c index 93e9751..76be1aa 100644 --- a/src/gsmd/usock.c +++ b/src/gsmd/usock.c @@ -88,7 +88,7 @@ static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,  	case GSMD_VOICECALL_DIAL:  		if (len < sizeof(*gph) + sizeof(*ga))  			return -EINVAL; -		ga = (struct gsmd_addr *) (void *)gph + sizeof(*gph); +		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); @@ -145,11 +145,57 @@ static int usock_rcv_pin(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,  	return atcmd_submit(gu->gsmd, cmd);  } +static int usock_rcv_phone(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,  +			   int len) +{ +	struct gsmd_atcmd *cmd; + +	switch (gph->msg_subtype) { +	case GSMD_PHONE_POWERUP: +		cmd = atcmd_fill("AT+CFUN=1", 9+1, +				 &null_cmd_cb, gu, 0); +		break; + +	case GSMD_PHONE_POWERDOWN: +		cmd = atcmd_fill("AT+CFUN=0", 9+1, +				 &null_cmd_cb, gu, 0); +		break; +	default: +		return -EINVAL; +	} +	if (!cmd) +		return -ENOMEM; + +	return atcmd_submit(gu->gsmd, cmd); +} + +static int usock_rcv_network(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,  +			     int len) +{ +	struct gsmd_atcmd *cmd; + +	switch (gph->msg_subtype) { +	case GSMD_NETWORK_REGISTER: +		cmd = atcmd_fill("AT+COPS", 9+1, +				 &null_cmd_cb, gu, 0); +		break; +	default: +		return -EINVAL; +	} +	if (!cmd) +		return -ENOMEM; + +	return atcmd_submit(gu->gsmd, cmd); +} + +  static usock_msg_handler *pcmd_type_handlers[__NUM_GSMD_MSGS] = {  	[GSMD_MSG_PASSTHROUGH]	= &usock_rcv_passthrough,  	[GSMD_MSG_EVENT]	= &usock_rcv_event,  	[GSMD_MSG_VOICECALL]	= &usock_rcv_voicecall,  	[GSMD_MSG_PIN]		= &usock_rcv_pin, +	[GSMD_MSG_PHONE]	= &usock_rcv_phone, +	[GSMD_MSG_NETWORK]	= &usock_rcv_network,  };  static int usock_rcv_pcmd(struct gsmd_user *gu, char *buf, int len) diff --git a/src/libgsmd/Makefile.am b/src/libgsmd/Makefile.am index 640f42a..08233d3 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_event.c +libgsmd_la_SOURCES = libgsmd.c libgsmd_input.c libgsmd_voicecall.c libgsmd_passthrough.c libgsmd_event.c libgsmd_phone.c libgsmd_network.c diff --git a/src/util/Makefile.am b/src/util/Makefile.am index aee83ca..fb17c85 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 event.c pin.c +libgsmd_tool_SOURCES = libgsmd-tool.c shell.c event.c pin.c atcmd.c  libgsmd_tool_LDADD = ../libgsmd/libgsmd.la  libgsmd_tool_LDFLAGS = -dynamic diff --git a/src/util/atcmd.c b/src/util/atcmd.c new file mode 100644 index 0000000..6cf9aa7 --- /dev/null +++ b/src/util/atcmd.c @@ -0,0 +1,66 @@ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +#include <libgsmd/libgsmd.h> + +#define STDIN_BUF_SIZE	1024 + +/* 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 atcmd_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) { +		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 (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); +		} +		/* this is a synchronous call for a passthrough command */ +		lgsm_passthrough(lgsmh, buf, rbuf, &rlen); +		printf("RSTR=`%s'\n", rbuf); +	} +} diff --git a/src/util/atcmd.h b/src/util/atcmd.h new file mode 100644 index 0000000..3a385ae --- /dev/null +++ b/src/util/atcmd.h @@ -0,0 +1,2 @@ + +extern int atcmd_main(struct lgsm_handle *lgsmh); diff --git a/src/util/event.c b/src/util/event.c index 601ea9a..0f09d47 100644 --- a/src/util/event.c +++ b/src/util/event.c @@ -20,7 +20,32 @@ static int clip_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata  static int netreg_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux)  { -	printf("EVENT: Netreg\n"); +	printf("EVENT: Netreg "); + +	switch (aux->u.netreg.state) { +	case 0: +		printf("not searching for network "); +		break; +	case 1: +		printf("registered (home network) "); +		break; +	case 2: +		printf("searching for network "); +		break; +	case 3: +		printf("registration denied "); +		break; +	case 5: +		printf("registered (roaming) "); +		break; +	} + +	if (aux->u.netreg.lac) +		printf("LocationAreaCode=0x%04X ", aux->u.netreg.lac); +	if (aux->u.netreg.ci) +		printf("CellID=0x%04X ", aux->u.netreg.ci); +	 +	printf("\n");  	return 0;  } diff --git a/src/util/libgsmd-tool.c b/src/util/libgsmd-tool.c index 8d4674c..42a8e7c 100644 --- a/src/util/libgsmd-tool.c +++ b/src/util/libgsmd-tool.c @@ -10,6 +10,8 @@  #include "pin.h"  #include "event.h" +#include "shell.h" +#include "atcmd.h"  #ifndef ARRAY_SIZE  #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) @@ -22,12 +24,14 @@ enum mode_enum {  	MODE_NONE,  	MODE_SHELL,  	MODE_EVENTLOG, +	MODE_ATCMD,  };  static char *modes[] = {  	[MODE_NONE]	= "",  	[MODE_SHELL]	= "shell",  	[MODE_EVENTLOG]	= "eventlog", +	[MODE_ATCMD]	= "atcmd",  };  static int parse_mode(char *modestr) @@ -56,7 +60,9 @@ static void help(void)  	printf("Usage:\n"  		"\t-h\t--help\tPrint this Help message\n"  		"\t-V\t--version\tPrint version number\n" -		"\t-v\t--verbose\tBe more verbose\n"); +		"\t-v\t--verbose\tBe more verbose\n" +		"\t-m\t--mode\tSet mode {passthrough,atcmd}\n" +		);  }  int main(int argc, char **argv) @@ -107,6 +113,9 @@ int main(int argc, char **argv)  	event_init(lgsmh);  	switch (mode) { +	case MODE_ATCMD: +		atcmd_main(lgsmh); +		break;  	case MODE_SHELL:  		shell_main(lgsmh);  		break; diff --git a/src/util/pin.c b/src/util/pin.c index b855e53..c51bd81 100644 --- a/src/util/pin.c +++ b/src/util/pin.c @@ -22,7 +22,7 @@ static int pin_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata  	} else {  		do {  			printf("Please enter PIN: "); -			rc = fscanf(stdin, "%32s\n", &pinbuf); +			rc = fscanf(stdin, "%32s", &pinbuf);  		} while (rc < 1);  		return lgsm_pin(lh, pinbuf); diff --git a/src/util/shell.c b/src/util/shell.c index 77f0c57..2875758 100644 --- a/src/util/shell.c +++ b/src/util/shell.c @@ -4,6 +4,8 @@  #include <unistd.h>  #include <libgsmd/libgsmd.h> +#include <libgsmd/voicecall.h> +#include <libgsmd/misc.h>  #define STDIN_BUF_SIZE	1024 @@ -14,6 +16,17 @@ static int pt_msghandler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh)  	printf("RSTR=`%s'\n", payload);  } +static int shell_help(void) +{ +	printf( "\tA\tAnswer incoming call\n" +		"\tD\tDial outgoing number\n" +		"\tH\tHangup call\n" +		"\tO\tPower On\n" +		"\to\tPower Off\n" +		"\tR\tRegister Netowrk\n" +		); +} +  int shell_main(struct lgsm_handle *lgsmh)  {  	int rc; @@ -48,6 +61,7 @@ int shell_main(struct lgsm_handle *lgsmh)  		if (FD_ISSET(0, &readset)) {  			/* we've received something on stdin.  send it as passthrough  			 * to gsmd */ +			printf("# ");  			rc = fscanf(stdin, "%s", buf);  			if (rc == EOF) {  				printf("EOF\n"); @@ -57,10 +71,32 @@ int shell_main(struct lgsm_handle *lgsmh)  				printf("NULL\n");  				continue;  			} -			printf("STR=`%s'\n", buf); +			if (!strcmp(buf, "h")) { +				shell_help(); +			} else if (!strcmp(buf, "?")) { +				shell_help(); +			} else if (!strcmp(buf, "H")) { +				printf("Hangup\n"); +				lgsm_voice_hangup(lgsmh); +			} else if (buf[0] == 'D') { +				struct lgsm_addr addr; +				printf("Dial %s\n", buf+1); +				addr.type = 129; +				strncpy(addr.addr, buf+1, sizeof(addr.addr)-1); +				addr.addr[sizeof(addr.addr)-1] = '\0'; +				lgsm_voice_out_init(lgsmh, &addr); +			} else if (!strcmp(buf, "A")) { +				printf("Answer\n"); +				lgsm_voice_in_accept(lgsmh); +			} else if (!strcmp(buf, "O")) { +				lgsm_phone_power(lgsmh, 1); +			} else if (!strcmp(buf, "o")) { +				lgsm_phone_power(lgsmh, 0); +			} else if (!strcmp(buf, "R")) { +				lgsm_netreg_register(lgsmh, 0); +			} else { +				printf("Unknown command `%s'\n", buf); +			}  		} -		/* this is a synchronous call for a passthrough command */ -		lgsm_passthrough(lgsmh, buf, rbuf, &rlen); -		printf("RSTR=`%s'\n", rbuf);  	}  } diff --git a/src/util/shell.h b/src/util/shell.h new file mode 100644 index 0000000..d383de9 --- /dev/null +++ b/src/util/shell.h @@ -0,0 +1,2 @@ + +extern int shell_main(struct lgsm_handle *lgsmh);  | 
