mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-17 07:18:15 +00:00
Add a bit of documentation on this code, including pointers
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
This commit is contained in:
412
apps/app_sms.c
412
apps/app_sms.c
@@ -16,10 +16,24 @@
|
||||
|
||||
/*! \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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user