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.
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.
21 #include <sys/types.h>
23 #include <sys/ioctl.h>
38 #define CMD_TYPE_MAND 1
39 #define CMD_TYPE_OPT 2
52 void alarm_sh(int sig);
53 int read_reply(int fh, char *reply, time_t secs);
54 int send_cmds(int fh, struct cmd *cmds, int cmds_n);
55 int ring_waiter(int fh, int ring_numb, int ring_inter);
56 int greetings_send(int fh, char *gree);
62 struct cmd init_cmds[] = {
63 { "ATZ", "OK", 5, CMD_TYPE_MAND }
64 , { "AT", "OK\r\n", 3, CMD_TYPE_MAND }
65 , { "ATH0", "OK\r\n", 3, CMD_TYPE_MAND }
66 , { "ATL1", "OK\r\n", 3, CMD_TYPE_MAND }
67 , { "ATE1", "OK\r\n", 3, CMD_TYPE_MAND }
68 , { "ATM2", "OK\r\n", 3, CMD_TYPE_MAND }
71 struct cmd answ_cmds[] = {
72 { "AT+FCLASS=8", "OK\r\n", 3, CMD_TYPE_MAND }
73 , { "AT+VLS=1", "OK\r\n", 3, CMD_TYPE_MAND }
74 , { "AT+VGT=135", "OK\r\n", 3, CMD_TYPE_MAND }
75 , { "AT+VTX", "CONNECT\r\n", 5, CMD_TYPE_MAND }
78 struct cmd rec_cmds[] = {
79 /* { "ATH1", "OK", 3, CMD_TYPE_MAND } */
80 { "AT+FCLASS=8", "OK\r\n", 3, CMD_TYPE_MAND }
81 , { "AT+VSD=129,200", "OK\r\n", 3, CMD_TYPE_MAND }
82 , { "AT+VLS=1", "OK\r\n", 3, CMD_TYPE_MAND }
83 , { "AT+VRX", "CONNECT\r\n", 5, CMD_TYPE_MAND }
86 struct cmd recmsg_cmds[] = {
87 { "\x10\x03","OK\r\n", 3, CMD_TYPE_MAND }
88 , { "AT+VSD=129,200", "OK\r\n", 3, CMD_TYPE_MAND }
89 , { "AT+VGR=255", "OK\r\n", 3, CMD_TYPE_MAND }
90 , { "AT+VTD=80", "OK\r\n", 3, CMD_TYPE_MAND }
91 , { "AT+VTS=[933,0]", "OK\r\n", 3, CMD_TYPE_MAND }
92 , { "AT+VLS=1", "OK\r\n", 3, CMD_TYPE_MAND }
93 , { "AT+VRX", "CONNECT\r\n", 5, CMD_TYPE_MAND }
96 struct cmd clo_cmds[] = {
97 { "\x10\x03","OK\r\n", 3, CMD_TYPE_MAND }
98 , { "AT", "OK\r\n", 3, CMD_TYPE_MAND }
99 , { "AT+VLS=0", "OK\r\n", 3, CMD_TYPE_MAND }
100 , { "AT+FCLASS=0", "OK\r\n", 3, CMD_TYPE_MAND }
110 void alarm_sh(int sig)
112 if (verbose >= 3) fprintf(stderr, "CATCHED %d\n", sig);
115 int read_reply(int fh, char *rep, time_t secs)
122 if (verbose >= 3) fprintf(stderr, "read_reply::begin\n");
127 clock_gettime(CLOCK_MONOTONIC, &ts);
128 tout = ts.tv_sec + secs;
131 clock_gettime(CLOCK_MONOTONIC, &ts);
132 if (ts.tv_sec >= tout) {
133 if (verbose >= 3) fprintf(stderr, "read_reply::end1\n");
136 alarm((unsigned int)secs + 1);
137 if (bf_l == sizeof(bf)) {
138 if (verbose >= 3) fprintf(stderr, "read_reply::end2\n");
141 if (verbose >= 3) fprintf(stderr, "read_reply::pre_read\n");
142 ret = read(fh, &(bf[bf_l]), 512 - bf_l);
143 if (verbose >= 3) fprintf(stderr, "read_reply::post_read %d\n", ret);
145 for (i = 0 ; i < ret ; i++) {
146 fprintf(stderr, "xx %02x ", bf[bf_l+i]);
148 fprintf(stderr, "\n");
152 fprintf(stderr, "\n");
155 if (errno == EINTR) {
156 if (verbose >= 3) fprintf(stderr, "read_reply::end3\n");
160 if (verbose >= 3) fprintf(stderr, "read_reply::end4\n");
167 if (verbose >= 3) fprintf(stderr, "bf_l: %d %ld %p\n", bf_l, strlen(rep), strstr(bf, rep));
168 if (strstr(bf, rep)) {
169 if (verbose >= 3) fprintf(stderr, "read_reply::end5\n");
170 if (verbose >= 2) fprintf(stderr, "RET: [%s]\n", bf);
175 if (verbose >= 3) fprintf(stderr, "read_reply::end6\n");
179 int send_cmds(int fh, struct cmd *cmds, int cmds_n)
184 if (verbose >= 3) fprintf(stderr, "send_cmds::begin\n");
186 for (i = 0 ; i < cmds_n ; i++) {
187 if (verbose >= 2) fprintf(stderr, "send: [%s](%ld)\n", cmds[i].snd,strlen(cmds[i].snd));
188 sprintf(bf, "%s\r\n", cmds[i].snd);
189 write(fh, bf, strlen(bf));
190 ret = read_reply(fh, cmds[i].repl, cmds[i].wai);
192 if (verbose >= 3) fprintf(stderr, "send_cmds::read_reply return %d\n", ret);
194 if (verbose >= 1) fprintf(stderr, "ERROR: read_reply return %d\n", ret);
195 if (verbose >= 3) fprintf(stderr, "send_cmds::end1\n");
199 if (verbose >= 3) fprintf(stderr, "DE CHE: %d\n", cmds[i].type);
200 if (cmds[i].type == CMD_TYPE_MAND) {
201 if (verbose >= 3) fprintf(stderr, "send_cmds::end2\n");
204 else if (cmds[i].type == CMD_TYPE_OPT) {
205 if (verbose >= 1) fprintf(stderr, "WARN: on command %d REPLY [%s] NOT ARRIVED\n", i, cmds[i].repl);
206 if (verbose >= 3) fprintf(stderr, "send_cmds::end3\n");
211 if (verbose >= 3) fprintf(stderr, "send_cmds::end4\n");
216 #define RING "RING\r\n"
218 int ring_waiter(int fh, int ring_numb, int ring_inter)
225 if (verbose >= 3) fprintf(stderr, "%s:: BEGIN\n", __FUNCTION__);
227 while ((ret = read(fh, bf, 511)) > 0) {
229 if (strstr(bf, RING)) {
230 clock_gettime(CLOCK_MONOTONIC, &ts);
233 if (ts.tv_sec < tout) {
234 if ((ct_cur + 1) == ring_numb) {
242 tout = ts.tv_sec + ring_inter;
245 if (verbose >= 3) fprintf(stderr, "%s:: ct_cur: %d\n", __FUNCTION__, ct_cur);
250 int greetings_send(int fh, char *gree)
254 unsigned char bf[10240], bf2[10240];
256 /* sox greetings.wav -e unsigned-integer -b 8 -r 8000 -c 1 greetings.raw */
257 if ((fp = fopen(gree, "r")) == NULL) {
258 if (verbose >= 1) fprintf(stderr, "open greetings [%s] failed\n", gree);
261 while ((ret = fread(bf, 1, 512, fp)) > 0) {
262 for (i = 0, e = 0 ; i < ret ; i++, e++) {
263 if (bf[i] == '\x10') {
266 if (verbose >= 5) fprintf(stderr, "bf[%u] bf[%u]\n", bf[i], bf[i+1]);
282 #define BAUDRATE B115200
283 #define RECORD_LEN 60
286 #define GREETINGS "/var/spool/mopice/messages/greetings.raw"
287 #define OUTPATH "/var/spool/mopice/incoming"
288 #define SDEVICE "/dev/ttyS0"
289 #define OUTFILE_FORMAT "%Y%m%d-%H%M%S"
290 int main(int argc, char *argv[])
294 struct termios oldtio,newtio;
297 unsigned char bf[10240], bf2[10240];
299 int ring_numb = RING_NUMB, ring_inter = RING_INTER;
308 /* --- signal handling --- */
309 /* NOTE: without it using the more simple old school
310 signal()/alarm() the read syscall restart and not exit */
311 sa.sa_handler = alarm_sh;
312 sigemptyset(&sa.sa_mask);
314 if (sigaction(SIGALRM, &sa, NULL))
317 if ((fh = open(SDEVICE, O_RDWR | O_NOCTTY)) == -1) {
318 if (verbose >= 1) fprintf(stderr, "tty open failed\n");
322 /* --- serial initialization --- */
323 ioctl( fh, TIOCNOTTY, 0 );
325 tcgetattr(fh,&oldtio); /* save current serial port settings */
326 bzero(&newtio, sizeof(newtio));
327 newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
328 newtio.c_iflag = IGNPAR;
331 /* set input mode (non-canonical, no echo,...) */
334 newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
335 newtio.c_cc[VMIN] = 1; /* blocking read until 5 chars received */
337 tcflush(fh, TCIFLUSH);
338 tcsetattr(fh,TCSANOW,&newtio);
341 /* --- modem initialization --- */
342 ret = send_cmds(fh, init_cmds, sizeof(init_cmds) / sizeof(struct cmd));
343 if (verbose >= 1) fprintf(stderr, "INIT_CMDS: %d\n", ret);
348 /* wait the right number of rings */
350 if (ring_waiter(fh, ring_numb, ring_inter) == 0) {
351 if (verbose >= 1) fprintf(stderr, "RING WAITER failed\n");
355 ring_numb = fgetc(stdin);
358 /* instruct modem for greetings message */
359 ret = send_cmds(fh, answ_cmds, sizeof(answ_cmds) / sizeof(struct cmd));
360 if (verbose >= 1) fprintf(stderr, "ANSW_CMDS: %d\n", ret);
365 /* send the greetings message */
366 /* NOTE: sox greetings.wav -e unsigned-integer -b 8 -r 8000 -c 1 greetings.raw */
367 if (greetings_send(fh, GREETINGS) == 0) {
371 /* instruct modem to send a beep and start message recording */
372 ret = send_cmds(fh, recmsg_cmds, sizeof(recmsg_cmds) / sizeof(struct cmd));
373 if (verbose >= 1) fprintf(stderr, "RECMSG_CMDS: %d\n", ret);
375 /* record the message */
379 if (verbose >= 1) fprintf(stderr, "localtime failed\n");
382 if (strftime(outstr, sizeof(outstr), OUTFILE_FORMAT, tmp) == 0) {
383 if (verbose >= 1) fprintf(stderr, "strftime failed\n");
386 sprintf(outname, "%s/%s.dli", OUTPATH, outstr);
387 if ((fp = fopen(outname, "w")) == NULL) {
390 clock_gettime(CLOCK_MONOTONIC, &ts);
391 tout = ts.tv_sec + RECORD_LEN;
394 while (is_busy == 0 && (ret = read(fh, bf, 4096)) > 0) {
395 clock_gettime(CLOCK_MONOTONIC, &ts);
396 if (ts.tv_sec >= tout) {
397 if (verbose >= 3) fprintf(stderr, "read_reply::end1\n");
401 for (i = 0, e = 0 ; i < ret ; i++, e++) {
402 if (bf[i] == '\x10') {
404 if (verbose >= 1) fprintf(stderr, "0x10 found followed by %d\n", bf[i]);
406 if (verbose >= 1) fprintf(stderr, "BUSY found, stop recording\n");
414 fwrite(bf2, 1, e, fp);
419 /* reset the modem for the next call */
420 ret = send_cmds(fh, clo_cmds, sizeof(clo_cmds) / sizeof(struct cmd));
421 if (verbose >= 1) fprintf(stderr, "CLO_CMDS: %d\n", ret);
424 /* reset the serial to the old configs */
426 tcsetattr(fh, TCSANOW, &oldtio);