1 /*
2 SMS Server Tools 3
3 Copyright (C) 2006- Keijo Kasvi
4 http://smstools3.kekekasvi.com/
5
6 Based on SMS Server Tools 2, http://stefanfrings.de/smstools/
7 SMS Server Tools version 2 and below are Copyright (C) Stefan Frings.
8
9 This program is free software unless you got it under another license directly
10 from the author. You can redistribute it and/or modify it under the terms of
11 the GNU General Public License as published by the Free Software Foundation.
12 Either version 2 of the License, or (at your option) any later version.
13 */
14
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <termios.h>
19 #include <regex.h>
20 #include <ctype.h>
21 #include <time.h>
22 #include "logging.h"
23 #include "alarm.h"
24
25 #ifdef SOLARIS
26 #include <sys/filio.h>
27 #include <strings.h> // for bzero().
28 #endif
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <syslog.h>
35 #include <sys/ioctl.h>
36 #include <errno.h>
37
38 #ifndef DISABLE_INET_SOCKET
39 // HG
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <netdb.h>
43 #endif
44
45 #include "extras.h"
46 #include "modeminit.h"
47 #include "smsd_cfg.h"
48 #include "version.h"
49 #include "pdu.h"
50 #include "stats.h"
51
52 // Define a dummy if the OS does not support hardware handshake
53 #ifndef CRTSCTS
54 #define CRTSCTS 0
55 #endif
56
57 // 3.1.16beta:
58 typedef struct {
59 char *keyword;
60 int value;
61 char *comment;
62 } _read_timeout;
63
64 _read_timeout read_timeouts[] =
65 {
66 {"askpin", 2, "Asking if PIN is required."},
67 {"atd", 24, "Initiating a voice call."},
68 {"ath", 1, "Ending a voice call using ATH or AT+CHUP."},
69 {"clcc", 24, "Listing current calls during a voice call."},
70 {"cmd", 1, "Sending regular_run command to modem."},
71 {"cmgd", 1, "Deleting a message, checking messages using +CMGD."},
72 {"cmgf", 1, "Selecting a PDU mode."},
73 {"cmgl", 12, "Listing messages."},
74 {"cmgr", 1, "Reading message."},
75 {"cmgs", 2, "Initiating a sending."},
76 {"cpas", 24, "Checking activity during a voice call."},
77 {"cpbr", 1, "Reading phonebook entry, check limits."},
78 {"cpbw", 1, "Writing (deleting) a phonebook entry."},
79 {"cpms", 1, "Selecting preferred memory, checking size."},
80 {"creg", 2, "Reading registration report."},
81 {"csca", 1, "Changing SMSC."},
82 {"csq", 2, "Reading signal quality."},
83 {"cusd", 3, "Sending USSD string."},
84 {"default", 1, "Default for basic commands: AT, ATE0, etc."},
85 {"enterpin", 6, "Entering a PIN."},
86 {"init", 2, "Sending init or init2 string."},
87 {"pdu", 12, "Sending a PDU."},
88 {"preinit", 2, "Sending pre_init string."},
89 {"start", 2, "Sending start string."},
90 {"stop", 2, "Sending stop string."}
91 };
92 // -------
93
94 typedef struct {
95 int code;
96 char *text;
97 } _gsm_general_error;
98
99 _gsm_general_error gsm_cme_errors[] =
100 {
101 // 3GPP TS 07.07 version 7.8.0 Release 1998 (page 90) ETSI TS 100 916 V7.8.0 (2003-03)
102 {0, "Phone failure"},
103 {1, "No connection to phone"},
104 {2, "Phone-adaptor link reserved"},
105 {3, "Operation not allowed"},
106 {4, "Operation not supported"},
107 {5, "PH-SIM PIN required"},
108 {6, "PH-FSIM PIN required"},
109 {7, "PH-FSIM PUK required"},
110 {10, "SIM not inserted"},
111 {11, "SIM PIN required"},
112 {12, "SIM PUK required"},
113 {13, "SIM failure"},
114 {14, "SIM busy"},
115 {15, "SIM wrong"},
116 {16, "Incorrect password"},
117 {17, "SIM PIN2 required"},
118 {18, "SIM PUK2 required"},
119 {20, "Memory full"},
120 {21, "Invalid index"},
121 {22, "Not found"},
122 {23, "Memory failure"},
123 {24, "Text string too long"},
124 {25, "Invalid characters in text string"},
125 {26, "Dial string too long"},
126 {27, "Invalid characters in dial string"},
127 {30, "No network service"},
128 {31, "Network timeout"},
129 {32, "Network not allowed - emergency calls only"},
130 {40, "Network personalisation PIN required"},
131 {41, "Network personalisation PUK required"},
132 {42, "Network subset personalisation PIN required"},
133 {43, "Network subset personalisation PUK required"},
134 {44, "Service provider personalisation PIN required"},
135 {45, "Service provider personalisation PUK required"},
136 {46, "Corporate personalisation PIN required"},
137 {47, "Corporate personalisation PUK required"},
138 {48, "PH-SIM PUK required"},
139
140 {100, "Unknown"},
141
142 {103, "Illegal MS"},
143 {106, "Illegal ME"},
144 {107, "GPRS services not allowed"},
145 {111, "PLMN not allowed"},
146 {112, "Location area not allowed"},
147 {113, "Roaming not allowed in this location area"},
148 {126, "Operation temporary not allowed"},
149 {132, "Service operation not supported"},
150 {133, "Requested service option not subscribed"},
151 {134, "Service option temporary out of order"},
152 {148, "Unspecified GPRS error"},
153 {149, "PDP authentication failure"},
154 {150, "Invalid mobile class"},
155
156 {256, "Operation temporarily not allowed"},
157 {257, "Call barred"},
158 {258, "Phone is busy"},
159 {259, "User abort"},
160 {260, "Invalid dial string"},
161 {261, "SS not executed"},
162 {262, "SIM Blocked"},
163 {263, "Invalid block"},
164
165 {515, "Device busy"},
166
167 {772, "SIM powered down"}
168
169 };
170
171 _gsm_general_error gsm_cms_errors[] =
172 {
173 // Table 8.4/GSM 04.11 (part 1):
174 {1, "Unassigned (unallocated) number"},
175 {8, "Operator determined barring"},
176 {10, "Call barred"},
177 {21, "Short message transfer rejected"},
178 {27, "Destination out of order"},
179 {28, "Unindentified subscriber"},
180 {29, "Facility rejected"},
181 {30, "Unknown subscriber"},
182 {38, "Network out of order"},
183 {41, "Temporary failure"},
184 {42, "Congestion"},
185 {47, "Recources unavailable, unspecified"},
186 {50, "Requested facility not subscribed"},
187 {69, "Requested facility not implemented"},
188 {81, "Invalid short message transfer reference value"},
189 {95, "Semantically incorrect message"},
190 {96, "Invalid mandatory information"},
191 {97, "Message type non-existent or not implemented"},
192 {98, "Message not compatible with short message protocol state"},
193 {99, "Information element non-existent or not implemented"},
194 {111, "Protocol error, unspecified"},
195 {127, "Internetworking , unspecified"},
196 // Table 8.4/GSM 04.11 (part 2):
197 {22, "Memory capacity exceeded"},
198 // GSM 03.40 subclause 9.2.3.22 values.
199 {128, "Telematic internetworking not supported"},
200 {129, "Short message type 0 not supported"},
201 {130, "Cannot replace short message"},
202 {143, "Unspecified TP-PID error"},
203 {144, "Data code scheme (alphabet) not supported"},
204 {145, "Message class not supported"},
205 {159, "Unspecified TP-DCS error"},
206 {160, "Command cannot be actioned"},
207 {161, "Command unsupported"},
208 {175, "Unspecified TP-Command error"},
209 {176, "Transfer Protocol Data Unit (TPDU) not supported"},
210 {192, "Service Center (SC) busy"},
211 {193, "No SC subscription"},
212 {194, "SC System failure"},
213 {195, "Invalid Short Message Entity (SME) address"},
214 {196, "Destination SME barred"},
215 {197, "SM Rejected-Duplicate SM"},
216 {198, "Validity Period Format (TP-VPF) not supported"},
217 {199, "Validity Period) TP-VP not supported"},
218 {208, "SIM SMS Storage full"},
219 {209, "No SMS Storage capability in SIM"},
220 {210, "Error in MS"},
221 {211, "Memory capacity exceeded"},
222 {212, "Sim Application Toolkit busy"},
223 {213, "SIM data download error"},
224 {255, "Unspecified error cause"},
225 // 3GPP TS 27.005 subclause 3.2.5 values /3/.
226 {300, "ME Failure"},
227 {301, "SMS service of ME reserved"},
228 {302, "Operation not allowed"},
229 {303, "Operation not supported"},
230 {304, "Invalid PDU mode parameter"},
231 {305, "Invalid Text mode parameter"},
232 {310, "(U)SIM not inserted"},
233 {311, "(U)SIM PIN required"},
234 {312, "PH-(U)SIM PIN required"},
235 {313, "(U)SIM failure"},
236 {314, "(U)SIM busy"},
237 {315, "(U)SIM wrong"},
238 {316, "(U)SIM PUK required"},
239 {317, "(U)SIM PIN2 required"},
240 {318, "(U)SIM PUK2 required"},
241 {320, "Memory failure"},
242 {321, "Invalid memory index"},
243 {322, "Memory full"},
244 {330, "SMSC address unknown"},
245 {331, "No network service"},
246 {332, "Network timeout"},
247 {340, "No +CNMA acknowledgement expected"},
248 {500, "Unknown error"},
249
250 // 3.1.5: This error occurs when you try to send a message and the module is receiving another one at the same time.
251 // This causes a collision in the message transfer protocol resulting in failure in sending the SMS.
252 // Sometimes, +CMS ERROR: 512 may also occur when the module is receiving weak signal and is loosing connection.
253 {512, "MM establishment failure / weak signal, loosing connection"},
254
255 // 3.1.5: ack for 28s after transmission or 42s after channel establishment
256 {513, "Lower layer failure: receiving of an acknowledgement timed out or lost the radio link."},
257
258 // 3.1.5:
259 {514, "Network error. Congestion in the network."},
260
261 {515, "Please wait, service is not available, init in progress"}
262 };
263
get_gsm_cme_error(int code)264 char *get_gsm_cme_error(int code)
265 {
266 int i;
267 int m = sizeof gsm_cme_errors / sizeof *gsm_cme_errors;
268
269 for (i = 0; i < m; i++)
270 if (code == gsm_cme_errors[i].code)
271 return gsm_cme_errors[i].text;
272
273 return "";
274 }
275
get_gsm_cms_error(int code)276 char *get_gsm_cms_error(int code)
277 {
278 int i;
279 int m = sizeof gsm_cms_errors / sizeof *gsm_cms_errors;
280
281 for (i = 0; i < m; i++)
282 if (code == gsm_cms_errors[i].code)
283 return gsm_cms_errors[i].text;
284
285 return "";
286 }
287
get_gsm_error(char * answer)288 char *get_gsm_error(char *answer)
289 {
290 char *p;
291
292 if (answer && *answer)
293 {
294 if ((p = strstr(answer, "+CME ERROR: ")))
295 return get_gsm_cme_error(atoi(p +12));
296 if ((p = strstr(answer, "+CMS ERROR: ")))
297 return get_gsm_cms_error(atoi(p +12));
298 }
299
300 return "";
301 }
302
get_read_timeout(char * keyword)303 int get_read_timeout(char *keyword)
304 {
305 int i;
306 int m = sizeof read_timeouts / sizeof *read_timeouts;
307 int result = 1;
308
309 if (!keyword)
310 return 0;
311
312 for (i = 0; i < m; i++)
313 if (!strcmp(keyword, read_timeouts[i].keyword))
314 result = read_timeouts[i].value;
315
316 // Accept direct value:
317 if ((i = atoi(keyword)) > 0)
318 result = i;
319
320 if (log_read_timing)
321 writelogfile(LOG_DEBUG, 0, "read_timeout for %s is %i sec", keyword, DEVICE.read_timeout * result);
322
323 return result;
324 }
325
set_read_timeout(char * error,int size_error,char * keyword,int value)326 int set_read_timeout(char *error, int size_error, char *keyword, int value)
327 {
328 int result = 0;
329 int i;
330 int m = sizeof read_timeouts / sizeof *read_timeouts;
331
332 *error = 0;
333
334 for (i = 0; i < m; i++)
335 if (!strcmp(keyword, read_timeouts[i].keyword))
336 break;
337
338 if (i < m)
339 {
340 if (value < 1)
341 snprintf(error, size_error, "Cannot set read_timeout_%s to less than 1.", keyword);
342 else
343 {
344 read_timeouts[i].value = value;
345 result = 1;
346 }
347 }
348 else
349 snprintf(error, size_error, "Unknown setting read_timeout_%s.", keyword);
350
351 return result;
352 }
353
log_read_timeouts(int level)354 void log_read_timeouts(int level)
355 {
356 int i;
357 int m = sizeof read_timeouts / sizeof *read_timeouts;
358
359 writelogfile(level, 0, "Using read_timeout %i seconds.", DEVICE.read_timeout);
360
361 for (i = 0; i < m; i++)
362 writelogfile(level, 0, "Using read_timeout_%s %i * read_timeout = %i seconds. %s",
363 read_timeouts[i].keyword, read_timeouts[i].value,
364 read_timeouts[i].value * DEVICE.read_timeout,
365 read_timeouts[i].comment);
366
367 }
368
explain_csq_buffer(char * buffer,int short_form,int ssi,int ber,int signal_quality_ber_ignore)369 char *explain_csq_buffer(char *buffer, int short_form, int ssi, int ber, int signal_quality_ber_ignore)
370 {
371
372 strcpy(buffer, (short_form)? "ssi: " : "Signal Strength Indicator: ");
373 if (ssi == 99 || ssi > 31 || ssi < 0)
374 strcat(buffer, (short_form)? "??" : "not present of not measurable");
375 else
376 {
377 // 3.1.12: explain level:
378 int dbm;
379 char *level = "";
380
381 dbm = -113 + 2 * ssi;
382
383 if (dbm <= -95)
384 level = " (Marginal)"; // Marginal - Levels of -95dBm or lower.
385 else if (dbm <= -85)
386 level = " (Workable)"; // Workable under most conditions - Levels of -85dBm to -95dBm.
387 else if (dbm <= -75)
388 level = " (Good)"; // Good - Levels between -75dBm and -85dBm.
389 else
390 level = " (Excellent)"; // Excellent - levels above -75dBm.
391
392 if (short_form)
393 sprintf(strchr(buffer, 0), "%i dBm%s", dbm, level);
394 else
395 sprintf(strchr(buffer, 0), "(%d,%d) %i dBm%s%s", ssi, ber, dbm, level, (ssi == 0)? " or less" : "");
396 }
397
398 if (!signal_quality_ber_ignore)
399 {
400 strcat(buffer, (short_form)? ", ber: " : ", Bit Error Rate: ");
401 switch (ber)
402 {
403 case 0:
404 strcat(buffer, (short_form)? "< 0.2 %" : "less than 0.2 %");
405 break;
406
407 case 1:
408 strcat(buffer, "0.2 - 0.4 %");
409 break;
410
411 case 2:
412 strcat(buffer, "0.4 - 0.8 %");
413 break;
414
415 case 3:
416 strcat(buffer, "0.8 - 1.6 %");
417 break;
418
419 case 4:
420 strcat(buffer, "1.6 - 3.2 %");
421 break;
422
423 case 5:
424 strcat(buffer, "3.2 - 6.4 %");
425 break;
426
427 case 6:
428 strcat(buffer, "6.4 - 12.8 %");
429 break;
430
431 case 7:
432 strcat(buffer, (short_form)? "> 12.8 %" : "more than 12.8 %");
433 break;
434
435 default:
436 strcat(buffer, (short_form)? "??" : "not known or not detectable");
437 break;
438 }
439 }
440
441 return buffer;
442 }
443
explain_csq(int loglevel,int short_form,char * answer,int signal_quality_ber_ignore)444 void explain_csq(int loglevel, int short_form, char *answer, int signal_quality_ber_ignore)
445 {
446 int ssi;
447 int ber = 99;
448 char *p;
449 char buffer[1024];
450
451 if (strstr(answer, "ERROR"))
452 return;
453
454 // 3.1.12: Allow "echo on":
455 //if (strncmp(answer, "+CSQ:", 5))
456 // return;
457 if (!(p = strstr(answer, "+CSQ:")))
458 return;
459
460 //ssi = atoi(answer +5);
461 ssi = atoi(p +5);
462 //if ((p = strchr(answer, ',')))
463 if ((p = strchr(p, ',')))
464 ber = atoi(p +1);
465
466 explain_csq_buffer(buffer, short_form, ssi, ber, signal_quality_ber_ignore);
467
468 writelogfile0(loglevel, 0, buffer);
469 }
470
write_to_modem(char * command,int timeout,int log_command,int print_error)471 int write_to_modem(char *command, int timeout, int log_command, int print_error)
472 {
473 int status=0;
474 int timeoutcounter=0;
475 int x=0;
476 struct termios tio;
477
478 if (command && command[0])
479 {
480 if (log_command)
481 writelogfile(LOG_DEBUG, 0, "-> %s",command);
482
483 // 3.1.9:
484 if (DEVICE.send_handshake_select)
485 {
486 size_t r = 0, bs, n;
487 ssize_t got;
488 fd_set writefds;
489
490 n = strlen(command);
491 while (n > 0)
492 {
493 bs = (DEVICE.send_delay < 1) ? n : 1;
494 got = write(modem_handle, command + r, bs);
495 if (got < 0)
496 {
497 if (errno == EINTR)
498 continue;
499
500 if (errno != EAGAIN)
501 {
502 writelogfile0(LOG_ERR, 1, tb_sprintf("write_to_modem: error %d: %s", errno, strerror(errno)));
503 alarm_handler0(LOG_ERR, tb);
504 return 0;
505 }
506
507 // 3.1.16beta: Do not log "device busy":
508 //writelogfile0(LOG_DEBUG, 0, tb_sprintf("write_to_modem: device busy, waiting"));
509 //alarm_handler0(LOG_DEBUG, tb);
510
511 FD_ZERO(&writefds);
512 FD_SET(modem_handle, &writefds);
513 select(modem_handle + 1, NULL, &writefds, NULL, NULL);
514 continue;
515 }
516
517 n -= got;
518 r += got;
519
520 if (DEVICE.send_delay > 0)
521 usleep_until(time_usec() + DEVICE.send_delay * 1000);
522
523 tcdrain(modem_handle);
524 }
525 }
526 else
527 {
528 tcgetattr(modem_handle, &tio);
529
530 if (!DEVICE_IS_SOCKET && tio.c_cflag & CRTSCTS)
531 {
532 ioctl(modem_handle, TIOCMGET, &status);
533 while (!(status & TIOCM_CTS))
534 {
535 usleep_until(time_usec() + 100000);
536 timeoutcounter++;
537 ioctl(modem_handle, TIOCMGET, &status);
538 if (timeoutcounter>timeout)
539 {
540 if (print_error)
541 printf("\nModem is not clear to send.\n");
542 else
543 {
544 writelogfile0(LOG_ERR, 1, tb_sprintf("Modem is not clear to send"));
545 alarm_handler0(LOG_ERR, tb);
546 }
547 return 0;
548 }
549 }
550 }
551
552 // 3.1.5:
553 if (DEVICE.send_delay < 1)
554 {
555 if ((size_t)write(modem_handle, command, strlen(command)) != strlen(command))
556 {
557 writelogfile0(LOG_ERR, 1, tb_sprintf("Could not send string, cause: %s", strerror(errno)));
558 alarm_handler0(LOG_ERR, tb);
559 return 0;
560 }
561
562 if (DEVICE.send_delay < 0)
563 tcdrain(modem_handle);
564 }
565 else
566 {
567 for(x=0;(size_t)x<strlen(command);x++)
568 {
569 if (write(modem_handle, command +x, 1) < 1)
570 {
571 if (print_error)
572 printf("\nCould not send character %c, cause: %s\n",command[x],strerror(errno));
573 else
574 {
575 writelogfile0(LOG_ERR, 1, tb_sprintf("Could not send character %c, cause: %s", command[x], strerror(errno)));
576 alarm_handler0(LOG_ERR, tb);
577 }
578 return 0;
579 }
580 usleep_until(time_usec() + DEVICE.send_delay *1000);
581 tcdrain(modem_handle);
582 }
583 }
584 }
585 }
586
587 return 1;
588 }
589
590 // 3.1.12:
negotiate_with_telnet(char * answer,int * len)591 void negotiate_with_telnet(char *answer, int *len)
592 {
593 #define IAC '\xFF' /* Interpret as command: */
594 #define DONT '\xFE' /* You are not to use option */
595 #define DO '\xFD' /* Please, you use option */
596 #define WONT '\xFC' /* I won't use option */
597 #define WILL '\xFB' /* I will use option */
598 #define SB '\xFA' /* Interpret as subnegotiation */
599 #define SE '\xF0' /* End sub negotiation */
600
601 char *title = "Telnet";
602 int idx;
603 int i;
604 int count;
605 char response[128];
606 char command;
607 int got_option;
608 char option;
609 const char *eol = DEVICE.telnet_crlf ? "\r\n" : "\n";
610
611 idx = 0;
612 while (idx < *len)
613 {
614 if (answer[idx] == IAC && idx +1 < *len)
615 {
616 *response = 0;
617 count = 3;
618 command = answer[idx +1];
619 got_option = idx +2 < *len;
620 option = (got_option)? answer[idx +2] : 0;
621
622 if (command == DO && got_option)
623 {
624 snprintf(response, sizeof(response), "%c%c%c", IAC, WONT, option);
625 writelogfile(LOG_DEBUG, 0, "%s: Got DO for %i (0x%02X), answering WONT.", title, (int)option, option);
626 }
627 else if (command == WILL && got_option)
628 {
629 snprintf(response, sizeof(response), "%c%c%c", IAC, DONT, option);
630 writelogfile(LOG_DEBUG, 0, "%s: Got WILL for %i (0x%02X), answering DONT.", title, (int)option, option);
631 }
632 else if (command == WONT && got_option)
633 {
634 writelogfile(LOG_DEBUG, 0, "%s: Got WONT for %i (0x%02X), ignoring.", title, (int)option, option);
635 }
636 // 3.1.16beta: Fixed a Telnet subnegotiation processing method.
637 //else if (command == SB && got_option)
638 //{
639 // writelogfile(LOG_DEBUG, 0, "%s: Got SB for %i (0x%02X), ignoring.", title, (int)option, option);
640 // count = 4;
641 //}
642 //else if (command == SE)
643 //{
644 // writelogfile(LOG_DEBUG, 0, "%s: Got SE, ignoring.", title);
645 // count = 2;
646 //}
647 else if (command == SB)
648 {
649 char commands[1024];
650
651 *commands = 0;
652
653 count = 2;
654 for (i = idx +2; i < *len; i++)
655 {
656 if (answer[i] == IAC && answer[i +1] == SE)
657 {
658 writelogfile(LOG_DEBUG, 0, "%s: Got subnegotiation for %i (0x%02X): %s - ignoring.", title, (int)option, option, commands);
659 count = i +2 -idx;
660 break;
661 }
662
663 if (i > idx +2 && strlen(commands) < sizeof(commands) - 6)
664 sprintf(strchr(commands, 0), "%s%i (0x%02X)", (*commands)? ", " : "", (int)answer[i], answer[i]);
665 }
666 }
667
668 if (*response)
669 if ((size_t)write(modem_handle, response, strlen(response)) != strlen(response))
670 writelogfile(LOG_ERR, 1, "%s: Failed to send response.", title);
671
672 for (i = idx; i +count < *len; i++)
673 answer[i] = answer[i +count];
674
675 *len -= count;
676 }
677 else
678 idx++;
679 }
680
681 answer[*len] = 0;
682
683 // 3.1.16beta: Now remove 0x00's from the answer:
684 if (strlen(answer) < (size_t)*len)
685 {
686 int i, j, l;
687
688 for (i = 0, j = 0, l = *len; i < *len; i++)
689 {
690 if (answer[i] == '\0')
691 {
692 l--;
693 continue;
694 }
695
696 if (i > j)
697 answer[j] = answer[i];
698 j++;
699 }
700
701 answer[l] = 0;
702 *len = l;
703 }
704
705 // 3.1.16beta: If login/password or cmd is sent, remove the prompt.
706 char *p;
707 int l = 0;
708 char *info = 0;
709
710 *response = 0;
711 if (DEVICE.telnet_login_prompt[0] && (p = strstr(answer, DEVICE.telnet_login_prompt)) && DEVICE.telnet_login[0])
712 {
713 if (DEVICE.telnet_login_prompt_ignore[0] == 0 || !strstr(answer, DEVICE.telnet_login_prompt_ignore))
714 {
715 snprintf(response, sizeof(response), "%s%s", DEVICE.telnet_login, eol);
716 l = strlen(DEVICE.telnet_login_prompt);
717 info = "login";
718 }
719 }
720 else if (DEVICE.telnet_password_prompt[0] && (p = strstr(answer, DEVICE.telnet_password_prompt)) && DEVICE.telnet_password[0])
721 {
722 snprintf(response, sizeof(response), "%s%s", DEVICE.telnet_password, eol);
723 l = strlen(DEVICE.telnet_password_prompt);
724 info = "password";
725 }
726 else if (DEVICE.telnet_cmd_prompt[0] && (p = strstr(answer, DEVICE.telnet_cmd_prompt)) && DEVICE.telnet_cmd[0])
727 {
728 snprintf(response, sizeof(response), "%s%s", DEVICE.telnet_cmd, eol);
729 l = strlen(DEVICE.telnet_cmd_prompt);
730 info = DEVICE.telnet_cmd;
731 }
732
733 if (l)
734 {
735 for (i = (int)(p -answer) +l; i <= *len; i++)
736 answer[i -l] = answer[i];
737 *len -= l;
738 }
739
740 if (*response)
741 {
742 if ((size_t)write(modem_handle, response, strlen(response)) != strlen(response))
743 writelogfile(LOG_ERR, 1, "%s: Failed to send response: %s", title, info);
744 else
745 writelogfile(LOG_DEBUG, 0, "%s: Sent %s", title, info);
746 }
747
748 #undef IAC
749 #undef DONT
750 #undef DO
751 #undef WONT
752 #undef WILL
753 #undef SB
754 #undef SE
755 }
756
read_from_modem(char * answer,int max,int timeout)757 int read_from_modem(char *answer, int max, int timeout)
758 {
759
760 return read_from_modem0(answer, max, timeout, 0, 0);
761 }
762
read_from_modem0(char * answer,int max,int timeout,regex_t * re,char * expect)763 int read_from_modem0(char *answer, int max, int timeout, regex_t *re, char *expect)
764 {
765 int count=0;
766 int got=0;
767 int timeoutcounter=0;
768 int success=0;
769 int toread=0;
770
771 // Cygwin does not support TIOC functions, so we cannot use it.
772 // ioctl(modem,FIONREAD,&available); // how many bytes are available to read?
773
774 // 3.1.16beta: Cannot use strlen(answer) in the loop when 0x00's are not removed here.
775 int answer_length = strlen(answer);
776
777 // 3.1.16beta2: If regular expression is defined, poll faster and stop as soon as regex matches.
778 char *check_answer = NULL;
779 int i;
780 int sleep_time = 100000;
781 int poll_faster = DEVICE.poll_faster;
782
783 if (re && poll_faster > 0)
784 {
785 check_answer = (char *)malloc(max);
786 timeout *= poll_faster;
787 sleep_time /= poll_faster;
788 }
789
790 if (log_read_timing)
791 writelogfile(LOG_DEBUG, 0, "read_from_modem, %i, '%s', %s", timeout, answer, (expect)? expect : "");
792
793 do
794 {
795 if (check_answer && success)
796 {
797 *check_answer = '\0';
798 for (i = 0; i < answer_length; i++)
799 check_answer[i] = (answer[i] == '\0')? '\n' : answer[i];
800 check_answer[i] = '\0';
801 if (log_read_timing)
802 writelogfile(LOG_DEBUG, 0, "answer now: %s", check_answer);
803 if (regexec(re, check_answer, (size_t) 0, NULL, 0) == 0)
804 {
805 if (log_read_timing)
806 writelogfile(LOG_DEBUG, 0, "answer is what expected, go ahead");
807 break;
808 }
809 }
810
811 // How many bytes do I want to read maximum? Not more than buffer size -1 for termination character.
812 count = answer_length; //count=strlen(answer);
813 toread=max-count-1;
814 if (toread<=0)
815 break;
816 // read data
817 got = read(modem_handle, answer +count, toread);
818
819 if (log_read_timing)
820 writelogfile(LOG_DEBUG, 0, "read, got %i", got);
821
822 // if nothing received ...
823 if (got<=0)
824 {
825 // wait a litte bit and then repeat this loop
826 got=0;
827 // 3.1.16beta: Do not sleep if the loop will not continue:
828 timeoutcounter++;
829 if (timeoutcounter < timeout)
830 {
831 if (log_read_timing)
832 writelogfile(LOG_DEBUG, 0, "sleeping %i us (%i)", sleep_time, timeoutcounter);
833 usleep_until(time_usec() + sleep_time /*100000*/);
834 }
835 }
836 else
837 {
838 if (log_read_from_modem)
839 {
840 char tmp[SIZE_LOG_LINE];
841 int i;
842
843 snprintf(tmp, sizeof(tmp), "read_from_modem: count=%i, got=%i:", count, got);
844 for (i = count; i < count + got; i++)
845 {
846 if (strlen(tmp) >= sizeof(tmp) - 6)
847 {
848 strcpy(tmp, "ERROR: too much data");
849 break;
850 }
851
852 sprintf(strchr(tmp, 0), " %02X[%c]", (unsigned char) answer[i], ((unsigned char) answer[i] >= ' ') ? answer[i] : '.');
853 }
854
855 writelogfile0(LOG_CRIT, 0, tmp);
856 }
857
858 // restart timout counter
859 timeoutcounter=0;
860 // append a string termination character
861 answer[count+got]=0;
862 answer_length = count +got;
863 success=1;
864
865 // 3.1.12: With Multitech network modem (telnet) there can be 0x00 inside the string:
866 // 3.1.16beta: Clean the string after telnet commands are handled, moved to negotiate_with_telnet.
867 //if (strlen(answer) < (size_t)count + got)
868 //{
869 // int i, j, len;
870 //
871 // len = count + got;
872 // j = 0;
873 // for (i = 0; i < count + got; i++)
874 // {
875 // if (answer[i] == '\0')
876 // {
877 // len--;
878 // continue;
879 // }
880 //
881 // if (i > j)
882 // answer[j] = answer[i];
883 // j++;
884 // }
885 //
886 // answer[len] = 0;
887 //}
888
889 }
890 }
891 while (timeoutcounter < timeout);
892
893 // 3.1.12:
894 if (success && DEVICE_IS_SOCKET)
895 {
896 count += got;
897 negotiate_with_telnet(answer, &count);
898 }
899
900 free(check_answer);
901
902 return success;
903 }
904
905 // 3.1.1:
change_crlf(char * str,char ch)906 char *change_crlf(char *str, char ch)
907 {
908 char *p;
909
910 while ((p = strchr(str, '\r')))
911 *p = ch;
912 while ((p = strchr(str, '\n')))
913 *p = ch;
914
915 return str;
916 }
917
detect_routed_message(char * answer)918 int detect_routed_message(char *answer)
919 {
920 int result = 0;
921 // keywords must have same length:
922 int keyword_length = 5;
923 char *keyword = "+CMT:";
924 char *keyword_sr = "+CDS:";
925 char *p;
926 char *term;
927 int pdu_length;
928 int can_handle;
929 int is_sr;
930 int send_ack = 0;
931 char *p1;
932 char *p2;
933
934 if (*answer)
935 {
936 // We can have answer which contains only routed message, or there can be answer like:
937 // +CPMS: "SM",0,20,"SM",0,20,"SM",0,20 OK ... +CMT: ,59 07915348150110...
938
939 is_sr = 0;
940 if (!(p1 = strstr(answer, keyword)))
941 if ((p1 = strstr(answer, keyword_sr)))
942 is_sr = 1;
943
944 if (p1)
945 {
946 if (!is_sr || !DEVICE.using_routed_status_report)
947 writelogfile(LOG_ERR, DEVICE.unexpected_input_is_trouble, "Routed %s detected:\n%s", (is_sr) ? "status report" : "message", p1);
948
949 if (DEVICE.routed_status_report_cnma)
950 send_ack = 1;
951
952 while (p1)
953 {
954 result++;
955 can_handle = 0;
956
957 if ((term = strchr(p1, '\r')))
958 {
959 p = term +1;
960 if (*p == '\n')
961 p++;
962 if (octet2bin(p) >= 0)
963 {
964 if ((term = strchr(p, '\r')))
965 {
966 // Original answer remains intact. Count the length and check that PDU does not contain delimiter character:
967 pdu_length = (int)(term - p);
968 p2 = strchr(p, ',');
969 if (!p2 || p2 > term)
970 {
971 // PDU is handled later. If it has some errors, explanation will be printed to the message file.
972
973 if (!routed_pdu_store)
974 {
975 if ((routed_pdu_store = (char *)malloc(pdu_length +2)))
976 *routed_pdu_store = 0;
977 }
978 else
979 routed_pdu_store = (char *)realloc((void *)routed_pdu_store, strlen(routed_pdu_store) +pdu_length +2);
980
981 if (routed_pdu_store)
982 {
983 // For easier handling, delimiter in routed_pdu_store is '\n'.
984 sprintf(strchr(routed_pdu_store, 0), "%.*s\n", pdu_length, p);
985 can_handle = 1;
986 }
987 }
988 }
989 }
990 }
991
992 p = (is_sr)? "status report" : "message";
993 if (can_handle)
994 {
995 if (is_sr && DEVICE.using_routed_status_report)
996 writelogfile0(LOG_INFO, 0, tb_sprintf("Saved routed %s for later handling.", p));
997 else
998 {
999 writelogfile0(LOG_ERR, 0, tb_sprintf("Saved routed %s for later handling. However, you MUST DISABLE %s routing with modem settings.", p, p));
1000 alarm_handler0(LOG_ERR, tb);
1001 }
1002 }
1003 else
1004 {
1005 writelogfile0(LOG_ERR, 0, tb_sprintf("Cannot handle this routed %s. You MUST DISABLE %s routing with modem settings.", p, p));
1006 alarm_handler0(LOG_ERR, tb);
1007 }
1008
1009 is_sr = 0;
1010 p = p1 +keyword_length;
1011 if (!(p1 = strstr(p, keyword)))
1012 if ((p1 = strstr(p, keyword_sr)))
1013 is_sr = 1;
1014 }
1015 }
1016
1017 // TODO: more than one ack if more than one messsage received?
1018 if (send_ack)
1019 {
1020 char loganswer[1024];
1021
1022 writelogfile(LOG_DEBUG, 0, "Sending acknowledgement");
1023 write_to_modem("AT+CNMA\r", 30, 1, 0);
1024
1025 *loganswer = 0;
1026 read_from_modem(loganswer, sizeof(loganswer), 2);
1027 if (log_single_lines)
1028 change_crlf(loganswer, ' ');
1029
1030 writelogfile(LOG_DEBUG, 0, "<- %s", loganswer);
1031 }
1032 }
1033
1034 return result;
1035 }
1036
do_hangup(char * answer)1037 void do_hangup(char *answer)
1038 {
1039
1040 if (DEVICE.hangup_incoming_call == 1 || (DEVICE.hangup_incoming_call == -1 && hangup_incoming_call == 1) || DEVICE.phonecalls == 2)
1041 {
1042 char *command = "AT+CHUP\r";
1043 char tmpanswer[1024];
1044 int timeoutcounter;
1045
1046 if (DEVICE.voicecall_hangup_ath == 1 || (DEVICE.voicecall_hangup_ath == -1 && voicecall_hangup_ath == 1))
1047 command = "ATH\r";
1048
1049 writelogfile(LOG_NOTICE, 0, "Ending incoming call: %s", answer);
1050
1051 write_to_modem(command, 30, 1, 0);
1052
1053 timeoutcounter = 0;
1054 *tmpanswer = 0;
1055
1056 do
1057 {
1058 read_from_modem(tmpanswer, sizeof(tmpanswer), 2);
1059
1060 // Any answer is ok:
1061 if (*tmpanswer)
1062 break;
1063
1064 timeoutcounter++;;
1065 }
1066 while (timeoutcounter < 5);
1067
1068 if (!log_unmodified)
1069 {
1070 cutspaces(tmpanswer);
1071 cut_emptylines(tmpanswer);
1072
1073 if (log_single_lines)
1074 change_crlf(tmpanswer, ' ');
1075 }
1076 writelogfile(LOG_DEBUG, 0, "<- %s", tmpanswer);
1077
1078 if (DEVICE.communication_delay > 0)
1079 usleep_until(time_usec() + DEVICE.communication_delay * 1000);
1080 }
1081 }
1082
handlephonecall_clip(char * answer)1083 int handlephonecall_clip(char *answer)
1084 {
1085 int result = 0;
1086 char *p, *e_start, *e_end;
1087 int len;
1088 char entry_number[SIZE_PB_ENTRY];
1089 //int entry_type;
1090
1091 if (DEVICE.phonecalls != 2)
1092 return 0;
1093
1094 *entry_number = 0;
1095 //entry_type = 0;
1096
1097 if ((p = strstr(answer, "+CLIP:")))
1098 {
1099 do_hangup(answer);
1100 result = -1;
1101
1102 if ((e_start = strchr(p, '"')))
1103 {
1104 e_start++;
1105 if ((e_end = strchr(e_start, '"')))
1106 {
1107 if ((len = e_end -e_start) < SIZE_PB_ENTRY)
1108 {
1109 sprintf(entry_number, "%.*s", len, e_start);
1110 cutspaces(entry_number);
1111 if (*entry_number == '+')
1112 strcpyo(entry_number, entry_number +1);
1113
1114 if (strlen(e_end) >= 3)
1115 {
1116 e_end += 2;
1117 writelogfile(LOG_INFO, 0, "Got phonecall from %s", entry_number);
1118 savephonecall(entry_number, atoi(e_end), "");
1119 result = 1;
1120 }
1121 }
1122 }
1123 }
1124
1125 if (result == -1)
1126 {
1127 writelogfile0(LOG_ERR, 1, tb_sprintf("Error while trying to handle +CLIP."));
1128 alarm_handler0(LOG_ERR, tb);
1129 }
1130 }
1131
1132 return result;
1133 }
1134
ignore_unexpected_input(char * answer)1135 int ignore_unexpected_input(char *answer)
1136 {
1137 int result = 0;
1138 char *p;
1139
1140 if (DEVICE.ignore_unexpected_input[0])
1141 {
1142 p = DEVICE.ignore_unexpected_input;
1143 while (*p && !result)
1144 {
1145 if (strstr(answer, p))
1146 result = 1;
1147 p = strchr(p, 0) + 1;
1148 }
1149 }
1150
1151 return result;
1152 }
1153
1154 // 3.1beta7: Not waiting any answer if answer is NULL. Return value is then 1/0.
1155 // 3.1.5: In case of timeout return value is -2.
1156
put_command(char * command,char * answer,int max,char * timeout_count,char * expect)1157 int put_command(char *command, char *answer, int max, char *timeout_count, char *expect)
1158 {
1159
1160 return put_command0(command, answer, max, timeout_count, expect, 0);
1161 }
1162
put_command0(char * command,char * answer,int max,char * timeout_count,char * expect,int silent)1163 int put_command0(char *command, char *answer, int max, char *timeout_count, char *expect, int silent)
1164 {
1165 char loganswer[SIZE_LOG_LINE];
1166 time_t start_time; // 3.1.16beta2: Changed timeout counter to use time(0).
1167 regex_t re;
1168 int got_timeout = 0;
1169 int regex_allocated = 0;
1170 int timeout;
1171 int i;
1172 static unsigned long long last_command_ended = 0;
1173 int last_length;
1174 // 3.1.16beta:
1175 unsigned long long got_answer;
1176 unsigned long long write_started;
1177
1178 if (DEVICE.communication_delay > 0)
1179 if (last_command_ended)
1180 usleep_until(last_command_ended +DEVICE.communication_delay *1000);
1181
1182 // compile regular expressions
1183 if (expect && expect[0])
1184 {
1185 if (regcomp(&re, expect, REG_EXTENDED|REG_NOSUB) != 0)
1186 {
1187 fprintf(stderr, "Programming error: Expected answer %s is not a valid regepr\n", expect);
1188 writelogfile(LOG_CRIT, 1, "Programming error: Expected answer %s is not a valid regepr", expect);
1189 exit(1);
1190 }
1191 regex_allocated = 1;
1192 }
1193
1194 // 3.1.5: Detect and handle routed message. Detect unexpected input.
1195 if ((DEVICE.incoming && DEVICE.detect_message_routing) || DEVICE.detect_unexpected_input)
1196 {
1197 if (log_read_timing)
1198 writelogfile(LOG_DEBUG, 0, "Detecting%s%s",
1199 (DEVICE.incoming && DEVICE.detect_message_routing)? " message_routing" : "",
1200 (DEVICE.detect_unexpected_input)? " unexpected_input" : "");
1201
1202 *loganswer = 0;
1203 do
1204 {
1205 i = strlen(loganswer);
1206 read_from_modem(loganswer, sizeof(loganswer), 2);
1207 }
1208 while (strlen(loganswer) > (size_t)i);
1209
1210 i = 0;
1211 if (DEVICE.incoming && DEVICE.detect_message_routing)
1212 i = detect_routed_message(loganswer);
1213
1214 if (!i && *loganswer && DEVICE.detect_unexpected_input)
1215 {
1216 if (!log_unmodified)
1217 {
1218 cutspaces(loganswer);
1219 cut_emptylines(loganswer);
1220
1221 if (log_single_lines)
1222 change_crlf(loganswer, ' ');
1223 }
1224
1225 if (*loganswer)
1226 {
1227 // Some modems send unsolicited result code even when status report is stored for future
1228 // reading. This and SMS-DELIVER indication is not logged.
1229 if (!strstr(loganswer, "+CDSI:") && !strstr(loganswer, "+CMTI:"))
1230 if (!(strstr(loganswer, "+CLIP:") && DEVICE.phonecalls == 2))
1231 if (!(strstr(loganswer, "+CREG:") && get_loglevel() >= DEVICE.loglevel_lac_ci)) // 3.1.14.
1232 if (!ignore_unexpected_input(loganswer)) // 3.1.16beta2.
1233 writelogfile(LOG_ERR, DEVICE.unexpected_input_is_trouble, "Unexpected input: %s", loganswer);
1234
1235 if (handlephonecall_clip(loganswer) != 1)
1236 if (strstr(loganswer, "RING") && DEVICE.phonecalls != 2)
1237 do_hangup(loganswer);
1238 }
1239 }
1240 }
1241
1242 // clean input buffer
1243 // It seems that this command does not do anything because actually it
1244 // does not clear the input buffer.
1245 tcflush(modem_handle, TCIFLUSH);
1246
1247 // 3.1.16beta:
1248 write_started = time_usec();
1249
1250 // send command
1251 if (write_to_modem(command, 30, 1, 0) == 0)
1252 {
1253 t_sleep(errorsleeptime);
1254 // Free memory used by regexp
1255 if (regex_allocated)
1256 regfree(&re);
1257
1258 last_command_ended = time_usec();
1259
1260 return 0;
1261 }
1262
1263 if (!answer)
1264 {
1265 if (!silent)
1266 writelogfile(LOG_DEBUG, 0, "Command is sent");
1267 }
1268 else
1269 {
1270 // 3.1.16beta:
1271 put_command_sent = time_usec();
1272
1273 // read_timeout is in seconds.
1274 if (!timeout_count)
1275 timeout = 0;
1276 else
1277 timeout = DEVICE.read_timeout * get_read_timeout(timeout_count);
1278
1279 if (!silent)
1280 {
1281 char tmp[64] = {0};
1282
1283 if (log_response_time)
1284 snprintf(tmp, sizeof(tmp), "time %i ms ", (int)((put_command_sent - write_started) / 1000));
1285
1286 writelogfile(LOG_DEBUG, 0, "%sCommand is sent, waiting for the answer. (%i)", tmp, timeout);
1287 }
1288
1289 // 3.1.16beta2: Give some time to modem, before start reading (read_delay).
1290 if (DEVICE.read_delay > 0)
1291 {
1292 if (log_read_timing)
1293 writelogfile(LOG_DEBUG, 0, "Spending read_delay (%i ms)", DEVICE.read_delay);
1294 usleep_until(time_usec() + DEVICE.read_delay * 1000);
1295 }
1296
1297 // wait for the modem-answer
1298 answer[0] = 0;
1299 got_timeout = 1;
1300 last_length = 0;
1301 start_time = time(0);
1302
1303 do
1304 {
1305 if (regex_allocated)
1306 read_from_modem0(answer, max, 2, &re, expect);
1307 else
1308 read_from_modem(answer, max, 2);
1309
1310 // check if it's the expected answer
1311 if (expect && expect[0] && (regexec(&re, answer, (size_t) 0, NULL, 0) == 0))
1312 {
1313 got_timeout = 0;
1314 put_command_timeouts = 0;
1315 break;
1316 }
1317
1318 // 3.1.1: Some modem does not give "OK" in the answer for CPMS:
1319 // +CPMS: "SM",0,30,"SM",0,30,"SM",0,30
1320 if (strstr(answer, "+CPMS:"))
1321 {
1322 int i = 0;
1323 char *p = answer;
1324
1325 while ((p = strchr(p +1, ',')))
1326 i++;
1327
1328 if (i >= 8)
1329 {
1330 // 8 commas is enough
1331 got_timeout = 0;
1332 put_command_timeouts = 0;
1333 break;
1334 }
1335 }
1336 // ------------------------------------------------------------
1337
1338 // 3.1.12: If got something from the modem, do not count timeout:
1339 i = strlen(answer);
1340 if (i != last_length)
1341 {
1342 last_length = i;
1343 start_time = time(0);
1344 }
1345 }
1346 // repeat until timeout
1347 while (time(0) - start_time < timeout);
1348
1349 // 3.1.16beta:
1350 got_answer = time_usec();
1351
1352 if (got_timeout)
1353 {
1354 put_command_timeouts++;
1355
1356 // 3.1.16beta:
1357 //if (expect && expect[0])
1358 // writelogfile(LOG_DEBUG, 1, "put_command expected %s, timeout occurred. %i.", expect, put_command_timeouts);
1359 if (expect && expect[0])
1360 {
1361 if (!terminate)
1362 writelogfile(LOG_DEBUG, 1, "%s answer, put_command expected %s, timeout occurred. %i.", (*answer)? "Incorrect" : "No", expect, put_command_timeouts);
1363 else
1364 writelogfile(LOG_DEBUG, 1, "%s answer, put_command expected %s, process is terminating. %i.", (*answer)? "Incorrect" : "No", expect, put_command_timeouts);
1365 }
1366 }
1367
1368 if (DEVICE.incoming && DEVICE.detect_message_routing)
1369 detect_routed_message(answer);
1370
1371 // 3.1.5: Some modems (like Westermo GDW-11) start answer with extra <CR><LF>, check and remove it:
1372 while (!got_timeout && !strncmp(answer, "\r\n", 2))
1373 strcpyo(answer, answer +2);
1374
1375 // 3.1.4: error explanation should be included in the answer.
1376 if (!got_timeout && strstr(answer, "ERROR"))
1377 {
1378 char *p;
1379
1380 p = get_gsm_error(answer);
1381 if (*p)
1382 if (max /*sizeof(answer)*/ -strlen(answer) > strlen(p) +3)
1383 sprintf(strchr(answer, 0), " (%s)", p);
1384 }
1385
1386 snprintf(loganswer, sizeof(loganswer), "%s", answer);
1387
1388 if (!log_unmodified)
1389 {
1390 cutspaces(loganswer);
1391 cut_emptylines(loganswer);
1392
1393 if (log_single_lines)
1394 change_crlf(loganswer, ' ');
1395 }
1396
1397 // 3.1.16beta:
1398 //writelogfile(LOG_DEBUG, 0, "<- %s", loganswer);
1399 if (log_response_time)
1400 {
1401 char tmp[64];
1402
1403 snprintf(tmp, sizeof(tmp), "time %i ms ", (int)((got_answer - put_command_sent) / 1000));
1404 writelogfile(LOG_DEBUG, 0, "%s<- %s", tmp, loganswer);
1405 }
1406 else
1407 writelogfile(LOG_DEBUG, 0, "<- %s", loganswer);
1408
1409 // 3.1.12: Check if the answer contains a phonecall:
1410 if (DEVICE.detect_unexpected_input)
1411 {
1412 if (handlephonecall_clip(loganswer) != 1)
1413 if (strstr(loganswer, "RING") && DEVICE.phonecalls != 2)
1414 do_hangup(loganswer);
1415 }
1416 }
1417
1418 // Free memory used by regexp
1419 if (regex_allocated)
1420 regfree(&re);
1421
1422 last_command_ended = time_usec();
1423
1424 if (got_timeout)
1425 return -2;
1426 if (answer)
1427 return strlen(answer);
1428 return 1;
1429 }
1430
setmodemparams()1431 void setmodemparams()
1432 {
1433 struct termios newtio;
1434 int baudrate;
1435
1436 if (DEVICE_IS_SOCKET)
1437 return;
1438
1439 bzero(&newtio, sizeof(newtio));
1440 newtio.c_cflag = CS8 | CLOCAL | CREAD | O_NDELAY | O_NONBLOCK;
1441 if (DEVICE.rtscts)
1442 newtio.c_cflag |= CRTSCTS;
1443 newtio.c_iflag = IGNPAR;
1444 newtio.c_oflag = 0;
1445 newtio.c_lflag = 0;
1446 newtio.c_cc[VTIME] = 0;
1447 newtio.c_cc[VMIN] = 0;
1448
1449 baudrate = DEVICE.baudrate;
1450
1451 switch (baudrate)
1452 {
1453 #ifdef B50
1454 case 50: baudrate = B50; break;
1455 #endif
1456 #ifdef B75
1457 case 75: baudrate = B75; break;
1458 #endif
1459 #ifdef B110
1460 case 110: baudrate = B110; break;
1461 #endif
1462 #ifdef B134
1463 case 134: baudrate = B134; break;
1464 #endif
1465 #ifdef B150
1466 case 150: baudrate = B150; break;
1467 #endif
1468 #ifdef B200
1469 case 200: baudrate = B200; break;
1470 #endif
1471 case 300: baudrate = B300; break;
1472 #ifdef B600
1473 case 600: baudrate = B600; break;
1474 #endif
1475 case 1200: baudrate = B1200; break;
1476 #ifdef B1800
1477 case 1800: baudrate = B1800; break;
1478 #endif
1479 case 2400: baudrate = B2400; break;
1480 #ifdef B4800
1481 case 4800: baudrate = B4800; break;
1482 #endif
1483 case 9600: baudrate = B9600; break;
1484 case 19200: baudrate = B19200; break;
1485 case 38400: baudrate = B38400; break;
1486 #ifdef B57600
1487 case 57600: baudrate = B57600; break;
1488 #endif
1489 #ifdef B115200
1490 case 115200: baudrate = B115200; break;
1491 #endif
1492 #ifdef B230400
1493 case 230400: baudrate = B230400; break;
1494 #endif
1495 #ifdef B460800
1496 case 460800: baudrate = B460800; break;
1497 #endif
1498 #ifdef B500000
1499 case 500000: baudrate = B500000; break;
1500 #endif
1501 #ifdef B576000
1502 case 576000: baudrate = B576000; break;
1503 #endif
1504 #ifdef B921600
1505 case 921600: baudrate = B921600; break;
1506 #endif
1507 #ifdef B1000000
1508 case 1000000: baudrate = B1000000; break;
1509 #endif
1510 #ifdef B1152000
1511 case 1152000: baudrate = B1152000; break;
1512 #endif
1513 #ifdef B1500000
1514 case 1500000: baudrate = B1500000; break;
1515 #endif
1516 #ifdef B2000000
1517 case 2000000: baudrate = B2000000; break;
1518 #endif
1519 #ifdef B2500000
1520 case 2500000: baudrate = B2500000; break;
1521 #endif
1522 #ifdef B3000000
1523 case 3000000: baudrate = B3000000; break;
1524 #endif
1525 #ifdef B3500000
1526 case 3500000: baudrate = B3500000; break;
1527 #endif
1528 #ifdef B4000000
1529 case 4000000: baudrate = B4000000; break;
1530 #endif
1531
1532 default:
1533 writelogfile(LOG_ERR, 0, "Baudrate %d not supported, using 19200", baudrate);
1534 baudrate = B19200;
1535 DEVICE.baudrate = 19200;
1536 }
1537 cfsetispeed(&newtio, baudrate);
1538 cfsetospeed(&newtio, baudrate);
1539 tcsetattr(modem_handle, TCSANOW, &newtio);
1540 }
1541
initmodem(char * new_smsc,int receiving)1542 int initmodem(char *new_smsc, int receiving)
1543 {
1544 char command[100];
1545 char answer[500];
1546 int retries=0;
1547 char *p;
1548
1549 static int reading_checked = 0;
1550
1551 STATISTICS->last_init = time(0);
1552
1553 // 3.1beta7: terminating is only checked in case of errors.
1554
1555 // -----------------------------------------------------------------------------------------------
1556 writelogfile(LOG_INFO, 0, "Checking if modem is ready");
1557
1558 // 3.1.16beta: If wakeup_init is defined, send it to the modem:
1559 if (DEVICE.wakeup_init[0])
1560 {
1561 writelogfile(LOG_INFO, 0, "Sending wakeup_init (%s)", DEVICE.wakeup_init);
1562 snprintf(command, sizeof(command), "%s%s", DEVICE.wakeup_init, (DEVICE_IS_SOCKET && DEVICE.telnet_crlf)? "\r\n" : "\n");
1563 put_command(command, 0, 0, "default", 0);
1564 usleep_until(time_usec() + 100000);
1565 read_from_modem(answer, sizeof(answer), 2);
1566 }
1567
1568 // 3.1.7: After being idle, some modems do not answer to the first AT command.
1569 // With BenQ M32, there can be OK answer, but in many times there is not.
1570 // To avoid error messages, first send AT and read the answer if it's available.
1571 if (DEVICE.needs_wakeup_at)
1572 {
1573 put_command("AT\r", 0, 0, "default", 0);
1574 usleep_until(time_usec() + 100000);
1575 read_from_modem(answer, sizeof(answer), 2);
1576 }
1577
1578 if (terminate)
1579 return 7;
1580
1581 // 3.1.16beta: Allow numeric result codes at this stage.
1582
1583 retries=0;
1584 do
1585 {
1586 flush_smart_logging();
1587
1588 retries++;
1589 //put_command("AT\r", answer, sizeof(answer), 1, EXPECT_OK_ERROR);
1590 put_command("AT\r", answer, sizeof(answer), "default", EXPECT_OK_ERROR_0_4);
1591 //if (!strstr(answer, "OK") && !strstr(answer, "ERROR"))
1592 if (!is_ok_error_0_4_answer(answer))
1593 {
1594 if (terminate)
1595 return 7;
1596
1597 // if Modem does not answer, try to send a PDU termination character
1598 //put_command("\x1A\r", answer, sizeof(answer), 1, EXPECT_OK_ERROR);
1599 put_command("\x1A\r", answer, sizeof(answer), "default", EXPECT_OK_ERROR_0_4);
1600
1601 if (terminate)
1602 return 7;
1603 }
1604
1605 // 3.1.7: If it looks like modem does not respond, try to close and open the port:
1606 //if (retries >= 5 && !strstr(answer, "OK"))
1607 if (retries >= 5 && !is_ok_0_answer(answer))
1608 {
1609 int save_timeouts;
1610 int opened;
1611
1612 // 3.1.16beta: Keep the value of timeouts:
1613 save_timeouts = put_command_timeouts;
1614
1615 try_closemodem(1);
1616 t_sleep(1);
1617
1618 // If open fails, nothing can be done. Error is already logged. Will return 1.
1619 //if (!try_openmodem())
1620 // break;
1621 opened = try_openmodem();
1622 put_command_timeouts = save_timeouts;
1623 if (!opened)
1624 break;
1625 }
1626 }
1627 //while (retries <= 10 && !strstr(answer,"OK"));
1628 while (retries <= 10 && !is_ok_0_answer(answer));
1629
1630 //if (!strstr(answer,"OK"))
1631 if (!is_ok_0_answer(answer))
1632 {
1633 // 3.1: more detailed error message:
1634 p = get_gsm_error(answer);
1635 // 3.1.5:
1636 writelogfile0(LOG_ERR, 1, tb_sprintf("Modem is not ready to answer commands%s%s (Timeouts: %i)",
1637 (*p)? ", " : "", p, put_command_timeouts));
1638 alarm_handler0(LOG_ERR, tb);
1639 return 1;
1640 }
1641
1642 // 3.1.16beta: Switch modem to use verbose mode if necessary:
1643 if (terminate)
1644 return 7;
1645
1646 if (!is_ok_answer(answer))
1647 {
1648 put_command("ATV1\r", answer, sizeof(answer), "default", EXPECT_OK_ERROR);
1649 if (is_ok_answer(answer))
1650 writelogfile(LOG_NOTICE, 0, "Switched modem to use verbose result codes");
1651 else
1652 writelogfile(LOG_ERR, 1, "Failed to switch modem to use verbose result codes");
1653 }
1654
1655 // -----------------------------------------------------------------------------------------------
1656 if (terminate)
1657 return 7;
1658
1659 if (DEVICE.check_sim) // 3.1.21
1660 {
1661 char reset_cmd[sizeof(DEVICE.check_sim_reset)];
1662 int sim_ok = 0;
1663 char save_status = STATISTICS->status;
1664
1665 writelogfile(LOG_INFO, 0, "Checking the SIM");
1666
1667 sprintf(command, "%s\r", (DEVICE.check_sim_cmd[0])? DEVICE.check_sim_cmd : "AT+CPIN?");
1668
1669 if (!strcasecmp(DEVICE.check_sim_reset, "RADIO_OFF_ON"))
1670 strcpy(reset_cmd, "AT+CFUN=0;+CFUN=1");
1671 else
1672 if (!strcasecmp(DEVICE.check_sim_reset, "RADIO_OFF_ON_SLOW"))
1673 strcpy(reset_cmd, "AT+CFUN=0[3]AT+CFUN=1[5]");
1674 else
1675 strcpy(reset_cmd, DEVICE.check_sim_reset);
1676
1677 retries = 0;
1678
1679 while (DEVICE.check_sim_retries < 0 || retries <= DEVICE.check_sim_retries)
1680 {
1681 if (try_openmodem())
1682 {
1683 if (retries > 0 && *reset_cmd)
1684 {
1685 char cmd[sizeof(command)];
1686 char *p1, *p2;
1687
1688 writelogfile(LOG_INFO, 0, "Trying to reset the modem");
1689
1690 p1 = reset_cmd;
1691
1692 while (*p1)
1693 {
1694 if (*p1 == '[')
1695 {
1696 if ((p2 = strchr(p1, ']')))
1697 {
1698 writelogfile(LOG_DEBUG, 0, "Sleeping %i sec", atoi(p1 + 1));
1699
1700 if (t_sleep(atoi(p1 + 1)))
1701 return 7;
1702
1703 p1 = p2 + 1;
1704 continue;
1705 }
1706 else
1707 break;
1708 }
1709
1710 if ((p2 = strchr(p1, '[')))
1711 {
1712 memset(cmd, 0, sizeof(cmd));
1713 strncpy(cmd, p1, (int)(p2 - p1));
1714 }
1715 else
1716 strcpy(cmd, p1);
1717
1718 p1 += strlen(cmd);
1719 strcat(cmd, "\r");
1720 put_command(cmd, answer, sizeof(answer), "init", EXPECT_OK_ERROR);
1721 }
1722 }
1723
1724 put_command(command, answer, sizeof(answer), "init", EXPECT_OK_ERROR);
1725
1726 if (!strstr(answer, "ERROR"))
1727 {
1728 sim_ok = 1;
1729 break;
1730 }
1731 }
1732
1733 retries++;
1734 STATISTICS->status = 't';
1735
1736 if (modem_handle >= 0)
1737 tb_sprintf("Check SIM returned ERROR, try: %i", retries);
1738 else
1739 tb_sprintf("Check SIM could not open the modem, try: %i", retries);
1740
1741 writelogfile0(LOG_ERR, 1, tb);
1742 alarm_handler0(LOG_ERR, tb);
1743
1744 if (DEVICE.check_sim_retries < 0 || retries <= DEVICE.check_sim_retries)
1745 {
1746 if (DEVICE.check_sim_keep_open == 0)
1747 try_closemodem(1);
1748
1749 writelogfile(LOG_DEBUG, 0, "Sleeping %i sec before retrying", DEVICE.check_sim_wait);
1750 if (t_sleep(DEVICE.check_sim_wait))
1751 return 7;
1752 }
1753 }
1754
1755 if (!sim_ok)
1756 {
1757 writelogfile0(LOG_ERR, 1, tb_sprintf("Check SIM failed and not retrying anymore"));
1758 alarm_handler0(LOG_ERR, tb);
1759 abnormal_termination(0);
1760 }
1761
1762 STATISTICS->status = save_status;
1763
1764 if (DEVICE.check_sim == 2)
1765 DEVICE.check_sim = 0;
1766 }
1767
1768 // -----------------------------------------------------------------------------------------------
1769 if (terminate)
1770 return 7;
1771
1772 // 3.1.21: Originally pre_init was containing "echo off" and "CMEE=1". If pre_init
1773 // is set to no, CLIP=1 and/or CREG=2 are still sent if required.
1774
1775 if (DEVICE.pre_init > 0 ||
1776 DEVICE.phonecalls == 2 || get_loglevel() >= DEVICE.loglevel_lac_ci)
1777 {
1778 // 3.1.21: Do not concatenate ATE0 and extended commands in pre_initialization.
1779
1780 writelogfile(LOG_INFO, 0, "Pre-initializing modem");
1781
1782 if (DEVICE.pre_init > 0)
1783 put_command("ATE0\r", answer, sizeof(answer), "preinit", EXPECT_OK_ERROR);
1784
1785 *command = 0;
1786
1787 if (DEVICE.pre_init > 0)
1788 strcpy(command, "AT+CMEE=1");
1789
1790 if (DEVICE.phonecalls == 2)
1791 sprintf(strchr(command, 0), "%s+CLIP=1", (*command)? ";" : "AT");
1792
1793 if (get_loglevel() >= DEVICE.loglevel_lac_ci)
1794 sprintf(strchr(command, 0), "%s+CREG=2", (*command)? ";" : "AT");
1795
1796 strcat(command, "\r");
1797
1798 put_command(command, answer, sizeof(answer), "preinit", EXPECT_OK_ERROR);
1799
1800 if (!strstr(answer,"OK"))
1801 writelogfile(LOG_ERR, 1, "Modem did not accept the pre-init string");
1802 }
1803
1804 // -----------------------------------------------------------------------------------------------
1805 if (terminate)
1806 return 7;
1807
1808 // 3.1.1:
1809 //if (pin[0])
1810 if (strcasecmp(DEVICE.pin, "ignore"))
1811 {
1812 // 3.1.20: Accept OK answer for PIN:
1813 //char *cpin_expect = "(READY)|( PIN)|( PUK)|(ERROR)"; // Previously: "(\\+CPIN:.*OK)|(ERROR)"
1814 char *cpin_expect = "(OK)|(READY)|( PIN)|( PUK)|(ERROR)";
1815
1816 writelogfile(LOG_INFO, 0, "Checking if modem needs PIN");
1817 // 3.1.5: timeout from 50 to 100:
1818 put_command("AT+CPIN?\r", answer, sizeof(answer), "askpin", cpin_expect);
1819
1820 // 3.1.7: Some modems include quotation marks in the answer, like +CPIN: "READY".
1821 while ((p = strchr(answer, '"')))
1822 strcpyo(p, p +1);
1823
1824 // 3.1.12: Allow "echo on":
1825 if ((p = strstr(answer, "+CPIN:")))
1826 if (p > answer)
1827 strcpyo(answer, p);
1828
1829 // 3.1.7: Some modems may leave a space away after +CPIN:
1830 if (!strncmp(answer, "+CPIN:", 6) && strncmp(answer, "+CPIN: ", 7))
1831 {
1832 if ((p = strdup(answer)))
1833 {
1834 snprintf(answer, sizeof(answer), "+CPIN: %s", p + 6);
1835 free(p);
1836 }
1837 }
1838
1839 if (strstr(answer,"+CPIN: SIM PIN") && !strstr(answer, "PIN2"))
1840 {
1841 // 3.1.1:
1842 if (DEVICE.pin[0] == 0)
1843 writelogfile(LOG_NOTICE, 1, "Modem needs PIN, but it's not defined for this modem");
1844 else
1845 {
1846 writelogfile(LOG_NOTICE, 0, "Modem needs PIN, entering PIN...");
1847 sprintf(command, "AT+CPIN=\"%s\"\r", DEVICE.pin);
1848 put_command(command, answer, sizeof(answer), "enterpin", EXPECT_OK_ERROR);
1849 if (strstr(answer, "ERROR"))
1850 {
1851 p = get_gsm_error(answer);
1852 writelogfile(LOG_NOTICE, 1, "PIN entering: modem answered %s%s%s",
1853 change_crlf(cut_emptylines(cutspaces(answer)), ' '), (*p)? ", " : "", p);
1854 }
1855 else
1856 // After a PIN is entered, some modems need some time before next commands are processed.
1857 if (DEVICE.pinsleeptime > 0)
1858 {
1859 writelogfile(LOG_INFO, 0, "Spending sleep time after PIN entering (%i sec)", DEVICE.pinsleeptime);
1860 t_sleep(DEVICE.pinsleeptime);
1861 }
1862
1863 put_command("AT+CPIN?\r", answer, sizeof(answer), "askpin", cpin_expect);
1864 if (strstr(answer,"+CPIN: SIM PIN") && !strstr(answer, "PIN2"))
1865 {
1866 writelogfile0(LOG_ERR, 1, tb_sprintf("Modem did not accept this PIN"));
1867 alarm_handler0(LOG_ERR, tb);
1868 abnormal_termination(0);
1869 }
1870 // 3.1.20: Accept OK answer for PIN:
1871 if (strstr(answer,"+CPIN: READY") || strstr(answer, "OK"))
1872 writelogfile(LOG_INFO, 0, "PIN Ready");
1873 }
1874 }
1875
1876 if (strstr(answer,"+CPIN: SIM PUK"))
1877 {
1878 writelogfile0(LOG_CRIT, 1, tb_sprintf("Your SIM is locked. Unlock it manually"));
1879 alarm_handler0(LOG_CRIT, tb);
1880 abnormal_termination(0);
1881 }
1882
1883 // 3.1.20: Accept OK answer for PIN:
1884 if (!strstr(answer, "+CPIN: READY") && !strstr(answer, "OK"))
1885 {
1886 p = get_gsm_error(answer);
1887 writelogfile0(LOG_CRIT, 1, tb_sprintf("PIN handling: expected READY or OK, modem answered %s%s%s",
1888 change_crlf(cut_emptylines(cutspaces(answer)), ' '), (*p)? ", " : "", p));
1889 alarm_handler0(LOG_CRIT, tb);
1890 abnormal_termination(0);
1891 }
1892
1893 // 3.1.1:
1894 if (DEVICE.pin[0] == 0)
1895 strcpy(DEVICE.pin, "ignore");
1896 }
1897
1898 // -----------------------------------------------------------------------------------------------
1899 if (terminate)
1900 return 7;
1901
1902 if (DEVICE.initstring[0] || DEVICE.initstring2[0])
1903 writelogfile(LOG_INFO, 0, "Initializing modem");
1904
1905 if (DEVICE.initstring[0])
1906 {
1907 retries=0;
1908 do
1909 {
1910 retries++;
1911 put_command(DEVICE.initstring, answer, sizeof(answer), "init", EXPECT_OK_ERROR);
1912 if (!strstr(answer, "OK"))
1913 if (retries < 2)
1914 if (t_sleep(errorsleeptime))
1915 return 7;
1916 }
1917 while (retries < 2 && !strstr(answer,"OK"));
1918 if (strstr(answer,"OK")==0)
1919 {
1920 // 3.1: more detailed error message:
1921 p = get_gsm_error(answer);
1922 writelogfile0(LOG_ERR, 1, tb_sprintf("Modem did not accept the init string%s%s", (*p)? ", " : "", p));
1923 alarm_handler0(LOG_ERR, tb);
1924 return 3;
1925 }
1926 }
1927
1928 if (DEVICE.initstring2[0])
1929 {
1930 retries=0;
1931 do
1932 {
1933 retries++;
1934 put_command(DEVICE.initstring2, answer, sizeof(answer), "init", EXPECT_OK_ERROR);
1935 if (strstr(answer, "ERROR"))
1936 if (retries < 2)
1937 if (t_sleep(errorsleeptime))
1938 return 7;
1939 }
1940 while (retries < 2 && !strstr(answer,"OK"));
1941 if (!strstr(answer,"OK"))
1942 {
1943 // 3.1: more detailed error message:
1944 p = get_gsm_error(answer);
1945 writelogfile0(LOG_ERR, 1, tb_sprintf("Modem did not accept the second init string%s%s", (*p)? ", " : "", p));
1946 alarm_handler0(LOG_ERR, tb);
1947 return 3;
1948 }
1949 // 3.1.5:
1950 else
1951 explain_csq(LOG_INFO, 0, answer, DEVICE.signal_quality_ber_ignore);
1952 }
1953
1954 // -----------------------------------------------------------------------------------------------
1955 if (terminate)
1956 return 7;
1957
1958 if (DEVICE.status_signal_quality == 1 ||
1959 (DEVICE.status_signal_quality == -1 && status_signal_quality == 1))
1960 {
1961 retries=0;
1962 do
1963 {
1964 retries++;
1965 put_command("AT+CSQ\r", answer, sizeof(answer), "csq", EXPECT_OK_ERROR);
1966 if (!strstr(answer, "OK"))
1967 if (retries < 2)
1968 if (t_sleep(errorsleeptime))
1969 return 7;
1970 }
1971 while (retries < 2 && !strstr(answer,"OK"));
1972
1973 // 3.1.12: Allow "echo on":
1974 //if (!strncmp(answer, "+CSQ:", 5))
1975 if ((p = strstr(answer, "+CSQ:")))
1976 {
1977 //STATISTICS->ssi = atoi(answer +5);
1978 STATISTICS->ssi = atoi(p +5);
1979 //if ((p = strchr(answer, ',')))
1980 if ((p = strchr(p, ',')))
1981 STATISTICS->ber = atoi(p +1);
1982 else
1983 STATISTICS->ber = -2;
1984
1985 // 3.1.7: Explain signal quality to the log:
1986 explain_csq(LOG_INFO, 0, answer, DEVICE.signal_quality_ber_ignore);
1987 }
1988 else
1989 {
1990 STATISTICS->ssi = -2;
1991 STATISTICS->ber = -2;
1992 }
1993 }
1994
1995 // -----------------------------------------------------------------------------------------------
1996 if (terminate)
1997 return 7;
1998
1999 // With check_network value 2 network is NOT checked when initializing for receiving:
2000 if (DEVICE.check_network == 1 ||
2001 (DEVICE.check_network == 2 && !receiving))
2002 {
2003 switch (wait_network_registration(1, 100))
2004 {
2005 case -1:
2006 return 4;
2007
2008 case -2:
2009 return 7;
2010 }
2011 }
2012
2013 // -----------------------------------------------------------------------------------------------
2014 if (terminate)
2015 return 7;
2016
2017 if (DEVICE.select_pdu_mode) // 3.1.16beta2.
2018 {
2019 writelogfile(LOG_INFO, 0, "Selecting PDU mode");
2020 strcpy(command,"AT+CMGF=0\r");
2021 retries=0;
2022 do
2023 {
2024 retries++;
2025 put_command(command, answer, sizeof(answer), "cmgf", EXPECT_OK_ERROR);
2026 if (!strstr(answer, "OK"))
2027 if (retries < 2)
2028 if (t_sleep(errorsleeptime))
2029 return 7;
2030 }
2031 while (retries < 2 && !strstr(answer,"OK"));
2032 if (strstr(answer,"ERROR"))
2033 {
2034 // 3.1: more detailed error message:
2035 p = get_gsm_error(answer);
2036 writelogfile0(LOG_ERR, 1, tb_sprintf("Error: Modem did not accept mode selection%s%s", (*p)? ", " : "", p));
2037 alarm_handler0(LOG_ERR, tb);
2038 return 5;
2039 }
2040 }
2041
2042 // -----------------------------------------------------------------------------------------------
2043 if (terminate)
2044 return 7;
2045
2046 if (!DEVICE.smsc_pdu && (new_smsc[0] || DEVICE.smsc[0]))
2047 {
2048 writelogfile(LOG_INFO, 0, "Changing SMSC");
2049
2050 // 3.1.7: clean + character(s) from the setting:
2051 //sprintf(command, "AT+CSCA=\"+%s\"\r", (new_smsc[0]) ? new_smsc : DEVICE.smsc);
2052 snprintf(answer, sizeof(answer), "%s", (new_smsc[0]) ? new_smsc : DEVICE.smsc);
2053 while (*answer == '+')
2054 strcpyo(answer, answer + 1);
2055 sprintf(command, "AT+CSCA=\"+%s\"\r", answer);
2056
2057 retries=0;
2058 do
2059 {
2060 retries++;
2061 put_command(command, answer, sizeof(answer), "csca", EXPECT_OK_ERROR);
2062 if (!strstr(answer, "OK"))
2063 if (retries < 2)
2064 if (t_sleep(errorsleeptime))
2065 return 7;
2066 }
2067 while (retries < 2 && !strstr(answer,"OK"));
2068 if (strstr(answer,"ERROR"))
2069 {
2070 // 3.1: more detailed error message:
2071 p = get_gsm_error(answer);
2072 writelogfile0(LOG_ERR, 1, tb_sprintf("Error: Modem did not accept SMSC%s%s", (*p)? ", " : "", p));
2073 alarm_handler0(LOG_ERR, tb);
2074 return 6;
2075 }
2076 }
2077
2078 // -----------------------------------------------------------------------------------------------
2079 if (terminate)
2080 return 7;
2081
2082 // 3.1.16beta: Ask IMEI once.
2083 if (DEVICE.imei[0] == 0)
2084 {
2085 sprintf(command,"AT+CGSN\r");
2086 put_command(command, answer, sizeof(answer), "default", EXPECT_OK_ERROR);
2087
2088 if (!strstr(answer, "ERROR"))
2089 while (answer[0] && !isdigitc(answer[0]))
2090 strcpyo(answer, answer +1);
2091
2092 if ((p = strstr(answer, "OK")))
2093 *p = 0;
2094 cut_ctrl(answer);
2095 cutspaces(answer);
2096 snprintf(DEVICE.imei, sizeof(DEVICE.imei), "%s", answer);
2097 writelogfile(LOG_NOTICE, 0, "IMEI: %s", DEVICE.imei);
2098 }
2099
2100 // -----------------------------------------------------------------------------------------------
2101 if (terminate)
2102 return 7;
2103
2104 // 3.1beta7, 3.0.9: International Mobile Subscriber Identity is asked once.
2105 if (DEVICE.identity[0] == 0)
2106 {
2107 sprintf(command,"AT+CIMI\r");
2108 put_command(command, DEVICE.identity, SIZE_IDENTITY, "default", EXPECT_OK_ERROR);
2109
2110 // 3.1.5: do not remove ERROR text:
2111 if (!strstr(DEVICE.identity, "ERROR"))
2112 while (DEVICE.identity[0] && !isdigitc(DEVICE.identity[0]))
2113 strcpyo(DEVICE.identity, DEVICE.identity +1);
2114
2115 // 3.1beta7: If CIMI is not supported, try CGSN (Product Serial Number)
2116 // TODO: is IMSI title still good?
2117 if (strstr(DEVICE.identity, "ERROR"))
2118 strcpy(DEVICE.identity, DEVICE.imei);
2119
2120 if (!strstr(DEVICE.identity, "ERROR"))
2121 {
2122 if ((p = strstr(DEVICE.identity, "OK")))
2123 *p = 0;
2124 cut_ctrl(DEVICE.identity);
2125 cutspaces(DEVICE.identity);
2126 writelogfile(LOG_NOTICE, 0, "IMSI: %s", DEVICE.identity);
2127 }
2128 else
2129 writelogfile(LOG_NOTICE, 1, "IMSI/CGSN not supported");
2130 }
2131
2132 // -----------------------------------------------------------------------------------------------
2133 if (terminate)
2134 return 7;
2135
2136 // 3.1.5: Check once if reading of messages is not supported:
2137 // 3.1.7: Do not check if not reading incoming messages:
2138 if (DEVICE.incoming && !reading_checked)
2139 {
2140 reading_checked = 1;
2141 writelogfile(LOG_INFO, 0, "Checking if reading of messages is supported");
2142
2143 sprintf(command,"AT+CPMS?\r");
2144 put_command(command, answer, sizeof(answer), "cpms", EXPECT_OK_ERROR);
2145
2146 if (strstr(answer, "+CPMS: ,,,,,,,,"))
2147 {
2148 sprintf(command,"AT+CPMS=?\r");
2149 put_command(command, answer, sizeof(answer), "cpms", EXPECT_OK_ERROR);
2150
2151 if (strstr(answer, "+CPMS: (),(),()"))
2152 {
2153 writelogfile0(LOG_ERR, 1, tb_sprintf("Error: Looks like your device does not support reading of messages"));
2154 alarm_handler0(LOG_ERR, tb);
2155 }
2156 }
2157 }
2158
2159 // -----------------------------------------------------------------------------------------------
2160 if (terminate)
2161 return 7;
2162
2163 // 3.1.7: Report details of device once:
2164 if (DEVICE.report_device_details)
2165 {
2166 int save_log_single_lines = log_single_lines;
2167 int i;
2168 char tmp[256];
2169 char *commands[] = {
2170 "AT+CGMI", "Manufacturer identification",
2171 "AT+CGMM", "Model identification",
2172 "AT+CGMR", "Revision identification",
2173 "AT+CNMI=?", "New message indications, list of supported modes",
2174 "AT+CNMI?", "New message indications, current settings",
2175 "AT+CPMS=?", "Preferred message storage, list of supported mem's",
2176 //"AT+CPMS?", "Preferred message storage, current mem's and counters",
2177 "AT+CPBS=?", "Phonebook storage, available mem's",
2178 //"AT+CPBS?", "Phonebook storage, current storage and counters",
2179 "AT+CMGL=?", "List messages, list of supported stat's",
2180 "AT+CMGD=?", "Delete message, list of supported values",
2181 "AT+CPAS=?", "Phone activity status, list of supported stat's",
2182 "AT+CSCS=?", "TE character set, list of supported charset's",
2183 "AT+CSCS?", "TE character set, current setting",
2184 "" // end marker
2185 };
2186
2187 DEVICE.report_device_details = 0;
2188 log_single_lines = 0;
2189 change_loglevel(LOG_DEBUG);
2190
2191 writelogfile(LOG_DEBUG, 0, "## Start of device details");
2192
2193 for (i = 0; commands[i][0]; i += 2)
2194 {
2195 if (terminate)
2196 break;
2197
2198 snprintf(tmp, sizeof(tmp), "# %s:", commands[i + 1]);
2199 writelogfile0(LOG_DEBUG, 0, tmp);
2200 sprintf(command, "%s\r", commands[i]);
2201 put_command0(command, answer, sizeof(answer), "default", EXPECT_OK_ERROR, 1);
2202 }
2203
2204 writelogfile(LOG_DEBUG, 0, "## End of device details");
2205
2206 log_single_lines = save_log_single_lines;
2207 restore_loglevel();
2208 }
2209
2210 // -----------------------------------------------------------------------------------------------
2211 // TODO: Check if AT+CMGD=? is supported.
2212
2213 if (terminate)
2214 return 7;
2215
2216 return 0;
2217 }
2218
initialize_modem_sending(char * new_smsc)2219 int initialize_modem_sending(char *new_smsc)
2220 {
2221 // 3.1.17: Check if modem is disabled here, and log it:
2222 if (DEVICE.modem_disabled)
2223 {
2224 writelogfile(LOG_DEBUG, 0, "initialize_modem_sending");
2225 return 0;
2226 }
2227
2228 return initmodem(new_smsc, 0);
2229 }
2230
initialize_modem_receiving()2231 int initialize_modem_receiving()
2232 {
2233 // 3.1.17: Check if modem is disabled here, and log it:
2234 if (DEVICE.modem_disabled)
2235 {
2236 writelogfile(LOG_DEBUG, 0, "initialize_modem_receiving");
2237 return 0;
2238 }
2239
2240 return initmodem("", 1);
2241 }
2242
2243 #ifndef DISABLE_INET_SOCKET
2244
2245 /* Start Changes by Hubert Gilch, SEP Logistik AG
2246 *
2247 * 2 functions for connecting to a socket instead of a serial device
2248 * in order to use ethernet GPRS-modems
2249 *
2250 * Code was "stolen" from interceptty by Scott W. Gifford
2251 *
2252 */
2253
inet_resolve(const char * sockname)2254 struct sockaddr_in inet_resolve(const char *sockname)
2255 {
2256 struct sockaddr_in sa;
2257 char *hostname, *netport;
2258 struct hostent *he;
2259
2260 if (!(hostname = strdup(sockname)))
2261 writelogfile(LOG_CRIT, 0, "Couldn't dup string: %s", strerror(errno));
2262
2263 netport = strchr(hostname, ':');
2264 *netport = '\0';
2265 netport++;
2266
2267 sa.sin_family = AF_INET;
2268
2269 if (!(he = gethostbyname(hostname)))
2270 writelogfile(LOG_ERR, 0, "Couldn't resolve name '%s': %s.", hostname,
2271 (h_errno == HOST_NOT_FOUND) ? "Host not found" :
2272 ((h_errno == NO_ADDRESS) || (h_errno == NO_DATA)) ? "No data available" :
2273 (h_errno == NO_RECOVERY) ? "A non-recoverable name server error occured" : (h_errno == TRY_AGAIN) ? "A temporary error occured." : "An unknown error occured");
2274
2275 memcpy(&(sa.sin_addr), he->h_addr, he->h_length);
2276
2277 #if 0
2278 if (!(se = getservbyname(netport)))
2279 writelogfile(LOG_ERR, 0, "Couldn't resolve port.");
2280
2281 host_port = htons(se->s_port);
2282 #endif
2283
2284 if (!(sa.sin_port = htons(atoi(netport))))
2285 writelogfile(LOG_ERR, 0, "Couldn't figure out port number.");
2286
2287 free(hostname);
2288
2289 return sa;
2290 }
2291
open_inet_socket(char * backend)2292 int open_inet_socket(char *backend)
2293 {
2294 struct sockaddr_in sa;
2295 int fd;
2296 int socketflags;
2297 int retries = 0;
2298
2299 sa = inet_resolve(backend + 1); // cut first character @
2300 if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 3)
2301 {
2302 tb_sprintf("Couldn't open socket: %s: %s", backend, strerror(errno));
2303 writelogfile0(LOG_ERR, 0, tb);
2304 alarm_handler0(LOG_ERR, tb);
2305 return -1;
2306 }
2307
2308 while (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) != 0)
2309 {
2310 retries++;
2311
2312 if (terminate || (DEVICE.socket_connection_retries != -1 && retries > DEVICE.socket_connection_retries))
2313 {
2314 close(fd);
2315 return (terminate)? -2 : -1;
2316 }
2317
2318 tb_sprintf("Couldn't connect socket %s, error: %s, waiting %i sec.", backend, strerror(errno), DEVICE.socket_connection_errorsleeptime);
2319
2320 if (retries - 1 == DEVICE.socket_connection_alarm_after)
2321 {
2322 writelogfile0(LOG_ERR, 0, tb);
2323 alarm_handler0(LOG_ERR, tb);
2324 }
2325 else
2326 {
2327 // Do not log the first failure:
2328 if (retries > 1)
2329 writelogfile0(LOG_INFO, 0, tb);
2330 }
2331
2332 t_sleep(DEVICE.socket_connection_errorsleeptime);
2333 }
2334
2335 socketflags = fcntl(fd, F_GETFL);
2336 fcntl(fd, F_SETFL, socketflags | O_NONBLOCK);
2337
2338 return fd;
2339 }
2340
2341 /*
2342 * End Changes by Hubert Gilch
2343 */
2344
2345 #endif
2346
openmodem()2347 int openmodem()
2348 {
2349 int retries = 0;
2350
2351 // 3.1.7:
2352 //modem_handle = open(DEVICE.device, O_RDWR | O_NOCTTY | O_NONBLOCK);
2353
2354 /*
2355 * if devicename starts with "@" it is not a serial device but
2356 * a socket, so open a socket instead a device file
2357 *
2358 * Change by Hubert Gilch, SEP Logistik AG
2359 */
2360 #ifndef DISABLE_INET_SOCKET
2361 if (DEVICE_IS_SOCKET)
2362 modem_handle = open_inet_socket(DEVICE.device);
2363 else
2364 #endif
2365 {
2366 // 3.1.12:
2367 if (DEVICE.modem_disabled)
2368 {
2369 struct stat statbuf;
2370
2371 if (stat(DEVICE.device, &statbuf) != 0)
2372 {
2373 FILE *fp;
2374
2375 if ((fp = fopen(DEVICE.device, "w")))
2376 fclose(fp);
2377 }
2378 }
2379
2380 // 3.1.7:
2381 while ((modem_handle = open(DEVICE.device, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0)
2382 {
2383 retries++;
2384
2385 if (terminate || (DEVICE.device_open_retries != -1 && retries > DEVICE.device_open_retries))
2386 break;
2387
2388 tb_sprintf("Couldn't open serial port %s, error: %s, waiting %i sec.", DEVICE.device, strerror(errno), DEVICE.device_open_errorsleeptime);
2389
2390 if (retries - 1 == DEVICE.device_open_alarm_after)
2391 {
2392 writelogfile0(LOG_ERR, 0, tb);
2393 alarm_handler0(LOG_ERR, tb);
2394 }
2395 else
2396 writelogfile0(LOG_INFO, 0, tb);
2397
2398 t_sleep(DEVICE.device_open_errorsleeptime);
2399 }
2400 }
2401
2402 if (modem_handle < 0)
2403 {
2404 if (modem_handle == -1)
2405 {
2406 writelogfile0(LOG_ERR, 1, tb_sprintf((DEVICE_IS_SOCKET)? "Cannot open socket %s, error: %s" : "Cannot open serial port %s, error: %s", DEVICE.device, strerror(errno)));
2407 alarm_handler0(LOG_ERR, tb);
2408 }
2409 return -1;
2410 }
2411
2412 if (strstr(smsd_version, "beta"))
2413 {
2414 if (DEVICE_IS_SOCKET)
2415 writelogfile(LOG_INFO, 0, "Socket %s opened as %i", DEVICE.device, modem_handle);
2416 else
2417 writelogfile(LOG_INFO, 0, "Serial port %s opened as %i, rtscts: %i, baudrate: %i", DEVICE.device, modem_handle, DEVICE.rtscts, DEVICE.baudrate);
2418 }
2419
2420 return modem_handle;
2421 }
2422
test_openmodem()2423 int test_openmodem()
2424 {
2425 int result = 1;
2426 int save_device_open_retries = DEVICE.device_open_retries;
2427 int save_socket_connection_retries = DEVICE.socket_connection_retries;
2428
2429 DEVICE.device_open_retries = 0;
2430 DEVICE.socket_connection_retries = 0;
2431
2432 try_closemodem(1);
2433
2434 if (openmodem() < 0)
2435 result = 0;
2436
2437 try_closemodem(1);
2438
2439 DEVICE.device_open_retries = save_device_open_retries;
2440 DEVICE.socket_connection_retries = save_socket_connection_retries;
2441
2442 return result;
2443 }
2444
show_a_commands()2445 void show_a_commands()
2446 {
2447 int i;
2448
2449 for (i = 0; i < COMMUNICATE_A_KEY_COUNT; i++)
2450 {
2451 if (communicate_a_keys[i][0])
2452 {
2453 printf("Alt shortcuts:\n");
2454
2455 while (i < COMMUNICATE_A_KEY_COUNT)
2456 {
2457 if (communicate_a_keys[i][0])
2458 printf("Alt-%i = %s\n", i, communicate_a_keys[i]);
2459
2460 i++;
2461 }
2462 printf("-- \n");
2463 fflush(stdout);
2464 break;
2465 }
2466 }
2467 }
2468
talk_with_modem()2469 int talk_with_modem()
2470 {
2471 int result = 0;
2472 int n;
2473 char tmp[256];
2474 struct termios newtset, oldtset;
2475 char newdevice[PATH_MAX];
2476 int stdinflags;
2477 int set_nonblock = 0;
2478 int idle;
2479 int echo_on = 0;
2480
2481 modem_handle = -1;
2482
2483 stdinflags = fcntl(STDIN_FILENO, F_GETFL);
2484
2485 if (!(stdinflags & O_NONBLOCK))
2486 {
2487 if (fcntl(STDIN_FILENO, F_SETFL, stdinflags | O_NONBLOCK) == -1)
2488 printf("Failed to set STDIN nonblock.\n");
2489 else
2490 set_nonblock = 1;
2491 }
2492
2493 tcgetattr(STDIN_FILENO, &oldtset);
2494 newtset = oldtset;
2495 newtset.c_lflag &= ~(ECHO | ICANON);
2496 newtset.c_iflag &= ~ICRNL;
2497 newtset.c_cc[VMIN] = 1;
2498 newtset.c_cc[VTIME] = 0;
2499 tcsetattr(STDIN_FILENO, TCSAFLUSH, &newtset);
2500
2501 printf("Communicating with %s. ( Press Ctrl-C to abort. )\n", process_title);
2502
2503 // 3.1.20: Ctrl-Z can be sent with Alt-Z:
2504 //printf("( If you need to send Ctrl-Z, change the suspend character first, like stty susp \\^N )\n");
2505 printf("( If you need to send Ctrl-Z, use Alt-Z )\n");
2506
2507 writelogfile(LOG_CRIT, 0, "Communicating with terminal.");
2508
2509 printf("Default device is %s\n", DEVICE.device);
2510 printf("Press Enter to start or type an another device name.\n");
2511 *newdevice = 0;
2512
2513 while (!terminate)
2514 {
2515 idle = 0;
2516
2517 // 3.1.16beta: Automatically set echo on when talking with modem. 3.1.16beta2: Not with network modems which may require login and/or password.
2518 if (!DEVICE_IS_SOCKET && modem_handle != -1 && !echo_on)
2519 {
2520 write_to_modem("ATE1\r", 5, 0, 1);
2521 echo_on = 1;
2522 }
2523
2524 if ((n = read(STDIN_FILENO, tmp, (modem_handle != -1)? sizeof(tmp) -1 : 1)) > 0)
2525 {
2526 if (modem_handle != -1)
2527 {
2528 tmp[n] = 0;
2529
2530 // 3.1.20: Handle Alt-0...9, Alt-Z and Alt-?:
2531 if (n == 2 && tmp[0] == 0x1B)
2532 {
2533 if (tmp[1] >= 0x30 && tmp[1] <= 0x39)
2534 strcpy(tmp, communicate_a_keys[tmp[1] - 0x30]);
2535 else if (tmp[1] == 0x5A || tmp[1] == 0x7A)
2536 sprintf(tmp, "%c", 0x1A);
2537 else if (tmp[1] == 0x3F)
2538 {
2539 show_a_commands();
2540 *tmp = 0;
2541 }
2542 }
2543
2544 if (*tmp)
2545 write_to_modem(tmp, 5, 0, 1);
2546 }
2547 else
2548 {
2549 if (*tmp == 13)
2550 {
2551 printf("\n");
2552 fflush(stdout);
2553 if (*newdevice)
2554 strcpy(DEVICE.device, newdevice);
2555 printf("Opening device %s\n", DEVICE.device);
2556 if (openmodem() == -1)
2557 {
2558 printf("Cannot open device %s, cause: %s.\n", DEVICE.device, strerror(errno));
2559 *newdevice = 0;
2560 continue;
2561 }
2562 setmodemparams();
2563 printf("Ready.\n");
2564
2565 // 3.1.20: Show Alt commands if any defined:
2566 show_a_commands();
2567
2568 fflush(stdout);
2569
2570 result = 1;
2571 }
2572 else if (*tmp)
2573 {
2574 printf("%c", *tmp);
2575 fflush(stdout);
2576 if (*tmp == 127 || *tmp == 8)
2577 {
2578 if (*newdevice)
2579 newdevice[strlen(newdevice) -1] = 0;
2580 }
2581 else
2582 {
2583 if (strlen(newdevice) < sizeof(newdevice) -1)
2584 sprintf(strchr(newdevice, 0), "%c", *tmp);
2585 else
2586 {
2587 printf("\nDevice name too long.\n");
2588 *newdevice = 0;
2589 continue;
2590 }
2591 }
2592 }
2593 }
2594 }
2595 else
2596 idle = 1;
2597
2598 if (modem_handle != -1)
2599 {
2600 if ((n = read(modem_handle, tmp, sizeof(tmp) -1)) > 0)
2601 {
2602 // 3.1.12:
2603 if (log_read_from_modem)
2604 {
2605 char temp[SIZE_LOG_LINE];
2606 int i;
2607 char *answer = tmp;
2608
2609 snprintf(temp, sizeof(temp), "read_from_modem: got=%i:", n);
2610 for (i = 0; i < n; i++)
2611 {
2612 if (strlen(temp) >= sizeof(temp) - 6)
2613 {
2614 strcpy(temp, "ERROR: too much data");
2615 break;
2616 }
2617
2618 sprintf(strchr(temp, 0), " %02X[%c]", (unsigned char) answer[i], ((unsigned char) answer[i] >= ' ') ? answer[i] : '.');
2619 }
2620
2621 writelogfile0(LOG_CRIT, 0, temp);
2622 }
2623
2624 // 3.1.12:
2625 if (DEVICE_IS_SOCKET)
2626 negotiate_with_telnet(tmp, &n);
2627
2628 write(STDOUT_FILENO, tmp, n);
2629 idle = 0;
2630 }
2631 }
2632
2633 if (idle)
2634 usleep_until(time_usec() + 100000);
2635 }
2636
2637 if (modem_handle >= 0)
2638 close(modem_handle);
2639
2640 if (set_nonblock)
2641 fcntl(STDIN_FILENO, F_SETFL, stdinflags & ~O_NONBLOCK);
2642 tcsetattr(STDIN_FILENO, TCSANOW, &oldtset);
2643
2644 return result;
2645 }
2646
2647 // Return value:
2648 // -2 = terminated
2649 // -1 = modem is not registered
2650 // >= 0 = number of retries, modem is registered
wait_network_registration(int waitnetwork_errorsleeptime,int retry_count)2651 int wait_network_registration(int waitnetwork_errorsleeptime, int retry_count)
2652 {
2653 char answer[500];
2654 int success = 0;
2655 int retries = 0;
2656 int registration_denied = 0;
2657 static int registration_ok = 0;
2658 char *p;
2659 // 3.1.14:
2660 static char prev_lac[32] = "";
2661 static char prev_ci[32] = "";
2662 char lac[32];
2663 char ci[32];
2664
2665 writelogfile(LOG_INFO, 0, "Checking if Modem is registered to the network");
2666
2667 do
2668 {
2669 flush_smart_logging();
2670
2671 // 3.1: signal quality is logged:
2672 // 3.1.16beta: only if logging "not registered":
2673 //if (retries > 0)
2674 if (retries > 0 && retries >= DEVICE.log_not_registered_after)
2675 {
2676 put_command("AT+CSQ\r", answer, sizeof(answer), "csq", EXPECT_OK_ERROR);
2677
2678 // 3.1.5: ...with details:
2679 explain_csq(LOG_NOTICE, 0, answer, DEVICE.signal_quality_ber_ignore);
2680 }
2681
2682 put_command("AT+CREG?\r", answer, sizeof(answer), "creg", "(\\+CREG:.*OK)|(ERROR)");
2683
2684 // 3.1.16beta: Remove everything before "+CREG:"
2685 if ((p = strstr(answer, "+CREG:")))
2686 memmove(answer, p, strlen(p) + 1);
2687
2688 // 3.1.14:
2689 if (get_loglevel() >= DEVICE.loglevel_lac_ci)
2690 {
2691 if ((p = strchr(answer, '\r')))
2692 *p = ',';
2693 getfield(answer, 3, lac, sizeof(lac));
2694 getfield(answer, 4, ci, sizeof(ci));
2695 if (strlen(ci) > 4)
2696 memmove(ci, ci +strlen(ci) -4, 5);
2697 }
2698
2699 // 3.1.1: Some modem include spaces in the response:
2700 while ((p = strchr(answer, ' ')))
2701 strcpyo(p, p +1);
2702
2703 // 3.1.1: Drop additional fields:
2704 if ((p = strchr(answer, ',')))
2705 if ((p = strchr(p +1, ',')))
2706 *p = 0;
2707
2708 // 3.1.1: Some modem (Motorola) gives values using three digits like "000,001":
2709 if ((p = strstr(answer, ",00")))
2710 strcpyo(p +1, p +3);
2711
2712 // 3.1:
2713 // Second field is tested.
2714 if (strstr(answer, ",1"))
2715 {
2716 writelogfile(LOG_INFO, 0, "Modem is registered to the network");
2717 success = 1;
2718 }
2719 else if (strstr(answer, ",5"))
2720 {
2721 writelogfile(LOG_INFO, 0, "Modem is registered to a roaming partner network");
2722 success = 1;
2723 }
2724 // 3.1.1: 3 - Registration denied is handled
2725 else if (strstr(answer, ",3"))
2726 {
2727 // 3.1.5: After a SIM has once been successfully registered to the network, failure with registration
2728 // does not stop the modem process.
2729 //if (registration_denied < 2)
2730 if (registration_ok || registration_denied < 2)
2731 {
2732 writelogfile(LOG_INFO, 1, "Modem said: registration denied. Retrying.");
2733 registration_denied++;
2734 if (t_sleep(waitnetwork_errorsleeptime))
2735 return -2;
2736 }
2737 else
2738 {
2739 writelogfile0(LOG_ERR, 1, tb_sprintf("Error: registration is denied."));
2740 alarm_handler0(LOG_ERR, tb);
2741 abnormal_termination(0);
2742 }
2743 }
2744 else if (strstr(answer,"ERROR"))
2745 {
2746 writelogfile(LOG_INFO, 1, "Ignoring that modem does not support +CREG command.");
2747 success = 1;
2748 DEVICE.check_network = 0;
2749 }
2750 else if (strstr(answer,"+CREG:"))
2751 {
2752 // 3.1.14: Skip logging if defined. Call alarmhandler.
2753 if (retries >= DEVICE.log_not_registered_after)
2754 {
2755 writelogfile0(LOG_NOTICE, 1, tb_sprintf("MODEM IS NOT REGISTERED, WAITING %i SEC. BEFORE RETRYING %i. TIME", waitnetwork_errorsleeptime, retries +1));
2756 alarm_handler0(LOG_NOTICE, tb);
2757 }
2758 else
2759 {
2760 // 3.1.16beta: log with level 7, start trouble logging:
2761 writelogfile0(LOG_DEBUG, 1, tb_sprintf("MODEM IS NOT REGISTERED, WAITING %i SEC. BEFORE RETRYING %i. TIME", waitnetwork_errorsleeptime, retries +1));
2762 }
2763
2764 if (t_sleep(waitnetwork_errorsleeptime))
2765 return -2;
2766 }
2767 else
2768 {
2769 writelogfile0(LOG_ERR, 1, tb_sprintf("Error: Unexpected answer from Modem after +CREG?, waiting %i sec. before retrying", waitnetwork_errorsleeptime));
2770 alarm_handler0(LOG_ERR, tb);
2771 if (t_sleep(waitnetwork_errorsleeptime))
2772 return -2;
2773 }
2774
2775 if (!success)
2776 retries++;
2777 }
2778 while (!success && retries < retry_count);
2779
2780 if (!success)
2781 {
2782 writelogfile0(LOG_ERR, 1, tb_sprintf("Error: Modem is not registered to the network"));
2783 alarm_handler0(LOG_ERR, tb);
2784 return -1;
2785 }
2786
2787 // 3.1.14:
2788 if (get_loglevel() >= DEVICE.loglevel_lac_ci && *lac && *ci)
2789 {
2790 if (*prev_lac && *prev_ci)
2791 {
2792 if (strcmp(prev_lac, lac))
2793 writelogfile(DEVICE.loglevel_lac_ci, 0, "Location area code changed: %s -> %s", prev_lac, lac);
2794
2795 if (strcmp(prev_ci, ci))
2796 writelogfile(DEVICE.loglevel_lac_ci, 0, "Cell ID changed: %s -> %s", prev_ci, ci);
2797
2798 if (strcmp(prev_lac, lac) || strcmp(prev_ci, ci))
2799 {
2800 put_command("AT+CSQ\r", answer, sizeof(answer), "csq", EXPECT_OK_ERROR);
2801 explain_csq(DEVICE.loglevel_lac_ci, 0, answer, DEVICE.signal_quality_ber_ignore);
2802 }
2803 }
2804 else
2805 {
2806 writelogfile(DEVICE.loglevel_lac_ci, 0, "Location area code: %s, Cell ID: %s", lac, ci);
2807 put_command("AT+CSQ\r", answer, sizeof(answer), "csq", EXPECT_OK_ERROR);
2808 explain_csq(DEVICE.loglevel_lac_ci, 0, answer, DEVICE.signal_quality_ber_ignore);
2809 }
2810
2811 snprintf(prev_lac, sizeof(prev_lac), "%s", lac);
2812 snprintf(prev_ci, sizeof(prev_ci), "%s", ci);
2813 }
2814
2815 registration_ok = 1;
2816
2817 return retries;
2818 }
2819
try_closemodem(int force)2820 int try_closemodem(int force)
2821 {
2822 int keep_open;
2823
2824 if (force)
2825 keep_open = 0;
2826 else
2827 keep_open = DEVICE.keep_open;
2828
2829 if (modem_handle >= 0 && !keep_open)
2830 {
2831 if (1 && strstr(smsd_version, "beta"))
2832 {
2833 writelogfile(LOG_INFO, 0, "Device %s (%i) closed", DEVICE.device, modem_handle);
2834 writelogfile(LOG_INFO, 0, "***********");
2835 }
2836 #ifdef DEBUGMSG
2837 printf("!! Closing device %s\n", DEVICE.device);
2838 #endif
2839
2840 // 3.1.16beta: Flush required when select() was used and there was no modem connected,
2841 // without flush the close() has 30 sec. delay:
2842 tcflush(modem_handle, TCIOFLUSH);
2843
2844 close(modem_handle);
2845 modem_handle = -2;
2846 }
2847
2848 return (modem_handle >= 0);
2849 }
2850
try_openmodem()2851 int try_openmodem()
2852 {
2853 int result = 1;
2854
2855 if (modem_handle >= 0)
2856 {
2857 #ifdef DEBUGMSG
2858 printf("!! Opening device %s: already open\n", DEVICE.device);
2859 #endif
2860 return 1;
2861 }
2862
2863 #ifdef DEBUGMSG
2864 printf("!! Opening device %s\n", DEVICE.device);
2865 #endif
2866 if (openmodem() == -1)
2867 {
2868 result = 0;
2869 #ifdef DEBUGMSG
2870 printf("!! Opening FAILED\n");
2871 #endif
2872 }
2873 else
2874 {
2875 #ifdef DEBUGMSG
2876 printf("!! Setting modem parameters\n");
2877 #endif
2878 put_command_timeouts = 0;
2879 setmodemparams();
2880 }
2881
2882 return result;
2883 }
2884