[RFC] SMS support

Petri Aarnio petri.aarnio at saunalahti.fi
Thu Jul 5 19:38:58 CEST 2007


Hi

Firstly fast comment on coding of the messages. It is defined in GSM 
spec 03.38.  The coding can be 7-bit, 8-bit or 16-bit.
7-bit is used for GSM default character set which includes all most 
significant European languages characters. Almost all ASCII control 
characters are dropped out.
8-bit format is originally meant for data messages.
16-bit is for UCS-2 coding which is a UNICODE format and thus can be 
used with most languages in the world.

One SMS message lenght can be 140 bytes, which allows 160 7-bit 
charactes and only 70 UCS-2 characters. Normally the phones deal with 
this so that 7-bit character set is the default format and is used when 
the string does not include characters outside of the default GSM 
character set. Otherwise 16-bit UCS-2 format is used.

I'll get back to the other issues later. But I must say I wonder how is 
it possible that SMS is under construction if the phone is going to be 
on market in 4 days.
Best Regards,
Petri Aarnio


andrzej zaborowski kirjoitti:
> Hi,
>  I made a first attempt at SMS sending support, I wanted to also have
> a go at listing messages and other functions but I started with
> sending and have a number of questions already.  The diff of my
> changes is attached, it contains some unrelated fixes and formatting
> changes - I will clean this up before submitting anywhere.
>
> - Do we want to support both PDU and TEXT modes?  Comments in
> different files suggest either.  Asking around on IRC I was told that
> we want both, which makes sense because PDU allows more control over
> what is sent out, but it is optional and not all vendors have to
> support it.
>
> In the attached version I support both, with a way for the machine or
> vendor plugin to decide what mode to use on initialisation. Both modes
> were tested to work on the GTA01Bv4, however in PDU mode we have to
> report the PDU length 1 byte shorter than it is defined in the specs
> for the modem to accept the command (which took some guess-work,
> especially that the modem is picky about the message format and the
> error doesn't give much information about the failure).
>
> For that reason the message sent from libgsmd through usock uses a
> format that doesn't determine either PDU or TEXT, and the formatting
> is done on gsmd side.
>
> - How should we choose the coding for the messages? I tested the 7-
> and 8-bit coding and both worked but my other phone on which I was
> receiving, couldn't read the 8-bit messages.  I don't know how GSM
> deals with national characters, but if it does at all, it probably
> needs 8- or 16-bit coding for that (but then we shouldn't make this
> default because 7-bit allows longest messages).
>
> - Did anyone notice that we're writing a \0 byte after every command
> before the final \r? I confirmed that everything is still fine without
> it, on the Neo.  Should we get rid of it? Also how about passing the
> correct cmd length to atcmd_fill() and gsmd_ucmd_fill() and adding 1
> inside these functions instead of in the caller?
>
> - I use atcmd_submit() to submit the message contents but this is a
> bit of a hack because technically it's not an AT command, and the "> "
> prompt returned from modem is not an AT response, so we should
> probably have a separate parser for it. Also the "> " has no line
> termination after it so it gets buffered until the next response comes
> (e.g. +CSQ).
>
> And it turns out we always have to wait for the "> " prompt before
> sending message contents because otherwise the beginning of the
> text/PDU gets eaten.
>
> BTW on the occasion of implementing the modem in QEMU, I saw that in
> case the read() returns two or more responses in a single call, they
> will be all treated as a single line and the responses after the first
> one, are lost.
>
> Unrelated to that I noticed that when we're suspending/resuming the
> kernel prints the whole lot of messages to UART0 even if the modem is
> on. This can be seen if echo is enabled before suspend (ATE1), after
> resuming the modem prints a whole lot of kernel messages back at us.
>
> Cheers,
> Andrew
> ------------------------------------------------------------------------
>
> From 9420718b9b2be18df88da430c4e8d858522c1751 Mon Sep 17 00:00:00 2001
> From: Andrzej Zaborowski <balrog at zabor.org>
> Date: Thu, 5 Jul 2007 02:46:47 +0200
> Subject: [PATCH] SMS hacks.
>
> ---
>  include/gsmd/gsmd.h       |    4 +-
>  include/gsmd/usock.h      |   35 +++++++++-
>  include/libgsmd/sms.h     |    2 +-
>  src/gsmd/atcmd.c          |    4 +-
>  src/gsmd/sms_cb.c         |   19 ++++--
>  src/gsmd/usock.c          |  176 +++++++++++++++++++++++++++++++++++++++++----
>  src/libgsmd/libgsmd_sms.c |   26 +++++--
>  8 files changed, 241 insertions(+), 29 deletions(-)
>
> diff --git a/include/gsmd/gsmd.h b/include/gsmd/gsmd.h
> index b4dfa62..8f1771e 100644
> --- a/include/gsmd/gsmd.h
> +++ b/include/gsmd/gsmd.h
> @@ -56,6 +56,7 @@ struct llparser {
>  struct gsmd;
>  
>  #define GSMD_FLAG_V0		0x0001	/* V0 responses to be expected from TA */
> +#define GSMD_FLAG_SMS_FMT	0x0002	/* Use TEXT rather than PDU mode */
>  
>  struct gsmd {
>  	unsigned int flags;
> @@ -89,7 +90,8 @@ struct gsmd_user {
>  
>  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, ...);
> +void __gsmd_log(int level, const char *file, int line, const char *function, const char *message, ...)
> +	__attribute__ ((__format__ (__printf__, 5, 6)));
>  /* macro for logging including filename and line number */
>  #define gsmd_log(level, format, args ...) \
>  	__gsmd_log(level, __FILE__, __LINE__, __FUNCTION__, format, ## args)
> diff --git a/include/gsmd/usock.h b/include/gsmd/usock.h
> index 2032230..ad7ef27 100644
> --- a/include/gsmd/usock.h
> +++ b/include/gsmd/usock.h
> @@ -139,7 +139,7 @@ enum gsmd_sms_tp_rp {
>  /* for SMS-SUBMIT, SMS-DELIVER */
>  enum gsmd_sms_tp_udhi {
>  	GSMD_SMS_TP_UDHI_NO_HEADER	= (0<<6),
> -	GSMD_SMS_TP_UDHI_WTIH_HEADER	= (1<<6),
> +	GSMD_SMS_TP_UDHI_WITH_HEADER	= (1<<6),
>  };
>  
>  /* SMS delflg from 3GPP TS 07.05, Clause 3.5.4 */
> @@ -160,6 +160,34 @@ enum gsmd_msg_phonebook {
>  	GSMD_PHONEBOOK_GET_SUPPORT	= 6,
>  };
>  
> +/* Type-of-Address, Numbering Plan Identification field */
> +enum gsmd_toa_npi {
> +	GSMD_TOA_NPI_UNKNOWN		= 0x0,
> +	GSMD_TOA_NPI_ISDN		= 0x1,
> +	GSMD_TOA_NPI_DATA		= 0x3,
> +	GSMD_TOA_NPI_TELEX		= 0x4,
> +	GSMD_TOA_NPI_NATIONAL		= 0x8,
> +	GSMD_TOA_NPI_PRIVATE		= 0x9,
> +	GSMD_TOA_NPI_ERMES		= 0xa,
> +	GSMD_TOA_NPI_RESERVED		= 0xf,
> +};
> +
> +/* Type-of-Address, Type-of-Number field */
> +enum gsmd_toa_ton {
> +	GSMD_TOA_TON_UNKNOWN		= (0<<4),
> +	GSMD_TOA_TON_INTERNATIONAL	= (1<<4),
> +	GSMD_TOA_TON_NATIONAL		= (2<<4),
> +	GSMD_TOA_TON_NETWORK		= (3<<4),
> +	GSMD_TOA_TON_SUBSCRIBER		= (4<<4),
> +	GSMD_TOA_TON_ALPHANUMERIC	= (5<<4),
> +	GSMD_TOA_TON_ABBREVIATED	= (6<<4),
> +};
> +
> +/* Type-of-Address, bit 7 always 1 */
> +enum gsmd_toa_reserved {
> +	GSMD_TOA_RESERVED		= (1<<7),
> +};
> +
>  /* Length from 3GPP TS 04.08, Clause 10.5.4.7 */
>  
>  #define GSMD_ADDR_MAXLEN	32
> @@ -269,6 +297,11 @@ struct gsmd_sms_deliver {
>  	char user_data[140];
>  } __attribute__ ((packed));
>  
> +struct gsmd_sms_send {
> +	struct gsmd_addr addr;
> +	struct gsmd_sms payload;
> +};
> +
>  /* Refer to GSM 07.07 subclause 8.12 */
>  struct gsmd_phonebook_readrg {
>  	u_int8_t index1;
> diff --git a/include/libgsmd/sms.h b/include/libgsmd/sms.h
> index a07fc74..d449933 100644
> --- a/include/libgsmd/sms.h
> +++ b/include/libgsmd/sms.h
> @@ -83,7 +83,7 @@ extern int lgsmd_sms_delete(struct lgsm_handle *lh,
>  extern int lgsmd_sms_send(struct lgsm_handle *lh, const struct lgsm_sms *sms);
>  
>  /* Write Message to Memory */
> -extern int lgsmd_sms_write(struct lgsm_handle *lh, 
> +extern int lgsmd_sms_write(struct lgsm_handle *lh,
>  		const struct lgsm_sms_write *sms_write);
>  
>  /* Packing of 7-bit characters, refer to GSM 03.38 subclause 6.1.2.1.1 */
> diff --git a/src/gsmd/atcmd.c b/src/gsmd/atcmd.c
> index 44e215c..36ccb6e 100644
> --- a/src/gsmd/atcmd.c
> +++ b/src/gsmd/atcmd.c
> @@ -384,8 +384,8 @@ static int atcmd_select_cb(int fd, unsigned int what, void *data)
>  	if ((what & GSMD_FD_WRITE) && g->interpreter_ready) {
>  		struct gsmd_atcmd *pos, *pos2;
>  		llist_for_each_entry_safe(pos, pos2, &g->pending_atcmds, list) {
> -			len = strlen(pos->buf);
> -			rc = write(fd, pos->buf, strlen(pos->buf));
> +			len = pos->buflen;
> +			rc = write(fd, pos->buf, len);
>  			if (rc == 0) {
>  				gsmd_log(GSMD_ERROR, "write returns 0, aborting\n");
>  				break;
> diff --git a/src/gsmd/sms_cb.c b/src/gsmd/sms_cb.c
> index 330317c..ba7b290 100644
> --- a/src/gsmd/sms_cb.c
> +++ b/src/gsmd/sms_cb.c
> @@ -91,9 +91,6 @@ static int usock_cpms_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
>  	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;
> @@ -188,14 +185,26 @@ static const struct gsmd_unsolocit gsm0705_unsolicit[] = {
>  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) {
> +		atcdm = 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) ?
> +			GSMD_SMS_FMT_TEXT : GSMD_SMS_FMT_PDU);
> +	atcdm = atcmd_fill(buffer, strlen(buffer), &sms_cb_init_cb, gu, 0);
>  	if (!atcmd)
>  		return -ENOMEM;
>  
> diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c
> index 0a29e86..b15f9c7 100644
> --- a/src/gsmd/usock.c
> +++ b/src/gsmd/usock.c
> @@ -100,7 +100,7 @@ static int usock_rcv_passthrough(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
>  
>  static int usock_rcv_event(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len)
>  {
> -	u_int32_t *evtmask = (u_int32_t *) ((char *)gph + sizeof(*gph), gph->id);
> +	u_int32_t *evtmask = (u_int32_t *) ((char *)gph + sizeof(*gph));
>  
>  	if (len < sizeof(*gph) + sizeof(u_int32_t))
>  		return -EINVAL;
> @@ -470,18 +470,38 @@ 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_atcmd *nextcmd = (struct gsmd_atcmd *) ctx;
> +	struct gsmd_user *gu = (struct gsmd_user *) nextcmd->ctx;
>  	struct gsmd_ucmd *ucmd;	
> -	
> -	ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS,
> -			      GSMD_SMS_SEND, 0);
> +
> +	/* The modem is asking for the message contents */
> +	if (resp[0] == '>' && resp[1] == ' ')
> +		return atcmd_submit(gu->gsmd, nextcmd);
> +
> +	/* Something went wrong */
> +	ucmd = gsmd_ucmd_fill(strlen(resp) + 1,
> +			GSMD_MSG_SMS, GSMD_SMS_SEND, cmd->id);
>  	if (!ucmd)
>  		return -ENOMEM;
> -	
>  	strcpy(ucmd->buf, resp);
> -
>  	usock_cmd_enqueue(ucmd, gu);
> +	return 0;
> +}
> +
> +static int sms_send_next_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
> +{
> +	struct gsmd_user *gu = (struct gsmd_user *) ctx;
> +	struct gsmd_ucmd *ucmd;	
>  
> +	if (resp[0] == '>' && resp[1] == ' ')
> +		return 0;
> +
> +	ucmd = gsmd_ucmd_fill(strlen(resp) + 1,
> +			GSMD_MSG_SMS, GSMD_SMS_SEND, cmd->id);
> +	if (!ucmd)
> +		return -ENOMEM;
> +	strcpy(ucmd->buf, resp);
> +	usock_cmd_enqueue(ucmd, gu);
>  	return 0;
>  }
>  
> @@ -519,18 +539,117 @@ static int sms_delete_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
>  	return 0;
>  }
>  
> +int packing_7bit_character(char *src, char *dest)
> +{
> +	int i,j = 0;
> +	unsigned char ch1, ch2;
> +	char tmp[2];
> +	int shift = 0;
> +	
> +	*dest = '\0';
> +
> +	for ( i=0; i<strlen(src); i++ ) {
> +		
> +		ch1 = src[i] & 0x7F;
> +		ch1 = ch1 >> shift;
> +		ch2 = src[(i+1)] & 0x7F;
> +		ch2 = ch2 << (7-shift); 
> +
> +		ch1 = ch1 | ch2;
> +		
> +		j = strlen(dest);
> + 		sprintf(tmp, "%X", (ch1 >> 4));	
> +		dest[j++] = tmp[0];
> +		sprintf(tmp, "%X", (ch1 & 0x0F));
> +		dest[j++] = tmp[0];		
> +		dest[j++] = '\0';		
> +			
> +		shift++;
> +		
> +		if ( 7 == shift ) {
> +			shift = 0;
> +			i++;
> +		}
> +	}			
> +	
> +	return 0;
> +}
> +
> +/* Refer to GSM 03.40 subclause 9.2.3.3, for SMS-SUBMIT */
> +static int usock_pdu_make_smssubmit(char *dest, struct gsmd_sms_send *src)
> +{
> +	u_int8_t header[10 + GSMD_ADDR_MAXLEN];
> +	int pos = 0, i, coding7bit = 1;
> +
> +	/* (Should be optional but some modems require it) SMSC Length octet
> +	 * is prepended.  If omitted or zero, use SMSC stored in the phone.  */
> +	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 |
> +		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 - 00 for 7-bit default alphabet */
> +	header[pos ++] = coding7bit ? 0x00 : 0x04;
> +
> +	/* TP-Validity-Period, if present, would go here */
> +
> +	header[pos ++] = src->payload.length;
> +
> +	if (dest) {
> +		for (i = 0; i < pos; i ++) {
> +			sprintf(dest, "%02X", header[i]);
> +			dest += 2;
> +		}
> +		if (coding7bit)
> +			packing_7bit_character(src->payload.data, dest);
> +		else
> +			for (i = 0; i < src->payload.length; i ++) {
> +				sprintf(dest, "%02X", src->payload.data[i]);
> +				dest += 2;
> +			}
> +	}
> +
> +	if (coding7bit)
> +		return ((src->payload.length * 7 + 7) >> 3) + pos;
> +	else
> +		return src->payload.length + pos;
> +}
> +
>  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_atcmd *cmd = NULL, *nextcmd;
>  	struct gsmd_sms_delete *gsd;
> -	struct gsmd_sms *gs;
> +	struct gsmd_sms_send *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!! */
> @@ -562,6 +681,37 @@ static int usock_rcv_sms(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
>  			return -ENOMEM;
>  		sprintf(cmd->buf, "AT+CMGR=%s", buf);
>  		break;
> +	case GSMD_SMS_SEND:
> +		if (len < sizeof(*gph) + sizeof(*gss))
> +			return -EINVAL;
> +		gss = (struct gsmd_sms_send *) ((void *) gph + sizeof(*gph));	
> +
> +		if (gu->gsmd->flags & GSMD_FLAG_SMS_FMT) {
> +			nextcmd = atcmd_fill(gss->payload.data,
> +					gss->payload.length + 2,
> +					&sms_send_next_cb, gu, gph->id);
> +			atcmd_len = sprintf(buf, "AT+CMGS=\"%s\"",
> +					gss->addr.number);
> +		} else {
> +			atcmd_len = usock_pdu_make_smssubmit(buf, gss);
> +			nextcmd = atcmd_fill(buf, atcmd_len * 2 + 2,
> +					&sms_send_next_cb, gu, gph->id);
> +			atcmd_len = sprintf(buf, "AT+CMGS=%i",
> +					atcmd_len - 1);
> +		}
> +		/* ^Z ends the message */
> +		nextcmd->buf[nextcmd->buflen - 2] = 26;
> +
> +		cmd = atcmd_fill(buf, atcmd_len + 1, &sms_send_cb, nextcmd, 0);
> +
> +		if (!cmd)
> +			return -ENOMEM;
> +
> +		gsmd_log(GSMD_DEBUG, "sms submitted with %s\n", buf);
> +		break;
> +	case GSMD_SMS_WRITE:
> +		gsmd_log(GSMD_DEBUG, "sms write\n");
> +		break;
>  #if 0
>  	case GSMD_SMS_SEND:
>  		/* FIXME: only support PDU mode!! */
> @@ -609,8 +759,8 @@ static int usock_rcv_sms(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
>  	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
> @@ -866,7 +1016,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,
>  };
>  
> diff --git a/src/libgsmd/libgsmd_sms.c b/src/libgsmd/libgsmd_sms.c
> index 261dca3..31c416b 100644
> --- a/src/libgsmd/libgsmd_sms.c
> +++ b/src/libgsmd/libgsmd_sms.c
> @@ -83,19 +83,33 @@ int lgsmd_sms_delete(struct lgsm_handle *lh,
>  	return 0;
>  }
>  
> -int lgsmd_sms_send(struct lgsm_handle *lh, 
> -		const struct lgsm_sms *sms)   
> +#ifndef MIN
> +# define MIN(a,b)	(((a) < (b)) ? (a) : (b))
> +#endif
> +
> +int lgsmd_sms_send(struct lgsm_handle *lh,
> +		const struct lgsm_sms *sms)
>  {
>  	/* FIXME: only support PDU mode */
>  	struct gsmd_msg_hdr *gmh;
> -	struct gsmd_sms *gs;
> +	struct gsmd_sms_send *gss;
>  	int rc;
>  
>  	gmh = lgsm_gmh_fill(GSMD_MSG_SMS,
> -			GSMD_SMS_SEND, sizeof(*gs));
> +			GSMD_SMS_SEND, sizeof(*gss));
>  	if (!gmh)
>  		return -ENOMEM;
> -	gs = (struct gsmd_sms *) gmh->data;
> +	gss = (struct gsmd_sms_send *) gmh->data;
> +
> +	gss->addr.type =
> +		GSMD_TOA_NPI_ISDN |
> +		GSMD_TOA_TON_UNKNOWN |
> +		GSMD_TOA_RESERVED;
> +	strncpy(gss->addr.number, sms->addr, sizeof(gss->addr.number));
> +
> +	gss->payload.length =
> +		MIN(strlen(sms->data), sizeof(gss->payload.data));
> +	memcpy(gss->payload.data, sms->data, gss->payload.length);
>  
>  	rc = lgsm_send(lh, gmh);
>  	if (rc < gmh->len + sizeof(*gmh)) {
> @@ -108,7 +122,7 @@ int lgsmd_sms_send(struct lgsm_handle *lh,
>  	return 0;
>  }
>  
> -int lgsmd_sms_write(struct lgsm_handle *lh, 
> +int lgsmd_sms_write(struct lgsm_handle *lh,
>  		const struct lgsm_sms_write *sms_write)
>  {
>  	/* FIXME: only support PDU mode */
>   




More information about the gsmd-devel mailing list