X-Git-Url: http://git.jankratochvil.net/?p=mdsms.git;a=blobdiff_plain;f=mdsms.c;h=686e4024fd2f246c29aff094331570a65c610c0e;hp=700cdc955eaf4e789c0e15bd478deab745732ea3;hb=a91863ee834a9b2ebe5cf5da1b0af0cb2bae342d;hpb=7ca18f8beb27d2f28a491dea63cb8f7c3db7c93a diff --git a/mdsms.c b/mdsms.c index 700cdc9..686e402 100644 --- a/mdsms.c +++ b/mdsms.c @@ -137,6 +137,8 @@ static char *body; static char *logoname,*gsmnet; /* --ring-send specific */ static char *ringname; +/* --picture-send specific */ +static char *picturename; static enum modenum { MODE_UNKNOWN=0, @@ -146,7 +148,8 @@ static enum modenum { MODE_SEND_MOBILDOCK=MODE_FIRST+1, /* --send-mobildock in before readtimen is set */ MODE_RECEIVE =MODE_FIRST+2, /* --receive */ MODE_LOGO_SEND =MODE_FIRST+3, /* --logo-send */ - MODE_RING_SEND =MODE_FIRST+4 /* --ring-send */ + MODE_RING_SEND =MODE_FIRST+4, /* --ring-send */ + MODE_PICTURE_SEND =MODE_FIRST+5 /* --picture-send */ } mode=MODE_UNKNOWN; #define MODE_ORDER(x) ((x)-MODE_FIRST) #define MODE_NAME(x) (longopts[MODE_ORDER((x))].name) @@ -281,6 +284,8 @@ Usage: %s [-c|--config ] [-d|--device ]\n\ []\n\ --ring-send:\n\ \n\ + --picture-send:\n\ + \n\ \n\ -c, --config\tRead this additional config file\n\ \t\t(def. \"%s\" and \"$HOME%s\")\n\ @@ -339,12 +344,14 @@ static const struct option longopts[]={ {"receive" ,0,0,MODE_RECEIVE}, {"logo-send" ,0,0,MODE_LOGO_SEND}, {"ring-send" ,0,0,MODE_RING_SEND}, +{"picture-send" ,0,0,MODE_PICTURE_SEND}, /* Mode aliases may follow in no particular order * * as long as no non-mode options is between them */ {"send-md" ,0,0,MODE_SEND_MOBILDOCK}, {"recv" ,0,0,MODE_RECEIVE}, {"logo" ,0,0,MODE_LOGO_SEND}, {"ring" ,0,0,MODE_RING_SEND}, +{"picture" ,0,0,MODE_PICTURE_SEND}, {"config" ,1,0,'c'}, {"device" ,1,0,'d'}, {"log" ,1,0,'L'}, @@ -617,6 +624,7 @@ int i; case MODE_RECEIVE: case MODE_LOGO_SEND: case MODE_RING_SEND: + case MODE_PICTURE_SEND: if (mode_stamp && mode_stamp!=seq) break; mode=optc; mode_stamp=seq; @@ -625,7 +633,9 @@ int i; readbody++; break; case 'v': +#ifndef DEBUG /* prevent suppositious overflow */ verbose++; +#endif break; case 'V': fprintf(stderr,version); @@ -654,8 +664,9 @@ static const struct nullcheck { } nullcheck[]={ {&phone,MODE_BIT(MODE_SEND)|MODE_BIT(MODE_SEND_MOBILDOCK)|MODE_BIT(MODE_LOGO_SEND), N_("destination phone number")}, - {&logoname,MODE_BIT(MODE_LOGO_SEND),N_("logo filename")}, - {&ringname,MODE_BIT(MODE_RING_SEND),N_("ring filename")}, + {& logoname,MODE_BIT( MODE_LOGO_SEND),N_( "logo filename")}, + {& ringname,MODE_BIT( MODE_RING_SEND),N_( "ring filename")}, + {&picturename,MODE_BIT(MODE_PICTURE_SEND),N_("picture filename")}, {&body,MODE_BIT(MODE_RECEIVE),N_("body text")}, /* we allow empty bodies for SENDs */ #if 0 {&gsmnet,MODE_BIT(MODE_LOGO_SEND),N_("GSM operator network code")}, @@ -779,13 +790,19 @@ static inline void cmdline_ring_send(void) if (!ringname) ringname=nextargstack(); } +static inline void cmdline_picture_send(void) +{ + cmdline_phone(); + if (!picturename) picturename=nextargstack(); +} + static void lockclose(int fd) { if (close(fd)) error(_("Error closing lockfile \"%s\""),lockreal); } -static inline int lockdevice(int attempt) +static int lockdevice(int attempt) { int fd=-1; char buf[64]; @@ -1237,7 +1254,7 @@ unsigned char bin[140]={ 0x05, /* IEI */ 0x04, /* IEDL */ 0x15, 0x83, /* dest port (group gfx) */ - 0x00, 0x00 /* src port (unused) */ + 0x15, 0x83 /* src port (unused) */ }; size_t got,r=0 /* GCC happiness */,w; ssize_t chars,bits; @@ -1384,6 +1401,91 @@ long size; #undef WORD } +#define PICTURE_WIDTH (72) +#define PICTURE_HEIGHT (28) + +static inline void pictureread(void) +{ +FILE *f; +unsigned char bin1[140]={ + 6, /* UDH length */ + 0x05, /* IEI */ + 0x04, /* IEDL */ + 0x15, 0x8A, /* dest port (ring tones) */ + 0x15, 0x8A /* src port (unused) */ +#define BIN1_PAYLOAD (140-7) + }; +unsigned char binn[140]={ + 11, /* UDH length */ + 0x05, /* IEI */ + 0x04, /* IEDL */ + 0x15, 0x8A, /* dest port (ring tones) */ + 0x15, 0x8A, /* src port (unused) */ + 0x00, 0x03, /* multipart */ + /* 0x??, unique serial ID */ + /* 0x??, total messages */ + /* 0x??, message number (# from 1) */ +#define BINN_PAYLOAD (140-12) + }; +unsigned char header[]={ + 0x30, /* version string '0' */ + 0x02, /* item=OTA bitmap */ +#define PICTURE_BYTES (((PICTURE_WIDTH+7)/8)*PICTURE_HEIGHT) +#define PICTURE_BYTES_INCL_HEADER (PICTURE_BYTES +4/*header*/) + PICTURE_BYTES_INCL_HEADER>>8,PICTURE_BYTES_INCL_HEADER&0xFF, /* picture size in bytes incl. header */ + 0x00, /* animation pictures - 0=static picture */ + PICTURE_WIDTH,PICTURE_HEIGHT, /* picture size in pixels */ + 0x01, /* picture depth - B/W */ + }; +size_t got,want; +int totn,fragn; +long size; + +#define WORD(n) (((unsigned char)buf[(n)])|(((unsigned char)buf[(n)+1])<<8)) + + if (!(f=fopen(picturename,"rb"))) + error(_("^!Cannot open picture file \"%s\" for r/o"),picturename); + if ((size=getfilesize(f,picturename))==-1) + error(_("!File size determination is essential to continue operation")); + if (size!=PICTURE_BYTES) + error(_("!File \"%s\" size %ld doesn't match .res size for %dx%d picture"), + picturename,size,PICTURE_WIDTH,PICTURE_HEIGHT); + if (size<=BIN1_PAYLOAD-sizeof(header)) { + memcpy(bin1+7,header,sizeof(header)); + if ((got=fread(bin1+7+sizeof(header),1,size,f))!=size) + error(_("^Read error on \"%s\", wanted %ld, got %d"),picturename,size,got); + error(_("\nSending picture \"%s\" as single SMS (size %ld, max %d)"), + picturename,size,BIN1_PAYLOAD-sizeof(header)); + nokiaprep(bin1,7+sizeof(header)+size); + } + else { + memcpy(binn+12,header,sizeof(header)); + totn=(sizeof(header)+size+BINN_PAYLOAD-1)/BINN_PAYLOAD; + if (totn>0xFF) + error(_("!File size %ld too large even for multi-SMS picture upload (max=%d)"), + size,BINN_PAYLOAD*0xFF-sizeof(header)); + binn[10]=totn; + if (verbose>=1) + error(_("\nSending picture \"%s\" as %d multi-SMSes (size %ld, max %d, frag %d, header %d)"), + picturename,totn,size,BIN1_PAYLOAD,BINN_PAYLOAD,sizeof(header)); + binn[9]=time(NULL)&0x100; /* rand() would be better but it is a compatibility pain */ + if (verbose>=1) + error(_("\nUsing unique multi-SMS ID 0x%02X"),(unsigned)binn[9]); + for (fragn=1;fragn<=totn;fragn++) { +size_t isheader=(fragn==1 ? sizeof(header) : 0); + + binn[11]=fragn; + want=MIN(size,BINN_PAYLOAD-isheader); + if ((got=fread(binn+12+isheader,1,want,f))!=want) + error(_("^Read error on \"%s\", wanted %d, got %d"),picturename,want,got); + nokiaprep(binn,12+isheader+want); + size-=want; + } + } + chkfclose(f,picturename); +#undef WORD +} + static inline void genpdu(void) { static unsigned char pdu[64+MAXNUMLEN/2+(MAXBODYLEN*7)/8]; @@ -1974,10 +2076,11 @@ char *buf=malloc(l+50); switch (mode) { case MODE_SEND: /* FALLTHRU */ - case MODE_SEND_MOBILDOCK: cmdline_send (); break; - case MODE_LOGO_SEND: cmdline_logo_send(); break; - case MODE_RING_SEND: cmdline_ring_send(); break; - case MODE_RECEIVE: cmdline_receive (); break; + case MODE_SEND_MOBILDOCK: cmdline_send (); break; + case MODE_LOGO_SEND: cmdline_logo_send (); break; + case MODE_RING_SEND: cmdline_ring_send (); break; + case MODE_PICTURE_SEND: cmdline_picture_send(); break; + case MODE_RECEIVE: cmdline_receive (); break; default: assert(0); } cmdline_done(); @@ -2045,6 +2148,9 @@ size_t l=strlen(device); case MODE_RING_SEND: ringread(); break; + case MODE_PICTURE_SEND: + pictureread(); + break; case MODE_RECEIVE: break; default: assert(0); } @@ -2091,34 +2197,38 @@ time_t start,end; if ((end-=start)>LOCKREPORT) logmsg(_("Device lock succeeded after %ld seconds"),(long)end); } + +retryopen: + if (verbose>=1) error(_(".Opening device \"%s\".."),device); if ((devfd=open(device,O_RDWR|O_NDELAY))<0) error(_("^!Cannot open device \"%s\" for r/w access"),device); - if (tcgetattr(devfd,&restios)) - error(_("^Unable to get termios settings")); - else { - restios.c_cflag=(restios.c_cflag&~(CBAUD|CBAUDEX))|B0|HUPCL; - restios_yes=1; - } - tios.c_iflag=IGNBRK|IGNPAR|(handshake_rtscts ? 0 : IXON|IXOFF); - tios.c_oflag=0; - tios.c_cflag=CS8|CREAD|CLOCAL|HUPCL|portbaud|(handshake_rtscts ? CRTSCTS : 0); - 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,portbaud); - if (cfsetospeed(&tios,portbaud)|cfsetispeed(&tios,portbaud)) - error(_("^Error setting termios baudrate on device")); - if (tcflush(devfd,TCIOFLUSH)) - error(_("^Error flushing termios (TCIOFLUSH) on device")); - if (tcsetattr(devfd,TCSANOW,&tios)) - error(_("^!Unable to set initial termios device settings")); +retryall: - setalarm(); + if (tcgetattr(devfd,&restios)) + error(_("^Unable to get termios settings")); + else { + restios.c_cflag=(restios.c_cflag&~(CBAUD|CBAUDEX))|B0|HUPCL; + restios_yes=1; + } + tios.c_iflag=IGNBRK|IGNPAR|(handshake_rtscts ? 0 : IXON|IXOFF); + tios.c_oflag=0; + tios.c_cflag=CS8|CREAD|CLOCAL|HUPCL|portbaud|(handshake_rtscts ? CRTSCTS : 0); + 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,portbaud); + if (cfsetospeed(&tios,portbaud)|cfsetispeed(&tios,portbaud)) + error(_("^Error setting termios baudrate on device")); + if (tcflush(devfd,TCIOFLUSH)) + error(_("^Error flushing termios (TCIOFLUSH) on device")); + if (tcsetattr(devfd,TCSANOW,&tios)) + error(_("^!Unable to set initial termios device settings")); + + setalarm(); -retryall: devcmd("",NULL,"\r\nAT\033\032"); /* ESCAPE, CTRL-Z */ devcmd(NULL,NULL,"\r\nAT"); smscset(); @@ -2164,7 +2274,8 @@ retryall: } break; case MODE_LOGO_SEND: - case MODE_RING_SEND: { + case MODE_RING_SEND: + case MODE_PICTURE_SEND: { struct hexdata *hd; restore="\r\nAT+CSMP=17,,0,0"; @@ -2197,8 +2308,11 @@ continue_receive: if (!lockdevice(1)) { if (verbose>=1) error(_(".Dialout detected, waiting for lock..")); + if (verbose>=1) error(_(".Closing device \"%s\".."),device); + if (close(devfd)) + error(_("Error closing device \"%s\""),device); lockdevice(0); - goto retryall; + goto retryopen; } d1("Lock-device succeeded\n"); do {