f6280cc7f2e9f454dcd0c7b05e9b97339ea0191d
[mopice.git] / mopice.c
1 /* 
2  *  mopice.c
3  * 
4  *  Copyright (C) 2011 
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABLILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * General Public License for more details. You should have received a
15  * copy of the GNU General Public License along with this program; if
16  * not, write to the Free Software Foundation, Inc, 59 Temple Place - 
17  * Suite 330, Boston, MA 02111-1307, USA.
18  * 
19  */
20
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/ioctl.h>
24 #include <fcntl.h>
25 #include <string.h>
26 #include <time.h>
27 #include <errno.h>
28 #include <signal.h>
29 #include <termios.h>
30
31 #include "mopice.h"
32
33 /*
34  *  STRUCTURES 
35  */
36
37 #define CMD_TYPE_MAND 1
38 #define CMD_TYPE_OPT  2
39
40 struct cmd {
41     char *snd;
42     char *repl;
43     int wai;
44     int type;
45 };
46
47
48 /* 
49  *  PROTOTYPES 
50  */
51 void alarm_sh(int sig);
52 int read_reply(int fh, char *reply, time_t secs);
53 int send_cmds(int fh, struct cmd *cmds, int cmds_n);
54
55
56 /*
57  *  GLOBALS
58  */
59 struct cmd init_cmds[] = {
60     /*      { "\x10!","OK", 3, CMD_TYPE_OPT  } */
61     /*      { "\x10\x18","OK", 3, CMD_TYPE_OPT  }
62             , */ { "ATZ",   "OK", 5, CMD_TYPE_MAND }
63     , { "AT",    "OK\r\n", 3, CMD_TYPE_MAND }
64     , { "ATL1",    "OK\r\n", 3, CMD_TYPE_MAND }
65     , { "ATE1",  "OK\r\n", 3, CMD_TYPE_MAND }
66     , { "ATM2",  "OK\r\n", 3, CMD_TYPE_MAND }
67 };
68
69 struct cmd answ_cmds[] = {
70     { "AT+FCLASS=8", "OK\r\n", 3, CMD_TYPE_MAND }
71     , { "AT+VLS=1",    "OK\r\n", 3, CMD_TYPE_MAND }
72     /*    , { "AT+VGT=255",  "OK\r\n", 3, CMD_TYPE_MAND } */
73     , { "AT+VTX",    "CONNECT\r\n", 5, CMD_TYPE_MAND }
74 };
75
76 struct cmd rec_cmds[] = {
77     /* { "ATH1",      "OK", 3, CMD_TYPE_MAND } */
78     { "AT+FCLASS=8", "OK\r\n", 3, CMD_TYPE_MAND }
79     , { "AT+VSD=129,200",  "OK\r\n", 3, CMD_TYPE_MAND }
80     , { "AT+VLS=1",    "OK\r\n", 3, CMD_TYPE_MAND }
81     , { "AT+VRX",    "CONNECT\r\n", 5, CMD_TYPE_MAND }
82 };
83
84 struct cmd recmsg_cmds[] = {
85     { "\x10\x03","OK\r\n", 3, CMD_TYPE_MAND }
86     , { "AT+VSD=129,200",  "OK\r\n", 3, CMD_TYPE_MAND }
87     , { "AT+VGR=255",  "OK\r\n", 3, CMD_TYPE_MAND }
88     , { "AT+VTD=80",  "OK\r\n", 3, CMD_TYPE_MAND }
89     , { "AT+VTS=[933,0]",  "OK\r\n", 3, CMD_TYPE_MAND }
90     , { "AT+VLS=1",    "OK\r\n", 3, CMD_TYPE_MAND }
91     , { "AT+VRX",    "CONNECT\r\n", 5, CMD_TYPE_MAND }
92 };
93
94 struct cmd clo_cmds[] = {
95     /* { "\x10\x18","OK", 3, CMD_TYPE_MAND  } */
96     /* { "\x10\x1c","", 3, CMD_TYPE_MAND } */
97       /* , { "\x10!\x10\x18\x10\x03","\x10\x62", 3, CMD_TYPE_MAND }
98          , { "\x10!\x10\x18\x10\x03","\x10\x62", 3, CMD_TYPE_MAND } */
99     { "\x10\x03","OK\r\n", 3, CMD_TYPE_MAND }
100     , { "AT",    "OK\r\n", 3, CMD_TYPE_MAND }
101     , { "AT+FCLASS=0", "OK\r\n", 3, CMD_TYPE_MAND }
102 };
103
104 int verbose = 0;
105
106
107 /*
108  *  FUNCTIONS
109  */
110
111 void alarm_sh(int sig)
112 {
113     fprintf(stderr, "CATCHED %d\n", sig);
114 }
115
116 int read_reply(int fh, char *rep, time_t secs)
117 {
118     time_t tout;
119     unsigned char bf[1024];
120     int bf_l, ret, i;
121     struct timespec ts;
122
123     if (verbose >= 3) fprintf(stderr, "read_reply::begin\n");
124
125     strcpy(bf,"");
126     bf_l = 0;
127
128     clock_gettime(CLOCK_MONOTONIC, &ts);
129     tout = ts.tv_sec + secs;
130
131     while (1) {
132         clock_gettime(CLOCK_MONOTONIC, &ts);
133         if (ts.tv_sec >= tout) {
134             if (verbose >= 3) fprintf(stderr, "read_reply::end1\n");
135             break;
136         }
137         alarm((unsigned int)secs + 1);
138         if (bf_l == sizeof(bf)) {
139             if (verbose >= 3) fprintf(stderr, "read_reply::end2\n");
140             return (-2);
141         }
142         if (verbose >= 3) fprintf(stderr, "read_reply::pre_read\n");
143         ret = read(fh, &(bf[bf_l]), 512 - bf_l);
144         if (verbose >= 3) fprintf(stderr, "read_reply::post_read %d\n", ret);
145         if (verbose >= 3) {
146             for (i = 0 ; i < ret ; i++) {
147                 fprintf(stderr, "xx %02x ", bf[bf_l+i]);
148                 if (i % 16 == 15) {
149                     fprintf(stderr, "\n");
150                 }
151             }
152             if (i % 16 != 15) 
153                 fprintf(stderr, "\n");
154         }
155         if (ret < 0) {
156             if (errno == EINTR) {
157                 if (verbose >= 3) fprintf(stderr, "read_reply::end3\n");
158                 return (0);
159             }
160             else {
161                 if (verbose >= 3) fprintf(stderr, "read_reply::end4\n");
162                 return (-1);
163             }
164         }
165         alarm(0);
166         bf[bf_l+ret] = '\0';
167         bf_l = strlen(bf);
168         fprintf(stderr, "bf_l: %d %d %p\n", bf_l, strlen(rep), strstr(bf, rep));
169         if (strstr(bf, rep)) {
170             if (verbose >= 3) fprintf(stderr, "read_reply::end5\n");
171             if (verbose >= 2) fprintf(stderr, "RET: [%s]\n", bf);
172             return (1);
173         }
174     }
175
176     if (verbose >= 3) fprintf(stderr, "read_reply::end6\n");
177     return (0);
178 }
179
180 int send_cmds(int fh, struct cmd *cmds, int cmds_n)
181 {
182     char bf[512];
183     int i, ret;
184
185     if (verbose >= 3) fprintf(stderr, "send_cmds::begin\n");
186
187     for (i = 0 ; i < cmds_n ; i++) {
188         if (verbose >= 2) fprintf(stderr, "send: [%s](%d)\n", cmds[i].snd,strlen(cmds[i].snd));
189         sprintf(bf, "%s\r\n", cmds[i].snd);
190         write(fh, bf, strlen(bf));
191         ret = read_reply(fh, cmds[i].repl, cmds[i].wai);
192         
193         if (verbose >= 3) fprintf(stderr, "send_cmds::read_reply return %d\n", ret);
194         if (ret < 0) {
195             fprintf(stderr, "ERROR: read_reply return %d\n", ret);
196             if (verbose >= 3) fprintf(stderr, "send_cmds::end1\n");
197             return 0;
198         }
199         else if (ret == 0) {
200             if (verbose >= 3) fprintf(stderr, "DE CHE: %d\n", cmds[i].type);
201             if (cmds[i].type == CMD_TYPE_MAND) {
202                 if (verbose >= 3) fprintf(stderr, "send_cmds::end2\n");
203                 return 0;
204             }
205             else if (cmds[i].type == CMD_TYPE_OPT) {
206                 fprintf(stderr, "WARN: on command %d REPLY [%s] NOT ARRIVED\n", i, cmds[i].repl);
207                 if (verbose >= 3) fprintf(stderr, "send_cmds::end3\n");
208             }
209         }
210     }
211     
212     if (verbose >= 3) fprintf(stderr, "send_cmds::end4\n");
213     return 1;
214 }
215
216 #define BAUDRATE B115200
217 /*
218  *  MAIN
219  */
220 int main(int argc, char *argv[])
221 {
222     int fh;
223     FILE *fp;
224     struct termios oldtio,newtio;
225     struct sigaction sa;
226     int i, e, a, n, ret;
227     unsigned char bf[10240], bf2[10240], c;
228
229     struct timespec ts;
230     time_t tout;
231
232     sa.sa_handler = alarm_sh;
233     sigemptyset(&sa.sa_mask);
234     sa.sa_flags = 0;
235     if (sigaction(SIGALRM, &sa, NULL))
236         exit(1);
237
238     if ((fh = open("/dev/ttyS0", O_RDWR | O_NOCTTY)) == -1) {
239         fprintf(stderr, "open failed\n");
240         exit(1);
241     }
242     ioctl( fh, TIOCNOTTY, 0 );
243
244
245     tcgetattr(fh,&oldtio); /* save current serial port settings */
246     bzero(&newtio, sizeof(newtio));
247         newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
248         newtio.c_iflag = IGNPAR;
249         newtio.c_oflag = 0;
250         
251         /* set input mode (non-canonical, no echo,...) */
252         newtio.c_lflag = 0;
253          
254         newtio.c_cc[VTIME]    = 0;   /* inter-character timer unused */
255         newtio.c_cc[VMIN]     = 1;   /* blocking read until 5 chars received */
256         
257         tcflush(fh, TCIFLUSH);
258         tcsetattr(fh,TCSANOW,&newtio);
259
260
261     printf("SIZE: %d  NCMD: %d\n", sizeof(init_cmds), sizeof(init_cmds) / sizeof(struct cmd));
262
263     ret = send_cmds(fh, init_cmds, sizeof(init_cmds) / sizeof(struct cmd));
264     fprintf(stderr, "INIT_CMDS: %d\n", ret);
265     
266     a = fgetc(stdin);
267
268 #if 0
269     if ((fp = fopen("output.raw", "w")) == NULL) {
270         exit(3);
271     }
272     ret = send_cmds(fh, rec_cmds, sizeof(rec_cmds) / sizeof(struct cmd));
273     fprintf(stderr, "ANSW_CMDS: %d\n", ret);
274
275     while ((ret = read(fh, bf2, 4096)) > 0) {
276         fwrite(bf2, 1, ret, fp);
277         fflush(fp);
278     }
279     
280     exit(123);
281 #endif
282
283
284     if ((fp = fopen("greetings.dli", "r")) == NULL) {
285         exit(3);
286     }
287     ret = send_cmds(fh, answ_cmds, sizeof(answ_cmds) / sizeof(struct cmd));
288     fprintf(stderr, "ANSW_CMDS: %d\n", ret);
289
290     while ((ret = fread(bf, 1, 512, fp)) > 0) {
291         for (i = 0, e = 0 ; i < ret ; i++, e++) {
292             if (bf[i] == '\x10') {
293                 bf2[e++] = '\x10';
294                 bf2[e]   = '\x10';
295                 fprintf(stderr, "bf[%u] bf[%u]\n", bf[i], bf[i+1]);
296             }
297             else {
298                 bf2[e] = bf[i];
299             }
300         }
301         write(fh, bf2, e);
302     }
303     fclose(fp);
304     
305     ret = send_cmds(fh, recmsg_cmds, sizeof(recmsg_cmds) / sizeof(struct cmd));
306     fprintf(stderr, "RECMSG_CMDS: %d\n", ret);
307     if ((fp = fopen("output_new.raw", "w")) == NULL) {
308         exit(3);
309     }
310     clock_gettime(CLOCK_MONOTONIC, &ts);
311     tout = ts.tv_sec + 10;
312
313     while ((ret = read(fh, bf2, 4096)) > 0) {
314         clock_gettime(CLOCK_MONOTONIC, &ts);
315         if (ts.tv_sec >= tout) {
316             if (verbose >= 3) fprintf(stderr, "read_reply::end1\n");
317             break;
318         }
319         fwrite(bf2, 1, ret, fp);
320         fflush(fp);
321     }
322     fclose(fp);
323
324     ret = send_cmds(fh, clo_cmds, sizeof(clo_cmds) / sizeof(struct cmd));
325     fprintf(stderr, "CLO_CMDS: %d\n", ret);
326
327
328     tcsetattr(fh,TCSANOW,&oldtio);
329
330     close(fh);
331
332     exit (0);
333     return (0);
334 }