1 /* -------------------------------------------------------------------- */
2 /* SMS Client, send messages to mobile phones and pagers */
3 /* */
4 /* modem.c */
5 /* */
6 /* Copyright (C) 1997,1998,1999 Angelo Masci */
7 /* */
8 /* This library is free software; you can redistribute it and/or */
9 /* modify it under the terms of the GNU Library General Public */
10 /* License as published by the Free Software Foundation; either */
11 /* version 2 of the License, or (at your option) any later version. */
12 /* */
13 /* This library is distributed in the hope that it will be useful, */
14 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
15 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
16 /* Library General Public License for more details. */
17 /* */
18 /* You should have received a copy of the GNU Library General Public */
19 /* License along with this library; if not, write to the Free */
20 /* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* */
22 /* You can contact the author at this e-mail address: */
23 /* */
24 /* angelo@styx.demon.co.uk */
25 /* */
26 /* -------------------------------------------------------------------- */
27 /* $Id$
28 -------------------------------------------------------------------- */
29
30 #include <stdio.h>
31 #include <termios.h>
32 #include <stdlib.h>
33 #include <time.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <signal.h>
37 #include <string.h>
38 #include <errno.h>
39
40 #include <sys/types.h>
41 #include <sys/stat.h>
42
43 #if defined(SOLARIS)
44 #include <sys/mkdev.h>
45 #endif
46
47 #include "modem.h"
48 #include "logfile/logfile.h"
49 #include "common/common.h"
50 #include "expect.h"
51 #include "lock/lock.h"
52 #include "resource/resource.h"
53
54 /* -------------------------------------------------------------------- */
55
56 #if !defined(MMODEMDIR)
57 #error "MMODEMDIR undefined"
58 #else
59 #define MODEMDIR MMODEMDIR
60 #endif
61
62
63 /* -------------------------------------------------------------------- */
64
65 #define MDM_OK 1
66 #define MDM_CONNECT 2
67 #define MDM_BUSY 3
68 #define MDM_NO_DIALTONE 4
69 #define MDM_NO_ANSWER 5
70 #define MDM_RING 6
71 #define MDM_NO_CARRIER 7
72 #define MDM_ERROR 8
73 #define MDM_UNKNOWN_RESPONSE 9
74 #define MDM_DISCONNECTED 10
75 #define MDM_RINGING 11
76
77 /* -------------------------------------------------------------------- */
78
79 struct response_struct
80 {
81 char *response_str;
82 int response_code;
83 };
84
85 typedef struct response_struct RESPONSE;
86
87 static RESPONSE response_list[] =
88 {
89 { "OK", MDM_OK },
90 { "CONNECT", MDM_CONNECT },
91 { "BUSY", MDM_BUSY },
92 { "NO DIALTONE", MDM_NO_DIALTONE },
93 { "NO DIAL TONE", MDM_NO_DIALTONE },
94 { "NO ANSWER", MDM_NO_ANSWER },
95 { "RINGING", MDM_RINGING },
96 { "RING", MDM_RING },
97 { "NO CARRIER", MDM_NO_CARRIER },
98 { "ERROR", MDM_ERROR },
99 { "UNKNOWN", MDM_UNKNOWN_RESPONSE },
100 { "CARRIER", MDM_CONNECT },
101 { NULL, 0 }
102 };
103
104 /* -------------------------------------------------------------------- */
105
106 #define MODEM_OPEN 0
107 #define MODEM_CLOSED 1
108
109 #define MAX_BUFSIZE 1024
110
111 /* -------------------------------------------------------------------- */
112
113 static int modem_status = MODEM_CLOSED;
114
115 /* -------------------------------------------------------------------- */
116
117 static struct termios
118 t,
119 t_orig;
120
121 static long
122 MDM_response_timeout,
123 MDM_hangup_timeout,
124 MDM_connect_timeout,
125 MDM_write_timeout,
126 MDM_echo_timeout,
127 MDM_drain_timeout,
128 MDM_test_echo_timeout,
129 MDM_dtr_hangup_sleep,
130 MDM_dtr_init_sleep,
131 MDM_settle_time,
132 MDM_max_rings,
133 MDM_lock_retry_delay,
134 MDM_pause_before_dial,
135 MDM_pause_after_connect;
136
137
138 static int
139 modem_echo = TRUE; /* Is the modem echoing */
140 /* Characters? Default is YES */
141
142 static long
143 soft_hangup_retries; /* Number of times I should */
144 /* continue sending +++ATH */
145 /* If 0 then don't bother */
146 /* and rely on lowering DTR */
147
148 static long
149 guard_time; /* Escape Code Guard Time */
150 /* in microseconds */
151
152 static long
153 test_guard_time; /* Echo Test Guard Time */
154 /* in microseconds */
155
156 static long
157 esc_time; /* Time between sending each */
158 /* character of attention */
159 /* string in microseconds */
160
161 static char
162 modem_file[512],
163 modem_lockfile[512];
164
165 static char
166 *device_dir,
167 *device,
168 *command_prefix,
169 *command_suffix,
170 *number_prefix,
171 *dial_command,
172 *hangup_command,
173 *init_command,
174 *attention_command,
175 *response_prefix,
176 *response_suffix,
177 *set_local_echo_off,
178 *lock_action,
179 *flow_control,
180 *lock_dir,
181 *lock_prefix,
182 *lock_platform,
183 *lock_format,
184 *MDM_disable_echo_test,
185 *restore_terminal;
186
187 static RESOURCE resource_list[] =
188 {
189 { RESOURCE_STRING, "MDM_device", 0, 1, NULL, 0, "modem", 0, &device },
190 { RESOURCE_STRING, "MDM_device_dir", 0, 0, NULL, 0, "/dev/", 0, &device_dir },
191
192 { RESOURCE_STRING, "MDM_lock_dir", 0, 0, NULL, 0, "/var/lock", 0, &lock_dir },
193 { RESOURCE_STRING, "MDM_lock_prefix", 0, 0, NULL, 0, "LCK..", 0, &lock_prefix },
194
195 { RESOURCE_STRING, "MDM_lock_platform", 0, 0, NULL, 0, "TRADITIONAL", 0, &lock_platform },
196 { RESOURCE_STRING, "MDM_lock_format", 0, 0, NULL, 0, "TRADITIONAL", 0, &lock_format },
197
198 { RESOURCE_STRING, "MDM_command_prefix", 0, 1, NULL, 0, "AT", 0, &command_prefix },
199 { RESOURCE_STRING, "MDM_flow_control", 0, 1, NULL, 0, "Hardware", 0, &flow_control },
200 { RESOURCE_STRING, "MDM_command_suffix", 0, 1, NULL, 0, "\r", 0, &command_suffix },
201 { RESOURCE_STRING, "MDM_number_prefix", 0, 1, NULL, 0, "", 0, &number_prefix },
202 { RESOURCE_STRING, "MDM_dial_command", 0, 1, NULL, 0, "DT", 0, &dial_command },
203 { RESOURCE_STRING, "MDM_hangup_command", 0, 1, NULL, 0, "H", 0, &hangup_command },
204 { RESOURCE_STRING, "MDM_init_command", 0, 1, NULL, 0, "Z", 0, &init_command },
205 { RESOURCE_STRING, "MDM_set_local_echo_off", 0, 0, NULL, 0, "E0", 0, &set_local_echo_off },
206 { RESOURCE_STRING, "MDM_response_prefix", 0, 1, NULL, 0, "\r\n", 0, &response_prefix },
207 { RESOURCE_STRING, "MDM_response_suffix", 0, 1, NULL, 0, "\r\n", 0, &response_suffix },
208 { RESOURCE_STRING, "MDM_attention_command", 0, 1, NULL, 0, "+++", 0, &attention_command },
209 { RESOURCE_NUMERIC, "MDM_soft_hangup_retries", 0, 0, NULL, 0, NULL, 3, &soft_hangup_retries },
210 { RESOURCE_NUMERIC, "MDM_guard_time", 0, 0, NULL, 0, NULL, 1750000, &guard_time },
211 { RESOURCE_NUMERIC, "MDM_test_guard_time", 0, 0, NULL, 0, NULL, 250000, &test_guard_time },
212 { RESOURCE_NUMERIC, "MDM_esc_time", 0, 0, NULL, 0, NULL, 125000, &esc_time },
213 { RESOURCE_STRING, "MDM_lock_action", 0, 1, NULL, 0, "NO_BLOCK", 0, &lock_action },
214 { RESOURCE_NUMERIC, "MDM_lock_retry_delay", 0, 1, NULL, 0, NULL, 5000000, &MDM_lock_retry_delay },
215 { RESOURCE_NUMERIC, "MDM_response_timeout", 0, 0, NULL, 0, NULL, 10, &MDM_response_timeout },
216 { RESOURCE_NUMERIC, "MDM_hangup_timeout", 0, 0, NULL, 0, NULL, 60, &MDM_hangup_timeout },
217 { RESOURCE_NUMERIC, "MDM_connect_timeout", 0, 0, NULL, 0, NULL, 60, &MDM_connect_timeout },
218 { RESOURCE_NUMERIC, "MDM_write_timeout", 0, 0, NULL, 0, NULL, 10, &MDM_write_timeout },
219 { RESOURCE_NUMERIC, "MDM_echo_timeout", 0, 0, NULL, 0, NULL, 10, &MDM_echo_timeout },
220 { RESOURCE_NUMERIC, "MDM_test_echo_timeout", 0, 0, NULL, 0, NULL, 10, &MDM_test_echo_timeout },
221 { RESOURCE_NUMERIC, "MDM_drain_timeout", 0, 0, NULL, 0, NULL, 2, &MDM_drain_timeout },
222 { RESOURCE_STRING, "MDM_disable_echo_test", 0, 0, NULL, 0, "NO", 0, &MDM_disable_echo_test },
223 { RESOURCE_STRING, "MDM_restore_terminal", 0, 0, NULL, 0, "YES", 0, &restore_terminal },
224 { RESOURCE_NUMERIC, "MDM_pause_before_dial", 0, 0, NULL, 0, NULL, 1000000, &MDM_pause_before_dial },
225 { RESOURCE_NUMERIC, "MDM_pause_after_connect", 0, 0, NULL, 0, NULL, 0, &MDM_pause_after_connect },
226 { RESOURCE_NUMERIC, "MDM_dtr_hangup_sleep", 0, 0, NULL, 0, NULL, 3000000, &MDM_dtr_hangup_sleep },
227 { RESOURCE_NUMERIC, "MDM_dtr_init_sleep", 0, 0, NULL, 0, NULL, 1000000, &MDM_dtr_init_sleep },
228 { RESOURCE_NUMERIC, "MDM_settle_time", 0, 0, NULL, 0, NULL, 1, &MDM_settle_time },
229
230 { RESOURCE_NUMERIC, "MDM_max_rings", 0, 0, NULL, 0, NULL, 4, &MDM_max_rings },
231 { RESOURCE_NULL, NULL, 0, 1, NULL, 0, NULL, 0, NULL },
232 };
233
234 /* --------------------------------------------------------------------
235
236 MDM_response_timeout Used as timeout for standard
237 AT command responses
238 ie. Waiting for OK
239
240 MDM_hangup_timeout Used as timeout for standard
241 ATH response
242 Waiting for OK
243
244 MDM_connect_timeout Used as timeout for connect
245 string response. Includes
246 time taken to dial,
247 other party to answer and
248 both modems to negotiate
249 ie. CONNECT
250
251 MDM_write_timeout Used as timeout for writes
252 of commands to modem
253
254 MDM_echo_timeout Used as timeout for echoing
255 of commands written to modem
256
257 MDM_drain_timeout Timeout period to watch modem and drain
258 any leftover characters before sending init string
259
260 MDM_test_echo_timeout Used as timeout for testing
261 whether the modem is
262 echoing commands we send it
263
264 MDM_dtr_hangup_sleep How many seconds should we
265 sleep after lowering DTR to
266 ensure disconnect
267
268 MDM_settle_time How many seconds should we
269 sleep after receiving the
270 lockfile
271
272 -------------------------------------------------------------------- */
273
274 int MDM_send(int modem, char *str);
275 int MDM_response(int modem, int timeout);
276
277 void fcntl_set(int fd, int flags);
278 void fcntl_clear(int fd, int flags);
279
280 int MDM_init(char *modem_file, char data, char parity, char stop, char flow, long baud);
281 int MDM_dial(char *number, char data, char parity, char stop, long baud);
282
283 void MDM_release_lock(void);
284 int MDM_obtain_lock(char *device);
285 void MDM_hangup(int modem);
286
287 int toggle_DTR(int modem, long sleep_period);
288
289 /* -------------------------------------------------------------------- */
290 /* -------------------------------------------------------------------- */
SMS_dial(char * number,char * params,long baud)291 int SMS_dial(char *number, char *params, long baud)
292 {
293 int fd;
294
295 lprintf(LOG_VERBOSE, "Using SMSmodem Package\n");
296
297 fd = MDM_dial(number,
298 params[0], /* Bits */
299 params[1], /* Parity */
300 params[2], /* Stop */
301 baud); /* Baud */
302
303 return fd;
304 }
305
306 /* -------------------------------------------------------------------- */
307 /* -------------------------------------------------------------------- */
SMS_hangup(int modem)308 void SMS_hangup(int modem)
309 {
310 MDM_hangup(modem);
311 }
312
313
314 /* -------------------------------------------------------------------- */
315 /* -------------------------------------------------------------------- */
get_response(int id)316 char *get_response(int id)
317 {
318 RESPONSE *ptr;
319
320 ptr = response_list;
321 while (ptr->response_str != NULL)
322 { if (ptr->response_code == id)
323 { return ptr->response_str;
324 }
325
326 ptr++;
327 }
328
329 return "UNKOWN";
330 }
331
332 /* -------------------------------------------------------------------- */
333 /* -------------------------------------------------------------------- */
MDM_send(int modem,char * str)334 int MDM_send(int modem, char *str)
335 {
336 char buf[1024];
337 int res;
338
339 res = twrite(modem, str, strlen(str), MDM_write_timeout);
340 if (res)
341 { return(res);
342 }
343
344 if (modem_echo)
345 {
346 /* The modem is echoing our commands. So we */
347 /* should expect to read these back */
348
349 res = expnstr(modem, buf, str, strlen(str), MDM_echo_timeout);
350 if (res)
351 { return(res);
352 }
353 }
354
355 return 0;
356 }
357
358 /* -------------------------------------------------------------------- */
359 /* -------------------------------------------------------------------- */
MDM_response(int modem,int timeout)360 int MDM_response(int modem, int timeout)
361 {
362 int i;
363 char buf[MAX_BUFSIZE];
364 int res;
365
366 res = expstr(modem, buf, response_prefix, MAX_BUFSIZE, timeout);
367 if (res)
368 {
369 if (res == -2)
370 { return(MDM_DISCONNECTED);
371 }
372
373 return(res);
374 }
375
376 res = expstr(modem, buf, response_suffix, MAX_BUFSIZE, timeout);
377 if (res)
378 {
379 if (res == -2)
380 { return(MDM_DISCONNECTED);
381 }
382
383 return(res);
384 }
385
386 for(i=0; response_list[i].response_str != NULL; i++)
387 { if (strncmp(buf, response_list[i].response_str, strlen(response_list[i].response_str)) == 0)
388 { return(response_list[i].response_code);
389 }
390 }
391
392 return(MDM_UNKNOWN_RESPONSE);
393 }
394
395 /* -------------------------------------------------------------------- */
396 /* -------------------------------------------------------------------- */
fcntl_set(int fd,int flags)397 void fcntl_set(int fd, int flags)
398 {
399 int val;
400
401
402 if ((val = fcntl(fd, F_GETFL, 0)) < 0)
403 { lprintf(LOG_ERROR, "MODEM: fcntl F_GETFL\n");
404 exit(-1);
405 }
406
407 val |= flags;
408
409 if (fcntl(fd, F_SETFL, val) < 0)
410 { lprintf(LOG_ERROR, "MODEM: fcntl F_SETFL\n");
411 exit(-1);
412 }
413 }
414
415 /* -------------------------------------------------------------------- */
416 /* -------------------------------------------------------------------- */
fcntl_clear(int fd,int flags)417 void fcntl_clear(int fd, int flags)
418 {
419 int val;
420
421
422 if ((val = fcntl(fd, F_GETFL, 0)) < 0)
423 { lprintf(LOG_ERROR, "MODEM: fcntl F_GETFL\n");
424 exit(-1);
425 }
426
427 val &= ~flags;
428
429 if (fcntl(fd, F_SETFL, val) < 0)
430 { lprintf(LOG_ERROR, "MODEM: fcntl F_SETFL\n");
431 exit(-1);
432 }
433 }
434
435 /* -------------------------------------------------------------------- */
436 /* -------------------------------------------------------------------- */
MDM_release_lock(void)437 void MDM_release_lock(void)
438 { resource_unlock(modem_lockfile);
439 }
440
441 /* -------------------------------------------------------------------- */
442 /* -------------------------------------------------------------------- */
MDM_obtain_lock(char * device)443 int MDM_obtain_lock(char *device)
444 {
445 int no_block,
446 notify;
447
448
449 if (resource_test_lockdir(modem_lockfile) == -1)
450 { return -1;
451 }
452
453 if (strcmp("NO_BLOCK", lock_action) == 0)
454 { no_block = TRUE;
455 }
456 else if (strcmp("BLOCK", lock_action) == 0)
457 { no_block = FALSE;
458 }
459 else
460 { lprintf(LOG_WARNING, "MDM_lock_action invalid, defaulting to NO_BLOCK\n");
461 no_block = TRUE;
462 }
463
464
465
466 notify = TRUE;
467 while(resource_lock(modem_lockfile))
468 {
469 if (no_block)
470 { lprintf(LOG_ERROR, "Could not obtain lock for modem device\n");
471 lprintf(LOG_STANDARD, "Another program is using the modem.\n");
472
473 return -1;
474 }
475
476 if (notify)
477 { lprintf(LOG_VERBOSE, "Blocking on lockfile '%s'\n", modem_lockfile);
478 lprintf(LOG_STANDARD, "Another program is using the modem.\n");
479 lprintf(LOG_STANDARD, "Waiting...\n");
480 notify = FALSE;
481 }
482
483 resource_wait(modem_lockfile, MDM_lock_retry_delay);
484 }
485
486 if (!notify)
487 { lprintf(LOG_STANDARD, "Modem is now free.\n");
488 lprintf(LOG_STANDARD, "Continuing...\n");
489 }
490
491 atexit(MDM_release_lock); /* Establish EXIT handler */
492 /* to release the lockfile if */
493 /* we leave prematurely */
494
495 sleep(MDM_settle_time); /* Allow modem to settle down */
496 /* I might have just obtained */
497 /* The lock on the device from */
498 /* another process */
499
500 return 0;
501 }
502
503 /* -------------------------------------------------------------------- */
504 /* -------------------------------------------------------------------- */
MDM_init(char * modem_file,char data,char parity,char stop,char flow,long baud)505 int MDM_init(char *modem_file, char data, char parity, char stop, char flow, long baud)
506 {
507 int retry,
508 modem,
509 t_baud;
510
511
512 modem = open(modem_file, O_RDWR|O_NONBLOCK);
513 if (modem == -1)
514 { lprintf(LOG_WARNING, "MODEM: Failed to open %s\n", modem_file);
515 return -1;
516 }
517
518 /* ---------------------------- */
519 /* Toggle DTR to reset modem */
520 /* ---------------------------- */
521
522 if (toggle_DTR(modem, MDM_dtr_init_sleep))
523 {
524 lprintf(LOG_WARNING, "MODEM: Failed to toggle DTR\n");
525
526 close(modem);
527 return -1;
528 }
529
530 /* ---------------------------- */
531 /* Get terminal line state */
532 /* ---------------------------- */
533
534 retry = 3;
535 while (retry--)
536 {
537 if (tcgetattr(modem, &t) == -1)
538 { lprintf(LOG_WARNING, "MODEM: Failed tcgetattr() errno %d\n", errno);
539
540 if (retry == 1)
541 {
542 close(modem);
543 return -1;
544 }
545
546 sleep(1);
547 }
548 else
549 { retry = 0;
550 }
551 }
552
553 /* ---------------------------- */
554 /* Save original line state */
555 /* ---------------------------- */
556
557 retry = 3;
558 while (retry--)
559 {
560 if (tcgetattr(modem, &t_orig) == -1)
561 { lprintf(LOG_WARNING, "MODEM: Failed tcgetattr() errno %d\n", errno);
562
563 if (retry == 1)
564 {
565 close(modem);
566 return -1;
567 }
568
569 sleep(1);
570 }
571 else
572 { retry = 0;
573 }
574 }
575
576 /* ---------------------------- */
577 /* Set up terminal attributes */
578 /* for the device */
579 /* ---------------------------- */
580
581 t.c_cflag = 0;
582 t.c_oflag = 0; /* Turn off all output processing */
583 t.c_iflag = 0;
584 t.c_lflag = 0; /* Everything off in local flags, */
585 /* disables: */
586 /* canonical mode */
587 /* signal generation */
588 /* echo */
589
590
591 t.c_cc[VMIN] = 1; /* 1 Character buffer */
592 t.c_cc[VTIME] = 0; /* Block indefinitely */
593
594 t.c_cflag |= CREAD | /* Enable receiver */
595 CLOCAL |
596 HUPCL; /* Lower modem lines on last close */
597 /* 1 stop bit (since CSTOPB off) */
598
599 /* ---------------------------- */
600 /* Set data bits 5 through 8 */
601 /* ---------------------------- */
602
603 t.c_cflag &= ~(CSIZE); /* Mask data size */
604 switch (data)
605 {
606 case '5':
607 t.c_cflag |= CS5; /* Set 5 bits */
608 break;
609 case '6':
610 t.c_cflag |= CS6; /* Set 6 bits */
611 break;
612 case '7':
613 t.c_cflag |= CS7; /* Set 7 bits */
614 break;
615 case '8':
616 t.c_cflag |= CS8; /* Set 8 bits */
617 break;
618 default:
619 lprintf(LOG_ERROR, "MODEM: Number of bits must be either 5,6,7 or 8\n");
620
621 close(modem);
622 return -1;
623 }
624
625 /* ---------------------------- */
626 /* Set parity Even, Odd or None */
627 /* ---------------------------- */
628
629 switch (parity)
630 {
631 case 'E':
632 t.c_cflag |= PARENB; /* Enable parity */
633 break;
634 case 'O':
635 t.c_cflag |= PARENB; /* Enable parity */
636 t.c_cflag |= PARODD; /* set parity to odd */
637 break;
638 case 'N':
639 break; /* No parity DEFAULT */
640 default:
641 lprintf(LOG_ERROR, "MODEM: Parity must be either E,O or N\n");
642
643 close(modem);
644 return -1;
645 }
646
647
648 /* ---------------------------- */
649 /* Set stop bits 1 or 2 */
650 /* ---------------------------- */
651
652 switch (stop)
653 {
654 case '2':
655 t.c_cflag |= CSTOPB; /* 2 Stop bits */
656 break;
657 case '1': /* 1 Stop bits DEFAULT */
658 break;
659 default:
660 lprintf(LOG_ERROR, "MODEM: Stop bits must be either 1 or 2\n");
661
662 close(modem);
663 return -1;
664 }
665
666
667 /* ---------------------------- */
668 /* Set flow control */
669 /* Hardware or Software */
670 /* ---------------------------- */
671
672 switch (flow)
673 {
674 #if defined(LINUX) || defined(SOLARIS) || defined(OSF1)
675 case 'H':
676 t.c_cflag |= CRTSCTS; /* Hardware Flow */
677 /* control */
678 break;
679 #endif
680 case 'S':
681 t.c_iflag |= IXON | /* Xon/Xoff Flow */
682 IXOFF | /* control */
683 IXANY;
684 break;
685 default:
686 #if !defined(LINUX) && !defined(SOLARIS)
687 lprintf(LOG_ERROR, "MODEM: Flow control must be S for this platform\n");
688 #else
689 lprintf(LOG_ERROR, "MODEM: Flow control must be either H or S for this platform\n");
690 #endif
691 close(modem);
692 return -1;
693 }
694
695
696 /* ---------------------------- */
697 /* Set baud rate */
698 /* Convert from numeric to */
699 /* defines set in termios */
700 /* ---------------------------- */
701
702 if (baud >= 38400)
703 { t_baud = B38400;
704 }
705 else if (baud >= 19200)
706 { t_baud = B19200;
707 }
708 else if (baud >= 9600)
709 { t_baud = B9600;
710 }
711 else if (baud >= 4800)
712 { t_baud = B4800;
713 }
714 else if (baud >= 2400)
715 { t_baud = B2400;
716 }
717 else if (baud >= 1200)
718 { t_baud = B1200;
719 }
720 else
721 { t_baud = B300;
722 }
723
724 if (cfsetispeed(&t, t_baud) == -1) /* Set Input Baud rate */
725 {
726 lprintf(LOG_WARNING, "MODEM: Failed Trying to set Input baud to %ld\n", baud);
727
728 close(modem);
729 return -1;
730 }
731
732 if (cfsetospeed(&t, t_baud) == -1) /* Set output Baud rate */
733 {
734 lprintf(LOG_WARNING, "MODEM: Failed Trying to set Output baud to %ld\n", baud);
735
736 close(modem);
737 return -1;
738 }
739
740 /* ---------------------------- */
741 /* Apply changes to modem */
742 /* device */
743 /* ---------------------------- */
744
745 if (tcflush(modem, TCIOFLUSH) == -1)
746 { lprintf(LOG_WARNING, "MODEM: Failed tcflush()\n");
747
748 close(modem);
749 return -1;
750 }
751
752 if (tcsetattr(modem,TCSANOW, &t) == -1)
753 { lprintf(LOG_WARNING, "MODEM: Failed tcsetattr()\n");
754
755 close(modem);
756 return -1;
757 }
758
759 /* ---------------------------- */
760 /* Reset mode to blocking */
761 /* ---------------------------- */
762
763 fcntl_clear(modem, O_NONBLOCK);
764
765 if (toggle_DTR(modem, MDM_dtr_init_sleep))
766 {
767 lprintf(LOG_WARNING, "MODEM: Failed to toggle DTR\n");
768
769 close(modem);
770 return -1;
771 }
772
773 modem_status = MODEM_OPEN;
774 return modem;
775 }
776
777
778 /* -------------------------------------------------------------------- */
779 /* Send AT string. Check if result contains AT. */
780 /* If command is echoed then set modem_echo flag. */
781 /* -------------------------------------------------------------------- */
test_modem_echo(int modem)782 int test_modem_echo(int modem)
783 {
784 char buf[MAX_BUFSIZE],
785 str[MAX_BUFSIZE];
786
787
788 strcpy(str, command_prefix);
789 strcat(str, command_suffix);
790
791 if (twrite(modem, str, strlen(str), MDM_write_timeout))
792 { return(-1);
793 }
794
795 if (expstr(modem, buf, response_prefix, MAX_BUFSIZE, MDM_echo_timeout))
796 { return(-1);
797 }
798
799 if (strncmp(buf, str, strlen(str)) == 0)
800 {
801 modem_echo = TRUE;
802 lprintf(LOG_VERBOSE, "MODEM: Modem echo is set to ON\n");
803 }
804 else
805 { modem_echo = FALSE;
806 lprintf(LOG_VERBOSE, "MODEM: Modem echo is set to OFF\n");
807 }
808
809 if (expstr(modem, buf, response_suffix, MAX_BUFSIZE, MDM_echo_timeout))
810 { return(-1);
811 }
812
813 if (strncmp(buf, "OK", strlen("OK")))
814 { return(-1);
815 }
816
817 return 0;
818 }
819
820 /* -------------------------------------------------------------------- */
821 /* Send ATE0 string to set local echo to off. */
822 /* -------------------------------------------------------------------- */
set_local_echo(int modem)823 int set_local_echo(int modem)
824 {
825 char str[MAX_BUFSIZE];
826 int res;
827
828 libcommon_usleep(test_guard_time);
829
830 if (twrite(modem, "\r", strlen("\r"), MDM_write_timeout))
831 { return(-1);
832 }
833
834 libcommon_usleep(test_guard_time);
835
836 if (twrite(modem, "\r", strlen("\r"), MDM_write_timeout))
837 { return(-1);
838 }
839
840 libcommon_usleep(test_guard_time);
841
842 strcpy(str, command_prefix);
843 strcat(str, set_local_echo_off);
844 strcat(str, command_suffix);
845
846 if (twrite(modem, str, strlen(str), MDM_write_timeout))
847 { return(-1);
848 }
849
850 if ((res = MDM_response(modem, MDM_response_timeout)) != MDM_OK)
851 { return(-1);
852 }
853
854 lprintf(LOG_VERBOSE, "MODEM: Setting Local Modem Echo to OFF\n");
855
856 if (test_modem_echo(modem))
857 { return(-1);
858 }
859
860 if (modem_echo)
861 { return(-1);
862 }
863
864 return 0;
865 }
866
867 /* -------------------------------------------------------------------- */
868 /* -------------------------------------------------------------------- */
MDM_send_hangup(int modem)869 int MDM_send_hangup(int modem)
870 {
871 char str[MAX_BUFSIZE],
872 *ptr;
873 int res,
874 retry,
875 hangup_status;
876
877
878 hangup_status = FALSE;
879 for (retry = soft_hangup_retries; retry > 0; retry--)
880 {
881 tcflush(modem, TCIOFLUSH); /* Flush all data */
882
883 libcommon_usleep(guard_time); /* Sleep for gaurd_time */
884 /* before transmitting */
885 /* any data */
886
887 for(ptr = attention_command; *ptr ;ptr++)
888 {
889 str[0] = *ptr;
890 str[1] = '\0';
891
892 if (twrite(modem, str, strlen(str), MDM_write_timeout))
893 { break;
894 }
895
896 if (ptr[1] != '\0')
897 { libcommon_usleep(esc_time);
898 }
899 }
900
901 if (*ptr)
902 { lprintf(LOG_WARNING, "MODEM: Failed to issue attention command - %s\n", attention_command);
903 break;
904 }
905
906 libcommon_usleep(guard_time); /* Sleep for gaurd_time */
907 /* before transmitting */
908 /* any data */
909
910
911
912 res = MDM_response(modem, MDM_hangup_timeout);
913 if (res != MDM_OK)
914 { lprintf(LOG_WARNING, "MODEM: Expecting OK response - %s\n", get_response(res));
915 }
916
917
918 libcommon_usleep(guard_time); /* Sleep for gaurd_time */
919
920
921 strcpy(str, command_prefix);
922 strcat(str, command_suffix);
923
924 twrite(modem, str, strlen(str), MDM_write_timeout);
925 res = MDM_response(modem, MDM_hangup_timeout);
926 if (res != MDM_OK)
927 { lprintf(LOG_WARNING, "MODEM: Expecting OK response - %s\n", get_response(res));
928 }
929
930 strcpy(str, command_prefix);
931 strcat(str, hangup_command);
932 strcat(str, command_suffix);
933
934 twrite(modem, str, strlen(str), MDM_write_timeout);
935 res = MDM_response(modem, MDM_hangup_timeout);
936 if ((res == MDM_OK) ||
937 (res == MDM_NO_CARRIER) ||
938 (res == MDM_DISCONNECTED))
939 {
940 hangup_status = TRUE;
941 break;
942 }
943 else
944 { lprintf(LOG_WARNING, "MODEM: Expecting OK or NO CARRIER - %s\n", get_response(res));
945 }
946 }
947
948 return hangup_status;
949 }
950
951
952 /* -------------------------------------------------------------------- */
953 /* -------------------------------------------------------------------- */
toggle_DTR(int modem,long sleep_period)954 int toggle_DTR(int modem, long sleep_period)
955 {
956 #if defined(TIOCSDTR)
957
958 lprintf(LOG_VERBOSE, "MODEM: Toggle DTR using ioctl() %ld Microseconds\n", sleep_period);
959
960
961 if (ioctl(modem, TIOCCDTR, 0) == -1)
962 {
963 lprintf(LOG_WARNING, "MODEM: Failed ioctl() errno %d\n", errno);
964 }
965
966 libcommon_usleep(sleep_period); /* Allow things to */
967 /* Settle down DTR may */
968 /* need to be left */
969 /* lowered for a period */
970 /* of time */
971
972
973 if (ioctl(modem, TIOCSDTR, 0) == -1)
974 {
975 lprintf(LOG_WARNING, "MODEM: Failed ioctl() errno %d\n", errno);
976 }
977
978 #else
979 int retry;
980 struct termios
981 t,
982 ot;
983
984
985 lprintf(LOG_VERBOSE, "MODEM: Toggle DTR %ld Microseconds\n", sleep_period);
986
987 retry = 3;
988 while (retry--)
989 {
990 if (tcgetattr(modem, &t) == -1)
991 { lprintf(LOG_WARNING, "MODEM: Failed tcgetattr() errno %d\n", errno);
992
993 if (retry == 1)
994 {
995 close(modem);
996 return -1;
997 }
998
999 sleep(1);
1000 }
1001 else
1002 { retry = 0;
1003 }
1004 }
1005
1006 retry = 3;
1007 while (retry--)
1008 {
1009 if (tcgetattr(modem, &ot) == -1)
1010 { lprintf(LOG_WARNING, "MODEM: Failed tcgetattr() errno %d\n", errno);
1011
1012 if (retry == 1)
1013 {
1014 close(modem);
1015 return -1;
1016 }
1017
1018 sleep(1);
1019 }
1020 else
1021 { retry = 0;
1022 }
1023 }
1024
1025 if ((cfsetospeed(&t, B0) == -1) || /* B0 causes */
1026 (cfsetispeed(&t, B0) == -1)) /* DTR to be lowered */
1027 {
1028 lprintf(LOG_WARNING, "MODEM: Failed cfsetspeed() - B0 HANGUP\n");
1029 return -1;
1030 }
1031
1032 retry = 3;
1033 while (retry--)
1034 {
1035 if (tcsetattr(modem,TCSANOW, &t) == -1)
1036 { lprintf(LOG_WARNING, "MODEM: Failed tcsetattr() errno %d - B0 HANGUP\n", errno);
1037
1038 if (retry == 1)
1039 {
1040 return -1;
1041 }
1042
1043 sleep(1);
1044 }
1045 else
1046 { retry = 0;
1047 }
1048 }
1049
1050 libcommon_usleep(sleep_period); /* Allow things to */
1051 /* Settle down DTR may */
1052 /* need to be left */
1053 /* lowered for a period */
1054 /* of time */
1055
1056 retry = 3;
1057 while (retry--)
1058 {
1059 if (tcsetattr(modem,TCSANOW, &ot) == -1)
1060 {
1061 lprintf(LOG_WARNING, "MODEM: Failed tcsetattr() errno %d - setting speed\n", errno);
1062
1063 if (retry == 1)
1064 {
1065 return -1;
1066 }
1067
1068 sleep(1);
1069 }
1070 else
1071 { retry = 0;
1072 }
1073 }
1074 #endif
1075 return 0;
1076 }
1077
1078 /* -------------------------------------------------------------------- */
1079 /* -------------------------------------------------------------------- */
MDM_hangup(int modem)1080 void MDM_hangup(int modem)
1081 {
1082 int retry;
1083
1084
1085 if (modem_status == MODEM_CLOSED)
1086 { return;
1087 }
1088
1089 MDM_send_hangup(modem);
1090 toggle_DTR(modem, MDM_dtr_hangup_sleep);
1091
1092 if (strcmp(restore_terminal, "YES") == 0)
1093 {
1094 lprintf(LOG_VERBOSE, "MODEM: Returning Terminal to original settings\n");
1095
1096 retry = 3;
1097 while (retry--)
1098 {
1099 if (tcsetattr(modem, TCSANOW, &t_orig) == -1)
1100 {
1101 /* Failed to return */
1102 /* to original terminal */
1103 /* settings */
1104
1105 lprintf(LOG_WARNING, "MODEM: Failed tcsetattr() errno %d - Trying to return modem device to original settting\n", errno);
1106
1107 sleep(1);
1108 }
1109 else
1110 { retry = 0;
1111 }
1112 }
1113 }
1114
1115 close(modem);
1116 modem_status = MODEM_CLOSED;
1117
1118 lprintf(LOG_VERBOSE, "MODEM: Hangup Complete\n");
1119
1120 resource_unlock(modem_lockfile); /* Remove lock file */
1121 /* on this device */
1122 }
1123
1124 /* -------------------------------------------------------------------- */
1125 /* -------------------------------------------------------------------- */
MDM_dial(char * number,char data,char parity,char stop,long baud)1126 int MDM_dial(char *number, char data, char parity, char stop, long baud)
1127 {
1128 struct stat
1129 stat_buf;
1130
1131 int modem,
1132 res,
1133 ring_count;
1134
1135
1136 char str[MAX_BUFSIZE],
1137 fname[MAX_BUFSIZE];
1138
1139
1140 strcpy(fname, MODEMDIR);
1141 libcommon_strfcat(fname, "sms_modem");
1142
1143 if (read_resource_file(fname, resource_list, TRUE) != RESOURCE_FILE_OK)
1144 { lprintf(LOG_ERROR, "MODEM: Unrecoverable Failure Parsing modem file '%s'\n", fname);
1145 exit(-1);
1146 }
1147
1148
1149
1150 strcpy(modem_file, device_dir);
1151 strcat(modem_file, device);
1152
1153 strcpy(modem_lockfile, lock_dir);
1154 libcommon_strfcat(modem_lockfile, lock_prefix);
1155
1156
1157 if (stat(modem_file, &stat_buf) == -1)
1158 {
1159 lprintf(LOG_ERROR, "MODEM: stat() Failed\n");
1160 lprintf(LOG_STANDARD, "\n");
1161 lprintf(LOG_STANDARD, "Ensure that the device entry '%s' exists\n", modem_file);
1162 lprintf(LOG_STANDARD, "If you want to use a different device, change the\n");
1163 lprintf(LOG_STANDARD, "value of 'MDM_device' in '%s' to that device.\n", MODEMDIR "/sms_modem");
1164 lprintf(LOG_STANDARD, "\n");
1165
1166 exit(-1);
1167 }
1168
1169 if (strcmp(lock_platform, "SOLARIS") == 0)
1170 {
1171 #if defined(SOLARIS)
1172 sms_snprintf(&modem_lockfile[strlen(modem_lockfile)], 64, "%03u.%03u.%03u",
1173 (unsigned int)(major(stat_buf.st_dev)),
1174 (unsigned int)(stat_buf.st_rdev >> 18),
1175 (unsigned int)(minor(stat_buf.st_rdev)));
1176
1177 lprintf(LOG_VERBOSE, "Generating SOLARIS style lockfile '%s'\n", modem_lockfile);
1178 #else
1179 lprintf(LOG_ERROR, "SOLARIS style lockfiles only supported under SOLARIS\n");
1180 exit(-1);
1181 #endif
1182 }
1183 else
1184 { if (strcmp(lock_platform, "TRADITIONAL") != 0)
1185 { lprintf(LOG_WARNING, "MODEM: MDM_lock_platform invalid using 'TRADITIONAL'\n");
1186 }
1187
1188 strcat(modem_lockfile, device);
1189 }
1190
1191
1192 if ((strcmp(flow_control, "Software") != 0) &&
1193 (strcmp(flow_control, "Hardware") != 0))
1194 {
1195 lprintf(LOG_ERROR, "MODEM: MDM_flow_control must be either 'Software' or 'Hardware'\n");
1196 exit(-1);
1197 }
1198
1199 if (MDM_obtain_lock(device) == -1)
1200 { exit(-1);
1201 }
1202
1203 modem = MDM_init(modem_file, data, parity, stop, flow_control[0], baud);
1204 if (modem < 0)
1205 { lprintf(LOG_ERROR, "MODEM: MDM_init() Failed\n");
1206 exit(-1);
1207 }
1208
1209 if (MDM_drain_timeout != 0)
1210 {
1211 /* Drain any pending chars from modem */
1212
1213 lprintf(LOG_VERBOSE, "MDM_send: Drain required.\n");
1214
1215 while (expdrain(modem, MDM_drain_timeout))
1216 {
1217 lprintf(LOG_VERBOSE, "MDM_send: Draining.");
1218 }
1219 }
1220
1221 if (strcmp(MDM_disable_echo_test, "NO") == 0)
1222 { if (set_local_echo(modem) == -1)
1223 { lprintf(LOG_ERROR, "MODEM: Setting Local echo Failed\n");
1224 exit(-1);
1225 }
1226 }
1227
1228 strcpy(str, command_prefix);
1229 strcat(str, init_command);
1230 strcat(str, command_suffix);
1231
1232 lprintf(LOG_VERBOSE, "MODEM: Sending Initialization string %s to modem\n", str);
1233
1234 if (MDM_send(modem, str) != 0)
1235 { lprintf(LOG_VERBOSE, "MODEM: Sending Initialization string\n");
1236 exit(-1);
1237 }
1238
1239 lprintf(LOG_VERBOSE, "MODEM: Waiting for Initialization to complete...\n");
1240
1241 if ((res = MDM_response(modem, MDM_response_timeout)) != MDM_OK)
1242 { lprintf(LOG_VERBOSE, "MODEM: Expecting OK response - %s\n", get_response(res));
1243 exit(-1);
1244 }
1245
1246 lprintf(LOG_VERBOSE, "MODEM: Initialization complete\n");
1247
1248
1249
1250 if (MDM_pause_before_dial)
1251 {
1252 lprintf(LOG_VERBOSE, "MODEM: Pause before dialing\n");
1253 lprintf(LOG_VERBOSE, "MODEM: Sleeping for %ld Microseconds...\n", MDM_pause_before_dial);
1254
1255 libcommon_usleep(MDM_pause_before_dial);
1256 }
1257
1258
1259
1260 lprintf(LOG_VERBOSE, "MODEM: Dialing %s\n", number);
1261
1262 strcpy(str, command_prefix);
1263 strcat(str, dial_command);
1264 strcat(str, number_prefix);
1265 strcat(str, number);
1266 strcat(str, command_suffix);
1267
1268 lprintf(LOG_VERBOSE, "MODEM: Sending dial string %s to modem\n", str);
1269
1270 if (MDM_send(modem, str) != 0)
1271 { lprintf(LOG_ERROR, "MODEM: Sending dial string\n");
1272 exit(-1);
1273 }
1274
1275 lprintf(LOG_VERBOSE, "MODEM: Waiting for Connection...\n");
1276
1277
1278 ring_count = 0;
1279 while ((res = MDM_response(modem, MDM_connect_timeout)) == MDM_RINGING)
1280 {
1281 lprintf(LOG_VERBOSE, "MODEM: Ringing...\n");
1282
1283 ring_count++;
1284 if (ring_count > MDM_max_rings)
1285 { lprintf(LOG_WARNING, "MODEM: Expecting CONNECT within %ld rings\n", MDM_max_rings);
1286 break;
1287 }
1288 }
1289
1290 if (res != MDM_CONNECT)
1291 {
1292 lprintf(LOG_VERBOSE, "MODEM: Expecting CONNECT response - %s\n", get_response(res));
1293 exit(-1);
1294 }
1295
1296
1297 lprintf(LOG_VERBOSE, "MODEM: Connection Established.\n");
1298
1299 if (MDM_pause_after_connect != 0)
1300 {
1301 lprintf(LOG_VERBOSE, "MODEM: Pausing after connection...\n");
1302
1303 usleep(MDM_pause_after_connect);
1304
1305 lprintf(LOG_VERBOSE, "MODEM: Continuing.\n");
1306 }
1307
1308 return modem;
1309 }
1310
1311