From ba7c11d0a73e626ba828d8ba29c697ea02f49a67 Mon Sep 17 00:00:00 2001 From: short <> Date: Tue, 7 Sep 1999 10:31:57 +0000 Subject: [PATCH] Many modifications for mdsms -> sms9110 branch transition. --- mdsms.c | 353 +++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 181 insertions(+), 172 deletions(-) diff --git a/mdsms.c b/mdsms.c index a4e6498..891d18e 100644 --- a/mdsms.c +++ b/mdsms.c @@ -29,14 +29,6 @@ static char rcsid[] ATTR_UNUSED = "$Id$"; #include "getopt.h" #endif -#if 0 -char *strdup(const char *s); -int kill(pid_t pid,int sig); -int snprintf(char *str,size_t n,const char *format,...); -int vsnprintf(char *str,size_t n,const char *format,va_list ap); -void usleep(unsigned long usec); -#endif - #define NELEM(x) (sizeof((x))/sizeof(*(x))) #ifndef DEBUG @@ -53,7 +45,7 @@ void usleep(unsigned long usec); #define d3(n1,n2,n3) dB((dO,n1,n2,n3 )) #define d4(n1,n2,n3,n4) dB((dO,n1,n2,n3,n4)) -static const char version[]="This is MobilDock SMS sender (" PACKAGE " " VERSION ")\n"; +static const char version[]="This is Nokia 9110 logo SMS sender (" PACKAGE " " VERSION ")\n"; static int verbose #ifdef DEBUG @@ -63,10 +55,8 @@ static int verbose static char *pname; static int dis_cleanup=0,devfd=-1; -static char *phone,*body,*device,*logname,*lockfile,*smsc,*maxretry,*readtime,*chartime,*cmdtime; -static int readbody; -static long maxretryn=DEF_MAXRETRY,readtimen=DEF_READTIME,chartimen=DEF_CHARTIME,cmdtimen=DEF_CMDTIME; -static size_t bodylen; +static char *phone,*logoname,*device,*logname,*lockfile,*smsc,*maxretry,*readtime,*chartime,*cmdtime,*baud,*gsmnet; +static long maxretryn=DEF_MAXRETRY,readtimen=DEF_READTIME,chartimen=DEF_CHARTIME,cmdtimen=DEF_CMDTIME,baudn=DEF_BAUD; static char *devicename; /* path stripped */ static char lockreal[512],locked; @@ -195,42 +185,45 @@ static void usage(void) %s\ \n\ Usage: " PACKAGE " [-c|--config ] [-d|--device ]\n\ - [-L|--log ]\n\ + [-L|--log ] [-b|--baud ]\n\ [-l|--lockfile ] [-s|--smsc ] [-m|--maxretry <#>]\n\ [-r|--readtime ] [-t|--chartime ] [-T|--cmdtime ]\n\ - [-f|--file] [-v|--verbose] [-h|--help] [-V|--version]\n\ - \n\ + [-v|--verbose] [-h|--help] [-V|--version]\n\ + []\n\ \n\ -c, --config\tRead this additional config file\n\ \t\t(def. \"" CONFIG_MAIN "\" and \"$HOME" CONFIG_HOME "\")\n\ - -d, --device\tMobilDock on this serial device (def. \"" DEF_DEVICE "\")\n\ + -d, --device\tNokia on this serial device (def. \"" DEF_DEVICE "\")\n\ -L, --log\tLog all important messages to this file (def. \"" DEF_LOGNAME "\")\n\ + -b, --baud\tSet baudrate, 2400-57600 supported (def. %d)\n\ -l, --lockfile\tLock serial port by this file, \"%%s\" is basename of device\n\ \t\t(def. \"%s\")\n\ - -s, --smsc\tUse this SMS Center number (def. query from Siemens A1)\n\ + -s, --smsc\tUse this SMS Center number (def. query from Nokia 9110)\n\ -m, --maxretry\tMaximum retries of any command before giving up (def. %d)\n\ -r, --readtime\tSeconds for maximum wait time for response (def. %ds)\n\ - -t, --chartime\tMilliseconds between each char on baud 19200 (def. %dms)\n\ + -t, --chartime\tMilliseconds between each char (def. %dms)\n\ -T, --cmdtime\tMilliseconds before each whole AT command (def. %dms)\n\ - -f, --file\tRead contents of message from file instead\n\ -v, --verbose\tIncrease verbosity level, more \"-v\"s give more messages\n\ -h, --help\tPrint a summary of the options\n\ -V, --version\tPrint the version number\n\ -\n",version,DEF_LOCKFILE,DEF_MAXRETRY,DEF_READTIME,DEF_CHARTIME,DEF_CMDTIME); + \t* Oper. logo: Enter custom network code MccMnc, e.g. 23002\n\ +\t\t* Oper. logo: Specify \"" WORD_NET "\" to read network code from NOL file\n\ +\t\t* Group gfx : Specify \"" WORD_GROUP "\" to send logo as group graphics\n\ +\n",version,DEF_BAUD,DEF_LOCKFILE,DEF_MAXRETRY,DEF_READTIME,DEF_CHARTIME,DEF_CMDTIME); exit(EXIT_FAILURE); } static const struct option longopts[]={ {"config" ,1,0,'c'}, {"device" ,1,0,'d'}, -{"log" ,1,0,'l'}, +{"log" ,1,0,'L'}, +{"baud" ,1,0,'b'}, {"lockfile",1,0,'l'}, {"smsc" ,1,0,'s'}, {"maxretry",1,0,'m'}, {"readtime",1,0,'r'}, {"chartime",1,0,'t'}, {"cmdtime" ,1,0,'T'}, -{"file" ,0,0,'f'}, {"verbose" ,0,0,'v'}, {"help" ,0,0,'h'}, {"version" ,0,0,'V'}}; @@ -319,6 +312,7 @@ static struct { } optset[]={ { 'd',&device }, { 'L',&logname }, + { 'b',&baud }, { 'l',&lockfile }, { 's',&smsc }, { 'm',&maxretry }, @@ -343,7 +337,7 @@ int i; } chk(cfgstack[cfgstacki++]=strdup(optarg)); break; - case 'd': case 'L': case 'l': case 's': case 'm': case 'r': case 't': case 'T': + case 'd': case 'L': case 'b': case 'l': case 's': case 'm': case 'r': case 't': case 'T': for (i=0;i'9') - error("!Error during conversion of number at: %s",addr); - tot++; - n=(*addr++)-'0'; - if ((flip=!flip)) *++d=0xF0|n; - else *d=(*d&0x0F)|(n<<4U); - } - return(tot); -} - -static char *finalsmsc; -#define SMSCBINSIZE (1+1+(MAXNUMLEN+1)/2) -static char pdusmsc[SMSCBINSIZE*2+1]; - static inline char tohex(unsigned char x) { x&=0x0F; @@ -655,7 +649,7 @@ static inline char tohex(unsigned char x) return(x-10+'A'); } -static void textconv(char *d,unsigned char *s,size_t len) +static inline void textconv(char *d,unsigned char *s,size_t len) { while (len--) { *d++=tohex(*s>>4U); @@ -669,14 +663,13 @@ static inline void smscset(void) { char *s,*t,*e,*serr; long l; -unsigned char bin[2+(MAXNUMLEN+1)/2]; if (smsc) devcmd(NULL,NULL,"\r\nAT+CSCA=\"%s\"",smsc); s=devcmd(NULL,"\n+CSCA:","\r\nAT+CSCA?"); while (isspace(*s)) s++; if (!*s || !strcmp(s,"EMPTY")) - error("!No SMS set in A1 found"); - if (verbose>=1) error("\nFound default SMSC in A1: %s",s); + error("!No SMS set in Nokia found"); + if (verbose>=1) error("\nFound default SMSC in Nokia: %s",s); if (*s!='"') error("!No left-quote found in: %s",s); if (!(t=strrchr(s+1,'"'))) error("!No right-quote found in: %s",s); e=t++; @@ -689,73 +682,99 @@ unsigned char bin[2+(MAXNUMLEN+1)/2]; if (l==ADDR_NAT || s[1]=='+') s++; else *s='+'; *e='\0'; - chk(finalsmsc=strdup(s)); - if (verbose>=2) error("\nDecoded SMSC address: %s",finalsmsc); - bin[0]=1+(prepaddr(bin,finalsmsc)+1)/2; - textconv(pdusmsc,bin,bin[0]+1); + if (verbose>=2) error("\nDecoded SMSC address: %s",s); } -static char *pdudata; +/* Logo format shamelessly stolen from GNokii-0.3.0: http://www.gnokii.org/ + * Beware - Nokia Smart Messaging specification 1.0.0 and 2.0.0 is incompatible + * with Nokia current product line implementation + * http://www.forum.nokia.com/developers/smartmsg/download/ssm2_0_0.pdf + */ -static inline unsigned char charconv(char c,size_t offs) -{ - switch (c) { - case '@': return(0); - case '$': return(2); - case 0: assert(0); - default: - return(c&0x7F); - } -#if 0 - if ((c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9')) return(c); - error("Can't convert character '%c' (0x%02X) at offs %d (0-based), substituted '?'", - c,(unsigned char)c,offs); - return('?'); -#endif -} +static char hexdata[140*2+1]; -static inline void genpdu(void) +static inline void logoread(void) { -static unsigned char pdu[64+MAXNUMLEN/2+(MAXBODYLEN*7)/8]; -unsigned char *d=pdu; -int i; -char inb=0,outb=0,xb; -unsigned char inreg; -size_t offs=0; - - *d++=PDU_TYPE; - *d++=PDU_MR; - i=prepaddr(d,phone); - *d=i; d+=1+1+(i+1)/2; - *d++=PDU_PID; - *d++=PDU_DCS; - *d++=PDU_VP; - if (bodylen>MAXBODYLEN) { - error("Body too large (%d>%d), cut",bodylen,MAXBODYLEN); - bodylen=MAXBODYLEN; - } - *d=bodylen; - assert(d0); assert(!!*body); - inreg=charconv(*body++,offs++); - bodylen--; - inb=7; - } - if (!outb) { - *++d=0x00; - outb=8; +FILE *f; +char buf[32+140*8+1]; +unsigned char bin[140]={ + 0x06, /* UDH length */ + 0x05, /* IEI */ + 0x04, /* IEDL */ + 0x15, 0x83, /* dest port (group gfx) */ + 0x00, 0x00 /* src port (unused) */ + }; +size_t got,r,w; +ssize_t chars,bits; +char gsmnetf[10]; +int sizex,sizey,bit; + +#define WORD(n) (((unsigned char)buf[(n)])|(((unsigned char)buf[(n)+1])<<8)) + + if (!(f=fopen(logoname,"rb"))) + error("!Cannot open logo file \"%s\" for r/o: %m",logoname); + got=fread(buf,1,sizeof(buf),f); + if (got>=20 && !memcmp(buf,"NOL",4)) { + VARPRINTF2(gsmnetf,"%03.3u%02.2u",WORD(6),WORD(8)); + assert(strlen(gsmnetf)==5); + r=10; + if (verbose>=1) error(".Reading NOL file \"%s\", GSMnet \"%s\", word@4=%d..", + logoname,gsmnetf,WORD(4)); + } + else if (got>=16 && !memcmp(buf,"NGG",4)) { + r=6; + if (verbose>=1) error(".Reading NGG file \"%s\", word@4=%d..", + logoname,gsmnetf,WORD(4)); + } + else error("!Unknown file format of logo file \"%s\""); + if (!strcasecmp(gsmnet,WORD_NET)) { + if (!*gsmnetf) error("!NOL network code detection requested but NOL file not loaded, please specify network code"); + gsmnet=gsmnetf; + } + if (!strcasecmp(gsmnet,WORD_GROUP) || !*gsmnet) { + error("\nSending logo as: group graphics"); + gsmnet=NULL; + } + else { + error("\nSending logo as: operator logo for \"%s\"",gsmnet); + bin[4]=0x82; /* dest port 0x1582 */ + } + + sizex=WORD(r); sizey=WORD(r+2); + if (verbose>=2) error(".Magic words: @+4=%d, @+6=%d, @+8=%d", + WORD(r+4),WORD(r+6),WORD(r+8)); + r+=10; + if (sizex<1 || sizex>255 + || sizey<1 || sizey>255) error("!Invalid size: %dx%d",sizex,sizey); + chars=((bits=sizex*sizey)+7)/8; + if (r+bits>got) error("!Logo file \"%s\" too short - actual=%d, need(%dx%d)=%d", + logoname,got,sizex,sizey,r+chars); + else if (r+bits=1) error("Ignoring trailing garbage in \"%s\", used only %d bytes",logoname,r+bits); + if ((got=(7+(gsmnet?3:0)+4+chars))>140) + error("!SMS size would be %d bytes but 140 is maximum",got); + w=7; + if (gsmnet) { + bin[w++]=((gsmnet[1]&0x0F)<<4)|(gsmnet[0]&0x0F); + bin[w++]=0xF0 |(gsmnet[2]&0x0F); + bin[w++]=((gsmnet[4]&0x0F)<<4)|(gsmnet[3]&0x0F); + } + bin[w++]=0x00; /* RFU by Nokia */ + bin[w++]=sizex; bin[w++]=sizey; + bin[w++]=0x01; /* one B/W plane */ + while (chars--) { + bin[w]=0; + for (bit=0x80;(bits>0) && (bit>0);bits--,bit>>=1) { + if (buf[r]!='0' && buf[r]!='1') + error("!Invalid character (neither '0' nor '1')in logo file \"%s\" at offset 0x%X", + logoname,r); + if (buf[r++]=='1') bin[w]|=bit; } - xb=MIN(inb,outb); - d4("inb=%d,outb=%d,xb=%d\n",inb,outb,xb); - *d|=((inreg>>(unsigned)(7-inb))&((1<=2) error("\nWill send hexdata: %s",hexdata); } static struct { @@ -767,14 +786,15 @@ static struct { { &readtime,&readtimen,"readtime" }, { &chartime,&chartimen,"chartime" }, { &cmdtime ,&cmdtimen ,"cmdtime" }, + { &baud ,&baudn ,"baud" }, }; int main(int argc,char **argv) { -char *s,*finame; -FILE *fin; +char *s; int i; unsigned fatal=0; +speed_t portbaud; if ((s=strrchr((pname=*argv),'/'))) pname=s+1; atexit(cleanup); @@ -808,33 +828,7 @@ char *buf=malloc(l+50); if (!logname) logname=DEF_LOGNAME; if (!lockfile) lockfile=DEF_LOCKFILE; if (!device) device=DEF_DEVICE; - if (body && readbody) { - finame=body; - body=NULL; - } - else { - finame=NULL; - fin=stdin; - } - if (!body) { - readbody=0; - if (!finame) { - if (verbose>=1) - error("\nPlease enter the SMS text body, end with EOF (ctrl-D):"); - } - else { - if (!(fin=fopen(finame,"rt"))) - error("!Can't open data file \"%s\" for r/o: %m",finame); - } - chk(body=malloc(BODYLOAD)); - bodylen=fread(body,1,BODYLOAD,fin); - if (bodylen==-1) - error("!Error reading stream \"%s\": %m",(finame?finame:"")); - if (finame) { - chkfclose(fin,finame); - free(finame); - } - } + logoread(); for (i=0;i=2) error(".Will use baudrate %d with hexval 0x%X",baudn,portbaud); if (lockfile && *lockfile && VARPRINTF(lockreal,lockfile,devicename)>0) { time_t start,end; @@ -893,13 +897,13 @@ time_t start,end; } tios.c_iflag=IGNBRK|IGNPAR|IXON|IXOFF; tios.c_oflag=0; - tios.c_cflag=CS8|CREAD|CLOCAL|B19200|HUPCL; + tios.c_cflag=CS8|CREAD|CLOCAL|HUPCL|portbaud; tios.c_lflag=IEXTEN|NOFLSH; memset(tios.c_cc,_POSIX_VDISABLE,sizeof(tios.c_cc)); tios.c_cc[VTIME]=0; tios.c_cc[VMIN ]=1; - cfsetispeed(&tios,B19200); - if (cfsetospeed(&tios,B19200)|cfsetispeed(&tios,B19200)) + cfsetispeed(&tios,portbaud); + if (cfsetospeed(&tios,portbaud)|cfsetispeed(&tios,portbaud)) error("Error setting termios baudrate on device: %m"); if (tcflush(devfd,TCIOFLUSH)) error("Error flushing termios (TCIOFLUSH) on device: %m"); @@ -908,13 +912,18 @@ time_t start,end; signal(SIGALRM,(RETSIGTYPE (*)(int))sigalarm); do { - devcmd("",NULL,"\r\nAT\032"); + devcmd("",NULL,"\r\nAT\033"); devcmd(NULL,NULL,"\r\nAT"); smscset(); - devcmd(NULL,NULL,"\r\nAT+CMGF=0"); - devcmd("\n> ",NULL,"\r\nAT+CMGS=%d",(strlen(pdusmsc)+strlen(pdudata))/2); - if (!(s=devcmd(NULL,"\n+CMGS:","!%s%s\032",pdusmsc,pdudata))) retrying(); - } while (!s); + devcmd(NULL,NULL,"\r\nAT+CSMP=81,,0,245"); + devcmd("\n> ",NULL,"\r\nAT+CMGS=\"%s\"",phone); + if (!(s=devcmd(NULL,"\n+CMGS:","!%s\032",hexdata))) { + retrying(); + continue; + } + devcmd(NULL,NULL,"\r\nAT+CSMP=17,,0,0"); + devcmd(NULL,NULL,"\r\nAT"); + } while (0); while (isspace(*s)) s++; if (verbose>=1) error("\nMessage successfuly sent with MR: %s",s); devcmd(NULL,NULL,"\r\nAT"); -- 1.8.3.1