Add a bit of documentation on this code, including pointers
authorLuigi Rizzo <rizzo@icir.org>
Thu, 21 Dec 2006 16:50:26 +0000 (16:50 +0000)
committerLuigi Rizzo <rizzo@icir.org>
Thu, 21 Dec 2006 16:50:26 +0000 (16:50 +0000)
to relevant documents and comment on timing issues.

Initial merge of the code in

http://bugs.digium.com/view.php?id=8586

by Filippo Grassilli (Hyppo) to support
the SMS Protocol 2.

In this commit i have tried to minimize the diffs, so further
code cleanup will come in subsequent commits.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@48736 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_sms.c

index 0fb7961..c6cb934 100644 (file)
 
 /*! \file
  *
- * \brief SMS application - ETSI ES 201 912 protocol 1 implimentation
+ * \brief SMS application - ETSI ES 201 912 protocol 1 implementation
+ * 
+ * \par Development notes
+ * \note The ETSI standards are available free of charge from ETSI at
+ *     http://pda.etsi.org/pda/queryform.asp
+ *     Among the relevant documents here we have:
+ *
+ *     ES 201 912      SMS for PSTN/ISDN
+ *     TS 123 040      Technical realization of SMS
+ *
+ * \note 2006-09-19: ETSI ES 201 912 protocol 2 used in Italy and Spain
+ *                   support added by Filippo Grassilli (Hyppo)
+ *                   <http://hyppo.com> (Hyppo)
+ *                   Not fully tested, under development
+ * 
  * \ingroup applications
  *
- * \author Adrian Kennard
+ * \author Adrian Kennard (for the original protocol 1 code)
  */
 
 #include "asterisk.h"
@@ -65,9 +79,10 @@ static char *app = "SMS";
 static char *synopsis = "Communicates with SMS service centres and SMS capable analogue phones";
 
 static char *descrip =
-       "  SMS(name|[a][s]):  SMS handles exchange of SMS data with a call to/from SMS capabale\n"
+       "  SMS(name|[a][s][t]):  SMS handles exchange of SMS data with a call to/from SMS capable\n"
        "phone or SMS PSTN service center. Can send and/or receive SMS messages.\n"
        "Works to ETSI ES 201 912 compatible with BT SMS PSTN service in UK\n"
+       "and Telecom Italia in Italy.\n"
        "Typical usage is to use to handle called from the SMS service centre CLI,\n"
        "or to set up a call using 'outgoing' or manager interface to connect\n"
        "service centre to SMS()\n"
@@ -75,9 +90,13 @@ static char *descrip =
        "Arguments:\n"
        " a: answer, i.e. send initial FSK packet.\n"
        " s: act as service centre talking to a phone.\n"
+       " t: use protocol 2 (default used is protocol 1).\n"
        "Messages are processed as per text file message queues.\n" 
        "smsq (a separate software) is a command to generate message\n"
-       "queues and send messages.\n";
+       "queues and send messages.\n"
+       "NOTE: the protocol has tight delay bounds. Please use short frames\n"
+       "and disable/keep short the jitter buffer on the ATA to make sure that\n"
+       "respones (ACK etc.) are received in time.\n";
 
 /*
  * 80 samples of a single period of the wave. At 8000 Hz, it means these
@@ -105,6 +124,43 @@ static const output_t *wave_out = wave;            /* outgoing samples */
 #define __OUT_FMT AST_FORMAT_SLINEAR
 #endif
 
+#define OSYNC_BITS     80      /* initial sync bits */
+
+/*!
+ * The SMS spec ETSI ES 201 912 defines two protocols with different message types.
+ * Also note that the high bit is used to indicate whether the message
+ * is complete or not, but in two opposite ways:
+ * for Protocol 1, 0x80 means that the message is complete;
+ * for Protocol 2, 0x00 means that the message is complete;
+ */
+enum message_types {
+       DLL_SMS_MASK    = 0x7f, /* mask for the valid bits */
+
+       /* Protocol 1 values */
+       DLL1_SMS_DATA           = 0x11, /* data packet */
+       DLL1_SMS_ERROR          = 0x12,
+       DLL1_SMS_EST            = 0x13, /* start the connection */
+       DLL1_SMS_REL            = 0x14, /* end the connection */
+       DLL1_SMS_ACK            = 0x15,
+       DLL1_SMS_NACK           = 0x16,
+
+       DLL1_SMS_COMPLETE       = 0x80, /* packet is complete */
+       DLL1_SMS_MORE           = 0x00, /* more data to follow */
+
+       /* Protocol 2 values */
+       DLL2_SMS_EST            = 0x7f, /* magic number. No message body */
+       DLL2_SMS_INFO_MO        = 0x10,
+       DLL2_SMS_INFO_MT        = 0x11,
+       DLL2_SMS_INFO_STA       = 0x12,
+       DLL2_SMS_NACK           = 0x13,
+       DLL2_SMS_ACK0           = 0x14, /* ack even-numbered frame */
+       DLL2_SMS_ACK1           = 0x15, /* ack odd-numbered frame */
+       DLL2_SMS_ENQ            = 0x16,
+       DLL2_SMS_REL            = 0x17, /* end the connection */
+
+       DLL2_SMS_COMPLETE       = 0x00, /* packet is complete */
+       DLL2_SMS_MORE           = 0x80, /* more data to follow */
+};
 
 /* SMS 7 bit character mapping to UCS-2 */
 static const unsigned short defaultalphabet[] = {
@@ -186,6 +242,11 @@ typedef struct sms_s
        unsigned char ibith;         /*!< history of last bits */
        unsigned char ibitt;         /*!< total of 1's in last 3 bytes */
        /* more to go here */
+
+       int protocol;                /*!< ETSI SMS protocol to use (passed at app call) */
+       int oseizure;                /*!< protocol 2: channel seizure bits to send */
+       int framenumber;             /*!< protocol 2: frame number (for sending ACK0 or ACK1) */
+       unsigned char udtxt[SMSLEN]; /*!< user data (message), PLAIN text */
 } sms_t;
 
 /* different types of encoding */
@@ -716,6 +777,7 @@ static void sms_readfile (sms_t * h, char *fn)
                                *p++ = 0;
                                if (!strcmp (line, "ud")) {      /* parse message (UTF-8) */
                                        unsigned char o = 0;
+                                       memcpy(h->udtxt,p,SMSLEN);      /* for protocol 2 */
                                        while (*p && o < SMSLEN)
                                                h->ud[o++] = utf8decode(pp);
                                        h->udl = o;
@@ -1007,6 +1069,216 @@ static unsigned char sms_handleincoming (sms_t * h)
 #define NAME_MAX 1024
 #endif
 
+/*!
+ * Add data to a protocol 2 message.
+ * Use the length field (h->omsg[1]) as a pointer to the next free position.
+ */
+static void adddata_proto2 (sms_t *h, unsigned char msg, char *data, int size)
+{
+       int x = h->omsg[1]+2;   /* Get current position */
+       if (x==2)
+               x += 2;         /* First: skip Payload length (set later) */
+       h->omsg[x++] = msg;     /* Message code */
+       h->omsg[x++]=(unsigned char)size;       /* Data size Low */
+       h->omsg[x++]=0;         /* Data size Hi */
+       for (; size>0 ; size--)
+               h->omsg[x++] = *data++;
+       h->omsg[1] = x-2;       /* Frame size */
+       h->omsg[2] = x-4;       /* Payload length (Lo) */
+       h->omsg[3] = 0;         /* Payload length (Hi) */
+}
+
+static void putdummydata_proto2 (sms_t *h)
+{
+       adddata_proto2 (h, 0x10, "\0", 1);              /* Media Identifier > SMS */
+       adddata_proto2 (h, 0x11, "\0\0\0\0\0\0", 6);    /* Firmware version */
+       adddata_proto2 (h, 0x12, "\2\0\4", 3);          /* SMS provider ID */
+       adddata_proto2 (h, 0x13, h->udtxt, h->udl);     /* Body */
+}
+
+static void sms_compose2(sms_t *h, int more)
+{
+       struct tm *tm;
+       char stm[9];
+
+       h->omsg[0] = 0x00;       /* set later... */
+       h->omsg[1] = 0;
+       putdummydata_proto2 (h);
+       if (h->smsc) {                  /* deliver */
+               h->omsg[0] = 0x11;      /* SMS_DELIVERY */
+               // Required: 10 11 12 13 14 15 17 (seems they must be ordered!)
+               tm=localtime(&h->scts);
+               sprintf (stm, "%02d%02d%02d%02d", tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min);     // Date mmddHHMM
+               adddata_proto2 (h, 0x14, stm, 8);               /* Date */
+               if(*h->oa==0)
+                       strcpy(h->oa,"00000000");
+               adddata_proto2 (h, 0x15, h->oa, strlen(h->oa)); /* Originator */
+               adddata_proto2 (h, 0x17, "\1", 1);              /* Calling Terminal ID */
+       } else {                        /* submit */
+               h->omsg[0] = 0x10;      /* SMS_SUBMIT */
+               // Required: 10 11 12 13 17 18 1B 1C (seems they must be ordered!)
+               adddata_proto2 (h, 0x17, "\1", 1);              /* Calling Terminal ID */
+               if(*h->da==0)
+                       strcpy(h->da,"00000000");
+               adddata_proto2 (h, 0x18, h->da, strlen(h->da)); /* Originator */
+               adddata_proto2 (h, 0x1B, "\1", 1);              /* Called Terminal ID */
+               adddata_proto2 (h, 0x1C, "\0\0\0", 3);          /* Notification */
+       }
+}
+
+static void putdummydata_proto2 (sms_t *h);
+
+#if 1 /* XXX debugging */
+static char *sms_hexdump (unsigned char buf[], int size)
+{
+       static char *s=NULL;
+       char *p;
+       int f;
+
+       s=(char *)realloc(s,(size*3)+1);
+       for(p=s,f=0; f<size && f<800/3; f++,p+=3) 
+               sprintf(p,"%02X ",(unsigned char)buf[f]);
+       return(s);
+}
+#endif
+
+/*! \brief sms_handleincoming_proto2: handle the incoming message */
+static int sms_handleincoming_proto2 (sms_t * h)
+{
+       int f, i, sz=0;
+       int msg, msgsz;
+       struct tm *tm;
+
+       sz = h->imsg[1]+2;
+       /* ast_verbose (VERBOSE_PREFIX_3 "SMS-P2 Frame: %s\n", sms_hexdump(h->imsg,sz)); */
+
+       /* Parse message body (called payload) */
+       h->scts = time (0);
+       for(f=4; f<sz; ) {
+               msg=h->imsg[f++];
+               msgsz=h->imsg[f++];
+               msgsz+=(h->imsg[f++]*256);
+               switch(msg) {
+               case 0x13:      /* Body */
+                       if (option_verbose > 2)
+                               ast_verbose (VERBOSE_PREFIX_3 "SMS-P2 Body#%02X=[%.*s]\n",msg,msgsz,&h->imsg[f]);
+                       if (msgsz >= sizeof(h->imsg))
+                               msgsz = sizeof(h->imsg)-1;
+                       for (i=0; i<msgsz; i++)
+                               h->ud[i]=h->imsg[f+i];
+                       h->udl = msgsz;
+                       break;
+               case 0x14:      /* Date SCTS */
+                       h->scts = time (0);
+                       tm = localtime (&h->scts);
+                       tm->tm_mon = ( (h->imsg[f]*10) + h->imsg[f+1] ) - 1;
+                       tm->tm_mday = ( (h->imsg[f+2]*10) + h->imsg[f+3] );
+                       tm->tm_hour = ( (h->imsg[f+4]*10) + h->imsg[f+5] );
+                       tm->tm_min = ( (h->imsg[f+6]*10) + h->imsg[f+7] );
+                       tm->tm_sec = 0;
+                       h->scts = mktime (tm);
+                       if (option_verbose > 2)
+                               ast_verbose (VERBOSE_PREFIX_3 "SMS-P2 Date#%02X=%02d/%02d %02d:%02d\n", msg, tm->tm_mday, tm->tm_mon+1, tm->tm_hour, tm->tm_min);
+                       break;
+               case 0x15:      /* Calling line (from SMSC) */
+                       if (msgsz>=20)
+                               msgsz=20-1;
+                       if (option_verbose > 2)
+                               ast_verbose (VERBOSE_PREFIX_3 "SMS-P2 Origin#%02X=[%.*s]\n",msg,msgsz,&h->imsg[f]);
+                       ast_copy_string (h->oa, &h->imsg[f], msgsz+1);
+                       break;
+               case 0x18:      /* Destination (from TE/phone) */
+                       if (msgsz>=20)
+                               msgsz=20-1;
+                       if (option_verbose > 2)
+                               ast_verbose (VERBOSE_PREFIX_3 "SMS-P2 Destination#%02X=[%.*s]\n",msg,msgsz,&h->imsg[f]);
+                       ast_copy_string (h->da, &h->imsg[f], msgsz+1);
+                       break;
+               case 0x1C:      /* Notify */
+                       if (option_verbose > 2)
+                               ast_verbose (VERBOSE_PREFIX_3 "SMS-P2 Notify#%02X=%s\n",msg,sms_hexdump(&h->imsg[f],3));
+                       break;
+               default:
+                       if (option_verbose > 2)
+                               ast_verbose (VERBOSE_PREFIX_3 "SMS-P2 Par#%02X [%d]: %s\n",msg,msgsz,sms_hexdump(&h->imsg[f],msgsz));
+                       break;
+               }
+               f+=msgsz;       /* Skip to next */
+       }
+       h->rx = 1;              /* received message */
+       sms_writefile (h);      /* write the file */
+       return 0;               /* no error */
+}
+
+#if 0
+static void smssend(sms_t *h, char *c)
+{
+       int f, x;
+       for(f=0; f<strlen(c); f++) {
+               sscanf(&c[f*3],"%x",&x);
+               h->omsg[f] = x;
+       }
+       sms_messagetx (h);
+}
+#endif
+
+static void sms_nextoutgoing (sms_t *h);
+
+static void sms_messagerx2(sms_t * h)
+{
+       int p = h->imsg[0] & DLL_SMS_MASK ; /* mask the high bit */
+       int cause;
+
+#define DLL2_ACK(h) ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1)
+       switch (p) {
+       case DLL2_SMS_EST:      /* Protocol 2: Connection ready (fake): send message  */
+               sms_nextoutgoing (h);
+               //smssend(h,"11 29 27 00 10 01 00 00 11 06 00 00 00 00 00 00 00 12 03 00 02 00 04 13 01 00 41 14 08 00 30 39 31 35 30 02 30 02 15 02 00 39 30 ");
+               break;
+
+       case DLL2_SMS_INFO_MO:  /* transport SMS_SUBMIT */
+       case DLL2_SMS_INFO_MT:  /* transport SMS_DELIVERY */
+               cause = sms_handleincoming_proto2(h);
+               if (!cause)     /* ACK */
+                       sms_log (h, 'Y');
+               h->omsg[0] = DLL2_ACK(h);
+               h->omsg[1] = 0x06;  /* msg len */
+               h->omsg[2] = 0x04;  /* payload len */
+               h->omsg[3] = 0x00;  /* payload len */
+               h->omsg[4] = 0x1f;  /* Response type */
+               h->omsg[5] = 0x01;  /* parameter len */
+               h->omsg[6] = 0x00;  /* parameter len */
+               h->omsg[7] = cause;  /* CONFIRM or error */
+               sms_messagetx (h);
+               break;
+
+       case DLL2_SMS_NACK:     /* Protocol 2: SMS_NAK */
+               h->omsg[0] = DLL2_SMS_REL;  /* SMS_REL */
+               h->omsg[1] = 0x00;  /* msg len */
+               sms_messagetx (h);
+               break;
+
+       case DLL2_SMS_ACK0:
+       case DLL2_SMS_ACK1:
+               /* SMS_ACK also transport SMS_SUBMIT or SMS_DELIVERY */
+               if( (h->omsg[0] & DLL_SMS_MASK) == DLL2_SMS_REL) {
+                       /* a response to our Release, just hangup */
+                       h->hangup = 1;          /* hangup */
+               } else {
+                       /* XXX depending on what we are.. */
+                       ast_log(LOG_NOTICE, "SMS_SUBMIT or SMS_DELIVERY");
+                       sms_nextoutgoing (h);
+               }
+               break;
+
+       case DLL2_SMS_REL:      /* Protocol 2: SMS_REL (hangup req) */
+               h->omsg[0] = DLL2_ACK(h);
+               h->omsg[1] = 0;
+               sms_messagetx (h);
+               break;
+       }
+}
+
 /*! \brief compose a message for protocol 1 */
 static void sms_compose1(sms_t *h, int more)
 {
@@ -1072,20 +1344,31 @@ static void sms_nextoutgoing (sms_t * h)
                closedir (d);
        }
        if (*h->da || *h->oa) {                                                                  /* message to send */
-               sms_compose1(h, more);
-       } else {                                 /* no message */
-               h->omsg[0] = 0x94;                /* SMS_REL */
-               h->omsg[1] = 0;
+               if (h->protocol==2)
+                       sms_compose2(h, more);
+               else
+                       sms_compose1(h,more);
+       } else {                                /* no message */
+               if (h->protocol==2) {
+                       h->omsg[0] = 0x17;      /* SMS_REL */
+                       h->omsg[1] = 0;
+               } else {
+                       h->omsg[0] = 0x94;      /* SMS_REL */
+                       h->omsg[1] = 0;
+               }
        }
        sms_messagetx (h);
 }
 
-static void sms_debug (char *dir, unsigned char *msg)
+#define DIR_RX 1
+#define DIR_TX 2
+static void sms_debug (int dir, sms_t *h)
 {
-       char txt[259 * 3 + 1],
-        *p = txt;                                               /* always long enough */
-       int n = msg[1] + 3,
-               q = 0;
+       char txt[259 * 3 + 1];
+       char *p = txt;                                           /* always long enough */
+       unsigned char *msg = (dir == DIR_RX) ? h->imsg : h->omsg;
+       int n = (dir == DIR_RX) ? h->ibytep : msg[1] + 2;
+       int q = 0;
        while (q < n && q < 30) {
                sprintf (p, " %02X", msg[q++]);
                p += 3;
@@ -1093,17 +1376,23 @@ static void sms_debug (char *dir, unsigned char *msg)
        if (q < n)
                sprintf (p, "...");
        if (option_verbose > 2)
-               ast_verbose (VERBOSE_PREFIX_3 "SMS %s%s\n", dir, txt);
+               ast_verbose (VERBOSE_PREFIX_3 "SMS %s%s\n", dir == DIR_RX ? "RX" : "TX", txt);
 }
 
+
 static void sms_messagerx(sms_t * h)
 {
-       sms_debug ("RX", h->imsg);
-       /* testing */
-       switch (h->imsg[0]) {   /* PROTOCOL version 1 */
+       int cause;
+
+       sms_debug (DIR_RX, h);
+       if (h->protocol == 2) {
+               sms_messagerx2(h);
+               return;
+       }
+       /* parse incoming message for Protocol 1 */
+       switch (h->imsg[0]) {
        case 0x91:                                              /* SMS_DATA */
-               {
-                       unsigned char cause = sms_handleincoming (h);
+                       cause = sms_handleincoming (h);
                        if (!cause) {
                                sms_log (h, 'Y');
                                h->omsg[0] = 0x95;  /* SMS_ACK */
@@ -1119,8 +1408,8 @@ static void sms_messagerx(sms_t * h)
                                h->omsg[4] = 0;   /* no parameters */
                        }
                        sms_messagetx (h);
-               }
-               break;
+                       break;
+
        case 0x92:                                              /* SMS_ERROR */
                h->err = 1;
                sms_messagetx (h);                /* send whatever we sent again */
@@ -1157,15 +1446,27 @@ static void sms_messagetx(sms_t * h)
        for (p = 0; p < len; p++)       /* compute checksum */
                c += h->omsg[p];
        h->omsg[len] = 0 - c;           /* actually, (256 - (c & 0fxx)) & 0xff) */
-       sms_debug ("TX", h->omsg);
-       h->obyte = 1;
+       sms_debug(DIR_TX, h);
+       h->framenumber++;       /* Proto 2 */
+       h->obyte = 1;           /* send mark ('1') at the beginning */
        h->opause = 200;
+       /* Change the initial message delay. BT requires 300ms,
+        * but for others this might be way too much and the phone
+        * could time out. XXX make it configurable.
+        */
        if (h->omsg[0] == 0x93)
-               h->opause = 2400;       /* initial message delay 300ms (for BT) */
+               h->opause = 200;        /* XXX initial message delay 300ms (for BT) */
        h->obytep = 0;
        h->obitp = 0;
+       if (h->protocol == 2) {
+               h->oseizure = 300;      /* Proto 2: 300bits (or more ?) */
+               h->obyte = 0;           /* Seizure starts with  space (0) */
+               h->opause = 400;
+       } else {
+               h->oseizure = 0;        /* Proto 1: No seizure */
+       }
        /* Note - setting osync triggers the generator */
-       h->osync = 80;                  /* 80 sync bits */
+       h->osync = OSYNC_BITS;                  /* 80 sync bits */
        h->obyten = len + 1;            /* bytes to send (including checksum) */
 }
 
@@ -1199,15 +1500,22 @@ static int sms_generate (struct ast_channel *chan, void *data, int len, int samp
 
                if (h->opause)
                        h->opause--;
-               else if (h->obyten || h->osync) {               /* sending data */
+               else if (h->obyten || h->osync) {       /* sending data */
                        buf[i] = wave_out[h->ophase];
                        h->ophase += (h->obyte & 1) ? 13 : 21;  /* compute next phase */
                        if (h->ophase >= 80)
                                h->ophase -= 80;
                        if ((h->ophasep += 12) >= 80) {         /* time to send the next bit */
                                h->ophasep -= 80;
-                               if (h->osync) {
+                               if (h->oseizure > 0) {           /* sending channel seizure (proto 2) */
+                                       h->oseizure--;
+                                       h->obyte ^= 1;  /* toggle low bit */
+                               } else if (h->osync) {
+                                       h->obyte = 1;   /* send mark as sync bit */
                                        h->osync--;             /* sending sync bits */
+                                       if (h->osync == 0 && h->protocol == 2 && h->omsg[0] == DLL2_SMS_EST) {
+                                               h->obytep = h->obyten = 0;      /* we are done */
+                                       }
                                } else {
                                        h->obitp++;
                                        if (h->obitp == 1)
@@ -1250,8 +1558,13 @@ static int sms_generate (struct ast_channel *chan, void *data, int len, int samp
  */
 static void sms_process (sms_t * h, int samples, signed short *data)
 {
+#if 1
+       /* Do we really need to remain deaf while a packet is
+        * being transmitted ?
+        */
        if (h->obyten || h->osync)
                return;                                          /* sending */
+#endif
        while (samples--) {
                unsigned long long m0, m1;
                if (abs (*data) > h->imag)
@@ -1301,27 +1614,43 @@ static void sms_process (sms_t * h, int samples, signed short *data)
                                        h->iphasep = 0;
                                }
                                if (bit && h->ibitc == 200) {                                            /* sync, restart message */
+                                       /* Protocol 2: empty connnection ready (I am master) */
+                                       if(h->framenumber<0 && h->ibytec>=160 && !memcmp(h->imsg,"UUUUUUUUUUUUUUUUUUUU",20)) {
+                                               h->framenumber = 1;
+                                               if (option_verbose > 2)
+                                                       ast_verbose (VERBOSE_PREFIX_3 "SMS protocol 2 detected\n");
+                                               h->protocol = 2;
+                                               h->imsg[0] = 0xff;      /* special message (fake) */
+                                               h->imsg[1] = h->imsg[2] = 0x00;
+                                               h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
+                                               sms_messagerx (h);
+                                       }
                                        h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
                                }
                                if (h->ibitn) {
                                        h->iphasep += 12;
-                                       if (h->iphasep >= 80) {                                  /* next bit */
+                                       if (h->iphasep >= 80) {                                 /* next bit */
                                                h->iphasep -= 80;
-                                               if (h->ibitn++ == 9) {                           /* end of byte */
-                                                       if (!bit)  /* bad stop bit */
+                                               if (h->ibitn++ == 9) {                          /* end of byte */
+                                                       if (!bit) { /* bad stop bit */
+                                                               ast_log(LOG_NOTICE, "bad stop bit");
                                                                h->ierr = 0xFF; /* unknown error */
-                                                       else {
+                                                       } else {
                                                                if (h->ibytep < sizeof (h->imsg)) {
                                                                        h->imsg[h->ibytep] = h->ibytev;
                                                                        h->ibytec += h->ibytev;
                                                                        h->ibytep++;
-                                                               } else if (h->ibytep == sizeof (h->imsg))
+                                                               } else if (h->ibytep == sizeof (h->imsg)) {
+                                                                       ast_log(LOG_NOTICE, "msg too large");
                                                                        h->ierr = 2; /* bad message length */
+                                                               }
                                                                if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr) {
                                                                        if (!h->ibytec)
                                                                                sms_messagerx (h);
-                                                                       else
+                                                                       else {
+                                                                               ast_log(LOG_NOTICE, "bad checksum");
                                                                                h->ierr = 1;            /* bad checksum */
+                                                                       }
                                                                }
                                                        }
                                                        h->ibitn = 0;
@@ -1332,11 +1661,12 @@ static void sms_process (sms_t * h, int samples, signed short *data)
                        }
                } else {                         /* lost carrier */
                        if (h->idle++ == 80000) {                /* nothing happening */
-                               ast_log (LOG_EVENT, "No data, hanging up\n");
+                               ast_log (LOG_NOTICE, "No data, hanging up\n");
                                h->hangup = 1;
                                h->err = 1;
                        }
                        if (h->ierr) {          /* error */
+                               ast_log (LOG_NOTICE, "Error %d, hanging up\n", h->ierr);
                                /* Protocol 1 */
                                h->err = 1;
                                h->omsg[0] = 0x92;  /* error */
@@ -1398,6 +1728,7 @@ static int sms_exec (struct ast_channel *chan, void *data)
                for (p = (unsigned char *)h.queue; *p; p++)
                        if (!isalnum (*p))
                                *p = '-';                         /* make very safe for filenames */
+ast_log(LOG_NOTICE, "sms to queue %s\n", h.queue);
                while (*d && *d != '|') {
                        switch (*d) {
                        case 'a':                                /* we have to send the initial FSK sequence */
@@ -1406,6 +1737,9 @@ static int sms_exec (struct ast_channel *chan, void *data)
                        case 's':                                /* we are acting as a service centre talking to a phone */
                                h.smsc = 1;
                                break;
+                       case 't':                                /* use protocol 2 ([t]wo)! couldn't use numbers *!* */
+                               h.protocol = 2;
+                               break;
                                /* the following apply if there is an arg3/4 and apply to the created message file */
                        case 'r':
                                h.srr = 1;
@@ -1462,9 +1796,15 @@ static int sms_exec (struct ast_channel *chan, void *data)
                }
 
                if (answer) {
+                       h.framenumber = 1;             /* Proto 2 */
                        /* set up SMS_EST initial message */
-                       h.omsg[0] = 0x93;
-                       h.omsg[1] = 0;
+                       if (h.protocol == 2) {
+                               h.omsg[0] = DLL2_SMS_EST;
+                               h.omsg[1] = 0;
+                       } else {
+                               h.omsg[0] = DLL1_SMS_EST | DLL1_SMS_COMPLETE;
+                               h.omsg[1] = 0;
+                       }
                        sms_messagetx (&h);
                }
        }