diff options
| -rw-r--r-- | include/gsmd/sms.h | 2 | ||||
| -rw-r--r-- | include/gsmd/usock.h | 23 | ||||
| -rw-r--r-- | src/gsmd/Makefile.am | 2 | ||||
| -rw-r--r-- | src/gsmd/gsmd.c | 4 | ||||
| -rw-r--r-- | src/gsmd/sms_cb.c | 201 | ||||
| -rw-r--r-- | src/gsmd/sms_pdu.c | 2 | ||||
| -rw-r--r-- | src/gsmd/usock.c | 2 | ||||
| -rw-r--r-- | src/util/event.c | 8 | 
8 files changed, 206 insertions, 38 deletions
diff --git a/include/gsmd/sms.h b/include/gsmd/sms.h index 145b585..ac16509 100644 --- a/include/gsmd/sms.h +++ b/include/gsmd/sms.h @@ -5,6 +5,8 @@  #include <gsmd/gsmd.h> +int sms_cb_init(struct gsmd *gsmd); +  int sms_pdu_make_smssubmit(char *dest, const struct gsmd_sms_submit *src);  int sms_pdu_to_msg(struct gsmd_sms_list *dst, const u_int8_t *src,  		int pdulen, int len); diff --git a/include/gsmd/usock.h b/include/gsmd/usock.h index 631238a..f42a766 100644 --- a/include/gsmd/usock.h +++ b/include/gsmd/usock.h @@ -55,6 +55,11 @@ enum gsmd_msg_phone {  	GSMD_PHONE_POWERDOWN	= 2,  }; +enum gsmd_msg_cb { +	GSMD_CB_SUBSCRIBE	= 1, +	GSMD_CB_UNSUBSCRIBE	= 2, +}; +  enum gsmd_msg_network {  	GSMD_NETWORK_REGISTER	= 1,  	GSMD_NETWORK_SIGQ_GET	= 2, @@ -65,11 +70,15 @@ enum gsmd_msg_network {  };  enum gsmd_msg_sms { -	GSMD_SMS_LIST		= 1, -	GSMD_SMS_READ		= 2, -	GSMD_SMS_SEND		= 3, -	GSMD_SMS_WRITE		= 4, -	GSMD_SMS_DELETE		= 5,	 +	GSMD_SMS_LIST			= 1, +	GSMD_SMS_READ			= 2, +	GSMD_SMS_SEND			= 3, +	GSMD_SMS_WRITE			= 4, +	GSMD_SMS_DELETE			= 5, +	GSMD_SMS_GET_MSG_STORAGE	= 6, +	GSMD_SMS_SET_MSG_STORAGE	= 7, +	GSMD_SMS_GET_SERVICE_CENTRE	= 8, +	GSMD_SMS_SET_SERVICE_CENTRE	= 9,  };  /* SMS stat from 3GPP TS 07.05, Clause 3.1 */ @@ -248,8 +257,8 @@ struct gsmd_evt_auxdata {  			struct gsmd_addr addr;  		} colp;  		struct { -			/* TBD */ -			struct gsmd_addr addr; +			u_int8_t memtype; +			int index;  		} sms;  		struct {  			enum gsmd_pin_type type; diff --git a/src/gsmd/Makefile.am b/src/gsmd/Makefile.am index 6b25812..1ff1970 100644 --- a/src/gsmd/Makefile.am +++ b/src/gsmd/Makefile.am @@ -7,7 +7,7 @@ sbin_PROGRAMS = gsmd  gsmd_CFLAGS = -D PLUGINDIR=\"$(plugindir)\"  gsmd_SOURCES = gsmd.c atcmd.c select.c machine.c vendor.c unsolicited.c log.c \  	       usock.c talloc.c timer.c operator_cache.c ext_response.c \ -	       sms_pdu.c +	       sms_cb.c sms_pdu.c  gsmd_LDADD = -ldl  gsmd_LDFLAGS = -Wl,--export-dynamic diff --git a/src/gsmd/gsmd.c b/src/gsmd/gsmd.c index 734620e..5e9b046 100644 --- a/src/gsmd/gsmd.c +++ b/src/gsmd/gsmd.c @@ -185,7 +185,9 @@ static int gsmd_initsettings2(struct gsmd *gsmd)  #if 0  	/* Select TE character set */		  	rc |= gsmd_simplecmd(gsmd, "AT+CSCS=\"UCS2\""); -#endif	 +#endif + +	sms_cb_init(gsmd);  	if (gsmd->vendorpl && gsmd->vendorpl->initsettings)  		return gsmd->vendorpl->initsettings(gsmd); diff --git a/src/gsmd/sms_cb.c b/src/gsmd/sms_cb.c index 22bf613..9884bfb 100644 --- a/src/gsmd/sms_cb.c +++ b/src/gsmd/sms_cb.c @@ -36,11 +36,11 @@  #include <gsmd/select.h>  #include <gsmd/atcmd.h>  #include <gsmd/usock.h> +#include <gsmd/unsolicited.h>  enum ts0705_mem_type {  	GSM0705_MEMTYPE_NONE,  	GSM0705_MEMTYPE_BROADCAST, -	GSM0705_MEMTYPE_BROADCAST,  	GSM0705_MEMTYPE_ME_MESSAGE,  	GSM0705_MEMTYPE_MT,  	GSM0705_MEMTYPE_SIM, @@ -48,7 +48,7 @@ enum ts0705_mem_type {  	GSM0705_MEMTYPE_SR,  }; -static const char *ts0705_memtype_name = { +static const char *ts0705_memtype_name[] = {  	[GSM0705_MEMTYPE_NONE]		= "NONE",  	[GSM0705_MEMTYPE_BROADCAST]	= "BM",  	[GSM0705_MEMTYPE_ME_MESSAGE]	= "ME", @@ -70,9 +70,10 @@ static inline int parse_memtype(char *memtype)  	return GSM0705_MEMTYPE_NONE;  } +/* TODO: move to headers */  struct __gsmd_sms_storage { -	u_int8 memtype; -	u_int8_t pad[3] +	u_int8_t memtype; +	u_int8_t pad[3];  	u_int16_t used;  	u_int16_t total;  } __attribute__ ((packed)); @@ -85,21 +86,34 @@ static int usock_cpms_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)  {  	struct gsmd_user *gu = ctx;  	struct gsmd_ucmd *ucmd = ucmd_alloc(sizeof(struct gsmd_sms_storage)); +	struct gsmd_sms_storage *gss = (typeof(gss)) ucmd->buf; +	char buf[3][3];  	DEBUGP("entering(cmd=%p, gu=%p)\n", cmd, gu);  	if (!ucmd)  		return -ENOMEM; - -	 -	  	ucmd->hdr.version = GSMD_PROTO_VERSION;  	ucmd->hdr.msg_type = GSMD_MSG_SMS; -	ucmd->hdr.msg_subtype = GSMD_SMS_GETMSG_STORAGE; -	ucmd->hdr.len = ...; +	ucmd->hdr.msg_subtype = GSMD_SMS_GET_MSG_STORAGE; +	ucmd->hdr.len = sizeof(struct gsmd_sms_storage);  	ucmd->hdr.id = cmd->id; -	 + +	if (sscanf(resp, "+CPMS: \"%2[A-Z]\",%hi,%hi," +				"\"%2[A-Z]\",%hi,%hi,\"%2[A-Z]\",%hi,%hi", +				buf[0], &gss->mem[0].used, &gss->mem[0].total, +				buf[1], &gss->mem[1].used, &gss->mem[1].total, +				buf[2], &gss->mem[2].used, &gss->mem[2].total) +			< 9) { +		talloc_free(ucmd); +		return -EINVAL; +	} + +	gss->mem[0].memtype = parse_memtype(buf[0]); +	gss->mem[1].memtype = parse_memtype(buf[1]); +	gss->mem[2].memtype = parse_memtype(buf[2]); +  	usock_cmd_enqueue(ucmd, gu);  	return 0; @@ -113,14 +127,13 @@ static int usock_rcv_sms(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,  	switch (gph->msg_subtype) {  	case GSMD_SMS_GET_SERVICE_CENTRE: -		 -		break; +		return;  	case GSMD_SMS_SET_SERVICE_CENTRE: -		break; +		return;  	case GSMD_SMS_SET_MSG_STORAGE: -		break; +		return;  	case GSMD_SMS_GET_MSG_STORAGE: -		cmd = atcmd_fill("AT+CPMS?", 8, ...); +		cmd = atcmd_fill("AT+CPMS?", 8 + 1, usock_cpms_cb, gu, 0);  		break;  	} @@ -131,7 +144,6 @@ static int usock_rcv_sms(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,  static int usock_rcv_cb(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,  			int len)  { -  	switch (gph->msg_subtype) {  	case GSMD_CB_SUBSCRIBE:  		break; @@ -139,44 +151,158 @@ static int usock_rcv_cb(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,  		break;  	} -	return  +	return -ENOSYS;  } -  /* Unsolicited messages related to SMS / CB */  static int cmti_parse(char *buf, int len, const char *param,  		      struct gsmd *gsmd)  { +	char memstr[3]; +	struct gsmd_ucmd *ucmd = ucmd_alloc(sizeof(struct gsmd_evt_auxdata)); +	struct gsmd_evt_auxdata *aux = (struct gsmd_evt_auxdata *) ucmd->buf; + +	if (!ucmd) +		return -ENOMEM; + +	ucmd->hdr.version = GSMD_PROTO_VERSION; +	ucmd->hdr.msg_type = GSMD_MSG_EVENT; +	ucmd->hdr.msg_subtype = GSMD_EVT_IN_SMS; +	ucmd->hdr.len = sizeof(*aux); + +	if (sscanf(param, "\"%2[A-Z]\",%i", memstr, &aux->u.sms.index) < 2) { +		talloc_free(ucmd); +		return -EINVAL; +	} + +	aux->u.sms.memtype = parse_memtype(memstr); + +	return usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_SMS);  }  static int cmt_parse(char *buf, int len, const char *param,  		     struct gsmd *gsmd)  { +	/* TODO: TEXT mode */ +	u_int8_t pdu[180]; +	const char *comma = strchr(param, ','); +	char *cr; +	int i; +	struct gsmd_sms_list msg; + +	if (!comma) +		return -EINVAL; +	len = strtoul(comma + 1, &cr, 10); +	if (cr[0] != '\n') +		return -EINVAL; + +	cr ++; +	for (i = 0; cr[0] >= '0' && cr[1] >= '0' && i < 180; i ++) { +		if (sscanf(cr, "%2hhX", &pdu[i]) < 1) { +			gsmd_log(GSMD_DEBUG, "malformed input (%i)\n", i); +			return -EINVAL; +		} +		cr += 2; +	} +	if (sms_pdu_to_msg(&msg, pdu, len, i)) { +		gsmd_log(GSMD_DEBUG, "malformed PDU\n"); +		return -EINVAL; +	} + +	/* FIXME: generate some kind of event */ +	return -ENOSYS;  }  static int cbmi_parse(char *buf, int len, const char *param,  		      struct gsmd *gsmd)  { +	char memstr[3]; +	int memtype, index; + +	if (sscanf(param, "\"%2[A-Z]\",%i", memstr, &index) < 2) +		return -EINVAL; + +	memtype = parse_memtype(memstr); +	/* FIXME: generate some kind of event */ +	return -ENOSYS;  }  static int cbm_parse(char *buf, int len, const char *param,  		     struct gsmd *gsmd)  { +	/* TODO: TEXT mode */ +	u_int8_t pdu[180]; +	char *cr; +	int i; +	struct gsmd_sms_list msg; + +	len = strtoul(param, &cr, 10); +	if (cr[0] != '\n') +		return -EINVAL; + +	cr ++; +	for (i = 0; cr[0] >= '0' && cr[1] >= '0' && i < 180; i ++) { +		if (sscanf(cr, "%2hhX", &pdu[i]) < 1) { +			gsmd_log(GSMD_DEBUG, "malformed input (%i)\n", i); +			return -EINVAL; +		} +		cr += 2; +	} +	if (sms_pdu_to_msg(&msg, pdu, len, i)) { +		gsmd_log(GSMD_DEBUG, "malformed PDU\n"); +		return -EINVAL; +	} + +	/* FIXME: generate some kind of event */ +	return -ENOSYS;  }  static int cdsi_parse(char *buf, int len, const char *param,  		      struct gsmd *gsmd)  { +	char memstr[3]; +	int memtype, index; + +	if (sscanf(param, "\"%2[A-Z]\",%i", memstr, &index) < 2) +		return -EINVAL; + +	memtype = parse_memtype(memstr); +	/* FIXME: generate some kind of event */ +	return -ENOSYS;  }  static int cds_parse(char *buf, int len, const char *param,  		     struct gsmd *gsmd)  { -} +	/* TODO: TEXT mode */ +	u_int8_t pdu[180]; +	char *cr; +	int i; +	struct gsmd_sms_list msg; + +	len = strtoul(param, &cr, 10); +	if (cr[0] != '\n') +		return -EINVAL; + +	cr ++; +	for (i = 0; cr[0] >= '0' && cr[1] >= '0' && i < 180; i ++) { +		if (sscanf(cr, "%2hhX", &pdu[i]) < 1) { +			gsmd_log(GSMD_DEBUG, "malformed input (%i)\n", i); +			return -EINVAL; +		} +		cr += 2; +	} +	if (sms_pdu_to_msg(&msg, pdu, len, i)) { +		gsmd_log(GSMD_DEBUG, "malformed PDU\n"); +		return -EINVAL; +	} +	/* FIXME: generate some kind of event */ +	return -ENOSYS; +} -static const struct gsmd_unsolocit gsm0705_unsolicit[] = { -	{ "+CMTI",	&cmti_parse },	/* SMS Deliver Index (stored in ME/TA) */ +static const struct gsmd_unsolicit gsm0705_unsolicit[] = { +	{ "+CMTI",	&cmti_parse },	/* SMS Deliver Index (stored in ME/TA)*/  	{ "+CMT",	&cmt_parse },	/* SMS Deliver to TE */  	{ "+CBMI",	&cbmi_parse },	/* Cell Broadcast Message Index */  	{ "+CBM",	&cbm_parse },	/* Cell Broadcast Message */ @@ -189,24 +315,43 @@ int sms_cb_init(struct gsmd *gsmd)  	struct gsmd_atcmd *atcmd;  	char buffer[10]; -	atcmd = atcmd_fill("AT+CSMS=0", NULL, gu, 0); +	atcmd = atcmd_fill("AT+CSMS=0", 9 + 1, NULL, gsmd, 0); +	if (!atcmd) +		return -ENOMEM; +	atcmd_submit(gsmd, atcmd); + +	/* Store and notify */ +	atcmd = atcmd_fill("AT+CNMI=1,1,1", 13 + 1, NULL, gsmd, 0); +	if (!atcmd) +		return -ENOMEM; +	atcmd_submit(gsmd, atcmd); + +	/* Store into ME/TA and notify */ +	atcmd = atcmd_fill("AT+CSBS=1", 9 + 1, NULL, gsmd, 0); +	if (!atcmd) +		return -ENOMEM; +	atcmd_submit(gsmd, atcmd); + +	/* Store into ME/TA and notify */ +	atcmd = atcmd_fill("AT+CSDS=2", 9 + 1, NULL, gsmd, 0);  	if (!atcmd)  		return -ENOMEM;  	atcmd_submit(gsmd, atcmd);  	/* If text mode, set the encoding */ -	if (gu->gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) { -		atcmd = atcmd_fill("AT+CSCS=\"IRA\"", 13, NULL, gu, 0); +	if (gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) { +		atcmd = atcmd_fill("AT+CSCS=\"IRA\"", 13 + 1, NULL, gsmd, 0);  		if (!atcmd)  			return -ENOMEM;  		atcmd_submit(gsmd, atcmd);  	}  	/* Switch into desired mode (Section 3.2.3) */ -	snprintf(buffer, sizeof(buffer), "AT+CMGF=%i", -			(gu->gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) ? -			GSMD_SMS_FMT_TEXT : GSMD_SMS_FMT_PDU); -	atcmd = atcmd_fill(buffer, strlen(buffer) + 1, NULL, gu, 0); +	atcmd = atcmd_fill(buffer, snprintf(buffer, sizeof(buffer), +				"AT+CMGF=%i", +				(gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) ? +				GSMD_SMS_FMT_TEXT : GSMD_SMS_FMT_PDU) + 1, +			NULL, gsmd, 0);  	if (!atcmd)  		return -ENOMEM; diff --git a/src/gsmd/sms_pdu.c b/src/gsmd/sms_pdu.c index 1ec3202..c9b9327 100644 --- a/src/gsmd/sms_pdu.c +++ b/src/gsmd/sms_pdu.c @@ -179,6 +179,8 @@ int sms_pdu_to_msg(struct gsmd_sms_list *dst,  		memset(dst->time_stamp, 0, 7);  		break; +	case GSMD_SMS_TP_MTI_STATUS_REPORT: +		/* TODO */  	default:  		/* Unknown PDU type */  		return 1; diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c index be8aee8..8496dd1 100644 --- a/src/gsmd/usock.c +++ b/src/gsmd/usock.c @@ -532,7 +532,7 @@ static int sms_send_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)  	struct gsmd_ucmd *ucmd;  	int msgref; -	if (cmd->ret == 0) { +	if (cmd->ret == 0 || cmd->ret == -255) {  		if (sscanf(resp, "+CMGS: %i", &msgref) < 1)  			return -EINVAL;  	} else diff --git a/src/util/event.c b/src/util/event.c index 0fe6472..209d34b 100644 --- a/src/util/event.c +++ b/src/util/event.c @@ -34,6 +34,13 @@ static int incall_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxda  	return 0;  } +static int insms_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux) +{ +	printf("EVENT: Incoming SMS stored at location %i\n", aux->u.sms.index); + +	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); @@ -131,6 +138,7 @@ int event_init(struct lgsm_handle *lh)  	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_IN_SMS, &insms_handler);  	rc |= lgsm_evt_handler_register(lh, GSMD_EVT_OUT_COLP, &colp_handler);  	rc |= lgsm_evt_handler_register(lh, GSMD_EVT_NETREG, &netreg_handler);  	rc |= lgsm_evt_handler_register(lh, GSMD_EVT_SIGNAL, &sigq_handler);  | 
