diff options
Diffstat (limited to 'src/gsmd')
| -rw-r--r-- | src/gsmd/Makefile.am | 3 | ||||
| -rw-r--r-- | src/gsmd/sms_cb.c | 17 | ||||
| -rw-r--r-- | src/gsmd/sms_pdu.c | 259 | ||||
| -rw-r--r-- | src/gsmd/usock.c | 260 | 
4 files changed, 455 insertions, 84 deletions
diff --git a/src/gsmd/Makefile.am b/src/gsmd/Makefile.am index 49d96e3..6b25812 100644 --- a/src/gsmd/Makefile.am +++ b/src/gsmd/Makefile.am @@ -6,7 +6,8 @@ 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 +	       usock.c talloc.c timer.c operator_cache.c ext_response.c \ +	       sms_pdu.c  gsmd_LDADD = -ldl  gsmd_LDFLAGS = -Wl,--export-dynamic diff --git a/src/gsmd/sms_cb.c b/src/gsmd/sms_cb.c index 330317c..22bf613 100644 --- a/src/gsmd/sms_cb.c +++ b/src/gsmd/sms_cb.c @@ -184,18 +184,29 @@ static const struct gsmd_unsolocit gsm0705_unsolicit[] = {  	{ "+CDS",	&cds_parse },	/* SMS Status Index (stored in ME/TA) */  }; -  int sms_cb_init(struct gsmd *gsmd)  {  	struct gsmd_atcmd *atcmd; +	char buffer[10];  	atcmd = atcmd_fill("AT+CSMS=0", NULL, gu, 0);  	if (!atcmd)  		return -ENOMEM;  	atcmd_submit(gsmd, atcmd); -	/* Switch into "text mode" (Section 3.2.3) */ -	atcdm = atcmd_fill("AT+CMGF=1", 9, &sms_cb_init_cb, gu, 0); +	/* 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 (!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);  	if (!atcmd)  		return -ENOMEM; diff --git a/src/gsmd/sms_pdu.c b/src/gsmd/sms_pdu.c new file mode 100644 index 0000000..1ec3202 --- /dev/null +++ b/src/gsmd/sms_pdu.c @@ -0,0 +1,259 @@ +/* Convert raw PDUs to and from gsmd format. + * + * Copyright (C) 2007 OpenMoko, Inc. + * Written by Andrzej Zaborowski <andrew@openedhand.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <stdio.h> +#include <string.h> + +#include "gsmd.h" + +#include <gsmd/gsmd.h> +#include <gsmd/usock.h> + +static int sms_number_bytelen(u_int8_t type, u_int8_t len) +{ +	switch (type & __GSMD_TOA_TON_MASK) { +	case GSMD_TOA_TON_ALPHANUMERIC: +		return (len + 1) >> 1; +	default: +		return (len + 1) >> 1; +	} +} + +static int sms_data_bytelen(u_int8_t data_coding_scheme, u_int8_t len) +{ +	switch (data_coding_scheme) {	/* Get length in bytes */ +	case ALPHABET_DEFAULT: +		return (len * 7 + 7) >> 3; +	case ALPHABET_8BIT: +		return len; +	case ALPHABET_UCS2: +		return len * 2; +	} +	return 0; +} + +static int sms_address2ascii(struct gsmd_addr *dst, u_int8_t *src) +{ +	int i; + +	if (src[0] > GSMD_ADDR_MAXLEN) +		return 1; + +	/* The Type-of-address field */ +	dst->type = src[1]; + +	switch (dst->type & __GSMD_TOA_TON_MASK) { +	case GSMD_TOA_TON_ALPHANUMERIC: +		for (i = 0; ((i * 7 + 3) >> 2) < src[0]; i ++) +			dst->number[i] = +				((src[2 + ((i * 7 + 7) >> 3)] << +				  (7 - ((i * 7 + 7) & 7))) | +				 (src[2 + ((i * 7) >> 3)] >> +				  ((i * 7) & 7))) & 0x7f; +		break; +	default: +		for (i = 0; i < src[0]; i ++) +			dst->number[i] = '0' + +				((src[2 + (i >> 1)] >> ((i << 2) & 4)) & 0xf); +	} +	dst->number[i] = 0; + +	return 0; +} + +int sms_pdu_to_msg(struct gsmd_sms_list *dst, +		u_int8_t *src, int pdulen, int len) +{ +	int i, vpf; +	if (len < 1 || len < 1 + src[0] + pdulen || pdulen < 1) +		return 1; + +	/* Skip SMSC number and its Type-of-address */ +	len -= 1 + src[0]; +	src += 1 + src[0]; + +	/* TP-UDHI */ +	dst->payload.has_header = !!(src[0] & GSMD_SMS_TP_UDHI_WITH_HEADER); + +	/* TP-VPF */ +	vpf = (src[0] >> 3) & 3; + +	/* TP-MTI */ +	switch (src[0] & 3) { +	case GSMD_SMS_TP_MTI_DELIVER: +		if (len < 3) +			return 1; +		i = sms_number_bytelen(src[2], src[1]); +		if (len < 13 + i) +			return 1; + +		if (sms_address2ascii(&dst->addr, src + 1)) +			return 1; + +		len -= 3 + i; +		src += 3 + i; + +		/* TP-DCS */ +		switch (src[1] >> 4) { +		case 0x0 ... 3:	/* General Data Coding indication */ +		case 0xc:	/* Message Waiting indication: Discard */ +			/* FIXME: support compressed data */ +			dst->payload.coding_scheme = src[1] & 0xc; +			break; +		case 0xd:	/* Message Waiting indication: Store */ +			dst->payload.coding_scheme = ALPHABET_DEFAULT; +			break; +		case 0xe:	/* Message Waiting indication: Store */ +			dst->payload.coding_scheme = ALPHABET_UCS2; +			break; +		case 0xf:	/* Data coding/message class */ +			dst->payload.coding_scheme = (src[1] & 4) ? +				ALPHABET_8BIT : ALPHABET_DEFAULT; +			break; +		default: +			return 1; +		} + +		/* TP-SCTS */ +		memcpy(dst->time_stamp, src + 2, 7); + +		/* Skip TP-PID */ +		len -= 9; +		src += 9; +		break; +	case GSMD_SMS_TP_MTI_SUBMIT: +		if (len < 4) +			return 1; +		i = sms_number_bytelen(src[3], src[2]); +		if (len < 8 + i) +			return 1; + +		if (sms_address2ascii(&dst->addr, src + 2)) +			return 1; + +		len -= 4 + i; +		src += 4 + i; + +		/* TP-DCS */ +		switch (src[1] >> 4) { +		case 0x0 ... 3:	/* General Data Coding indication */ +		case 0xc:	/* Message Waiting indication: Discard */ +			/* FIXME: compressed data */ +			dst->payload.coding_scheme = src[1] & 0xc; +			break; +		case 0xd:	/* Message Waiting indication: Store */ +			dst->payload.coding_scheme = ALPHABET_DEFAULT; +			break; +		case 0xe:	/* Message Waiting indication: Store */ +			dst->payload.coding_scheme = ALPHABET_UCS2; +			break; +		case 0xf:	/* Data coding/message class */ +			dst->payload.coding_scheme = (src[1] & 4) ? +				ALPHABET_8BIT : ALPHABET_DEFAULT; +			break; +		default: +			return 1; +		} + +		/* Skip TP-PID and TP-Validity-Period */ +		len -= vpf ? 3 : 2; +		src += vpf ? 3 : 2; + +		memset(dst->time_stamp, 0, 7); +		break; +	default: +		/* Unknown PDU type */ +		return 1; +	} + +	/* TP-UDL */ +	dst->payload.length = src[0]; +	i = sms_data_bytelen(dst->payload.coding_scheme, src[0]); + +	/* TP-UD */ +	if (len < 1 + i || i > GSMD_SMS_DATA_MAXLEN) +		return 1; +	memcpy(dst->payload.data, src + 1, i); +	dst->payload.data[i] = 0; + +	return 0; +} + +/* Refer to GSM 03.40 subclause 9.2.3.3, for SMS-SUBMIT */ +int sms_pdu_make_smssubmit(char *dest, struct gsmd_sms_submit *src) +{ +	/* FIXME: ALPHANUMERIC encoded addresses can be longer than 13B */ +	u_int8_t header[15 + GSMD_ADDR_MAXLEN]; +	int pos = 0, i, len; + +	/* SMSC Length octet.  If omitted or zero, use SMSC stored in the +	 * phone.  One some phones this can/has to be omitted.  */ +	header[pos ++] = 0x00; + +	header[pos ++] = +		GSMD_SMS_TP_MTI_SUBMIT | +		(0 << 2) |		/* Reject Duplicates: 0 */ +		GSMD_SMS_TP_VPF_NOT_PRESENT | +		GSMD_SMS_TP_SRR_NOT_REQUEST | +		(src->payload.has_header ? GSMD_SMS_TP_UDHI_WITH_HEADER : +		 GSMD_SMS_TP_UDHI_NO_HEADER) | +		GSMD_SMS_TP_RP_NOT_SET; + +	/* TP-Message-Reference - 00 lets the phone set the number itself */ +	header[pos ++] = 0x00; + +	header[pos ++] = strlen(src->addr.number); +	header[pos ++] = src->addr.type; +	for (i = 0; src->addr.number[i]; i ++) { +		header[pos] = src->addr.number[i ++] - '0'; +		if (src->addr.number[i]) +			header[pos ++] |= (src->addr.number[i] - '0') << 4; +		else { +			header[pos ++] |= 0xf0; +			break; +		} +	} + +	/* TP-Protocol-Identifier - 00 means implicit */ +	header[pos ++] = 0x00; + +	/* TP-Data-Coding-Scheme */ +	header[pos ++] = src->payload.coding_scheme; + +	/* TP-Validity-Period, if present, would go here */ + +	header[pos ++] = src->payload.length; +	len = sms_data_bytelen(src->payload.coding_scheme, +			src->payload.length); + +	if (dest) { +		for (i = 0; i < pos; i ++) { +			sprintf(dest, "%02X", header[i]); +			dest += 2; +		} +		for (i = 0; i < len; i ++) { +			sprintf(dest, "%02X", src->payload.data[i]); +			dest += 2; +		} +	} + +	return pos + len; +} diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c index db073a4..be8aee8 100644 --- a/src/gsmd/usock.c +++ b/src/gsmd/usock.c @@ -434,17 +434,46 @@ static int usock_rcv_network(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,  static int sms_list_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)  { -	struct gsmd_user *gu = ctx;	 -	struct gsmd_ucmd *ucmd;	 +	struct gsmd_user *gu = ctx; +	struct gsmd_ucmd *ucmd; +	struct gsmd_sms_list msg; +	int i, idx, stat, len, cr; +	u_int8_t pdu[180]; + +	if (cmd->ret && cmd->ret != -255) +		return 0; -	ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS, -			      GSMD_SMS_LIST, 0); +	/* FIXME: TEXT mode */ +	if ( +			sscanf(resp, "+CMGL: %i,%i,,%i\n%n", +				&idx, &stat, &len, &cr) < 3 && +			sscanf(resp, "+CMGL: %i,%i,%*i,%i\n%n", +				&idx, &stat, &len, &cr) < 3) +		return -EINVAL; +	if (len > 164) +		return -EINVAL; + +	msg.index = idx; +	msg.stat = stat; +	msg.is_last = (cmd->ret == 0); +	for (i = 0; resp[cr] >= '0' && resp[cr + 1] >= '0' && i < 180; i ++) { +		if (sscanf(resp + 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; +	} + +	ucmd = gsmd_ucmd_fill(sizeof(msg), GSMD_MSG_SMS, +			      GSMD_SMS_LIST, cmd->id);  	if (!ucmd)  		return -ENOMEM; +	memcpy(ucmd->buf, &msg, sizeof(msg)); -	/* FIXME: implementation */ -	strcpy(ucmd->buf, resp); -	  	usock_cmd_enqueue(ucmd, gu);  	return 0; @@ -452,17 +481,45 @@ static int sms_list_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)  static int sms_read_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)  { -	struct gsmd_user *gu = ctx;	 -	struct gsmd_ucmd *ucmd;	 +	struct gsmd_user *gu = ctx; +	struct gsmd_ucmd *ucmd; +	struct gsmd_sms_list msg; +	int i, stat, len, cr; +	u_int8_t pdu[180]; -	/* FIXME: implementation */ +	if (cmd->ret) +		return 0; + +	/* FIXME: TEXT mode */ +	if ( +			sscanf(resp, "+CMGR: %i,,%i\n%n", +				&stat, &len, &cr) < 2 && +			sscanf(resp, "+CMGR: %i,%*i,%i\n%n", +				&stat, &len, &cr) < 2) +		return -EINVAL; +	if (len > 164) +		return -EINVAL; + +	msg.index = 0; +	msg.stat = stat; +	msg.is_last = 1; +	for (i = 0; resp[cr] >= '0' && resp[cr + 1] >= '0' && i < 180; i ++) { +		if (sscanf(resp + 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; +	} -	ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS, -			      GSMD_SMS_READ, 0); +	ucmd = gsmd_ucmd_fill(sizeof(msg), GSMD_MSG_SMS, +			      GSMD_SMS_READ, cmd->id);  	if (!ucmd)  		return -ENOMEM; - -	strcpy(ucmd->buf, resp);	 +	memcpy(ucmd->buf, &msg, sizeof(msg));  	usock_cmd_enqueue(ucmd, gu); @@ -471,15 +528,21 @@ static int sms_read_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)  static int sms_send_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)  { -	struct gsmd_user *gu = ctx;	 -	struct gsmd_ucmd *ucmd;	 -	 -	ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS, -			      GSMD_SMS_SEND, 0); +	struct gsmd_user *gu = ctx; +	struct gsmd_ucmd *ucmd; +	int msgref; + +	if (cmd->ret == 0) { +		if (sscanf(resp, "+CMGS: %i", &msgref) < 1) +			return -EINVAL; +	} else +		msgref = -cmd->ret; + +	ucmd = gsmd_ucmd_fill(sizeof(int), GSMD_MSG_SMS, +			GSMD_SMS_SEND, cmd->id);  	if (!ucmd)  		return -ENOMEM; -	 -	strcpy(ucmd->buf, resp); +	*(int *) ucmd->buf = msgref;  	usock_cmd_enqueue(ucmd, gu); @@ -488,15 +551,21 @@ static int sms_send_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)  static int sms_write_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)  { -	struct gsmd_user *gu = ctx;	 -	struct gsmd_ucmd *ucmd;	 -	 -	ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS, -			      GSMD_SMS_WRITE, 0); -	if (!ucmd) -		return -ENOMEM;	 +	struct gsmd_user *gu = ctx; +	struct gsmd_ucmd *ucmd; +	int result; -	strcpy(ucmd->buf, resp); +	if (cmd->ret == 0) { +		if (sscanf(resp, "+CMGW: %i", &result) < 1) +			return -EINVAL; +	} else +		result = -cmd->ret; + +	ucmd = gsmd_ucmd_fill(sizeof(int), GSMD_MSG_SMS, +			GSMD_SMS_WRITE, cmd->id); +	if (!ucmd) +		return -ENOMEM; +	*(int *) ucmd->buf = result;  	usock_cmd_enqueue(ucmd, gu); @@ -505,113 +574,144 @@ static int sms_write_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)  static int sms_delete_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)  { -	struct gsmd_user *gu = ctx;	 -	struct gsmd_ucmd *ucmd;	 +	struct gsmd_user *gu = ctx; +	struct gsmd_ucmd *ucmd; +	int *result; -	ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS, -			      GSMD_SMS_DELETE, 0); +	ucmd = gsmd_ucmd_fill(sizeof(int), GSMD_MSG_SMS, +			      GSMD_SMS_DELETE, cmd->id);  	if (!ucmd)  		return -ENOMEM;	 -	strcpy(ucmd->buf, resp); +	result = (int *) ucmd->buf; +	*result = cmd->ret;  	usock_cmd_enqueue(ucmd, gu);  	return 0;  } +static const char *gsmd_cmgl_stat[] = { +	"REC UNREAD", "REC READ", "STO UNSENT", "STO SENT", "ALL", +}; +  static int usock_rcv_sms(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,   			 int len)  {  	/* FIXME: TEXT mode support!!  */  	struct gsmd_atcmd *cmd = NULL;  	struct gsmd_sms_delete *gsd; -	struct gsmd_sms *gs; +	struct gsmd_sms_submit *gss;  	struct gsmd_sms_write *gsw;  	int *stat, *index;  	int atcmd_len;  	char buf[1024]; -	 +  	switch (gph->msg_subtype) {  	case GSMD_SMS_LIST: -		/* FIXME: only support PDU mode!! */  		if(len < sizeof(*gph) + sizeof(int))  			return -EINVAL; -		stat = (int *) ((void *)gph + sizeof(*gph));	 +		stat = (int *) ((void *)gph + sizeof(*gph)); +		if (*stat < 0 || *stat > 4) +			return -EINVAL; -		sprintf(buf, "%d", *stat);	 -				 -		atcmd_len = 1 + strlen("AT+CMGL=") + strlen(buf); -		cmd = atcmd_fill("AT+CMGL=", atcmd_len, -				 &sms_list_cb, gu, gph->id); +		/* FIXME: should we set <mem1> to "SM"/"ME" before that? */ +		if (gu->gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) +			atcmd_len = sprintf(buf, "AT+CMGL=\"%s\"", +					gsmd_cmgl_stat[*stat]); +		else +			atcmd_len = sprintf(buf, "AT+CMGL=%i", *stat); + +		cmd = atcmd_fill(buf, atcmd_len + 1, +				&sms_list_cb, gu, gph->id);  		if (!cmd)  			return -ENOMEM; -		sprintf(cmd->buf, "AT+CMGL=%s", buf);  		break; +  	case GSMD_SMS_READ: -		/* FIXME: only support PDU mode!! */  		if(len < sizeof(*gph) + sizeof(int))  			return -EINVAL;  		index = (int *) ((void *)gph + sizeof(*gph)); -		sprintf(buf, "%d", *index); -		 -		atcmd_len = 1 + strlen("AT+CMGR=") + strlen(buf); -		cmd = atcmd_fill("AT+CMGR=", atcmd_len, +		/* FIXME: should we set <mem1> to "SM"/"ME" before that? */ +		atcmd_len = sprintf(buf, "AT+CMGR=%i", *index); + +		cmd = atcmd_fill(buf, atcmd_len + 1,  				 &sms_read_cb, gu, gph->id);  		if (!cmd)  			return -ENOMEM; -		sprintf(cmd->buf, "AT+CMGR=%s", buf);  		break; -#if 0 +  	case GSMD_SMS_SEND: -		/* FIXME: only support PDU mode!! */ -		if(len < sizeof(*gph) + sizeof(*gs)) +		if (len < sizeof(*gph) + sizeof(*gss))  			return -EINVAL; -		gs = (struct gsmd_sms *) ((void *)gph + sizeof(*gph)); +		gss = (struct gsmd_sms_submit *) ((void *) gph + sizeof(*gph)); + +		if (gu->gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) { +			atcmd_len = sprintf(buf, "AT+CMGS=\"%s\"\n%.*s", +					gss->addr.number, +					gss->payload.length, +					gss->payload.data);	/* FIXME */ +		} else { +			atcmd_len = sprintf(buf, "AT+CMGS=%i\n", +					sms_pdu_make_smssubmit(NULL, gss) - 1); +			atcmd_len += sms_pdu_make_smssubmit(buf + atcmd_len, +					gss) * 2; +		} +		buf[atcmd_len ++] = 26;	/* ^Z ends the message */ +		buf[atcmd_len ++] = 0; -		sprintf(buf, "%d", *index); -		 -		atcmd_len = 1 + strlen("AT+CMGR=") + 1; -		cmd = atcmd_fill("AT+CMGR=", atcmd_len, -				 &sms_send_cb, gu, gph->id); -		if (!cmd)GSMD_SMS_WRITE +		cmd = atcmd_fill(buf, atcmd_len, &sms_send_cb, gu, gph->id); +		if (!cmd)  			return -ENOMEM; -		sprintf(cmd->buf, "AT+CMGR=%d", index);  		break; +  	case GSMD_SMS_WRITE: -		/* FIXME: only support PDU mode!! */ -		if(len < sizeof(*gph) + sizeof(*gsw)) +		if (len < sizeof(*gph) + sizeof(*gsw))  			return -EINVAL; -		&index = (int *) ((void *)gph + sizeof(*gph)); -		 -		atcmd_len = 1 + strlen("AT+CMGR=") + 1; -		cmd = atcmd_fill("AT+CMGR=", atcmd_len, -				 &sms_write_cb, gu, gph->id); +		gsw = (struct gsmd_sms_write *) ((void *) gph + sizeof(*gph)); +		if (gsw->stat > 4) +			return -EINVAL; + +		/* FIXME: should we set <mem2> to "SM"/"ME" before that? */ +		if (gu->gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) { +			atcmd_len = sprintf(buf, "AT+CMGW=\"%s\"\n%.*s", +					gsw->sms.addr.number, +					gsw->sms.payload.length, +					gsw->sms.payload.data);	/* FIXME */ +		} else { +			atcmd_len = sprintf(buf, "AT+CMGW=%i,%i\n", +					sms_pdu_make_smssubmit(NULL, +						&gsw->sms) - 1, gsw->stat); +			atcmd_len += sms_pdu_make_smssubmit(buf + atcmd_len, +					&gsw->sms) * 2; +		} +		buf[atcmd_len ++] = 26;	/* ^Z ends the message */ +		buf[atcmd_len ++] = 0; + +		cmd = atcmd_fill(buf, atcmd_len, &sms_write_cb, gu, gph->id);  		if (!cmd)  			return -ENOMEM; -		sprintf(cmd->buf, "AT+CMGR=%d", index);  		break; -#endif -	case GSMD_SMS_DELETE:		 + +	case GSMD_SMS_DELETE:  		if(len < sizeof(*gph) + sizeof(*gsd))  			return -EINVAL;  		gsd = (struct gsmd_sms_delete *) ((void *)gph + sizeof(*gph)); -	     -		sprintf(buf, "%d,%d", gsd->index, gsd->delflg); -	 -		atcmd_len = 1 + strlen("AT+CMGR=") + strlen(buf); -		cmd = atcmd_fill("AT+CMGD=", atcmd_len, + +		atcmd_len = sprintf(buf, "AT+CMGD=%d,%d", +				gsd->index, gsd->delflg); + +		cmd = atcmd_fill(buf, atcmd_len + 1,  				 &sms_delete_cb, gu, gph->id);  		if (!cmd)  			return -ENOMEM; -		sprintf(cmd->buf, "AT+CMGD=%s", buf);		  		break;	  	default:  		return -EINVAL;  	} -		 -	gsmd_log(GSMD_DEBUG, "%s\n", cmd->buf); + +	gsmd_log(GSMD_DEBUG, "%s\n", cmd ? cmd->buf : 0);  	if (cmd)  		return atcmd_submit(gu->gsmd, cmd);  	else @@ -867,7 +967,7 @@ static usock_msg_handler *pcmd_type_handlers[__NUM_GSMD_MSGS] = {  	[GSMD_MSG_PIN]		= &usock_rcv_pin,  	[GSMD_MSG_PHONE]	= &usock_rcv_phone,  	[GSMD_MSG_NETWORK]	= &usock_rcv_network, -	[GSMD_MSG_SMS]		= &usock_rcv_sms,	 +	[GSMD_MSG_SMS]		= &usock_rcv_sms,  	//[GSMD_MSG_PHONEBOOK]	= &usock_rcv_phonebook,  };  | 
