7 A Linux/Unix toolset and driver for Nokia mobile phones.
9 Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
10 Copyright (C) 2001 Pavel Machek
11 Copyright (C) 2001 Pawe³ Kot
13 Released under the terms of the GNU GPL, see file COPYING for more details.
15 Mainline code for gnokii utility. Handles command line parsing and
16 reading/writing phonebook entries and other stuff.
18 WARNING: this code is the test tool. Well, our test tool is now
19 really powerful and useful :-)
22 Revision 1.1.1.11 2002/04/03 00:08:17 short
23 Found in "gnokii-working" directory, some November-patches version
25 Revision 1.143 2001/09/14 13:30:07 pkot
26 Fixed bugs introduced during 0.3.3 merge
28 Revision 1.142 2001/09/14 13:02:03 pkot
29 Gnokii calendar changes from 0.3.3
31 Revision 1.141 2001/09/14 12:53:00 pkot
34 Set valid operator on logos xgnokii screen.
36 Revision 1.140 2001/07/27 00:02:21 pkot
37 Generic AT support for the new structure (Manfred Jonsson)
39 Revision 1.139 2001/07/01 23:16:45 pkot
40 Fixed a typo in gnokii.c avoiding saving logo (Jan Havelka)
42 Revision 1.138 2001/06/28 00:28:45 pkot
43 Small docs updates (Pawel Kot)
45 Revision 1.137 2001/06/27 23:52:50 pkot
46 7110/6210 updates (Marian Jancar)
48 Revision 1.136 2001/06/10 23:49:49 pkot
49 Small fixes to hide compilation warnings and allow gnokii.c to compile
51 Revision 1.135 2001/06/10 11:42:26 machek
52 Cleanup: some formating, made Statemachine global, converted to new
53 structure w.r.t. SMS-es
55 Revision 1.134 2001/05/24 20:47:30 chris
56 More updating of 7110 code and some of xgnokii_lowlevel changed over.
58 Revision 1.133 2001/04/23 17:20:01 pkot
59 Added possibility for viewing logos (currently nol and ngg) on console (Bartek Klepacz)
61 Revision 1.132 2001/03/21 23:36:06 chris
62 Added the statemachine
63 This will break gnokii --identify and --monitor except for 6210/7110
65 Revision 1.131 2001/03/19 23:43:46 pkot
66 Solaris / BSD '#if defined' cleanup
68 Revision 1.130 2001/03/13 01:23:18 pkot
69 Windows updates (Manfred Jonsson)
71 Revision 1.129 2001/03/13 01:21:39 pkot
72 *BSD updates (Bert Driehuis)
74 Revision 1.128 2001/03/08 00:49:06 pkot
75 Fixed bug (introduced by me) in getmemory function. Now gnokii.c should compile
77 Revision 1.127 2001/03/08 00:18:13 pkot
78 Fixed writephonebook once again. Someone kick me please...
80 Revision 1.126 2001/03/07 21:46:12 pkot
81 Fixed writephonebook patch
83 Revision 1.125 2001/03/06 22:19:14 pkot
84 Cleanups and fixes in gnokii.c:
86 - fixed bug reported by Gabriele Zappi
87 - fixed small bugs introduced by Pavel Machek
89 Revision 1.124 2001/02/28 21:42:00 machek
90 Possibility to force overwrite in --getsms (-F). Possibility to get
91 multiple files (use --getsms -f xyzzy%d), cleanup.
93 Revision 1.123 2001/02/20 21:55:11 pkot
94 Small #include updates
96 Revision 1.122 2001/02/16 14:29:53 chris
97 Restructure of common/. Fixed a problem in fbus-phonet.c
98 Lots of dprintfs for Marcin
99 Any size xpm can now be loaded (eg for 7110 startup logos)
100 nk7110 code detects 7110/6210 and alters startup logo size to suit
101 Moved Marcin's extended phonebook code into gnokii.c
103 Revision 1.121 2001/02/06 21:15:35 chris
104 Preliminary irda support for 7110 etc. Not well tested!
106 Revision 1.120 2001/02/06 08:13:32 pkot
107 One more include in gnokii.c needed
109 Revision 1.119 2001/02/05 12:29:37 pkot
110 Changes needed to let unicode work
112 Revision 1.118 2001/02/01 15:17:33 pkot
113 Fixed --identify and added Manfred's manufacturer patch
115 Revision 1.117 2001/01/31 23:45:27 pkot
116 --identify should work ok now
118 Revision 1.116 2001/01/24 20:19:55 machek
119 Do not retry identification, if it is not implemented, it is bad idea.
121 Revision 1.115 2001/01/22 01:25:10 hugh
122 Tweaks for 3810 series, datacalls seem to be broken so need to do
123 some more debugging...
125 Revision 1.114 2001/01/17 02:54:55 chris
126 More 7110 work. Use with care! (eg it is not possible to delete phonebook entries)
127 I can now edit my phonebook in xgnokii but it is 'work in progress'.
129 Revision 1.113 2001/01/15 17:00:49 pkot
130 Initial keypress sequence support. Disable compilation warning
132 Revision 1.112 2001/01/12 14:09:13 pkot
133 More cleanups. This time mainly in the code.
135 Revision 1.111 2001/01/10 16:32:18 pkot
136 Documentation updates.
137 FreeBSD fix for 3810 code.
138 Added possibility for deleting SMS just after reading it in gnokii.
142 Revision 1.110 2001/01/08 15:11:37 pkot
143 Documentation updates.
144 Fixed some bugs and removed FIXMEs.
145 We need to move some stuff from configure.in to aclocal.m4
147 Revision 1.109 2000/12/29 15:39:07 pkot
148 Reverted a change in fbus-3810.c which broke compling with --enable-debug.
149 Small fixes in gnokii.c
151 Revision 1.108 2000/12/19 16:18:16 pkot
152 configure script updates and added shared function for configfile reading
165 # include <strings.h> /* for memset */
168 #include <sys/types.h>
169 #include <sys/stat.h>
174 #define sleep(x) Sleep((x) * 1000)
175 #define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
177 #include "win32/getopt.h"
192 #include "gsm-common.h"
194 #include "gsm-networks.h"
195 #include "cfgreader.h"
197 #include "gsm-filetypes.h"
198 #include "gsm-bitmaps.h"
199 #include "gsm-ringtones.h"
200 #include "gsm-statemachine.h"
202 char *model; /* Model from .gnokiirc file. */
203 char *Port; /* Serial port from .gnokiirc file */
204 char *Initlength; /* Init length from .gnokiirc file */
205 char *Connection; /* Connection type from .gnokiirc file */
206 char *BinDir; /* Binaries directory from .gnokiirc file - not used here yet */
207 /* Local variables */
209 char *GetProfileCallAlertString(int code)
212 case PROFILE_CALLALERT_RINGING: return "Ringing";
213 case PROFILE_CALLALERT_ASCENDING: return "Ascending";
214 case PROFILE_CALLALERT_RINGONCE: return "Ring once";
215 case PROFILE_CALLALERT_BEEPONCE: return "Beep once";
216 case PROFILE_CALLALERT_CALLERGROUPS: return "Caller groups";
217 case PROFILE_CALLALERT_OFF: return "Off";
218 default: return "Unknown";
222 char *GetProfileVolumeString(int code)
225 case PROFILE_VOLUME_LEVEL1: return "Level 1";
226 case PROFILE_VOLUME_LEVEL2: return "Level 2";
227 case PROFILE_VOLUME_LEVEL3: return "Level 3";
228 case PROFILE_VOLUME_LEVEL4: return "Level 4";
229 case PROFILE_VOLUME_LEVEL5: return "Level 5";
230 default: return "Unknown";
234 char *GetProfileKeypadToneString(int code)
237 case PROFILE_KEYPAD_OFF: return "Off";
238 case PROFILE_KEYPAD_LEVEL1: return "Level 1";
239 case PROFILE_KEYPAD_LEVEL2: return "Level 2";
240 case PROFILE_KEYPAD_LEVEL3: return "Level 3";
241 default: return "Unknown";
245 char *GetProfileMessageToneString(int code)
248 case PROFILE_MESSAGE_NOTONE: return "No tone";
249 case PROFILE_MESSAGE_STANDARD: return "Standard";
250 case PROFILE_MESSAGE_SPECIAL: return "Special";
251 case PROFILE_MESSAGE_BEEPONCE: return "Beep once";
252 case PROFILE_MESSAGE_ASCENDING: return "Ascending";
253 default: return "Unknown";
257 char *GetProfileWarningToneString(int code)
260 case PROFILE_WARNING_OFF: return "Off";
261 case PROFILE_WARNING_ON: return "On";
262 default: return "Unknown";
266 char *GetProfileVibrationString(int code)
269 case PROFILE_VIBRATION_OFF: return "Off";
270 case PROFILE_VIBRATION_ON: return "On";
271 default: return "Unknown";
275 /* This function shows the copyright and some informations usefull for
280 fprintf(stdout, _("GNOKII Version %s\n"
281 "Copyright (C) Hugh Blemings <hugh@blemings.org>, 1999, 2000\n"
282 "Copyright (C) Pavel Janík ml. <Pavel.Janik@suse.cz>, 1999, 2000\n"
283 "Copyright (C) Pavel Machek <pavel@ucw.cz>, 2001\n"
284 "Copyright (C) Pawe³ Kot <pkot@linuxnews.pl>, 2001\n"
285 "gnokii is free software, covered by the GNU General Public License, and you are\n"
286 "welcome to change it and/or distribute copies of it under certain conditions.\n"
287 "There is absolutely no warranty for gnokii. See GPL for details.\n"
288 "Built %s %s for %s on %s \n"), VERSION, __TIME__, __DATE__, model, Port);
292 /* The function usage is only informative - it prints this program's usage and
293 command-line options. */
297 fprintf(stdout, _(" usage: gnokii [--help|--monitor|--version]\n"
298 " gnokii --getmemory memory_type start [end]\n"
299 " gnokii --writephonebook [-i]\n"
300 " gnokii --getspeeddial number\n"
301 " gnokii --setspeeddial number memory_type location\n"
302 " gnokii --getsms memory_type start [end] [-f file] [-F file] [-d]\n"
303 " gnokii --deletesms memory_type start [end]\n"
304 " gnokii --sendsms destination [-r] [-C n] [-v n]\n"
305 " [--longtext|--longudh] [--udh] [-8]\n"
306 " [--smsc message_center_number | --smscno message_center_index]\n"
307 " gnokii --savesms [-m] [-l n] [-i]\n"
308 " gnokii --getsmsc message_center_number\n"
309 " gnokii --setdatetime [YYYY [MM [DD [HH [MM]]]]]\n"
310 " gnokii --getdatetime\n"
311 " gnokii --setalarm HH MM\n"
312 " gnokii --getalarm\n"
313 " gnokii --dialvoice number\n"
314 " gnokii --getcalendarnote start [end] [-v]\n"
315 " gnokii --writecalendarnote vcardfile number\n"
316 " gnokii --deletecalendarnote start [end]\n"
317 " gnokii --getdisplaystatus\n"
318 " gnokii --netmonitor {reset|off|field|devel|next|nr}\n"
319 " gnokii --identify\n"
320 " gnokii --senddtmf string\n"
321 " gnokii --sendlogo {caller|op} destination logofile [network code]\n"
322 " [--smsc message_center_number | --smscno message_center_index]\n"
323 " gnokii --sendringtone destination rtttlfile\n"
324 " [--smsc message_center_number | --smscno message_center_index]\n"
325 " gnokii --setlogo op [logofile] [network code]\n"
326 " gnokii --setlogo startup [logofile]\n"
327 " gnokii --setlogo caller [logofile] [caller group number] [group name]\n"
328 " gnokii --setlogo {dealer|text} [text]\n"
329 " gnokii --getlogo op [logofile] [network code]\n"
330 " gnokii --getlogo startup [logofile] [network code]\n"
331 " gnokii --getlogo caller [logofile][caller group number][network code]\n"
332 " gnokii --getlogo {dealer|text}\n"
333 " gnokii --viewlogo logofile\n"
334 " gnokii --setringtone rtttlfile\n"
335 " gnokii --reset [soft|hard]\n"
336 " gnokii --getprofile [number]\n"
337 " gnokii --displayoutput\n"
338 " gnokii --keysequence\n"
342 " gnokii --entersecuritycode PIN|PIN2|PUK|PUK2\n"
343 " gnokii --getsecuritycodestatus\n"
349 /* fbusinit is the generic function which waits for the FBUS link. The limit
350 is 10 seconds. After 10 seconds we quit. */
352 static GSM_Statemachine State;
353 static GSM_Data data;
355 void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame))
359 GSM_ConnectionType connection=GCT_Serial;
361 GSM_DataClear(&data);
363 if (!strcmp(Connection, "infrared")) connection=GCT_Infrared;
364 if (!strcmp(Connection, "irda")) connection=GCT_Irda;
366 /* Initialise the code for the GSM interface. */
368 error = GSM_Initialise(model, Port, Initlength, connection, rlp_handler, &State);
370 if (error != GE_NONE) {
371 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
375 /* First (and important!) wait for GSM link to be active. We allow 10
378 while (count++ < 200 && *GSM_LinkOK == false)
381 if (*GSM_LinkOK == false) {
382 fprintf (stderr, _("Hmmm... GSM_LinkOK never went true. Quitting.\n"));
387 /* This function checks that the argument count for a given options is withing
389 int checkargs(int opt, struct gnokii_arg_len gals[], int argc)
393 /* Walk through the whole array with options requiring arguments. */
394 for (i = 0; !(gals[i].gal_min == 0 && gals[i].gal_max == 0); i++) {
396 /* Current option. */
397 if (gals[i].gal_opt == opt) {
399 /* Argument count checking. */
400 if (gals[i].gal_flags == GAL_XOR) {
401 if (gals[i].gal_min == argc || gals[i].gal_max == argc)
404 if (gals[i].gal_min <= argc && gals[i].gal_max >= argc)
412 /* We do not have options without arguments in the array, so check them. */
413 if (argc == 0) return 0;
417 /* Main function - handles command line arguments, passes them to separate
418 functions accordingly. */
419 int main(int argc, char *argv[])
425 /* Every option should be in this array. */
426 static struct option long_options[] =
428 /* FIXME: these comments are nice, but they would be more usefull as docs for the user */
430 { "help", no_argument, NULL, OPT_HELP },
432 // Display version and build information.
433 { "version", no_argument, NULL, OPT_VERSION },
436 { "monitor", no_argument, NULL, OPT_MONITOR },
440 // Enter Security Code mode
441 { "entersecuritycode", required_argument, NULL, OPT_ENTERSECURITYCODE },
443 // Get Security Code status
444 { "getsecuritycodestatus", no_argument, NULL, OPT_GETSECURITYCODESTATUS },
449 { "setdatetime", optional_argument, NULL, OPT_SETDATETIME },
451 // Get date and time mode
452 { "getdatetime", no_argument, NULL, OPT_GETDATETIME },
455 { "setalarm", required_argument, NULL, OPT_SETALARM },
458 { "getalarm", no_argument, NULL, OPT_GETALARM },
461 { "dialvoice", required_argument, NULL, OPT_DIALVOICE },
463 // Get calendar note mode
464 { "getcalendarnote", required_argument, NULL, OPT_GETCALENDARNOTE },
466 // Write calendar note mode
467 { "writecalendarnote", required_argument, NULL, OPT_WRITECALENDARNOTE },
469 // Delete calendar note mode
470 { "deletecalendarnote", required_argument, NULL, OPT_DELCALENDARNOTE },
472 // Get display status mode
473 { "getdisplaystatus", no_argument, NULL, OPT_GETDISPLAYSTATUS },
476 { "getmemory", required_argument, NULL, OPT_GETMEMORY },
478 // Write phonebook (memory) mode
479 { "writephonebook", optional_argument, NULL, OPT_WRITEPHONEBOOK },
481 // Get speed dial mode
482 { "getspeeddial", required_argument, NULL, OPT_GETSPEEDDIAL },
484 // Set speed dial mode
485 { "setspeeddial", required_argument, NULL, OPT_SETSPEEDDIAL },
487 // Get SMS message mode
488 { "getsms", required_argument, NULL, OPT_GETSMS },
490 // Delete SMS message mode
491 { "deletesms", required_argument, NULL, OPT_DELETESMS },
493 // Send SMS message mode
494 { "sendsms", required_argument, NULL, OPT_SENDSMS },
496 // Save SMS message mode
497 { "savesms", optional_argument, NULL, OPT_SAVESMS },
499 // Send logo as SMS message mode
500 { "sendlogo", required_argument, NULL, OPT_SENDLOGO },
502 // Send ringtone as SMS message
503 { "sendringtone", required_argument, NULL, OPT_SENDRINGTONE },
506 { "setringtone", required_argument, NULL, OPT_SETRINGTONE },
508 // Get SMS center number mode
509 { "getsmsc", required_argument, NULL, OPT_GETSMSC },
511 // For development purposes: run in passive monitoring mode
512 { "pmon", no_argument, NULL, OPT_PMON },
515 { "netmonitor", required_argument, NULL, OPT_NETMONITOR },
518 { "identify", no_argument, NULL, OPT_IDENTIFY },
520 // Send DTMF sequence
521 { "senddtmf", required_argument, NULL, OPT_SENDDTMF },
524 { "reset", optional_argument, NULL, OPT_RESET },
527 { "setlogo", optional_argument, NULL, OPT_SETLOGO },
530 { "getlogo", required_argument, NULL, OPT_GETLOGO },
533 { "viewlogo", required_argument, NULL, OPT_VIEWLOGO },
536 { "getprofile", optional_argument, NULL, OPT_GETPROFILE },
538 // Show texts from phone's display
539 { "displayoutput", no_argument, NULL, OPT_DISPLAYOUTPUT },
541 // Simulate pressing the keys
542 { "keysequence", no_argument, NULL, OPT_KEYPRESS },
544 // For development purposes: insert you function calls here
545 { "foogle", no_argument, NULL, OPT_FOOGLE },
550 /* Every command which requires arguments should have an appropriate entry
552 struct gnokii_arg_len gals[] =
556 { OPT_ENTERSECURITYCODE, 1, 1, 0 },
559 { OPT_SETDATETIME, 0, 5, 0 },
560 { OPT_SETALARM, 2, 2, 0 },
561 { OPT_DIALVOICE, 1, 1, 0 },
562 { OPT_GETCALENDARNOTE, 1, 3, 0 },
563 { OPT_WRITECALENDARNOTE, 2, 2, 0 },
564 { OPT_DELCALENDARNOTE, 1, 2, 0 },
565 { OPT_GETMEMORY, 2, 3, 0 },
566 { OPT_GETSPEEDDIAL, 1, 1, 0 },
567 { OPT_SETSPEEDDIAL, 3, 3, 0 },
568 { OPT_GETSMS, 2, 5, 0 },
569 { OPT_DELETESMS, 2, 3, 0 },
570 { OPT_SENDSMS, 1, 10, 0 },
571 { OPT_SAVESMS, 0, 6, 0 },
572 { OPT_SENDLOGO, 3, 6, 0 },
573 { OPT_SENDRINGTONE, 2, 6, 0 },
574 { OPT_GETSMSC, 1, 1, 0 },
575 { OPT_GETWELCOMENOTE, 1, 1, 0 },
576 { OPT_SETWELCOMENOTE, 1, 1, 0 },
577 { OPT_NETMONITOR, 1, 1, 0 },
578 { OPT_SENDDTMF, 1, 1, 0 },
579 { OPT_SETLOGO, 1, 4, 0 },
580 { OPT_GETLOGO, 1, 4, 0 },
581 { OPT_VIEWLOGO, 1, 1, 0 },
582 { OPT_SETRINGTONE, 1, 1, 0 },
583 { OPT_RESET, 0, 1, 0 },
584 { OPT_GETPROFILE, 0, 1, 0 },
585 { OPT_WRITEPHONEBOOK, 0, 1, 0 },
592 /* For GNU gettext */
594 textdomain("gnokii");
595 setlocale(LC_ALL, "");
598 /* Read config file */
599 if (readconfig(&model, &Port, &Initlength, &Connection, &BinDir) < 0) {
603 /* Handle command line arguments. */
604 c = getopt_long(argc, argv, "", long_options, NULL);
605 if (c == -1) /* No argument given - we should display usage. */
609 // First, error conditions
612 fprintf(stderr, _("Use '%s --help' for usage informations.\n"), argv[0]);
614 // Then, options with no arguments
621 /* We have to build an array of the arguments which will be passed to the
622 functions. Please note that every text after the --command will be
623 passed as arguments. A syntax like gnokii --cmd1 args --cmd2 args will
624 not work as expected; instead args --cmd2 args is passed as a
626 if ((nargv = malloc(sizeof(char *) * argc)) != NULL) {
627 for (i = 2; i < argc; i++)
628 nargv[i-2] = argv[i];
630 if (checkargs(c, gals, nargc)) {
631 free(nargv); /* Wrong number of arguments - we should display usage. */
636 /* have to ignore SIGALARM */
640 /* Initialise the code for the GSM interface. */
648 case OPT_ENTERSECURITYCODE:
649 rc = entersecuritycode(optarg);
651 case OPT_GETSECURITYCODESTATUS:
652 rc = getsecuritycodestatus();
655 case OPT_GETDATETIME:
661 case OPT_GETDISPLAYSTATUS:
662 rc = getdisplaystatus();
667 case OPT_WRITEPHONEBOOK:
668 rc = writephonebook(nargc, nargv);
670 // Now, options with arguments
671 case OPT_SETDATETIME:
672 rc = setdatetime(nargc, nargv);
675 rc = setalarm(nargv);
678 rc = dialvoice(optarg);
680 case OPT_GETCALENDARNOTE:
681 rc = getcalendarnote(nargc, nargv);
683 case OPT_DELCALENDARNOTE:
684 rc = deletecalendarnote(nargc, nargv);
686 case OPT_WRITECALENDARNOTE:
687 rc = writecalendarnote(nargv);
690 rc = getmemory(nargc, nargv);
692 case OPT_GETSPEEDDIAL:
693 rc = getspeeddial(optarg);
695 case OPT_SETSPEEDDIAL:
696 rc = setspeeddial(nargv);
699 rc = getsms(argc, argv);
702 rc = deletesms(nargc, nargv);
705 rc = sendsms(nargc, nargv);
708 rc = savesms(argc, argv);
711 rc = sendlogo(nargc, nargv);
714 rc = getsmsc(optarg);
717 rc = netmonitor(optarg);
723 rc = setlogo(nargc, nargv);
726 rc = getlogo(nargc, nargv);
729 rc = viewlogo(optarg);
731 case OPT_SETRINGTONE:
732 rc = setringtone(nargc, nargv);
734 case OPT_SENDRINGTONE:
735 rc = sendringtone(argc, argv);
738 rc = getprofile(nargc, nargv);
740 case OPT_DISPLAYOUTPUT:
741 rc = displayoutput();
744 rc = presskeysequence();
752 rc = senddtmf(optarg);
758 fprintf(stderr, _("Unknown option: %d\n"), c);
765 fprintf(stderr, _("Wrong number of arguments\n"));
769 #define SMSC_SHORTCHAR_SMSC (0xF0)
770 #define SMSC_SHORTCHAR_SMSCNO (0xF1)
771 #define SMSC_OPTIONS \
772 { "smsc", required_argument, NULL, SMSC_SHORTCHAR_SMSC}, \
773 { "smscno", required_argument, NULL, SMSC_SHORTCHAR_SMSCNO}
775 /* RETURNS: Whether the options was found as ours (=>rerun getopt_long())
777 static bool smsc_options_parse(int option,GSM_SMSMessage *SMS)
781 case SMSC_SHORTCHAR_SMSC: /* SMSC number */
782 SMS->MessageCenter.No = 0;
783 strcpy(SMS->MessageCenter.Number,optarg);
786 case SMSC_SHORTCHAR_SMSCNO: /* SMSC number index in phone memory */
787 SMS->MessageCenter.No = atoi(optarg);
789 if (SMS->MessageCenter.No < 1 || SMS->MessageCenter.No > 5)
794 return(false); /* option not recognized */
797 return(true); /* option was successfuly processed */
802 bool sendsms_deconcatenated(GSM_SMSMessage *sms,char *buf,size_t buflen,bool useudh)
804 GSM_Deconcatenate_state SMS_Deconcatenate_state;
807 SMS_Deconcatenate_state.first=true;
808 while (SMS_Deconcatenate(&SMS_Deconcatenate_state,sms,buf,buflen,useudh)) {
809 /* Send the message. */
810 error = GSM->SendSMSMessage(sms);
812 if (error == GE_SMSSENDOK) {
813 fprintf(stdout, _("Send succeeded!\n"));
815 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
818 /* Here the sleep have no meaning.
819 * If it is required by some backend phone driver, it should be done THERE!
826 /* Send SMS messages. */
827 int sendsms(int argc, char *argv[])
830 /* The maximum length of an uncompressed concatenated short message is
831 255 * 153 = 39015 default alphabet characters */
832 char message_buffer[GSM_MAX_CONCATENATED_SMS_LENGTH];
833 int input_len, chars_read;
837 struct option options[] = {
839 { "longtext", no_argument, NULL, '3'},
840 { "longudh", no_argument, NULL, '4'},
841 { "udh", no_argument, NULL, '5'},
845 input_len = GSM_MAX_SMS_LENGTH;
853 - message validity for 3 days
854 - unset user data header indicator
859 SMS.Compression = false;
860 SMS.EightBit = false;
861 SMS.MessageCenter.No = 1;
862 SMS.Validity = 4320; /* 4320 minutes == 72 hours */
863 SMS.UDHPresent = false;
865 strcpy(SMS.Destination, argv[0]);
870 while ((i = getopt_long(argc, argv, "r8cC:v:", options, NULL)) != -1) {
871 if (smsc_options_parse(i,&SMS))
873 switch (i) { // -c for compression. not yet implemented.
874 case '3': /* we send long message in text format */
875 input_len = GSM_MAX_CONCATENATED_SMS_LENGTH;
878 case '4': /* we send long message in UDH format */
879 input_len = GSM_MAX_CONCATENATED_SMS_LENGTH;
882 case '5': /* UDH indication requested */
883 SMS.UDHPresent = true;
885 case 'r': /* request for delivery report */
888 case 'C': /* class Message */
906 case '8': /* 8-bit data */
910 SMS.Validity = atoi(optarg);
913 usage(); /* Would be better to have an sendsms_usage() here. */
917 /* Get message text from stdin. */
918 chars_read = fread(message_buffer, 1, input_len, stdin);
920 if (chars_read == 0) {
921 fprintf(stderr, _("Couldn't read from stdin!\n"));
923 } else if (chars_read > input_len) {
924 fprintf(stderr, _("Input too long!\n"));
928 if (SMS.UDHPresent) {
929 u8 UDHlen = 1 + message_buffer[0]; /* designifify */
931 if (chars_read < UDHlen || sizeof(SMS.UDH) < UDHlen) {
932 fprintf(stderr, _("Input too short to satisfy UDH!\n"));
935 memcpy(SMS.UDH, message_buffer, UDHlen);
937 memmove(message_buffer, message_buffer + UDHlen, chars_read);
940 /* Null terminate. */
941 message_buffer[chars_read] = 0x00;
943 sendsms_deconcatenated(&SMS,message_buffer,chars_read,useudh);
950 int savesms(int argc, char *argv[])
954 /* The maximum length of an uncompressed concatenated short message is
955 255 * 153 = 39015 default alphabet characters */
956 char message_buffer[GSM_MAX_CONCATENATED_SMS_LENGTH];
957 int input_len, chars_read;
964 SMS.Destination[0] = '\0';
966 SMS.Compression = false;
967 SMS.EightBit = false;
968 SMS.MessageCenter.No = 1;
969 SMS.Validity = 4320; /* 4320 minutes == 72 hours */
970 SMS.UDHPresent = false;
971 SMS.Status = GSS_NOTSENTREAD;
973 SMS.MemoryType = GMT_SM;
975 input_len = GSM_MAX_SMS_LENGTH;
978 while ((i = getopt(argc, argv, "ml:in:s:c:")) != -1) {
980 case 'm': /* mark the message as sent */
981 SMS.Status = GSS_SENTREAD;
983 case 'l': /* Specify the location */
984 SMS.Location = atoi(optarg);
986 case 'i': /* Ask before overwriting */
989 case 'n': /* Specify the from number */
991 case 's': /* Specify the smsc number */
993 case 'c': /* Specify the smsc location */
1004 aux.Location = SMS.Location;
1005 data.SMSMessage = &aux;
1006 error = SM_Functions(GOP_GetSMS, &data, &State);
1009 fprintf(stderr, _("Message at specified location exists. "));
1010 while (confirm < 0) {
1011 fprintf(stderr, _("Overwrite? (yes/no) "));
1012 GetLine(stdin, ans, 7);
1013 if (!strcmp(ans, "yes")) confirm = 1;
1014 else if (!strcmp(ans, "no")) confirm = 0;
1016 if (!confirm) { GSM->Terminate(); return 0; }
1018 case GE_INVALIDSMSLOCATION:
1019 fprintf(stderr, _("Invalid location\n"));
1023 /* FIXME: Remove this fprintf when the function is thoroughly tested */
1025 fprintf(stderr, _("Location %d empty. Saving\n"), SMS.Location);
1030 chars_read = fread(message_buffer, 1, input_len, stdin);
1032 if (chars_read == 0) {
1034 fprintf(stderr, _("Couldn't read from stdin!\n"));
1037 } else if (chars_read > input_len) {
1039 fprintf(stderr, _("Input too long!\n"));
1044 strncpy (SMS.MessageText, message_buffer, chars_read);
1045 SMS.MessageText[chars_read] = 0;
1046 SMS.MessageTextLength=chars_read;
1048 error = GSM->SaveSMSMessage(&SMS);
1050 if (error == GE_NONE) {
1051 fprintf(stdout, _("Saved!\n"));
1053 fprintf(stdout, _("Saving failed (error=%d)\n"), error);
1061 /* Get SMSC number */
1062 int getsmsc(char *MessageCenterNumber)
1064 GSM_MessageCenter MessageCenter;
1068 memset(&MessageCenter, 0, sizeof(MessageCenter));
1069 MessageCenter.No=atoi(MessageCenterNumber);
1071 if (GSM && GSM->GetSMSCenter && GSM->Terminate) {
1072 error = GSM->GetSMSCenter(&MessageCenter);
1075 GSM_DataClear(&data);
1076 data.MessageCenter = &MessageCenter;
1077 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
1082 fprintf(stdout, _("%d. SMS center (%s) number is %s\n"), MessageCenter.No, MessageCenter.Name, MessageCenter.Number);
1083 fprintf(stdout, _("Default recipient number is %s\n"), MessageCenter.Recipient);
1084 fprintf(stdout, _("Messages sent as "));
1086 switch (MessageCenter.Format) {
1088 fprintf(stdout, _("Text"));
1091 fprintf(stdout, _("Paging"));
1094 fprintf(stdout, _("Fax"));
1098 fprintf(stdout, _("Email"));
1101 fprintf(stdout, _("ERMES"));
1104 fprintf(stdout, _("X.400"));
1107 fprintf(stdout, _("Unknown"));
1112 fprintf(stdout, _("Message validity is "));
1114 switch (MessageCenter.Validity) {
1116 fprintf(stdout, _("1 hour"));
1119 fprintf(stdout, _("6 hours"));
1122 fprintf(stdout, _("24 hours"));
1125 fprintf(stdout, _("72 hours"));
1128 fprintf(stdout, _("1 week"));
1131 fprintf(stdout, _("Maximum time"));
1134 fprintf(stdout, _("Unknown"));
1138 fprintf(stdout, "\n");
1141 case GE_NOTIMPLEMENTED:
1142 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1145 fprintf(stdout, _("SMS center can not be found :-(\n"));
1152 /* Get SMS messages. */
1153 int getsms(int argc, char *argv[])
1156 GSM_SMSMessage message;
1157 char *memory_type_string;
1158 int start_message, end_message, count, mode = 1;
1165 /* Handle command line args that set type, start and end locations. */
1166 memory_type_string = argv[2];
1167 message.MemoryType = StrToMemoryType(memory_type_string);
1168 if (message.MemoryType == GMT_XX) {
1169 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[2]);
1173 memset(&filename, 0, 64);
1175 start_message = end_message = atoi(argv[3]);
1179 /* [end] can be only argv[4] */
1180 if (argv[4][0] != '-') {
1181 end_message = atoi(argv[4]);
1184 /* parse all options (beginning with '-' */
1185 while ((i = getopt(argc, argv, "f:F:d")) != -1) {
1194 dprintf(_("Saving into %s\n"), optarg);
1195 strncpy(filename, optarg, 64);
1196 if (strlen(optarg) > 63) {
1197 fprintf(stderr, _("Filename too long - will be truncated to 63 characters.\n"));
1200 filename[strlen(optarg)] = 0;
1210 /* Now retrieve the requested entries. */
1211 for (count = start_message; count <= end_message; count ++) {
1213 message.Location = count;
1214 data.SMSMessage = &message;
1215 error = SM_Functions(GOP_GetSMS, &data, &State);
1219 switch (message.Type) {
1221 fprintf(stdout, _("%d. Outbox Message "), message.MessageNumber);
1223 fprintf(stdout, _("(sent)\n"));
1225 fprintf(stdout, _("(not sent)\n"));
1226 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1229 fprintf(stdout, _("%d. Delivery Report "), message.MessageNumber);
1231 fprintf(stdout, _("(read)\n"));
1233 fprintf(stdout, _("(not read)\n"));
1234 fprintf(stdout, _("Sending date/time: %d/%d/%d %d:%02d:%02d "), \
1235 message.Time.Day, message.Time.Month, message.Time.Year, \
1236 message.Time.Hour, message.Time.Minute, message.Time.Second);
1237 if (message.Time.Timezone) {
1238 if (message.Time.Timezone > 0)
1239 fprintf(stdout,_("+%02d00"), message.Time.Timezone);
1241 fprintf(stdout,_("%02d00"), message.Time.Timezone);
1243 fprintf(stdout, "\n");
1244 fprintf(stdout, _("Response date/time: %d/%d/%d %d:%02d:%02d "), \
1245 message.SMSCTime.Day, message.SMSCTime.Month, message.SMSCTime.Year, \
1246 message.SMSCTime.Hour, message.SMSCTime.Minute, message.SMSCTime.Second);
1247 if (message.SMSCTime.Timezone) {
1248 if (message.SMSCTime.Timezone > 0)
1249 fprintf(stdout,_("+%02d00"),message.SMSCTime.Timezone);
1251 fprintf(stdout,_("%02d00"),message.SMSCTime.Timezone);
1253 fprintf(stdout, "\n");
1254 fprintf(stdout, _("Receiver: %s Msg Center: %s\n"), message.Sender, message.MessageCenter.Number);
1255 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1258 fprintf(stdout, _("%d. Inbox Message "), message.MessageNumber);
1260 fprintf(stdout, _("(read)\n"));
1262 fprintf(stdout, _("(not read)\n"));
1263 fprintf(stdout, _("Date/time: %d/%d/%d %d:%02d:%02d "), \
1264 message.Time.Day, message.Time.Month, message.Time.Year, \
1265 message.Time.Hour, message.Time.Minute, message.Time.Second);
1266 if (message.Time.Timezone) {
1267 if (message.Time.Timezone > 0)
1268 fprintf(stdout,_("+%02d00"),message.Time.Timezone);
1270 fprintf(stdout,_("%02d00"),message.Time.Timezone);
1272 fprintf(stdout, "\n");
1273 fprintf(stdout, _("Sender: %s Msg Center: %s\n"), message.Sender, message.MessageCenter.Number);
1274 switch (SMS_DetectUDH(&message)) {
1276 fprintf(stdout, _("GSM operator logo for %s (%s) network.\n"), bitmap.netcode, GSM_GetNetworkName(bitmap.netcode));
1277 if (!strcmp(message.Sender, "+998000005") && !strcmp(message.MessageCenter.Number, "+886935074443")) dprintf(_("Saved by Logo Express\n"));
1278 if (!strcmp(message.Sender, "+998000002") || !strcmp(message.Sender, "+998000003")) dprintf(_("Saved by Operator Logo Uploader by Thomas Kessler\n"));
1279 case GSM_CallerIDLogo:
1280 fprintf(stdout, ("Logo:\n"));
1281 /* put bitmap into bitmap structure */
1282 GSM_ReadSMSBitmap(&message, &bitmap);
1283 GSM_PrintBitmap(&bitmap);
1286 if ((stat(filename, &buf) == 0)) {
1287 fprintf(stdout, _("File %s exists.\n"), filename);
1288 fprintf(stderr, _("Overwrite? (yes/no) "));
1289 GetLine(stdin, ans, 4);
1290 if (!strcmp(ans, "yes")) {
1291 error = GSM_SaveBitmapFile(filename, &bitmap);
1293 } else error = GSM_SaveBitmapFile(filename, &bitmap);
1294 if (error!=GE_NONE) fprintf(stderr, _("Couldn't save logofile %s!\n"), filename);
1297 case GSM_RingtoneUDH:
1298 fprintf(stdout, ("Ringtone\n"));
1300 case GSM_ConcatenatedMessages:
1301 fprintf(stdout, _("Linked (%d/%d):\n"),message.UDH[5],message.UDH[4]);
1303 fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText);
1304 if ((mode != -1) && *filename) {
1306 sprintf(buf, "%s%d", filename, count);
1307 mode = GSM_SaveTextFile(buf, message.MessageText, mode);
1311 fprintf(stderr, _("Unknown\n"));
1317 data.SMSMessage = &message;
1318 if (GE_NONE != SM_Functions(GOP_DeleteSMS, &data, &State))
1319 fprintf(stdout, _("(delete failed)\n"));
1321 fprintf(stdout, _("(message deleted)\n"));
1324 case GE_NOTIMPLEMENTED:
1325 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1326 if (GSM && GSM->Terminate) GSM->Terminate();
1328 case GE_INVALIDSMSLOCATION:
1329 fprintf(stderr, _("Invalid location: %s %d\n"), memory_type_string, count);
1331 case GE_EMPTYSMSLOCATION:
1332 fprintf(stderr, _("SMS location %s %d empty.\n"), memory_type_string, count);
1335 fprintf(stdout, _("GetSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
1340 if (GSM && GSM->Terminate) GSM->Terminate();
1345 /* Delete SMS messages. */
1346 int deletesms(int argc, char *argv[])
1348 GSM_SMSMessage message;
1349 char *memory_type_string;
1350 int start_message, end_message, count;
1353 /* Handle command line args that set type, start and end locations. */
1354 memory_type_string = argv[0];
1355 message.MemoryType = StrToMemoryType(memory_type_string);
1356 if (message.MemoryType == GMT_XX) {
1357 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
1361 start_message = end_message = atoi (argv[1]);
1362 if (argc > 2) end_message = atoi (argv[2]);
1364 /* Now delete the requested entries. */
1365 for (count = start_message; count <= end_message; count ++) {
1367 message.Location = count;
1368 data.SMSMessage = &message;
1369 error = SM_Functions(GOP_DeleteSMS, &data, &State);
1371 if (error == GE_NONE)
1372 fprintf(stdout, _("Deleted SMS %s %d\n"), memory_type_string, count);
1374 if (error == GE_NOTIMPLEMENTED) {
1375 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1379 fprintf(stdout, _("DeleteSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
1388 static volatile bool bshutdown = false;
1390 /* SIGINT signal handler. */
1391 static void interrupted(int sig)
1393 signal(sig, SIG_IGN);
1399 /* In this mode we get the code from the keyboard and send it to the mobile
1401 int entersecuritycode(char *type)
1404 GSM_SecurityCode SecurityCode;
1406 if (!strcmp(type,"PIN"))
1407 SecurityCode.Type=GSCT_Pin;
1408 else if (!strcmp(type,"PUK"))
1409 SecurityCode.Type=GSCT_Puk;
1410 else if (!strcmp(type,"PIN2"))
1411 SecurityCode.Type=GSCT_Pin2;
1412 else if (!strcmp(type,"PUK2"))
1413 SecurityCode.Type=GSCT_Puk2;
1414 // FIXME: Entering of SecurityCode does not work :-(
1415 // else if (!strcmp(type,"SecurityCode"))
1416 // SecurityCode.Type=GSCT_SecurityCode;
1421 printf("Enter your code: ");
1422 gets(SecurityCode.Code);
1424 strcpy(SecurityCode.Code,getpass(_("Enter your code: ")));
1427 test = GSM->EnterSecurityCode(SecurityCode);
1428 if (test == GE_INVALIDSECURITYCODE)
1429 fprintf(stdout, _("Error: invalid code.\n"));
1430 else if (test == GE_NONE)
1431 fprintf(stdout, _("Code ok.\n"));
1432 else if (test == GE_NOTIMPLEMENTED)
1433 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1435 fprintf(stdout, _("Other error.\n"));
1442 int getsecuritycodestatus(void)
1446 if (GSM->GetSecurityCodeStatus(&Status) == GE_NONE) {
1448 fprintf(stdout, _("Security code status: "));
1451 case GSCT_SecurityCode:
1452 fprintf(stdout, _("waiting for Security Code.\n"));
1455 fprintf(stdout, _("waiting for PIN.\n"));
1458 fprintf(stdout, _("waiting for PIN2.\n"));
1461 fprintf(stdout, _("waiting for PUK.\n"));
1464 fprintf(stdout, _("waiting for PUK2.\n"));
1467 fprintf(stdout, _("nothing to enter.\n"));
1470 fprintf(stdout, _("Unknown!\n"));
1483 /* Voice dialing mode. */
1484 int dialvoice(char *Number)
1486 GSM->DialVoice(Number);
1493 /* The following function allows to send logos using SMS */
1494 int sendlogo(int argc, char *argv[])
1499 char Data[sizeof(bitmap.bitmap) +64/*headers safety*/];
1503 struct option options[] = {
1508 /* Default settings for SMS message:
1509 - no delivery report
1515 - set UserDataHeaderIndicator
1520 SMS.Compression = false;
1521 SMS.EightBit = true;
1522 SMS.MessageCenter.No = 1;
1523 SMS.Validity = 4320; /* 4320 minutes == 72 hours */
1527 while ((i = getopt_long(argc, argv, "", options, NULL)) != -1) {
1528 if (smsc_options_parse(i,&SMS))
1532 usage(); /* Would be better to have an sendsms_usage() here. */
1537 if (argc!=3 && argc!=4)
1541 /* The first argument is the type of the logo. */
1542 if (!strcmp(argv[0], "op")) {
1543 SMS_SetupUDH(&SMS,GSM_OpLogo); /* error ignored */
1544 fprintf(stdout, _("Sending operator logo.\n"));
1545 } else if (!strcmp(argv[0], "caller")) { /* error ignored */
1546 SMS_SetupUDH(&SMS,GSM_CallerIDLogo);
1547 fprintf(stdout, _("Sending caller line identification logo.\n"));
1549 fprintf(stderr, _("You should specify what kind of logo to send!\n"));
1553 /* The second argument is the destination, ie the phone number of recipient. */
1554 strcpy(SMS.Destination,argv[1]);
1556 /* The third argument is the bitmap file. */
1557 GSM_ReadBitmapFile(argv[2], &bitmap);
1559 /* If we are sending op logo we can rewrite network code. */
1560 if (!strcmp(argv[0], "op")) {
1562 * The fourth argument, if present, is the Network code of the operator.
1563 * Network code is in this format: "xxx yy".
1566 strcpy(bitmap.netcode, argv[3]);
1568 fprintf(stdout, _("Operator code: %s\n"), argv[3]);
1572 /* Set the network code */
1573 Data[current++] = ((bitmap.netcode[1] & 0x0f) << 4) | (bitmap.netcode[0] & 0xf);
1574 Data[current++] = 0xf0 | (bitmap.netcode[2] & 0x0f);
1575 Data[current++] = ((bitmap.netcode[5] & 0x0f) << 4) | (bitmap.netcode[4] & 0xf);
1578 /* Set the logo size */
1579 Data[current++] = 0x00; /* RFU by Nokia */
1580 Data[current++] = bitmap.width;
1581 Data[current++] = bitmap.height;
1583 Data[current++] = 0x01; /* depth=number of grayscales */
1585 memcpy(Data+current,bitmap.bitmap,bitmap.size);
1586 current+=bitmap.size;
1588 /* Send the message. */
1589 sendsms_deconcatenated(&SMS,Data,current,true/*useudh*/);
1595 /* Getting logos. */
1596 GSM_Error SaveBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1603 /* Ask before overwriting */
1604 while (stat(FileName, &buf) == 0) {
1607 fprintf(stderr, _("Saving logo. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "), FileName);
1608 GetLine(stdin, ans, 4);
1609 if (!strcmp(ans, "O") || !strcmp(ans, "o")) confirm = 1;
1610 if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm = 2;
1611 if (!strcmp(ans, "S") || !strcmp(ans, "s")) return GE_USERCANCELED;
1613 if (confirm == 1) break;
1615 fprintf(stderr, _("Enter name of new file: "));
1616 GetLine(stdin, FileName, 50);
1617 if (!FileName || (*FileName == 0)) return GE_USERCANCELED;
1621 error = GSM_SaveBitmapFile(FileName, bitmap);
1624 case GE_CANTOPENFILE:
1625 fprintf(stderr, _("Failed to write file \"%s\"\n"), FileName);
1634 int getlogo(int argc, char *argv[])
1638 GSM_Statemachine *sm = &State;
1640 bitmap.type=GSM_None;
1642 if (!strcmp(argv[0], "op"))
1643 bitmap.type = GSM_OperatorLogo;
1645 if (!strcmp(argv[0], "caller")) {
1646 /* There is caller group number missing in argument list. */
1648 bitmap.number=argv[2][0]-'0';
1649 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1653 bitmap.type = GSM_CallerLogo;
1656 if (!strcmp(argv[0],"startup"))
1657 bitmap.type = GSM_StartupLogo;
1658 else if (!strcmp(argv[0], "dealer"))
1659 bitmap.type = GSM_DealerNoteText;
1660 else if (!strcmp(argv[0], "text"))
1661 bitmap.type=GSM_WelcomeNoteText;
1663 if (bitmap.type != GSM_None) {
1665 fprintf(stdout, _("Getting Logo\n"));
1667 data.Bitmap=&bitmap;
1668 error=SM_Functions(GOP_GetBitmap, &data, sm);
1672 if (bitmap.type == GSM_DealerNoteText) fprintf(stdout, _("Dealer welcome note "));
1673 if (bitmap.type == GSM_WelcomeNoteText) fprintf(stdout, _("Welcome note "));
1674 if (bitmap.type == GSM_DealerNoteText || bitmap.type==GSM_WelcomeNoteText) {
1675 if (bitmap.text[0]) {
1676 fprintf(stdout, _("currently set to \"%s\"\n"), bitmap.text);
1678 fprintf(stdout, _("currently empty\n"));
1682 switch (bitmap.type) {
1683 case GSM_OperatorLogo:
1684 fprintf(stdout,"Operator logo for %s (%s) network got succesfully\n",bitmap.netcode,GSM_GetNetworkName(bitmap.netcode));
1686 strncpy(bitmap.netcode,argv[2], 7);
1687 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1688 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1693 case GSM_StartupLogo:
1694 fprintf(stdout, "Startup logo got successfully\n");
1696 strncpy(bitmap.netcode,argv[2], 7);
1697 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1698 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1703 case GSM_CallerLogo:
1704 fprintf(stdout,"Caller logo got successfully\n");
1706 strncpy(bitmap.netcode,argv[3],7);
1707 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1708 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1714 fprintf(stdout,"Unknown bitmap type.\n");
1718 if (SaveBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) return (-1);
1721 fprintf(stdout,"Your phone doesn't have logo uploaded !\n");
1726 case GE_NOTIMPLEMENTED:
1727 fprintf(stderr, _("Function not implemented !\n"));
1729 case GE_NOTSUPPORTED:
1730 fprintf(stderr, _("This kind of logo is not supported !\n"));
1733 fprintf(stderr, _("Error getting logo !\n"));
1737 fprintf(stderr, _("What kind of logo do you want to get ?\n"));
1745 /* Sending logos. */
1746 GSM_Error ReadBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1750 error = GSM_ReadBitmapFile(FileName, bitmap);
1753 case GE_CANTOPENFILE:
1754 fprintf(stderr, _("Failed to read file \"%s\"\n"), FileName);
1756 case GE_WRONGNUMBEROFCOLORS:
1757 fprintf(stderr, _("Wrong number of colors in \"%s\" logofile (accepted only 2-colors files) !\n"), FileName);
1759 case GE_WRONGCOLORS:
1760 fprintf(stderr, _("Wrong colors in \"%s\" logofile !\n"), FileName);
1762 case GE_INVALIDFILEFORMAT:
1763 fprintf(stderr, _("Invalid format of \"%s\" logofile !\n"), FileName);
1765 case GE_SUBFORMATNOTSUPPORTED:
1766 fprintf(stderr, _("Sorry, gnokii doesn't support used subformat in file \"%s\" !\n"), FileName);
1768 case GE_FILETOOSHORT:
1769 fprintf(stderr, _("\"%s\" logofile is too short !\n"), FileName);
1771 case GE_INVALIDIMAGESIZE:
1772 fprintf(stderr, _("Bitmap size doesn't supported by fileformat or different from 72x14, 84x48 and 72x28 !\n"));
1782 int setlogo(int argc, char *argv[])
1784 GSM_Bitmap bitmap,oldbit;
1785 GSM_NetworkInfo NetworkInfo;
1791 if (!strcmp(argv[0],"text") || !strcmp(argv[0],"dealer")) {
1792 if (!strcmp(argv[0], "text")) bitmap.type = GSM_WelcomeNoteText;
1793 else bitmap.type = GSM_DealerNoteText;
1794 bitmap.text[0] = 0x00;
1795 if (argc > 1) strncpy(bitmap.text, argv[1], 255);
1797 if (!strcmp(argv[0], "op") || !strcmp(argv[0], "startup") || !strcmp(argv[0], "caller")) {
1799 if (ReadBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) {
1804 if (!strcmp(argv[0], "op")) {
1805 if (bitmap.type != GSM_OperatorLogo || argc < 3) {
1806 if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode, NetworkInfo.NetworkCode, 7);
1808 GSM_ResizeBitmap(&bitmap, GSM_OperatorLogo, GSM_Info);
1810 strncpy(bitmap.netcode, argv[2], 7);
1811 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1812 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1817 if (!strcmp(argv[0], "startup")) {
1818 GSM_ResizeBitmap(&bitmap, GSM_StartupLogo, GSM_Info);
1820 if (!strcmp(argv[0],"caller")) {
1821 GSM_ResizeBitmap(&bitmap, GSM_CallerLogo, GSM_Info);
1823 bitmap.number = argv[2][0] - '0';
1824 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1828 oldbit.type = GSM_CallerLogo;
1829 oldbit.number = bitmap.number;
1830 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1831 /* We have to get the old name and ringtone!! */
1832 bitmap.ringtone = oldbit.ringtone;
1833 strncpy(bitmap.text, oldbit.text, 255);
1835 if (argc > 3) strncpy(bitmap.text, argv[3], 255);
1837 fprintf(stdout, _("Setting Logo.\n"));
1839 /* FIX ME: is it possible to permanently remove op logo ? */
1840 if (!strcmp(argv[0], "op"))
1842 bitmap.type = GSM_OperatorLogo;
1843 strncpy(bitmap.netcode, "000 00", 7);
1846 bitmap.size = bitmap.width * bitmap.height / 8;
1847 GSM_ClearBitmap(&bitmap);
1849 /* FIX ME: how to remove startup and group logos ? */
1850 fprintf(stdout, _("Removing Logo.\n"));
1853 fprintf(stderr, _("What kind of logo do you want to set ?\n"));
1859 error=GSM->SetBitmap(&bitmap);
1863 oldbit.type = bitmap.type;
1864 oldbit.number = bitmap.number;
1865 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1866 if (bitmap.type == GSM_WelcomeNoteText ||
1867 bitmap.type == GSM_DealerNoteText) {
1868 if (strcmp(bitmap.text, oldbit.text)) {
1869 fprintf(stderr, _("Error setting"));
1870 if (bitmap.type == GSM_DealerNoteText) fprintf(stderr, _(" dealer"));
1871 fprintf(stderr, _(" welcome note - "));
1873 /* I know, it looks horrible, but... */
1874 /* I set it to the short string - if it won't be set */
1875 /* it means, PIN is required. If it will be correct, previous */
1876 /* (user) text was too long */
1878 /* Without it, I could have such thing: */
1879 /* user set text to very short string (for example, "Marcin") */
1880 /* then enable phone without PIN and try to set it to the very long (too long for phone) */
1881 /* string (which start with "Marcin"). If we compare them as only length different, we could think, */
1882 /* that phone accepts strings 6 chars length only (length of "Marcin") */
1883 /* When we make it correct, we don't have this mistake */
1885 strcpy(oldbit.text, "!\0");
1886 GSM->SetBitmap(&oldbit);
1887 GSM->GetBitmap(&oldbit);
1888 if (oldbit.text[0]!='!') {
1889 fprintf(stderr, _("SIM card and PIN is required\n"));
1891 GSM->SetBitmap(&bitmap);
1892 GSM->GetBitmap(&oldbit);
1893 fprintf(stderr, _("too long, truncated to \"%s\" (length %i)\n"),oldbit.text,strlen(oldbit.text));
1898 if (bitmap.type == GSM_StartupLogo) {
1899 for (i = 0; i < oldbit.size; i++) {
1900 if (oldbit.bitmap[i] != bitmap.bitmap[i]) {
1901 fprintf(stderr, _("Error setting startup logo - SIM card and PIN is required\n"));
1909 if (ok) fprintf(stdout, _("Done.\n"));
1911 case GE_NOTIMPLEMENTED:
1912 fprintf(stderr, _("Function not implemented.\n"));
1914 case GE_NOTSUPPORTED:
1915 fprintf(stderr, _("This kind of logo is not supported.\n"));
1918 fprintf(stderr, _("Error !\n"));
1928 int viewlogo(char *filename)
1932 error = GSM_ShowBitmapFile(filename);
1936 /* Calendar notes receiving. */
1937 int getcalendarnote(int argc, char *argv[])
1939 GSM_CalendarNote CalendarNote;
1941 GSM_Error error = GE_NONE;
1942 int i, first_location, last_location;
1945 struct option options[] = {
1946 { "vCard", optional_argument, NULL, '1'},
1953 first_location = last_location = atoi(argv[0]);
1954 if ((argc > 1) && (argv[1][0] != '-')) {
1955 last_location = atoi(argv[1]);
1958 while ((i = getopt_long(argc, argv, "v", options, NULL)) != -1) {
1964 usage(); /* Would be better to have an calendar_usage() here. */
1970 for (i = first_location; i <= last_location; i++) {
1971 CalendarNote.Location = i;
1972 if (GSM && GSM->GetCalendarNote && GSM->Terminate) {
1973 error = GSM->GetCalendarNote(&CalendarNote);
1976 GSM_DataClear(&data);
1977 data.CalendarNote = &CalendarNote;
1979 error = SM_Functions(GOP_GetCalendarNote, &data, &State);
1984 fprintf(stdout, "BEGIN:VCALENDAR\n");
1985 fprintf(stdout, "VERSION:1.0\n");
1986 fprintf(stdout, "BEGIN:VEVENT\n");
1987 fprintf(stdout, "CATEGORIES:");
1988 switch (CalendarNote.Type) {
1990 fprintf(stdout, "MISCELLANEOUS\n");
1993 fprintf(stdout, "PHONE CALL\n");
1996 fprintf(stdout, "MEETING\n");
1999 fprintf(stdout, "SPECIAL OCCASION\n");
2002 fprintf(stdout, "UNKNOWN\n");
2005 fprintf(stdout, "SUMMARY:%s\n",CalendarNote.Text);
2006 fprintf(stdout, "DTSTART:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Time.Year,
2007 CalendarNote.Time.Month, CalendarNote.Time.Day, CalendarNote.Time.Hour,
2008 CalendarNote.Time.Minute, CalendarNote.Time.Second);
2009 if (CalendarNote.Alarm.Year!=0) {
2010 fprintf(stdout, "DALARM:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Alarm.Year,
2011 CalendarNote.Alarm.Month, CalendarNote.Alarm.Day, CalendarNote.Alarm.Hour,
2012 CalendarNote.Alarm.Minute, CalendarNote.Alarm.Second);
2014 fprintf(stdout, "END:VEVENT\n");
2015 fprintf(stdout, "END:VCALENDAR\n");
2017 } else { /* not vCal */
2018 fprintf(stdout, _(" Type of the note: "));
2020 switch (CalendarNote.Type) {
2022 fprintf(stdout, _("Reminder\n"));
2025 fprintf(stdout, _("Call\n"));
2028 fprintf(stdout, _("Meeting\n"));
2031 fprintf(stdout, _("Birthday\n"));
2034 fprintf(stdout, _("Unknown\n"));
2038 fprintf(stdout, _(" Date: %d-%02d-%02d\n"), CalendarNote.Time.Year,
2039 CalendarNote.Time.Month,
2040 CalendarNote.Time.Day);
2042 fprintf(stdout, _(" Time: %02d:%02d:%02d\n"), CalendarNote.Time.Hour,
2043 CalendarNote.Time.Minute,
2044 CalendarNote.Time.Second);
2046 if (CalendarNote.Alarm.AlarmEnabled == 1) {
2047 fprintf(stdout, _(" Alarm date: %d-%02d-%02d\n"), CalendarNote.Alarm.Year,
2048 CalendarNote.Alarm.Month,
2049 CalendarNote.Alarm.Day);
2051 fprintf(stdout, _(" Alarm time: %02d:%02d:%02d\n"), CalendarNote.Alarm.Hour,
2052 CalendarNote.Alarm.Minute,
2053 CalendarNote.Alarm.Second);
2056 fprintf(stdout, _(" Text: %s\n"), CalendarNote.Text);
2058 if (CalendarNote.Type == GCN_CALL)
2059 fprintf(stdout, _(" Phone: %s\n"), CalendarNote.Phone);
2062 case GE_NOTIMPLEMENTED:
2063 fprintf(stderr, _("Function not implemented.\n"));
2066 fprintf(stderr, _("The calendar note can not be read\n"));
2075 /* Writing calendar notes. */
2076 int writecalendarnote(char *argv[])
2078 GSM_CalendarNote CalendarNote;
2080 if (GSM_ReadVCalendarFile(argv[0], &CalendarNote, atoi(argv[1]))) {
2081 fprintf(stdout, _("Failed to load vCalendar file.\n"));
2085 /* Error 22=Calendar full ;-) */
2086 if ((GSM->WriteCalendarNote(&CalendarNote)) == GE_NONE)
2087 fprintf(stdout, _("Succesfully written!\n"));
2089 fprintf(stdout, _("Failed to write calendar note!\n"));
2096 /* Calendar note deleting. */
2097 int deletecalendarnote(int argc, char *argv[])
2099 GSM_CalendarNote CalendarNote;
2100 int i, first_location, last_location;
2102 first_location = last_location = atoi(argv[0]);
2103 if (argc > 1) last_location = atoi(argv[1]);
2105 for (i = first_location; i <= last_location; i++) {
2107 CalendarNote.Location = i;
2109 if (GSM->DeleteCalendarNote(&CalendarNote) == GE_NONE) {
2110 fprintf(stdout, _(" Calendar note deleted.\n"));
2112 fprintf(stderr, _("The calendar note can not be deleted\n"));
2122 /* Setting the date and time. */
2123 int setdatetime(int argc, char *argv[])
2130 now = localtime(&nowh);
2132 Date.Year = now->tm_year;
2133 Date.Month = now->tm_mon+1;
2134 Date.Day = now->tm_mday;
2135 Date.Hour = now->tm_hour;
2136 Date.Minute = now->tm_min;
2137 Date.Second = now->tm_sec;
2139 if (argc > 0) Date.Year = atoi (argv[0]);
2140 if (argc > 1) Date.Month = atoi (argv[1]);
2141 if (argc > 2) Date.Day = atoi (argv[2]);
2142 if (argc > 3) Date.Hour = atoi (argv[3]);
2143 if (argc > 4) Date.Minute = atoi (argv[4]);
2145 if (Date.Year < 1900) {
2147 /* Well, this thing is copyrighted in U.S. This technique is known as
2148 Windowing and you can read something about it in LinuxWeekly News:
2149 http://lwn.net/1999/features/Windowing.phtml. This thing is beeing
2150 written in Czech republic and Poland where algorithms are not allowed
2154 Date.Year = Date.Year + 1900;
2156 Date.Year = Date.Year + 2000;
2159 /* FIXME: Error checking should be here. */
2160 GSM->SetDateTime(&Date);
2167 /* In this mode we receive the date and time from mobile phone. */
2168 int getdatetime(void) {
2170 GSM_DateTime date_time;
2173 if (GSM && GSM->GetDateTime && GSM->Terminate) {
2174 error = GSM->GetDateTime(&date_time);
2177 GSM_DataClear(&data);
2178 data.DateTime = &date_time;
2180 error = SM_Functions(GOP_GetDateTime, &data, &State);
2185 fprintf(stdout, _("Date: %4d/%02d/%02d\n"), date_time.Year, date_time.Month, date_time.Day);
2186 fprintf(stdout, _("Time: %02d:%02d:%02d\n"), date_time.Hour, date_time.Minute, date_time.Second);
2188 case GE_NOTIMPLEMENTED:
2189 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2192 fprintf(stdout, _("Internal error\n"));
2199 /* Setting the alarm. */
2200 int setalarm(char *argv[])
2204 Date.Hour = atoi(argv[0]);
2205 Date.Minute = atoi(argv[1]);
2207 GSM->SetAlarm(1, &Date);
2214 /* Getting the alarm. */
2219 GSM_DateTime date_time;
2221 if (GSM && GSM->GetAlarm && GSM->Terminate) {
2222 error = GSM->GetAlarm(0, &date_time);
2225 GSM_DataClear(&data);
2226 data.DateTime = &date_time;
2228 error = SM_Functions(GOP_GetAlarm, &data, &State);
2233 fprintf(stdout, _("Alarm: %s\n"), (date_time.AlarmEnabled==0)?"off":"on");
2234 fprintf(stdout, _("Time: %02d:%02d\n"), date_time.Hour, date_time.Minute);
2236 case GE_NOTIMPLEMENTED:
2237 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2240 fprintf(stdout, _("Internal error\n"));
2247 /* In monitor mode we don't do much, we just initialise the fbus code.
2248 Note that the fbus code no longer has an internal monitor mode switch,
2249 instead compile with DEBUG enabled to get all the gumpf. */
2250 int monitormode(void)
2252 float rflevel = -1, batterylevel = -1;
2253 // GSM_PowerSource powersource = -1;
2254 GSM_RFUnits rf_units = GRF_Arbitrary;
2255 GSM_BatteryUnits batt_units = GBU_Arbitrary;
2256 GSM_Statemachine *sm = &State;
2259 // GSM_NetworkInfo NetworkInfo;
2260 // GSM_CBMessage CBMessage;
2262 GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0};
2263 GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0};
2264 GSM_MemoryStatus DC_MemoryStatus = {GMT_DC, 0, 0};
2265 GSM_MemoryStatus EN_MemoryStatus = {GMT_EN, 0, 0};
2266 GSM_MemoryStatus FD_MemoryStatus = {GMT_FD, 0, 0};
2267 GSM_MemoryStatus LD_MemoryStatus = {GMT_LD, 0, 0};
2268 GSM_MemoryStatus MC_MemoryStatus = {GMT_MC, 0, 0};
2269 GSM_MemoryStatus ON_MemoryStatus = {GMT_ON, 0, 0};
2270 GSM_MemoryStatus RC_MemoryStatus = {GMT_RC, 0, 0};
2272 // GSM_SMSStatus SMSStatus = {0, 0};
2276 GSM_DataClear(&data);
2278 /* We do not want to monitor serial line forever - press Ctrl+C to stop the
2280 signal(SIGINT, interrupted);
2282 fprintf (stderr, _("Entering monitor mode...\n"));
2285 //GSM->EnableCellBroadcast();
2287 /* Loop here indefinitely - allows you to see messages from GSM code in
2288 response to unknown messages etc. The loops ends after pressing the
2290 data.RFUnits=&rf_units;
2291 data.RFLevel=&rflevel;
2292 data.BatteryUnits=&batt_units;
2293 data.BatteryLevel=&batterylevel;
2295 while (!bshutdown) {
2296 if (SM_Functions(GOP_GetRFLevel,&data,sm) == GE_NONE)
2297 fprintf(stdout, _("RFLevel: %d\n"), (int)rflevel);
2299 if (SM_Functions(GOP_GetBatteryLevel,&data,sm) == GE_NONE)
2300 fprintf(stdout, _("Battery: %d\n"), (int)batterylevel);
2302 // if (GSM->GetPowerSource(&powersource) == GE_NONE)
2303 // fprintf(stdout, _("Power Source: %s\n"), (powersource==GPS_ACDC)?_("AC/DC"):_("battery"));
2305 data.MemoryStatus=&SIMMemoryStatus;
2306 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2307 fprintf(stdout, _("SIM: Used %d, Free %d\n"), SIMMemoryStatus.Used, SIMMemoryStatus.Free);
2309 data.MemoryStatus=&PhoneMemoryStatus;
2310 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2311 fprintf(stdout, _("Phone: Used %d, Free %d\n"), PhoneMemoryStatus.Used, PhoneMemoryStatus.Free);
2313 data.MemoryStatus=&DC_MemoryStatus;
2314 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2315 fprintf(stdout, _("DC: Used %d, Free %d\n"), DC_MemoryStatus.Used, DC_MemoryStatus.Free);
2317 data.MemoryStatus=&EN_MemoryStatus;
2318 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2319 fprintf(stdout, _("EN: Used %d, Free %d\n"), EN_MemoryStatus.Used, EN_MemoryStatus.Free);
2321 data.MemoryStatus=&FD_MemoryStatus;
2322 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2323 fprintf(stdout, _("FD: Used %d, Free %d\n"), FD_MemoryStatus.Used, FD_MemoryStatus.Free);
2325 data.MemoryStatus=&LD_MemoryStatus;
2326 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2327 fprintf(stdout, _("LD: Used %d, Free %d\n"), LD_MemoryStatus.Used, LD_MemoryStatus.Free);
2329 data.MemoryStatus=&MC_MemoryStatus;
2330 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2331 fprintf(stdout, _("MC: Used %d, Free %d\n"), MC_MemoryStatus.Used, MC_MemoryStatus.Free);
2333 data.MemoryStatus=&ON_MemoryStatus;
2334 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2335 fprintf(stdout, _("ON: Used %d, Free %d\n"), ON_MemoryStatus.Used, ON_MemoryStatus.Free);
2337 data.MemoryStatus=&RC_MemoryStatus;
2338 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2339 fprintf(stdout, _("RC: Used %d, Free %d\n"), RC_MemoryStatus.Used, RC_MemoryStatus.Free);
2341 // if (GSM->GetSMSStatus(&SMSStatus) == GE_NONE)
2342 // fprintf(stdout, _("SMS Messages: UnRead %d, Number %d\n"), SMSStatus.UnRead, SMSStatus.Number);
2344 // if (GSM->GetIncomingCallNr(Number) == GE_NONE)
2345 // fprintf(stdout, _("Incoming call: %s\n"), Number);
2347 // if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE)
2348 // fprintf(stdout, _("Network: %s (%s), LAC: %s, CellID: %s\n"), GSM_GetNetworkName (NetworkInfo.NetworkCode), GSM_GetCountryName(NetworkInfo.NetworkCode), NetworkInfo.LAC, NetworkInfo.CellID);
2350 // if (GSM->ReadCellBroadcast(&CBMessage) == GE_NONE)
2351 // fprintf(stdout, _("Cell broadcast received on channel %d: %s\n"), CBMessage.Channel, CBMessage.Message);
2356 fprintf (stderr, _("Leaving monitor mode...\n"));
2366 static GSM_Error PrettyOutputFn(char *Display, char *Indicators)
2369 printf(ESC "[10;0H Display is:\n%s\n", Display);
2371 printf(ESC "[9;0H Indicators: %s \n", Indicators);
2372 printf(ESC "[1;1H");
2377 // Uncomment it if used
2378 static GSM_Error OutputFn(char *Display, char *Indicators)
2381 printf("New display is:\n%s\n", Display);
2383 printf("Indicators: %s\n", Indicators);
2388 void console_raw(void)
2393 tcgetattr(fileno(stdin), &it);
2394 it.c_lflag &= ~(ICANON);
2395 //it.c_iflag &= ~(INPCK|ISTRIP|IXON);
2399 tcsetattr(fileno(stdin), TCSANOW, &it);
2403 int displayoutput(void)
2406 GSM_Statemachine *sm = &State;
2409 data.OutputFn = PrettyOutputFn;
2411 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2413 fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
2415 if (error == GE_NONE) {
2417 /* We do not want to see texts forever - press Ctrl+C to stop. */
2418 signal(SIGINT, interrupted);
2420 fprintf (stderr, _("Entered display monitoring mode...\n"));
2421 fprintf (stderr, ESC "c" );
2423 /* Loop here indefinitely - allows you to read texts from phone's
2424 display. The loops ends after pressing the Ctrl+C. */
2425 while (!bshutdown) {
2427 memset(&buf[0], 0, 102);
2428 while (read(0, buf, 100) > 0) {
2429 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
2430 if (GSM->HandleString(buf) != GE_NONE)
2431 fprintf(stdout, _("Key press simulation failed.\n"));
2432 memset(buf, 0, 102);
2436 fprintf (stderr, "Shutting down\n");
2438 fprintf (stderr, _("Leaving display monitor mode...\n"));
2439 data.OutputFn = NULL;
2441 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2442 if (error != GE_NONE)
2443 fprintf (stderr, _("Error!\n"));
2445 fprintf (stderr, _("Error!\n"));
2451 /* Reads profile from phone and displays its' settings */
2452 int getprofile(int argc, char *argv[])
2456 GSM_Profile profile;
2459 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2463 error = GSM->GetProfile(&profile);
2465 if (error == GE_NONE) {
2467 while (GSM->GetModel(model) != GE_NONE)
2470 max_profiles = 7; /* This is correct for 6110 (at least my). How do we get
2471 the number of profiles? */
2474 /*FIX ME: It should be set to 3 for N5130 and 3210 too*/
2475 if (!strcmp(model, "NSE-1"))
2479 profile.Number = atoi(argv[0]) - 1;
2480 start = profile.Number;
2483 if (profile.Number < 0) {
2484 fprintf(stderr, _("Profile number must be value from 1 to %d!\n"), max_profiles);
2489 if (profile.Number >= max_profiles) {
2490 fprintf(stderr, _("This phone supports only %d profiles!\n"), max_profiles);
2496 stop = max_profiles;
2503 if (profile.Number != 0)
2504 GSM->GetProfile(&profile);
2506 fprintf(stdout, "%d. \"%s\"\n", profile.Number + 1, profile.Name);
2507 if (profile.DefaultName == -1) fprintf(stdout, _(" (name defined)\n"));
2509 fprintf(stdout, _("Incoming call alert: %s\n"), GetProfileCallAlertString(profile.CallAlert));
2511 /* For different phones different ringtones names */
2513 if (!strcmp(model, "NSE-3"))
2514 fprintf(stdout, _("Ringing tone: %s (%d)\n"), RingingTones[profile.Ringtone], profile.Ringtone);
2516 fprintf(stdout, _("Ringtone number: %d\n"), profile.Ringtone);
2518 fprintf(stdout, _("Ringing volume: %s\n"), GetProfileVolumeString(profile.Volume));
2520 fprintf(stdout, _("Message alert tone: %s\n"), GetProfileMessageToneString(profile.MessageTone));
2522 fprintf(stdout, _("Keypad tones: %s\n"), GetProfileKeypadToneString(profile.KeypadTone));
2524 fprintf(stdout, _("Warning and game tones: %s\n"), GetProfileWarningToneString(profile.WarningTone));
2526 /* FIXME: Light settings is only used for Car */
2527 if (profile.Number == (max_profiles - 2)) fprintf(stdout, _("Lights: %s\n"), profile.Lights ? _("On") : _("Automatic"));
2529 fprintf(stdout, _("Vibration: %s\n"), GetProfileVibrationString(profile.Vibration));
2531 /* FIXME: it will be nice to add here reading caller group name. */
2532 if (max_profiles != 3) fprintf(stdout, _("Caller groups: 0x%02x\n"), profile.CallerGroups);
2534 /* FIXME: Automatic answer is only used for Car and Headset. */
2535 if (profile.Number >= (max_profiles - 2)) fprintf(stdout, _("Automatic answer: %s\n"), profile.AutomaticAnswer ? _("On") : _("Off"));
2537 fprintf(stdout, "\n");
2542 if (error == GE_NOTIMPLEMENTED) {
2543 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2547 fprintf(stderr, _("Unspecified error\n"));
2557 /* Get requested range of memory storage entries and output to stdout in
2558 easy-to-parse format */
2559 int getmemory(int argc, char *argv[])
2561 GSM_PhonebookEntry entry;
2564 char *memory_type_string;
2567 GSM_Statemachine *sm = &State;
2569 /* Handle command line args that set type, start and end locations. */
2570 memory_type_string = argv[0];
2571 entry.MemoryType = StrToMemoryType(memory_type_string);
2572 if (entry.MemoryType == GMT_XX) {
2573 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
2577 start_entry = atoi (argv[1]);
2578 if (argc > 2) end_entry = atoi (argv[2]);
2579 else end_entry = start_entry;
2581 /* Now retrieve the requested entries. */
2582 for (count = start_entry; count <= end_entry; count ++) {
2584 entry.Location = count;
2586 data.PhonebookEntry=&entry;
2587 error=SM_Functions(GOP_ReadPhonebook,&data,sm);
2589 if (error == GE_NONE) {
2590 fprintf(stdout, "%s;%s;%s;%d;%d\n", entry.Name, entry.Number, memory_type_string, entry.Location, entry.Group);
2591 if (entry.MemoryType == GMT_MC || entry.MemoryType == GMT_DC || entry.MemoryType == GMT_RC)
2592 fprintf(stdout, "%02u.%02u.%04u %02u:%02u:%02u\n", entry.Date.Day, entry.Date.Month, entry.Date.Year, entry.Date.Hour, entry.Date.Minute, entry.Date.Second);
2595 if (error == GE_NOTIMPLEMENTED) {
2596 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2599 else if (error == GE_INVALIDMEMORYTYPE) {
2600 fprintf(stderr, _("Memory type %s not supported!\n"), memory_type_string);
2604 fprintf(stdout, _("%s|%d|Bad location or other error!(%d)\n"), memory_type_string, count, error);
2610 /* Read data from stdin, parse and write to phone. The parsing is relatively
2611 crude and doesn't allow for much variation from the stipulated format. */
2612 /* FIXME: I guess there's *very* similar code in xgnokii */
2613 int writephonebook(int argc, char *args[])
2615 GSM_PhonebookEntry entry;
2617 char *memory_type_string;
2621 char *Line, OLine[100], BackLine[100];
2624 /* Check argument */
2625 if (argc && (strcmp("-i", args[0])))
2630 /* Go through data from stdin. */
2631 while (GetLine(stdin, Line, 99)) {
2632 strcpy(BackLine, Line);
2635 ptr = strtok(Line, ";");
2636 if (ptr) strcpy(entry.Name, ptr);
2637 else entry.Name[0] = 0;
2639 ptr = strtok(NULL, ";");
2640 if (ptr) strcpy(entry.Number, ptr);
2641 else entry.Number[0] = 0;
2643 ptr = strtok(NULL, ";");
2646 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2651 if (!strncmp(ptr,"ME", 2)) {
2652 memory_type_string = "int";
2653 entry.MemoryType = GMT_ME;
2655 if (!strncmp(ptr,"SM", 2)) {
2656 memory_type_string = "sim";
2657 entry.MemoryType = GMT_SM;
2659 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2664 ptr = strtok(NULL, ";");
2665 if (ptr) entry.Location = atoi(ptr);
2666 else entry.Location = 0;
2668 ptr = strtok(NULL, ";");
2669 if (ptr) entry.Group = atoi(ptr);
2670 else entry.Group = 0;
2673 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2677 for (subentry = 0; ; subentry++) {
2678 ptr = strtok(NULL, ";");
2680 if (ptr && *ptr != 0)
2681 entry.SubEntries[subentry].EntryType = atoi(ptr);
2685 ptr = strtok(NULL, ";");
2687 entry.SubEntries[subentry].NumberType=atoi(ptr);
2689 /* Phone Numbers need to have a number type. */
2690 if (!ptr && entry.SubEntries[subentry].EntryType == GSM_Number) {
2691 fprintf(stderr, _("Missing phone number type on line %d"
2692 " entry %d [%s]\n"), line_count, subentry, BackLine);
2697 ptr = strtok(NULL, ";");
2699 entry.SubEntries[subentry].BlockNumber=atoi(ptr);
2701 ptr = strtok(NULL, ";");
2703 /* 0x13 Date Type; it is only for Dailed Numbers, etc.
2704 we don't store to this memories so it's an error to use it. */
2705 if (!ptr || entry.SubEntries[subentry].EntryType == GSM_Date) {
2706 fprintf(stdout, _("There is no phone number on line %d entry %d [%s]\n"),
2707 line_count, subentry, BackLine);
2711 strcpy(entry.SubEntries[subentry].data.Number, ptr);
2714 entry.SubEntriesCount = subentry;
2716 /* This is to send other exports (like from 6110) to 7110 */
2717 if (!entry.SubEntriesCount) {
2718 entry.SubEntriesCount = 1;
2719 entry.SubEntries[subentry].EntryType = GSM_Number;
2720 entry.SubEntries[subentry].NumberType = GSM_General;
2721 entry.SubEntries[subentry].BlockNumber = 2;
2722 strcpy(entry.SubEntries[subentry].data.Number, entry.Number);
2728 GSM_PhonebookEntry aux;
2730 aux.Location = entry.Location;
2731 error = GSM->GetMemoryLocation(&aux);
2733 if (error == GE_NONE) {
2738 fprintf(stdout, _("Location busy. "));
2739 while (confirm < 0) {
2740 fprintf(stdout, _("Overwrite? (yes/no) "));
2741 GetLine(stdin, ans, 7);
2742 if (!strcmp(ans, _("yes"))) confirm = 1;
2743 else if (!strcmp(ans, _("no"))) confirm = 0;
2745 if (!confirm) continue;
2748 fprintf(stderr, _("Unknown error (%d)\n"), error);
2754 /* Do write and report success/failure. */
2755 error = GSM->WritePhonebookLocation(&entry);
2757 if (error == GE_NONE)
2758 fprintf (stdout, _("Write Succeeded: memory type: %s, loc: %d, name: %s, number: %s\n"), memory_type_string, entry.Location, entry.Name, entry.Number);
2760 fprintf (stdout, _("Write FAILED(%d): memory type: %s, loc: %d, name: %s, number: %s\n"), error, memory_type_string, entry.Location, entry.Name, entry.Number);
2768 /* Getting speed dials. */
2769 int getspeeddial(char *Number)
2771 GSM_SpeedDial SpeedDial;
2775 SpeedDial.Number = atoi(Number);
2777 if (GSM && GSM->GetSpeedDial && GSM->Terminate) {
2778 error = GSM->GetSpeedDial(&SpeedDial);
2781 GSM_DataClear(&data);
2782 data.SpeedDial = &SpeedDial;
2784 error = SM_Functions(GOP_GetSpeedDial, &data, &State);
2789 fprintf(stdout, _("SpeedDial nr. %d: %d:%d\n"), SpeedDial.Number, SpeedDial.MemoryType, SpeedDial.Location);
2791 case GE_NOTIMPLEMENTED:
2792 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2795 fprintf(stdout, _("Internal error\n"));
2802 /* Setting speed dials. */
2803 int setspeeddial(char *argv[])
2805 GSM_SpeedDial entry;
2807 char *memory_type_string;
2809 /* Handle command line args that set type, start and end locations. */
2811 if (strcmp(argv[1], "ME") == 0) {
2812 entry.MemoryType = 0x02;
2813 memory_type_string = "ME";
2814 } else if (strcmp(argv[1], "SM") == 0) {
2815 entry.MemoryType = 0x03;
2816 memory_type_string = "SM";
2818 fprintf(stderr, _("Unknown memory type %s!\n"), argv[1]);
2822 entry.Number = atoi(argv[0]);
2823 entry.Location = atoi(argv[2]);
2825 if (GSM->SetSpeedDial(&entry) == GE_NONE) {
2826 fprintf(stdout, _("Succesfully written!\n"));
2833 /* Getting the status of the display. */
2834 int getdisplaystatus(void)
2838 GSM->GetDisplayStatus(&Status);
2840 fprintf(stdout, _("Call in progress: %s\n"), Status & (1<<DS_Call_In_Progress)?_("on"):_("off"));
2841 fprintf(stdout, _("Unknown: %s\n"), Status & (1<<DS_Unknown)?_("on"):_("off"));
2842 fprintf(stdout, _("Unread SMS: %s\n"), Status & (1<<DS_Unread_SMS)?_("on"):_("off"));
2843 fprintf(stdout, _("Voice call: %s\n"), Status & (1<<DS_Voice_Call)?_("on"):_("off"));
2844 fprintf(stdout, _("Fax call active: %s\n"), Status & (1<<DS_Fax_Call)?_("on"):_("off"));
2845 fprintf(stdout, _("Data call active: %s\n"), Status & (1<<DS_Data_Call)?_("on"):_("off"));
2846 fprintf(stdout, _("Keyboard lock: %s\n"), Status & (1<<DS_Keyboard_Lock)?_("on"):_("off"));
2847 fprintf(stdout, _("SMS storage full: %s\n"), Status & (1<<DS_SMS_Storage_Full)?_("on"):_("off"));
2853 int netmonitor(char *Mode)
2855 unsigned char mode = atoi(Mode);
2858 if (!strcmp(Mode, "reset"))
2860 else if (!strcmp(Mode, "off"))
2862 else if (!strcmp(Mode, "field"))
2864 else if (!strcmp(Mode, "devel"))
2866 else if (!strcmp(Mode, "next"))
2869 memset(&Screen, 0, 50);
2870 GSM->NetMonitor(mode, Screen);
2873 fprintf(stdout, "%s\n", Screen);
2881 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2882 char imei[64], model[64], rev[64], manufacturer[64];
2883 GSM_Statemachine *sm = &State;
2885 data.Manufacturer=manufacturer;
2890 /* Retrying is bad idea: what if function is simply not implemented?
2891 Anyway let's wait 2 seconds for the right packet from the phone. */
2894 strcpy(imei, "(unknown)");
2895 strcpy(manufacturer, "(unknown)");
2896 strcpy(model, "(unknown)");
2897 strcpy(rev, "(unknown)");
2899 SM_Functions(GOP_Identify, &data, sm);
2901 fprintf(stdout, _("IMEI: %s\n"), imei);
2902 fprintf(stdout, _("Manufacturer: %s\n"), manufacturer);
2903 fprintf(stdout, _("Model: %s\n"), model);
2904 fprintf(stdout, _("Revision: %s\n"), rev);
2911 int senddtmf(char *String)
2913 GSM->SendDTMF(String);
2918 /* Resets the phone */
2919 int reset( char *type)
2921 unsigned char _type = 0x03;
2924 if(!strcmp(type, "soft"))
2927 if(!strcmp(type, "hard"))
2930 fprintf(stderr, _("What kind of reset do you want??\n"));
2941 /* pmon allows fbus code to run in a passive state - it doesn't worry about
2942 whether comms are established with the phone. A debugging/development
2948 GSM_ConnectionType connection=GCT_Serial;
2949 GSM_Statemachine sm;
2951 /* Initialise the code for the GSM interface. */
2952 error = GSM_Initialise(model, Port, Initlength, connection, NULL, &sm);
2954 if (error != GE_NONE) {
2955 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
2966 int sendringtone(int argc, char *argv[])
2969 GSM_Ringtone ringtone;
2971 int size = GSM_MAX_RINGTONE_PACKAGE_LENGTH;
2972 char Package[GSM_MAX_RINGTONE_PACKAGE_LENGTH];
2974 struct option options[] = {
2979 /* Default settings for SMS message:
2980 - no delivery report
2986 - set UserDataHeaderIndicator
2991 SMS.Compression = false;
2992 SMS.EightBit = true;
2993 SMS.MessageCenter.No = 1;
2994 SMS.Validity = 4320; /* 4320 minutes == 72 hours */
2996 SMS_SetupUDH(&SMS,GSM_RingtoneUDH); /* error ignored */
3003 while ((i = getopt_long(argc, argv, "", options, NULL)) != -1) {
3004 if (smsc_options_parse(i,&SMS))
3008 usage(); /* Would be better to have an sendsms_usage() here. */
3017 if (GSM_ReadRingtoneFile(argv[1], &ringtone)) {
3018 fprintf(stdout, _("Failed to load ringtone.\n"));
3021 if (strlen(argv[0])+1 > sizeof(SMS.Destination)) {
3022 fprintf(stdout, _("Destination number \"%s\" length too long!\n"), argv[0]);
3025 strcpy(SMS.Destination, argv[0]);
3026 GSM_PackRingtone(&ringtone, Package, &size);
3028 sendsms_deconcatenated(&SMS,Package,size,true/*useudh*/);
3035 int setringtone(int argc, char *argv[])
3037 GSM_Ringtone ringtone;
3040 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
3041 fprintf(stdout, _("Failed to load ringtone.\n"));
3045 error = GSM->SetRingtone(&ringtone);
3047 if (error == GE_NONE)
3048 fprintf(stdout, _("Send succeeded!\n"));
3050 fprintf(stdout, _("Send failed\n"));
3056 int presskeysequence(void)
3062 memset(&buf[0], 0, 102);
3063 while (read(0, buf, 100) > 0) {
3064 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
3065 if (GSM->HandleString(buf) != GE_NONE)
3066 fprintf(stdout, _("Key press simulation failed.\n"));
3067 memset(buf, 0, 102);
3074 /* This is a "convenience" function to allow quick test of new API stuff which
3075 doesn't warrant a "proper" command line function. */
3077 int foogle(char *argv[])
3079 /* Initialise the code for the GSM interface. */
3081 // Fill in what you would like to test here...