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.1 2001/11/25 21:59:18 short
23 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
25 Revision 1.151 2001/11/22 17:56:53 pkot
26 smslib update. sms sending
28 Revision 1.150 2001/11/20 16:22:22 pkot
29 First attempt to read Picture Messages. They should appear when you enable DEBUG. Nokia seems to break own standards. :/ (Markus Plail)
31 Revision 1.149 2001/11/19 16:00:15 pkot
34 Revision 1.148 2001/11/19 13:46:43 pkot
35 reading unread SMS in 6210 from Inbox. Folder updates (Markus Plail)
37 Revision 1.147 2001/11/18 00:54:32 pkot
38 Bugfixes. I18n of the user responses. UDH support in libsms. Business Card UDH Type
40 Revision 1.146 2001/11/17 20:18:33 pkot
41 Added dau9p connection type for 6210/7110
43 Revision 1.145 2001/11/14 10:46:12 pkot
44 Small cleanup with __unices__
46 Revision 1.144 2001/11/08 16:34:19 pkot
47 Updates to work with new libsms
49 Revision 1.143 2001/09/14 13:30:07 pkot
50 Fixed bugs introduced during 0.3.3 merge
52 Revision 1.142 2001/09/14 13:02:03 pkot
53 Gnokii calendar changes from 0.3.3
55 Revision 1.141 2001/09/14 12:53:00 pkot
58 Set valid operator on logos xgnokii screen.
60 Revision 1.140 2001/07/27 00:02:21 pkot
61 Generic AT support for the new structure (Manfred Jonsson)
63 Revision 1.139 2001/07/01 23:16:45 pkot
64 Fixed a typo in gnokii.c avoiding saving logo (Jan Havelka)
66 Revision 1.138 2001/06/28 00:28:45 pkot
67 Small docs updates (Pawel Kot)
69 Revision 1.137 2001/06/27 23:52:50 pkot
70 7110/6210 updates (Marian Jancar)
72 Revision 1.136 2001/06/10 23:49:49 pkot
73 Small fixes to hide compilation warnings and allow gnokii.c to compile
75 Revision 1.135 2001/06/10 11:42:26 machek
76 Cleanup: some formating, made Statemachine global, converted to new
77 structure w.r.t. SMS-es
79 Revision 1.134 2001/05/24 20:47:30 chris
80 More updating of 7110 code and some of xgnokii_lowlevel changed over.
82 Revision 1.133 2001/04/23 17:20:01 pkot
83 Added possibility for viewing logos (currently nol and ngg) on console (Bartek Klepacz)
85 Revision 1.132 2001/03/21 23:36:06 chris
86 Added the statemachine
87 This will break gnokii --identify and --monitor except for 6210/7110
89 Revision 1.131 2001/03/19 23:43:46 pkot
90 Solaris / BSD '#if defined' cleanup
92 Revision 1.130 2001/03/13 01:23:18 pkot
93 Windows updates (Manfred Jonsson)
95 Revision 1.129 2001/03/13 01:21:39 pkot
96 *BSD updates (Bert Driehuis)
98 Revision 1.128 2001/03/08 00:49:06 pkot
99 Fixed bug (introduced by me) in getmemory function. Now gnokii.c should compile
101 Revision 1.127 2001/03/08 00:18:13 pkot
102 Fixed writephonebook once again. Someone kick me please...
104 Revision 1.126 2001/03/07 21:46:12 pkot
105 Fixed writephonebook patch
107 Revision 1.125 2001/03/06 22:19:14 pkot
108 Cleanups and fixes in gnokii.c:
110 - fixed bug reported by Gabriele Zappi
111 - fixed small bugs introduced by Pavel Machek
113 Revision 1.124 2001/02/28 21:42:00 machek
114 Possibility to force overwrite in --getsms (-F). Possibility to get
115 multiple files (use --getsms -f xyzzy%d), cleanup.
117 Revision 1.123 2001/02/20 21:55:11 pkot
118 Small #include updates
120 Revision 1.122 2001/02/16 14:29:53 chris
121 Restructure of common/. Fixed a problem in fbus-phonet.c
122 Lots of dprintfs for Marcin
123 Any size xpm can now be loaded (eg for 7110 startup logos)
124 nk7110 code detects 7110/6210 and alters startup logo size to suit
125 Moved Marcin's extended phonebook code into gnokii.c
127 Revision 1.121 2001/02/06 21:15:35 chris
128 Preliminary irda support for 7110 etc. Not well tested!
130 Revision 1.120 2001/02/06 08:13:32 pkot
131 One more include in gnokii.c needed
133 Revision 1.119 2001/02/05 12:29:37 pkot
134 Changes needed to let unicode work
136 Revision 1.118 2001/02/01 15:17:33 pkot
137 Fixed --identify and added Manfred's manufacturer patch
139 Revision 1.117 2001/01/31 23:45:27 pkot
140 --identify should work ok now
142 Revision 1.116 2001/01/24 20:19:55 machek
143 Do not retry identification, if it is not implemented, it is bad idea.
145 Revision 1.115 2001/01/22 01:25:10 hugh
146 Tweaks for 3810 series, datacalls seem to be broken so need to do
147 some more debugging...
149 Revision 1.114 2001/01/17 02:54:55 chris
150 More 7110 work. Use with care! (eg it is not possible to delete phonebook entries)
151 I can now edit my phonebook in xgnokii but it is 'work in progress'.
153 Revision 1.113 2001/01/15 17:00:49 pkot
154 Initial keypress sequence support. Disable compilation warning
156 Revision 1.112 2001/01/12 14:09:13 pkot
157 More cleanups. This time mainly in the code.
159 Revision 1.111 2001/01/10 16:32:18 pkot
160 Documentation updates.
161 FreeBSD fix for 3810 code.
162 Added possibility for deleting SMS just after reading it in gnokii.
166 Revision 1.110 2001/01/08 15:11:37 pkot
167 Documentation updates.
168 Fixed some bugs and removed FIXMEs.
169 We need to move some stuff from configure.in to aclocal.m4
171 Revision 1.109 2000/12/29 15:39:07 pkot
172 Reverted a change in fbus-3810.c which broke compling with --enable-debug.
173 Small fixes in gnokii.c
175 Revision 1.108 2000/12/19 16:18:16 pkot
176 configure script updates and added shared function for configfile reading
188 # include <strings.h> /* for memset */
191 #include <sys/types.h>
192 #include <sys/stat.h>
197 #define sleep(x) Sleep((x) * 1000)
198 #define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
200 #include "win32/getopt.h"
215 #include "gsm-common.h"
217 #include "gsm-networks.h"
218 #include "cfgreader.h"
220 #include "gsm-filetypes.h"
221 #include "gsm-bitmaps.h"
222 #include "gsm-ringtones.h"
223 #include "gsm-statemachine.h"
225 char *model; /* Model from .gnokiirc file. */
226 char *Port; /* Serial port from .gnokiirc file */
227 char *Initlength; /* Init length from .gnokiirc file */
228 char *Connection; /* Connection type from .gnokiirc file */
229 char *BinDir; /* Binaries directory from .gnokiirc file - not used here yet */
230 /* Local variables */
232 char *GetProfileCallAlertString(int code)
235 case PROFILE_CALLALERT_RINGING: return "Ringing";
236 case PROFILE_CALLALERT_ASCENDING: return "Ascending";
237 case PROFILE_CALLALERT_RINGONCE: return "Ring once";
238 case PROFILE_CALLALERT_BEEPONCE: return "Beep once";
239 case PROFILE_CALLALERT_CALLERGROUPS: return "Caller groups";
240 case PROFILE_CALLALERT_OFF: return "Off";
241 default: return "Unknown";
245 char *GetProfileVolumeString(int code)
248 case PROFILE_VOLUME_LEVEL1: return "Level 1";
249 case PROFILE_VOLUME_LEVEL2: return "Level 2";
250 case PROFILE_VOLUME_LEVEL3: return "Level 3";
251 case PROFILE_VOLUME_LEVEL4: return "Level 4";
252 case PROFILE_VOLUME_LEVEL5: return "Level 5";
253 default: return "Unknown";
257 char *GetProfileKeypadToneString(int code)
260 case PROFILE_KEYPAD_OFF: return "Off";
261 case PROFILE_KEYPAD_LEVEL1: return "Level 1";
262 case PROFILE_KEYPAD_LEVEL2: return "Level 2";
263 case PROFILE_KEYPAD_LEVEL3: return "Level 3";
264 default: return "Unknown";
268 char *GetProfileMessageToneString(int code)
271 case PROFILE_MESSAGE_NOTONE: return "No tone";
272 case PROFILE_MESSAGE_STANDARD: return "Standard";
273 case PROFILE_MESSAGE_SPECIAL: return "Special";
274 case PROFILE_MESSAGE_BEEPONCE: return "Beep once";
275 case PROFILE_MESSAGE_ASCENDING: return "Ascending";
276 default: return "Unknown";
280 char *GetProfileWarningToneString(int code)
283 case PROFILE_WARNING_OFF: return "Off";
284 case PROFILE_WARNING_ON: return "On";
285 default: return "Unknown";
289 char *GetProfileVibrationString(int code)
292 case PROFILE_VIBRATION_OFF: return "Off";
293 case PROFILE_VIBRATION_ON: return "On";
294 default: return "Unknown";
298 /* This function shows the copyright and some informations usefull for
303 fprintf(stdout, _("GNOKII Version %s\n"
304 "Copyright (C) Hugh Blemings <hugh@blemings.org>, 1999, 2000\n"
305 "Copyright (C) Pavel Janík ml. <Pavel.Janik@suse.cz>, 1999, 2000\n"
306 "Copyright (C) Pavel Machek <pavel@ucw.cz>, 2001\n"
307 "Copyright (C) Pawe³ Kot <pkot@linuxnews.pl>, 2001\n"
308 "gnokii is free software, covered by the GNU General Public License, and you are\n"
309 "welcome to change it and/or distribute copies of it under certain conditions.\n"
310 "There is absolutely no warranty for gnokii. See GPL for details.\n"
311 "Built %s %s for %s on %s \n"), VERSION, __TIME__, __DATE__, model, Port);
315 /* The function usage is only informative - it prints this program's usage and
316 command-line options. */
320 fprintf(stdout, _(" usage: gnokii [--help|--monitor|--version]\n"
321 " gnokii --getmemory memory_type start [end]\n"
322 " gnokii --writephonebook [-i]\n"
323 " gnokii --getspeeddial number\n"
324 " gnokii --setspeeddial number memory_type location\n"
325 " gnokii --getsms memory_type start [end] [-f file] [-F file] [-d]\n"
326 " gnokii --deletesms memory_type start [end]\n"
327 " gnokii --sendsms destination [--smsc message_center_number |\n"
328 " --smscno message_center_index] [-r] [-C n] [-v n]\n"
330 " gnokii --savesms [-m] [-l n] [-i]\n"
331 " gnokii --getsmsc message_center_number\n"
332 " gnokii --setdatetime [YYYY [MM [DD [HH [MM]]]]]\n"
333 " gnokii --getdatetime\n"
334 " gnokii --setalarm HH MM\n"
335 " gnokii --getalarm\n"
336 " gnokii --dialvoice number\n"
337 " gnokii --getcalendarnote start [end] [-v]\n"
338 " gnokii --writecalendarnote vcardfile number\n"
339 " gnokii --deletecalendarnote start [end]\n"
340 " gnokii --getdisplaystatus\n"
341 " gnokii --netmonitor {reset|off|field|devel|next|nr}\n"
342 " gnokii --identify\n"
343 " gnokii --senddtmf string\n"
344 " gnokii --sendlogo {caller|op} destination logofile [network code]\n"
345 " gnokii --sendringtone destination rtttlfile\n"
346 " gnokii --setlogo op [logofile] [network code]\n"
347 " gnokii --setlogo startup [logofile]\n"
348 " gnokii --setlogo caller [logofile] [caller group number] [group name]\n"
349 " gnokii --setlogo {dealer|text} [text]\n"
350 " gnokii --getlogo op [logofile] [network code]\n"
351 " gnokii --getlogo startup [logofile] [network code]\n"
352 " gnokii --getlogo caller [logofile][caller group number][network code]\n"
353 " gnokii --getlogo {dealer|text}\n"
354 " gnokii --viewlogo logofile\n"
355 " gnokii --setringtone rtttlfile\n"
356 " gnokii --reset [soft|hard]\n"
357 " gnokii --getprofile [number]\n"
358 " gnokii --displayoutput\n"
359 " gnokii --keysequence\n"
363 " gnokii --entersecuritycode PIN|PIN2|PUK|PUK2\n"
364 " gnokii --getsecuritycodestatus\n"
370 /* fbusinit is the generic function which waits for the FBUS link. The limit
371 is 10 seconds. After 10 seconds we quit. */
373 static GSM_Statemachine State;
374 static GSM_Data data;
376 void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame))
380 GSM_ConnectionType connection = GCT_Serial;
382 GSM_DataClear(&data);
384 if (!strcasecmp(Connection, "dau9p")) connection = GCT_DAU9P;
385 if (!strcasecmp(Connection, "infrared")) connection = GCT_Infrared;
386 if (!strcasecmp(Connection, "irda")) connection = GCT_Irda;
388 /* Initialise the code for the GSM interface. */
390 error = GSM_Initialise(model, Port, Initlength, connection, rlp_handler, &State);
392 if (error != GE_NONE) {
393 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
397 /* First (and important!) wait for GSM link to be active. We allow 10
400 while (count++ < 200 && *GSM_LinkOK == false)
403 if (*GSM_LinkOK == false) {
404 fprintf (stderr, _("Hmmm... GSM_LinkOK never went true. Quitting.\n"));
409 /* This function checks that the argument count for a given options is withing
411 int checkargs(int opt, struct gnokii_arg_len gals[], int argc)
415 /* Walk through the whole array with options requiring arguments. */
416 for (i = 0; !(gals[i].gal_min == 0 && gals[i].gal_max == 0); i++) {
418 /* Current option. */
419 if (gals[i].gal_opt == opt) {
421 /* Argument count checking. */
422 if (gals[i].gal_flags == GAL_XOR) {
423 if (gals[i].gal_min == argc || gals[i].gal_max == argc)
426 if (gals[i].gal_min <= argc && gals[i].gal_max >= argc)
434 /* We do not have options without arguments in the array, so check them. */
435 if (argc == 0) return 0;
439 /* Main function - handles command line arguments, passes them to separate
440 functions accordingly. */
441 int main(int argc, char *argv[])
447 /* Every option should be in this array. */
448 static struct option long_options[] =
450 /* FIXME: these comments are nice, but they would be more usefull as docs for the user */
452 { "help", no_argument, NULL, OPT_HELP },
454 // Display version and build information.
455 { "version", no_argument, NULL, OPT_VERSION },
458 { "monitor", no_argument, NULL, OPT_MONITOR },
462 // Enter Security Code mode
463 { "entersecuritycode", required_argument, NULL, OPT_ENTERSECURITYCODE },
465 // Get Security Code status
466 { "getsecuritycodestatus", no_argument, NULL, OPT_GETSECURITYCODESTATUS },
471 { "setdatetime", optional_argument, NULL, OPT_SETDATETIME },
473 // Get date and time mode
474 { "getdatetime", no_argument, NULL, OPT_GETDATETIME },
477 { "setalarm", required_argument, NULL, OPT_SETALARM },
480 { "getalarm", no_argument, NULL, OPT_GETALARM },
483 { "dialvoice", required_argument, NULL, OPT_DIALVOICE },
485 // Get calendar note mode
486 { "getcalendarnote", required_argument, NULL, OPT_GETCALENDARNOTE },
488 // Write calendar note mode
489 { "writecalendarnote", required_argument, NULL, OPT_WRITECALENDARNOTE },
491 // Delete calendar note mode
492 { "deletecalendarnote", required_argument, NULL, OPT_DELCALENDARNOTE },
494 // Get display status mode
495 { "getdisplaystatus", no_argument, NULL, OPT_GETDISPLAYSTATUS },
498 { "getmemory", required_argument, NULL, OPT_GETMEMORY },
500 // Write phonebook (memory) mode
501 { "writephonebook", optional_argument, NULL, OPT_WRITEPHONEBOOK },
503 // Get speed dial mode
504 { "getspeeddial", required_argument, NULL, OPT_GETSPEEDDIAL },
506 // Set speed dial mode
507 { "setspeeddial", required_argument, NULL, OPT_SETSPEEDDIAL },
509 // Get SMS message mode
510 { "getsms", required_argument, NULL, OPT_GETSMS },
512 // Delete SMS message mode
513 { "deletesms", required_argument, NULL, OPT_DELETESMS },
515 // Send SMS message mode
516 { "sendsms", required_argument, NULL, OPT_SENDSMS },
518 // Ssve SMS message mode
519 { "savesms", optional_argument, NULL, OPT_SAVESMS },
521 // Send logo as SMS message mode
522 { "sendlogo", required_argument, NULL, OPT_SENDLOGO },
524 // Send ringtone as SMS message
525 { "sendringtone", required_argument, NULL, OPT_SENDRINGTONE },
528 { "setringtone", required_argument, NULL, OPT_SETRINGTONE },
530 // Get SMS center number mode
531 { "getsmsc", required_argument, NULL, OPT_GETSMSC },
533 // For development purposes: run in passive monitoring mode
534 { "pmon", no_argument, NULL, OPT_PMON },
537 { "netmonitor", required_argument, NULL, OPT_NETMONITOR },
540 { "identify", no_argument, NULL, OPT_IDENTIFY },
542 // Send DTMF sequence
543 { "senddtmf", required_argument, NULL, OPT_SENDDTMF },
546 { "reset", optional_argument, NULL, OPT_RESET },
549 { "setlogo", optional_argument, NULL, OPT_SETLOGO },
552 { "getlogo", required_argument, NULL, OPT_GETLOGO },
555 { "viewlogo", required_argument, NULL, OPT_VIEWLOGO },
558 { "getprofile", optional_argument, NULL, OPT_GETPROFILE },
560 // Show texts from phone's display
561 { "displayoutput", no_argument, NULL, OPT_DISPLAYOUTPUT },
563 // Simulate pressing the keys
564 { "keysequence", no_argument, NULL, OPT_KEYPRESS },
566 // For development purposes: insert you function calls here
567 { "foogle", no_argument, NULL, OPT_FOOGLE },
572 /* Every command which requires arguments should have an appropriate entry
574 struct gnokii_arg_len gals[] =
578 { OPT_ENTERSECURITYCODE, 1, 1, 0 },
581 { OPT_SETDATETIME, 0, 5, 0 },
582 { OPT_SETALARM, 2, 2, 0 },
583 { OPT_DIALVOICE, 1, 1, 0 },
584 { OPT_GETCALENDARNOTE, 1, 3, 0 },
585 { OPT_WRITECALENDARNOTE, 2, 2, 0 },
586 { OPT_DELCALENDARNOTE, 1, 2, 0 },
587 { OPT_GETMEMORY, 2, 3, 0 },
588 { OPT_GETSPEEDDIAL, 1, 1, 0 },
589 { OPT_SETSPEEDDIAL, 3, 3, 0 },
590 { OPT_GETSMS, 2, 5, 0 },
591 { OPT_DELETESMS, 2, 3, 0 },
592 { OPT_SENDSMS, 1, 10, 0 },
593 { OPT_SAVESMS, 0, 6, 0 },
594 { OPT_SENDLOGO, 3, 4, GAL_XOR },
595 { OPT_SENDRINGTONE, 2, 2, 0 },
596 { OPT_GETSMSC, 1, 1, 0 },
597 { OPT_GETWELCOMENOTE, 1, 1, 0 },
598 { OPT_SETWELCOMENOTE, 1, 1, 0 },
599 { OPT_NETMONITOR, 1, 1, 0 },
600 { OPT_SENDDTMF, 1, 1, 0 },
601 { OPT_SETLOGO, 1, 4, 0 },
602 { OPT_GETLOGO, 1, 4, 0 },
603 { OPT_VIEWLOGO, 1, 1, 0 },
604 { OPT_SETRINGTONE, 1, 1, 0 },
605 { OPT_RESET, 0, 1, 0 },
606 { OPT_GETPROFILE, 0, 1, 0 },
607 { OPT_WRITEPHONEBOOK, 0, 1, 0 },
614 /* For GNU gettext */
616 textdomain("gnokii");
617 setlocale(LC_ALL, "");
620 /* Read config file */
621 if (readconfig(&model, &Port, &Initlength, &Connection, &BinDir) < 0) {
625 /* Handle command line arguments. */
626 c = getopt_long(argc, argv, "", long_options, NULL);
627 if (c == -1) /* No argument given - we should display usage. */
631 // First, error conditions
634 fprintf(stderr, _("Use '%s --help' for usage informations.\n"), argv[0]);
636 // Then, options with no arguments
643 /* We have to build an array of the arguments which will be passed to the
644 functions. Please note that every text after the --command will be
645 passed as arguments. A syntax like gnokii --cmd1 args --cmd2 args will
646 not work as expected; instead args --cmd2 args is passed as a
648 if ((nargv = malloc(sizeof(char *) * argc)) != NULL) {
649 for (i = 2; i < argc; i++)
650 nargv[i-2] = argv[i];
652 if (checkargs(c, gals, nargc)) {
653 free(nargv); /* Wrong number of arguments - we should display usage. */
658 /* have to ignore SIGALARM */
662 /* Initialise the code for the GSM interface. */
670 case OPT_ENTERSECURITYCODE:
671 rc = entersecuritycode(optarg);
673 case OPT_GETSECURITYCODESTATUS:
674 rc = getsecuritycodestatus();
677 case OPT_GETDATETIME:
683 case OPT_GETDISPLAYSTATUS:
684 rc = getdisplaystatus();
689 case OPT_WRITEPHONEBOOK:
690 rc = writephonebook(nargc, nargv);
692 // Now, options with arguments
693 case OPT_SETDATETIME:
694 rc = setdatetime(nargc, nargv);
697 rc = setalarm(nargv);
700 rc = dialvoice(optarg);
702 case OPT_GETCALENDARNOTE:
703 rc = getcalendarnote(nargc, nargv);
705 case OPT_DELCALENDARNOTE:
706 rc = deletecalendarnote(nargc, nargv);
708 case OPT_WRITECALENDARNOTE:
709 rc = writecalendarnote(nargv);
712 rc = getmemory(nargc, nargv);
714 case OPT_GETSPEEDDIAL:
715 rc = getspeeddial(optarg);
717 case OPT_SETSPEEDDIAL:
718 rc = setspeeddial(nargv);
721 rc = getsms(argc, argv);
724 rc = deletesms(nargc, nargv);
727 rc = sendsms(nargc, nargv);
730 rc = savesms(argc, argv);
733 rc = sendlogo(nargc, nargv);
736 rc = getsmsc(optarg);
739 rc = netmonitor(optarg);
745 rc = setlogo(nargc, nargv);
748 rc = getlogo(nargc, nargv);
751 rc = viewlogo(optarg);
753 case OPT_SETRINGTONE:
754 rc = setringtone(nargc, nargv);
756 case OPT_SENDRINGTONE:
757 rc = sendringtone(nargc, nargv);
760 rc = getprofile(nargc, nargv);
762 case OPT_DISPLAYOUTPUT:
763 rc = displayoutput();
766 rc = presskeysequence();
774 rc = senddtmf(optarg);
780 fprintf(stderr, _("Unknown option: %d\n"), c);
787 fprintf(stderr, _("Wrong number of arguments\n"));
791 /* Send SMS messages. */
792 int sendsms(int argc, char *argv[])
796 // char UDH[GSM_MAX_USER_DATA_HEADER_LENGTH];
797 /* The maximum length of an uncompressed concatenated short message is
798 255 * 153 = 39015 default alphabet characters */
799 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
800 int input_len, chars_read;
801 int i; /*, offset, nr_msg, aux;*/
803 struct option options[] = {
804 { "smsc", required_argument, NULL, '1'},
805 { "smscno", required_argument, NULL, '2'},
806 { "long", required_argument, NULL, '3'},
810 input_len = GSM_MAX_SMS_LENGTH;
818 - message validity for 3 days
819 - unset user data header indicator
822 memset(&SMS, 0, sizeof(GSM_SMSMessage));
824 SMS.Type = SMS_Submit;
825 SMS.DCS.Type = SMS_GeneralDataCoding;
826 SMS.DCS.u.General.Compressed = false;
827 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
828 SMS.DCS.u.General.Class = 0;
829 SMS.MessageCenter.No = 1;
830 SMS.Validity.VPF = SMS_RelativeFormat;
831 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
834 strcpy(SMS.RemoteNumber.number, argv[0]);
835 if (SMS.RemoteNumber.number[0] == '+') SMS.RemoteNumber.type = SMS_International;
836 else SMS.RemoteNumber.type = SMS_Unknown;
841 while ((i = getopt_long(argc, argv, "r8cC:v:", options, NULL)) != -1) {
842 switch (i) { // -8 is for 8-bit data, -c for compression. both are not yet implemented.
843 case '1': /* SMSC number */
844 SMS.MessageCenter.No = 0;
845 strcpy(SMS.MessageCenter.Number, optarg);
847 case '2': /* SMSC number index in phone memory */
848 SMS.MessageCenter.No = atoi(optarg);
850 if (SMS.MessageCenter.No < 1 || SMS.MessageCenter.No > 5)
852 data.MessageCenter = &SMS.MessageCenter;
853 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
855 case '3': /* we send long message */
856 input_len = atoi(optarg);
857 if (input_len > 255 * GSM_MAX_SMS_LENGTH) {
858 fprintf(stderr, _("Input too long!\n"));
862 case 'r': /* request for delivery report */
863 SMS.Type = SMS_Delivery_Report;
865 case 'C': /* class Message */
868 SMS.DCS.u.General.Class = 1;
871 SMS.DCS.u.General.Class = 2;
874 SMS.DCS.u.General.Class = 3;
877 SMS.DCS.u.General.Class = 4;
884 SMS.Validity.u.Relative = atoi(optarg);
887 usage(); /* Would be better to have an sendsms_usage() here. */
891 /* Get message text from stdin. */
892 chars_read = fread(message_buffer, 1, input_len, stdin);
894 if (chars_read == 0) {
895 fprintf(stderr, _("Couldn't read from stdin!\n"));
897 } else if (chars_read > input_len) {
898 fprintf(stderr, _("Input too long!\n"));
902 /* Null terminate. */
903 message_buffer[chars_read] = 0x00;
904 strncpy(SMS.MessageText, message_buffer, chars_read);
905 data.SMSMessage = &SMS;
907 /* Send the message. */
908 error = SM_Functions(GOP_SendSMS, &data, &State);
910 if (error == GE_SMSSENDOK) {
911 fprintf(stdout, _("Send succeeded!\n"));
913 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
916 if (GSM && GSM->Terminate) GSM->Terminate();
921 int savesms(int argc, char *argv[])
925 /* The maximum length of an uncompressed concatenated short message is
926 255 * 153 = 39015 default alphabet characters */
927 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
928 int input_len, chars_read;
934 SMS.Type = SMS_Deliver;
935 SMS.DCS.Type = SMS_GeneralDataCoding;
936 SMS.DCS.u.General.Compressed = false;
937 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
938 SMS.DCS.u.General.Class = 0;
939 SMS.MessageCenter.No = 1;
940 SMS.Validity.VPF = SMS_RelativeFormat;
941 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
943 SMS.Status = SMS_Unsent;
946 input_len = GSM_MAX_SMS_LENGTH;
949 while ((i = getopt(argc, argv, "ml:in:s:c:")) != -1) {
951 case 'm': /* mark the message as sent */
952 SMS.Status = SMS_Sent;
954 case 'l': /* Specify the location */
955 SMS.Number = atoi(optarg);
957 case 'i': /* Ask before overwriting */
960 case 'n': /* Specify the from number */
962 case 's': /* Specify the smsc number */
964 case 'c': /* Specify the smsc location */
975 aux.Number = SMS.Number;
976 data.SMSMessage = &aux;
977 error = SM_Functions(GOP_GetSMS, &data, &State);
980 fprintf(stderr, _("Message at specified location exists. "));
981 while (confirm < 0) {
982 fprintf(stderr, _("Overwrite? (yes/no) "));
983 GetLine(stdin, ans, 7);
984 if (!strcmp(ans, _("yes"))) confirm = 1;
985 else if (!strcmp(ans, _("no"))) confirm = 0;
987 if (!confirm) { GSM->Terminate(); return 0; }
989 case GE_INVALIDSMSLOCATION:
990 fprintf(stderr, _("Invalid location\n"));
994 /* FIXME: Remove this fprintf when the function is thoroughly tested */
996 fprintf(stderr, _("Location %d empty. Saving\n"), SMS.Number);
1001 chars_read = fread(message_buffer, 1, input_len, stdin);
1003 if (chars_read == 0) {
1005 fprintf(stderr, _("Couldn't read from stdin!\n"));
1008 } else if (chars_read > input_len) {
1010 fprintf(stderr, _("Input too long!\n"));
1015 strncpy (SMS.MessageText, message_buffer, chars_read);
1016 SMS.MessageText[chars_read] = 0;
1018 error = GSM->SaveSMSMessage(&SMS);
1020 if (error == GE_NONE) {
1021 fprintf(stdout, _("Saved!\n"));
1023 fprintf(stdout, _("Saving failed (error=%d)\n"), error);
1031 /* Get SMSC number */
1032 int getsmsc(char *MessageCenterNumber)
1034 SMS_MessageCenter MessageCenter;
1038 memset(&MessageCenter, 0, sizeof(MessageCenter));
1039 MessageCenter.No=atoi(MessageCenterNumber);
1041 if (GSM && GSM->GetSMSCenter && GSM->Terminate) {
1042 error = GSM->GetSMSCenter(&MessageCenter);
1045 GSM_DataClear(&data);
1046 data.MessageCenter = &MessageCenter;
1047 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
1052 fprintf(stdout, _("%d. SMS center (%s) number is %s\n"), MessageCenter.No, MessageCenter.Name, MessageCenter.Number);
1053 fprintf(stdout, _("Default recipient number is %s\n"), MessageCenter.Recipient);
1054 fprintf(stdout, _("Messages sent as "));
1056 switch (MessageCenter.Format) {
1058 fprintf(stdout, _("Text"));
1061 fprintf(stdout, _("VoiceMail"));
1064 fprintf(stdout, _("Fax"));
1068 fprintf(stdout, _("Email"));
1071 fprintf(stdout, _("ERMES"));
1074 fprintf(stdout, _("X.400"));
1077 fprintf(stdout, _("Unknown"));
1082 fprintf(stdout, _("Message validity is "));
1084 switch (MessageCenter.Validity) {
1086 fprintf(stdout, _("1 hour"));
1089 fprintf(stdout, _("6 hours"));
1092 fprintf(stdout, _("24 hours"));
1095 fprintf(stdout, _("72 hours"));
1098 fprintf(stdout, _("1 week"));
1101 fprintf(stdout, _("Maximum time"));
1104 fprintf(stdout, _("Unknown"));
1108 fprintf(stdout, "\n");
1111 case GE_NOTIMPLEMENTED:
1112 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1115 fprintf(stdout, _("SMS center can not be found :-(\n"));
1122 /* Get SMS messages. */
1123 int getsms(int argc, char *argv[])
1127 SMS_FolderList folderlist;
1128 GSM_SMSMessage message;
1129 char *memory_type_string;
1130 int start_message, end_message, count, mode = 1;
1137 /* Handle command line args that set type, start and end locations. */
1138 memory_type_string = argv[2];
1139 message.MemoryType = StrToMemoryType(memory_type_string);
1140 if (message.MemoryType == GMT_XX) {
1141 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[2]);
1145 memset(&filename, 0, 64);
1147 start_message = end_message = atoi(argv[3]);
1151 /* [end] can be only argv[4] */
1152 if (argv[4][0] != '-') {
1153 end_message = atoi(argv[4]);
1156 /* parse all options (beginning with '-' */
1157 while ((i = getopt(argc, argv, "f:F:d")) != -1) {
1166 dprintf("Saving into %s\n", optarg);
1167 strncpy(filename, optarg, 64);
1168 if (strlen(optarg) > 63) {
1169 fprintf(stderr, _("Filename too long - will be truncated to 63 characters.\n"));
1172 filename[strlen(optarg)] = 0;
1181 data.SMSFolderList = &folderlist;
1182 folder.FolderID = 0;
1183 data.SMSFolder = &folder;
1184 /* Now retrieve the requested entries. */
1185 for (count = start_message; count <= end_message; count ++) {
1188 message.Number = count;
1189 data.SMSMessage = &message;
1190 dprintf("MemoryType (gnokii.c) : %i\n", data.SMSMessage->MemoryType);
1191 error = SM_Functions(GOP_GetSMS, &data, &State);
1195 switch (message.Type) {
1197 fprintf(stdout, _("%d. MO Message "), message.Number);
1199 fprintf(stdout, _("(sent)\n"));
1200 fprintf(stdout, _("%d. MO Message "), message.Number);
1202 fprintf(stdout, _("(not sent)\n"));
1203 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1205 case SMS_Delivery_Report:
1206 fprintf(stdout, _("%d. Delivery Report "), message.Number);
1208 fprintf(stdout, _("(read)\n"));
1210 fprintf(stdout, _("(not read)\n"));
1211 fprintf(stdout, _("Sending date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1212 message.Time.Day, message.Time.Month, message.Time.Year, \
1213 message.Time.Hour, message.Time.Minute, message.Time.Second);
1214 if (message.Time.Timezone) {
1215 if (message.Time.Timezone > 0)
1216 fprintf(stdout,_("+%02d00"), message.Time.Timezone);
1218 fprintf(stdout,_("%02d00"), message.Time.Timezone);
1220 fprintf(stdout, "\n");
1221 fprintf(stdout, _("Response date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1222 message.SMSCTime.Day, message.SMSCTime.Month, message.SMSCTime.Year, \
1223 message.SMSCTime.Hour, message.SMSCTime.Minute, message.SMSCTime.Second);
1224 if (message.SMSCTime.Timezone) {
1225 if (message.SMSCTime.Timezone > 0)
1226 fprintf(stdout,_("+%02d00"),message.SMSCTime.Timezone);
1228 fprintf(stdout,_("%02d00"),message.SMSCTime.Timezone);
1230 fprintf(stdout, "\n");
1231 fprintf(stdout, _("Receiver: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1232 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1235 fprintf(stdout, _("%d. Inbox Message "), message.Number);
1237 fprintf(stdout, _("(read)\n"));
1239 fprintf(stdout, _("(not read)\n"));
1240 fprintf(stdout, _("Date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1241 message.Time.Day, message.Time.Month, message.Time.Year, \
1242 message.Time.Hour, message.Time.Minute, message.Time.Second);
1243 if (message.Time.Timezone) {
1244 if (message.Time.Timezone > 0)
1245 fprintf(stdout,_("+%02d00"),message.Time.Timezone);
1247 fprintf(stdout,_("%02d00"),message.Time.Timezone);
1249 fprintf(stdout, "\n");
1250 fprintf(stdout, _("Sender: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1251 switch (message.UDH[0].Type) {
1253 fprintf(stdout, _("GSM operator logo for %s (%s) network.\n"), bitmap.netcode, GSM_GetNetworkName(bitmap.netcode));
1254 if (!strcmp(message.RemoteNumber.number, "+998000005") && !strcmp(message.MessageCenter.Number, "+886935074443")) dprintf(_("Saved by Logo Express\n"));
1255 if (!strcmp(message.RemoteNumber.number, "+998000002") || !strcmp(message.RemoteNumber.number, "+998000003")) dprintf(_("Saved by Operator Logo Uploader by Thomas Kessler\n"));
1257 case SMS_CallerIDLogo:
1258 fprintf(stdout, ("Logo:\n"));
1259 /* put bitmap into bitmap structure */
1260 GSM_ReadSMSBitmap(message.UDH[0].Type, message.MessageText+2+offset, message.MessageText, &bitmap);
1261 GSM_PrintBitmap(&bitmap);
1264 if ((stat(filename, &buf) == 0)) {
1265 fprintf(stdout, _("File %s exists.\n"), filename);
1266 fprintf(stderr, _("Overwrite? (yes/no) "));
1267 GetLine(stdin, ans, 4);
1268 if (!strcmp(ans, _("yes"))) {
1269 error = GSM_SaveBitmapFile(filename, &bitmap);
1271 } else error = GSM_SaveBitmapFile(filename, &bitmap);
1272 if (error != GE_NONE) fprintf(stderr, _("Couldn't save logofile %s!\n"), filename);
1276 fprintf(stdout, _("Ringtone\n"));
1278 case SMS_ConcatenatedMessages:
1279 fprintf(stdout, _("Linked (%d/%d):\n"),
1280 message.UDH[0].u.ConcatenatedShortMessage.CurrentNumber,
1281 message.UDH[0].u.ConcatenatedShortMessage.MaximumNumber);
1283 fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText);
1284 if ((mode != -1) && *filename) {
1286 sprintf(buf, "%s%d", filename, count);
1287 mode = GSM_SaveTextFile(buf, message.MessageText, mode);
1290 case SMS_BusinessCard:
1291 fprintf(stdout, _("Business Card:\n%s"), message.MessageText);
1294 fprintf(stderr, _("Unknown\n"));
1300 data.SMSMessage = &message;
1301 if (GE_NONE != SM_Functions(GOP_DeleteSMS, &data, &State))
1302 fprintf(stdout, _("(delete failed)\n"));
1304 fprintf(stdout, _("(message deleted)\n"));
1307 case GE_NOTIMPLEMENTED:
1308 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1309 if (GSM && GSM->Terminate) GSM->Terminate();
1311 case GE_INVALIDSMSLOCATION:
1312 fprintf(stderr, _("Invalid location: %s %d\n"), memory_type_string, count);
1314 case GE_EMPTYSMSLOCATION:
1315 fprintf(stderr, _("SMS location %s %d empty.\n"), memory_type_string, count);
1318 fprintf(stdout, _("GetSMS %s %d failed!(%s)\n\n"), memory_type_string, count, print_error(error));
1323 if (GSM && GSM->Terminate) GSM->Terminate();
1328 /* Delete SMS messages. */
1329 int deletesms(int argc, char *argv[])
1331 GSM_SMSMessage message;
1332 char *memory_type_string;
1333 int start_message, end_message, count;
1336 /* Handle command line args that set type, start and end locations. */
1337 memory_type_string = argv[0];
1338 message.MemoryType = StrToMemoryType(memory_type_string);
1339 if (message.MemoryType == GMT_XX) {
1340 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
1344 start_message = end_message = atoi (argv[1]);
1345 if (argc > 2) end_message = atoi (argv[2]);
1347 /* Now delete the requested entries. */
1348 for (count = start_message; count <= end_message; count ++) {
1350 message.Number = count;
1351 data.SMSMessage = &message;
1352 error = SM_Functions(GOP_DeleteSMS, &data, &State);
1354 if (error == GE_NONE)
1355 fprintf(stdout, _("Deleted SMS %s %d\n"), memory_type_string, count);
1357 if (error == GE_NOTIMPLEMENTED) {
1358 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1362 fprintf(stdout, _("DeleteSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
1371 static volatile bool bshutdown = false;
1373 /* SIGINT signal handler. */
1374 static void interrupted(int sig)
1376 signal(sig, SIG_IGN);
1382 /* In this mode we get the code from the keyboard and send it to the mobile
1384 int entersecuritycode(char *type)
1387 GSM_SecurityCode SecurityCode;
1389 if (!strcmp(type,"PIN"))
1390 SecurityCode.Type=GSCT_Pin;
1391 else if (!strcmp(type,"PUK"))
1392 SecurityCode.Type=GSCT_Puk;
1393 else if (!strcmp(type,"PIN2"))
1394 SecurityCode.Type=GSCT_Pin2;
1395 else if (!strcmp(type,"PUK2"))
1396 SecurityCode.Type=GSCT_Puk2;
1397 // FIXME: Entering of SecurityCode does not work :-(
1398 // else if (!strcmp(type,"SecurityCode"))
1399 // SecurityCode.Type=GSCT_SecurityCode;
1404 printf("Enter your code: ");
1405 gets(SecurityCode.Code);
1407 strcpy(SecurityCode.Code,getpass(_("Enter your code: ")));
1410 test = GSM->EnterSecurityCode(SecurityCode);
1411 if (test == GE_INVALIDSECURITYCODE)
1412 fprintf(stdout, _("Error: invalid code.\n"));
1413 else if (test == GE_NONE)
1414 fprintf(stdout, _("Code ok.\n"));
1415 else if (test == GE_NOTIMPLEMENTED)
1416 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1418 fprintf(stdout, _("Other error.\n"));
1425 int getsecuritycodestatus(void)
1429 if (GSM->GetSecurityCodeStatus(&Status) == GE_NONE) {
1431 fprintf(stdout, _("Security code status: "));
1434 case GSCT_SecurityCode:
1435 fprintf(stdout, _("waiting for Security Code.\n"));
1438 fprintf(stdout, _("waiting for PIN.\n"));
1441 fprintf(stdout, _("waiting for PIN2.\n"));
1444 fprintf(stdout, _("waiting for PUK.\n"));
1447 fprintf(stdout, _("waiting for PUK2.\n"));
1450 fprintf(stdout, _("nothing to enter.\n"));
1453 fprintf(stdout, _("Unknown!\n"));
1466 /* Voice dialing mode. */
1467 int dialvoice(char *Number)
1469 GSM->DialVoice(Number);
1476 /* The following function allows to send logos using SMS */
1477 int sendlogo(int argc, char *argv[])
1483 char UserDataHeader[7] = { 0x06, /* UDH Length */
1484 0x05, /* IEI: application port addressing scheme, 16 bit address */
1485 0x04, /* IEI length */
1486 0x15, /* destination address: high byte */
1487 0x00, /* destination address: low byte */
1488 0x00, /* originator address */
1491 char Data[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1495 /* Default settings for SMS message:
1496 - no delivery report
1502 - set UserDataHeaderIndicator
1504 SMS.Type = SMS_Submit;
1505 SMS.DCS.Type = SMS_GeneralDataCoding;
1506 SMS.DCS.u.General.Compressed = false;
1507 SMS.DCS.u.General.Alphabet = SMS_8bit;
1508 SMS.DCS.u.General.Class = 2;
1509 SMS.MessageCenter.No = 1;
1510 SMS.Validity.VPF = SMS_RelativeFormat;
1511 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
1513 /* The first argument is the type of the logo. */
1514 if (!strcmp(argv[0], "op")) {
1515 SMS.UDH[0].Type = SMS_OpLogo;
1516 UserDataHeader[4] = 0x82; /* NBS port 0x1582 */
1517 fprintf(stdout, _("Sending operator logo.\n"));
1518 } else if (!strcmp(argv[0], "caller")) {
1519 SMS.UDH[0].Type = SMS_CallerIDLogo;
1520 UserDataHeader[4] = 0x83; /* NBS port 0x1583 */
1521 fprintf(stdout, _("Sending caller line identification logo.\n"));
1523 fprintf(stderr, _("You should specify what kind of logo to send!\n"));
1527 /* The second argument is the destination, ie the phone number of recipient. */
1528 SMS.MemoryType = atoi(argv[1]);
1530 /* The third argument is the bitmap file. */
1531 GSM_ReadBitmapFile(argv[2], &bitmap);
1533 /* If we are sending op logo we can rewrite network code. */
1534 if (!strcmp(argv[0], "op")) {
1536 * The fourth argument, if present, is the Network code of the operator.
1537 * Network code is in this format: "xxx yy".
1540 strcpy(bitmap.netcode, argv[3]);
1542 fprintf(stdout, _("Operator code: %s\n"), argv[3]);
1546 /* Set the network code */
1547 Data[current++] = ((bitmap.netcode[1] & 0x0f) << 4) | (bitmap.netcode[0] & 0xf);
1548 Data[current++] = 0xf0 | (bitmap.netcode[2] & 0x0f);
1549 Data[current++] = ((bitmap.netcode[5] & 0x0f) << 4) | (bitmap.netcode[4] & 0xf);
1552 /* Set the logo size */
1554 Data[current++] = bitmap.width;
1555 Data[current++] = bitmap.height;
1557 Data[current++] = 0x01;
1559 memcpy(SMS.MessageText, UserDataHeader, 7);
1560 memcpy(SMS.MessageText, Data, current);
1561 memcpy(SMS.MessageText+current, bitmap.bitmap, bitmap.size);
1563 /* Send the message. */
1564 error = GSM->SendSMSMessage(&SMS,current+bitmap.size);
1566 if (error == GE_SMSSENDOK)
1567 fprintf(stdout, _("Send succeeded!\n"));
1569 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
1575 /* Getting logos. */
1576 GSM_Error SaveBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1583 /* Ask before overwriting */
1584 while (stat(FileName, &buf) == 0) {
1587 fprintf(stderr, _("Saving logo. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "), FileName);
1588 GetLine(stdin, ans, 4);
1589 if (!strcmp(ans, "O") || !strcmp(ans, "o")) confirm = 1;
1590 if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm = 2;
1591 if (!strcmp(ans, "S") || !strcmp(ans, "s")) return GE_USERCANCELED;
1593 if (confirm == 1) break;
1595 fprintf(stderr, _("Enter name of new file: "));
1596 GetLine(stdin, FileName, 50);
1597 if (!FileName || (*FileName == 0)) return GE_USERCANCELED;
1601 error = GSM_SaveBitmapFile(FileName, bitmap);
1604 case GE_CANTOPENFILE:
1605 fprintf(stderr, _("Failed to write file \"%s\"\n"), FileName);
1614 int getlogo(int argc, char *argv[])
1618 GSM_Statemachine *sm = &State;
1620 bitmap.type=GSM_None;
1622 if (!strcmp(argv[0], "op"))
1623 bitmap.type = GSM_OperatorLogo;
1625 if (!strcmp(argv[0], "caller")) {
1626 /* There is caller group number missing in argument list. */
1628 bitmap.number=argv[2][0]-'0';
1629 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1633 bitmap.type = GSM_CallerLogo;
1636 if (!strcmp(argv[0],"startup"))
1637 bitmap.type = GSM_StartupLogo;
1638 else if (!strcmp(argv[0], "dealer"))
1639 bitmap.type = GSM_DealerNoteText;
1640 else if (!strcmp(argv[0], "text"))
1641 bitmap.type=GSM_WelcomeNoteText;
1643 if (bitmap.type != GSM_None) {
1645 fprintf(stdout, _("Getting Logo\n"));
1647 data.Bitmap=&bitmap;
1648 error=SM_Functions(GOP_GetBitmap, &data, sm);
1652 if (bitmap.type == GSM_DealerNoteText) fprintf(stdout, _("Dealer welcome note "));
1653 if (bitmap.type == GSM_WelcomeNoteText) fprintf(stdout, _("Welcome note "));
1654 if (bitmap.type == GSM_DealerNoteText || bitmap.type==GSM_WelcomeNoteText) {
1655 if (bitmap.text[0]) {
1656 fprintf(stdout, _("currently set to \"%s\"\n"), bitmap.text);
1658 fprintf(stdout, _("currently empty\n"));
1662 switch (bitmap.type) {
1663 case GSM_OperatorLogo:
1664 fprintf(stdout,"Operator logo for %s (%s) network got succesfully\n",bitmap.netcode,GSM_GetNetworkName(bitmap.netcode));
1666 strncpy(bitmap.netcode,argv[2], 7);
1667 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1668 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1673 case GSM_StartupLogo:
1674 fprintf(stdout, "Startup logo got successfully\n");
1676 strncpy(bitmap.netcode,argv[2], 7);
1677 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1678 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1683 case GSM_CallerLogo:
1684 fprintf(stdout,"Caller logo got successfully\n");
1686 strncpy(bitmap.netcode,argv[3],7);
1687 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1688 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1694 fprintf(stdout,"Unknown bitmap type.\n");
1698 if (SaveBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) return (-1);
1701 fprintf(stdout,"Your phone doesn't have logo uploaded !\n");
1706 case GE_NOTIMPLEMENTED:
1707 fprintf(stderr, _("Function not implemented !\n"));
1709 case GE_NOTSUPPORTED:
1710 fprintf(stderr, _("This kind of logo is not supported !\n"));
1713 fprintf(stderr, _("Error getting logo !\n"));
1717 fprintf(stderr, _("What kind of logo do you want to get ?\n"));
1725 /* Sending logos. */
1726 GSM_Error ReadBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1730 error = GSM_ReadBitmapFile(FileName, bitmap);
1733 case GE_CANTOPENFILE:
1734 fprintf(stderr, _("Failed to read file \"%s\"\n"), FileName);
1736 case GE_WRONGNUMBEROFCOLORS:
1737 fprintf(stderr, _("Wrong number of colors in \"%s\" logofile (accepted only 2-colors files) !\n"), FileName);
1739 case GE_WRONGCOLORS:
1740 fprintf(stderr, _("Wrong colors in \"%s\" logofile !\n"), FileName);
1742 case GE_INVALIDFILEFORMAT:
1743 fprintf(stderr, _("Invalid format of \"%s\" logofile !\n"), FileName);
1745 case GE_SUBFORMATNOTSUPPORTED:
1746 fprintf(stderr, _("Sorry, gnokii doesn't support used subformat in file \"%s\" !\n"), FileName);
1748 case GE_FILETOOSHORT:
1749 fprintf(stderr, _("\"%s\" logofile is too short !\n"), FileName);
1751 case GE_INVALIDIMAGESIZE:
1752 fprintf(stderr, _("Bitmap size doesn't supported by fileformat or different from 72x14, 84x48 and 72x28 !\n"));
1762 int setlogo(int argc, char *argv[])
1764 GSM_Bitmap bitmap,oldbit;
1765 GSM_NetworkInfo NetworkInfo;
1771 if (!strcmp(argv[0],"text") || !strcmp(argv[0],"dealer")) {
1772 if (!strcmp(argv[0], "text")) bitmap.type = GSM_WelcomeNoteText;
1773 else bitmap.type = GSM_DealerNoteText;
1774 bitmap.text[0] = 0x00;
1775 if (argc > 1) strncpy(bitmap.text, argv[1], 255);
1777 if (!strcmp(argv[0], "op") || !strcmp(argv[0], "startup") || !strcmp(argv[0], "caller")) {
1779 if (ReadBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) {
1784 if (!strcmp(argv[0], "op")) {
1785 if (bitmap.type != GSM_OperatorLogo || argc < 3) {
1786 if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode, NetworkInfo.NetworkCode, 7);
1788 GSM_ResizeBitmap(&bitmap, GSM_OperatorLogo, GSM_Info);
1790 strncpy(bitmap.netcode, argv[2], 7);
1791 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1792 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1797 if (!strcmp(argv[0], "startup")) {
1798 GSM_ResizeBitmap(&bitmap, GSM_StartupLogo, GSM_Info);
1800 if (!strcmp(argv[0],"caller")) {
1801 GSM_ResizeBitmap(&bitmap, GSM_CallerLogo, GSM_Info);
1803 bitmap.number = argv[2][0] - '0';
1804 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1808 oldbit.type = GSM_CallerLogo;
1809 oldbit.number = bitmap.number;
1810 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1811 /* We have to get the old name and ringtone!! */
1812 bitmap.ringtone = oldbit.ringtone;
1813 strncpy(bitmap.text, oldbit.text, 255);
1815 if (argc > 3) strncpy(bitmap.text, argv[3], 255);
1817 fprintf(stdout, _("Setting Logo.\n"));
1819 /* FIX ME: is it possible to permanently remove op logo ? */
1820 if (!strcmp(argv[0], "op"))
1822 bitmap.type = GSM_OperatorLogo;
1823 strncpy(bitmap.netcode, "000 00", 7);
1826 bitmap.size = bitmap.width * bitmap.height / 8;
1827 GSM_ClearBitmap(&bitmap);
1829 /* FIX ME: how to remove startup and group logos ? */
1830 fprintf(stdout, _("Removing Logo.\n"));
1833 fprintf(stderr, _("What kind of logo do you want to set ?\n"));
1839 error=GSM->SetBitmap(&bitmap);
1843 oldbit.type = bitmap.type;
1844 oldbit.number = bitmap.number;
1845 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1846 if (bitmap.type == GSM_WelcomeNoteText ||
1847 bitmap.type == GSM_DealerNoteText) {
1848 if (strcmp(bitmap.text, oldbit.text)) {
1849 fprintf(stderr, _("Error setting"));
1850 if (bitmap.type == GSM_DealerNoteText) fprintf(stderr, _(" dealer"));
1851 fprintf(stderr, _(" welcome note - "));
1853 /* I know, it looks horrible, but... */
1854 /* I set it to the short string - if it won't be set */
1855 /* it means, PIN is required. If it will be correct, previous */
1856 /* (user) text was too long */
1858 /* Without it, I could have such thing: */
1859 /* user set text to very short string (for example, "Marcin") */
1860 /* then enable phone without PIN and try to set it to the very long (too long for phone) */
1861 /* string (which start with "Marcin"). If we compare them as only length different, we could think, */
1862 /* that phone accepts strings 6 chars length only (length of "Marcin") */
1863 /* When we make it correct, we don't have this mistake */
1865 strcpy(oldbit.text, "!\0");
1866 GSM->SetBitmap(&oldbit);
1867 GSM->GetBitmap(&oldbit);
1868 if (oldbit.text[0]!='!') {
1869 fprintf(stderr, _("SIM card and PIN is required\n"));
1871 GSM->SetBitmap(&bitmap);
1872 GSM->GetBitmap(&oldbit);
1873 fprintf(stderr, _("too long, truncated to \"%s\" (length %i)\n"),oldbit.text,strlen(oldbit.text));
1878 if (bitmap.type == GSM_StartupLogo) {
1879 for (i = 0; i < oldbit.size; i++) {
1880 if (oldbit.bitmap[i] != bitmap.bitmap[i]) {
1881 fprintf(stderr, _("Error setting startup logo - SIM card and PIN is required\n"));
1889 if (ok) fprintf(stdout, _("Done.\n"));
1891 case GE_NOTIMPLEMENTED:
1892 fprintf(stderr, _("Function not implemented.\n"));
1894 case GE_NOTSUPPORTED:
1895 fprintf(stderr, _("This kind of logo is not supported.\n"));
1898 fprintf(stderr, _("Error !\n"));
1908 int viewlogo(char *filename)
1912 error = GSM_ShowBitmapFile(filename);
1916 /* Calendar notes receiving. */
1917 int getcalendarnote(int argc, char *argv[])
1919 GSM_CalendarNote CalendarNote;
1921 GSM_Error error = GE_NONE;
1922 int i, first_location, last_location;
1925 struct option options[] = {
1926 { "vCard", optional_argument, NULL, '1'},
1933 first_location = last_location = atoi(argv[0]);
1934 if ((argc > 1) && (argv[1][0] != '-')) {
1935 last_location = atoi(argv[1]);
1938 while ((i = getopt_long(argc, argv, "v", options, NULL)) != -1) {
1944 usage(); /* Would be better to have an calendar_usage() here. */
1950 for (i = first_location; i <= last_location; i++) {
1951 CalendarNote.Location = i;
1952 if (GSM && GSM->GetCalendarNote && GSM->Terminate) {
1953 error = GSM->GetCalendarNote(&CalendarNote);
1956 GSM_DataClear(&data);
1957 data.CalendarNote = &CalendarNote;
1959 error = SM_Functions(GOP_GetCalendarNote, &data, &State);
1964 fprintf(stdout, "BEGIN:VCALENDAR\n");
1965 fprintf(stdout, "VERSION:1.0\n");
1966 fprintf(stdout, "BEGIN:VEVENT\n");
1967 fprintf(stdout, "CATEGORIES:");
1968 switch (CalendarNote.Type) {
1970 fprintf(stdout, "MISCELLANEOUS\n");
1973 fprintf(stdout, "PHONE CALL\n");
1976 fprintf(stdout, "MEETING\n");
1979 fprintf(stdout, "SPECIAL OCCASION\n");
1982 fprintf(stdout, "UNKNOWN\n");
1985 fprintf(stdout, "SUMMARY:%s\n",CalendarNote.Text);
1986 fprintf(stdout, "DTSTART:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Time.Year,
1987 CalendarNote.Time.Month, CalendarNote.Time.Day, CalendarNote.Time.Hour,
1988 CalendarNote.Time.Minute, CalendarNote.Time.Second);
1989 if (CalendarNote.Alarm.Year!=0) {
1990 fprintf(stdout, "DALARM:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Alarm.Year,
1991 CalendarNote.Alarm.Month, CalendarNote.Alarm.Day, CalendarNote.Alarm.Hour,
1992 CalendarNote.Alarm.Minute, CalendarNote.Alarm.Second);
1994 fprintf(stdout, "END:VEVENT\n");
1995 fprintf(stdout, "END:VCALENDAR\n");
1997 } else { /* not vCal */
1998 fprintf(stdout, _(" Type of the note: "));
2000 switch (CalendarNote.Type) {
2002 fprintf(stdout, _("Reminder\n"));
2005 fprintf(stdout, _("Call\n"));
2008 fprintf(stdout, _("Meeting\n"));
2011 fprintf(stdout, _("Birthday\n"));
2014 fprintf(stdout, _("Unknown\n"));
2018 fprintf(stdout, _(" Date: %d-%02d-%02d\n"), CalendarNote.Time.Year,
2019 CalendarNote.Time.Month,
2020 CalendarNote.Time.Day);
2022 fprintf(stdout, _(" Time: %02d:%02d:%02d\n"), CalendarNote.Time.Hour,
2023 CalendarNote.Time.Minute,
2024 CalendarNote.Time.Second);
2026 if (CalendarNote.Alarm.AlarmEnabled == 1) {
2027 fprintf(stdout, _(" Alarm date: %d-%02d-%02d\n"), CalendarNote.Alarm.Year,
2028 CalendarNote.Alarm.Month,
2029 CalendarNote.Alarm.Day);
2031 fprintf(stdout, _(" Alarm time: %02d:%02d:%02d\n"), CalendarNote.Alarm.Hour,
2032 CalendarNote.Alarm.Minute,
2033 CalendarNote.Alarm.Second);
2036 fprintf(stdout, _(" Text: %s\n"), CalendarNote.Text);
2038 if (CalendarNote.Type == GCN_CALL)
2039 fprintf(stdout, _(" Phone: %s\n"), CalendarNote.Phone);
2042 case GE_NOTIMPLEMENTED:
2043 fprintf(stderr, _("Function not implemented.\n"));
2046 fprintf(stderr, _("The calendar note can not be read\n"));
2055 /* Writing calendar notes. */
2056 int writecalendarnote(char *argv[])
2058 GSM_CalendarNote CalendarNote;
2060 if (GSM_ReadVCalendarFile(argv[0], &CalendarNote, atoi(argv[1]))) {
2061 fprintf(stdout, _("Failed to load vCalendar file.\n"));
2065 /* Error 22=Calendar full ;-) */
2066 if ((GSM->WriteCalendarNote(&CalendarNote)) == GE_NONE)
2067 fprintf(stdout, _("Succesfully written!\n"));
2069 fprintf(stdout, _("Failed to write calendar note!\n"));
2076 /* Calendar note deleting. */
2077 int deletecalendarnote(int argc, char *argv[])
2079 GSM_CalendarNote CalendarNote;
2080 int i, first_location, last_location;
2082 first_location = last_location = atoi(argv[0]);
2083 if (argc > 1) last_location = atoi(argv[1]);
2085 for (i = first_location; i <= last_location; i++) {
2087 CalendarNote.Location = i;
2089 if (GSM->DeleteCalendarNote(&CalendarNote) == GE_NONE) {
2090 fprintf(stdout, _(" Calendar note deleted.\n"));
2092 fprintf(stderr, _("The calendar note can not be deleted\n"));
2102 /* Setting the date and time. */
2103 int setdatetime(int argc, char *argv[])
2110 now = localtime(&nowh);
2112 Date.Year = now->tm_year;
2113 Date.Month = now->tm_mon+1;
2114 Date.Day = now->tm_mday;
2115 Date.Hour = now->tm_hour;
2116 Date.Minute = now->tm_min;
2117 Date.Second = now->tm_sec;
2119 if (argc > 0) Date.Year = atoi (argv[0]);
2120 if (argc > 1) Date.Month = atoi (argv[1]);
2121 if (argc > 2) Date.Day = atoi (argv[2]);
2122 if (argc > 3) Date.Hour = atoi (argv[3]);
2123 if (argc > 4) Date.Minute = atoi (argv[4]);
2125 if (Date.Year < 1900) {
2127 /* Well, this thing is copyrighted in U.S. This technique is known as
2128 Windowing and you can read something about it in LinuxWeekly News:
2129 http://lwn.net/1999/features/Windowing.phtml. This thing is beeing
2130 written in Czech republic and Poland where algorithms are not allowed
2134 Date.Year = Date.Year + 1900;
2136 Date.Year = Date.Year + 2000;
2139 /* FIXME: Error checking should be here. */
2140 GSM->SetDateTime(&Date);
2147 /* In this mode we receive the date and time from mobile phone. */
2148 int getdatetime(void) {
2150 GSM_DateTime date_time;
2153 if (GSM && GSM->GetDateTime && GSM->Terminate) {
2154 error = GSM->GetDateTime(&date_time);
2157 GSM_DataClear(&data);
2158 data.DateTime = &date_time;
2160 error = SM_Functions(GOP_GetDateTime, &data, &State);
2165 fprintf(stdout, _("Date: %4d/%02d/%02d\n"), date_time.Year, date_time.Month, date_time.Day);
2166 fprintf(stdout, _("Time: %02d:%02d:%02d\n"), date_time.Hour, date_time.Minute, date_time.Second);
2168 case GE_NOTIMPLEMENTED:
2169 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2172 fprintf(stdout, _("Internal error\n"));
2179 /* Setting the alarm. */
2180 int setalarm(char *argv[])
2184 Date.Hour = atoi(argv[0]);
2185 Date.Minute = atoi(argv[1]);
2187 GSM->SetAlarm(1, &Date);
2194 /* Getting the alarm. */
2199 GSM_DateTime date_time;
2201 if (GSM && GSM->GetAlarm && GSM->Terminate) {
2202 error = GSM->GetAlarm(0, &date_time);
2205 GSM_DataClear(&data);
2206 data.DateTime = &date_time;
2208 error = SM_Functions(GOP_GetAlarm, &data, &State);
2213 fprintf(stdout, _("Alarm: %s\n"), (date_time.AlarmEnabled==0)?"off":"on");
2214 fprintf(stdout, _("Time: %02d:%02d\n"), date_time.Hour, date_time.Minute);
2216 case GE_NOTIMPLEMENTED:
2217 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2220 fprintf(stdout, _("Internal error\n"));
2227 /* In monitor mode we don't do much, we just initialise the fbus code.
2228 Note that the fbus code no longer has an internal monitor mode switch,
2229 instead compile with DEBUG enabled to get all the gumpf. */
2230 int monitormode(void)
2232 float rflevel = -1, batterylevel = -1;
2233 // GSM_PowerSource powersource = -1;
2234 GSM_RFUnits rf_units = GRF_Arbitrary;
2235 GSM_BatteryUnits batt_units = GBU_Arbitrary;
2236 GSM_Statemachine *sm = &State;
2239 // GSM_NetworkInfo NetworkInfo;
2240 // GSM_CBMessage CBMessage;
2242 GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0};
2243 GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0};
2244 GSM_MemoryStatus DC_MemoryStatus = {GMT_DC, 0, 0};
2245 GSM_MemoryStatus EN_MemoryStatus = {GMT_EN, 0, 0};
2246 GSM_MemoryStatus FD_MemoryStatus = {GMT_FD, 0, 0};
2247 GSM_MemoryStatus LD_MemoryStatus = {GMT_LD, 0, 0};
2248 GSM_MemoryStatus MC_MemoryStatus = {GMT_MC, 0, 0};
2249 GSM_MemoryStatus ON_MemoryStatus = {GMT_ON, 0, 0};
2250 GSM_MemoryStatus RC_MemoryStatus = {GMT_RC, 0, 0};
2252 // GSM_SMSStatus SMSStatus = {0, 0};
2256 GSM_DataClear(&data);
2258 /* We do not want to monitor serial line forever - press Ctrl+C to stop the
2260 signal(SIGINT, interrupted);
2262 fprintf (stderr, _("Entering monitor mode...\n"));
2265 //GSM->EnableCellBroadcast();
2267 /* Loop here indefinitely - allows you to see messages from GSM code in
2268 response to unknown messages etc. The loops ends after pressing the
2270 data.RFUnits=&rf_units;
2271 data.RFLevel=&rflevel;
2272 data.BatteryUnits=&batt_units;
2273 data.BatteryLevel=&batterylevel;
2275 while (!bshutdown) {
2276 if (SM_Functions(GOP_GetRFLevel,&data,sm) == GE_NONE)
2277 fprintf(stdout, _("RFLevel: %d\n"), (int)rflevel);
2279 if (SM_Functions(GOP_GetBatteryLevel,&data,sm) == GE_NONE)
2280 fprintf(stdout, _("Battery: %d\n"), (int)batterylevel);
2282 // if (GSM->GetPowerSource(&powersource) == GE_NONE)
2283 // fprintf(stdout, _("Power Source: %s\n"), (powersource==GPS_ACDC)?_("AC/DC"):_("battery"));
2285 data.MemoryStatus=&SIMMemoryStatus;
2286 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2287 fprintf(stdout, _("SIM: Used %d, Free %d\n"), SIMMemoryStatus.Used, SIMMemoryStatus.Free);
2289 data.MemoryStatus=&PhoneMemoryStatus;
2290 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2291 fprintf(stdout, _("Phone: Used %d, Free %d\n"), PhoneMemoryStatus.Used, PhoneMemoryStatus.Free);
2293 data.MemoryStatus=&DC_MemoryStatus;
2294 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2295 fprintf(stdout, _("DC: Used %d, Free %d\n"), DC_MemoryStatus.Used, DC_MemoryStatus.Free);
2297 data.MemoryStatus=&EN_MemoryStatus;
2298 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2299 fprintf(stdout, _("EN: Used %d, Free %d\n"), EN_MemoryStatus.Used, EN_MemoryStatus.Free);
2301 data.MemoryStatus=&FD_MemoryStatus;
2302 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2303 fprintf(stdout, _("FD: Used %d, Free %d\n"), FD_MemoryStatus.Used, FD_MemoryStatus.Free);
2305 data.MemoryStatus=&LD_MemoryStatus;
2306 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2307 fprintf(stdout, _("LD: Used %d, Free %d\n"), LD_MemoryStatus.Used, LD_MemoryStatus.Free);
2309 data.MemoryStatus=&MC_MemoryStatus;
2310 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2311 fprintf(stdout, _("MC: Used %d, Free %d\n"), MC_MemoryStatus.Used, MC_MemoryStatus.Free);
2313 data.MemoryStatus=&ON_MemoryStatus;
2314 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2315 fprintf(stdout, _("ON: Used %d, Free %d\n"), ON_MemoryStatus.Used, ON_MemoryStatus.Free);
2317 data.MemoryStatus=&RC_MemoryStatus;
2318 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2319 fprintf(stdout, _("RC: Used %d, Free %d\n"), RC_MemoryStatus.Used, RC_MemoryStatus.Free);
2321 // if (GSM->GetSMSStatus(&SMSStatus) == GE_NONE)
2322 // fprintf(stdout, _("SMS Messages: UnRead %d, Number %d\n"), SMSStatus.UnRead, SMSStatus.Number);
2324 // if (GSM->GetIncomingCallNr(Number) == GE_NONE)
2325 // fprintf(stdout, _("Incoming call: %s\n"), Number);
2327 // if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE)
2328 // fprintf(stdout, _("Network: %s (%s), LAC: %s, CellID: %s\n"), GSM_GetNetworkName (NetworkInfo.NetworkCode), GSM_GetCountryName(NetworkInfo.NetworkCode), NetworkInfo.LAC, NetworkInfo.CellID);
2330 // if (GSM->ReadCellBroadcast(&CBMessage) == GE_NONE)
2331 // fprintf(stdout, _("Cell broadcast received on channel %d: %s\n"), CBMessage.Channel, CBMessage.Message);
2336 fprintf (stderr, _("Leaving monitor mode...\n"));
2346 static GSM_Error PrettyOutputFn(char *Display, char *Indicators)
2349 printf(ESC "[10;0H Display is:\n%s\n", Display);
2351 printf(ESC "[9;0H Indicators: %s \n", Indicators);
2352 printf(ESC "[1;1H");
2357 // Uncomment it if used
2358 static GSM_Error OutputFn(char *Display, char *Indicators)
2361 printf("New display is:\n%s\n", Display);
2363 printf("Indicators: %s\n", Indicators);
2368 void console_raw(void)
2373 tcgetattr(fileno(stdin), &it);
2374 it.c_lflag &= ~(ICANON);
2375 //it.c_iflag &= ~(INPCK|ISTRIP|IXON);
2379 tcsetattr(fileno(stdin), TCSANOW, &it);
2383 int displayoutput(void)
2386 GSM_Statemachine *sm = &State;
2389 data.OutputFn = PrettyOutputFn;
2391 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2393 fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
2395 if (error == GE_NONE) {
2397 /* We do not want to see texts forever - press Ctrl+C to stop. */
2398 signal(SIGINT, interrupted);
2400 fprintf (stderr, _("Entered display monitoring mode...\n"));
2401 fprintf (stderr, ESC "c" );
2403 /* Loop here indefinitely - allows you to read texts from phone's
2404 display. The loops ends after pressing the Ctrl+C. */
2405 while (!bshutdown) {
2407 memset(&buf[0], 0, 102);
2408 while (read(0, buf, 100) > 0) {
2409 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
2410 if (GSM->HandleString(buf) != GE_NONE)
2411 fprintf(stdout, _("Key press simulation failed.\n"));
2412 memset(buf, 0, 102);
2416 fprintf (stderr, "Shutting down\n");
2418 fprintf (stderr, _("Leaving display monitor mode...\n"));
2419 data.OutputFn = NULL;
2421 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2422 if (error != GE_NONE)
2423 fprintf (stderr, _("Error!\n"));
2425 fprintf (stderr, _("Error!\n"));
2431 /* Reads profile from phone and displays its' settings */
2432 int getprofile(int argc, char *argv[])
2436 GSM_Profile profile;
2439 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2443 error = GSM->GetProfile(&profile);
2445 if (error == GE_NONE) {
2447 while (GSM->GetModel(model) != GE_NONE)
2450 max_profiles = 7; /* This is correct for 6110 (at least my). How do we get
2451 the number of profiles? */
2454 /*FIX ME: It should be set to 3 for N5130 and 3210 too*/
2455 if (!strcmp(model, "NSE-1"))
2459 profile.Number = atoi(argv[0]) - 1;
2460 start = profile.Number;
2463 if (profile.Number < 0) {
2464 fprintf(stderr, _("Profile number must be value from 1 to %d!\n"), max_profiles);
2469 if (profile.Number >= max_profiles) {
2470 fprintf(stderr, _("This phone supports only %d profiles!\n"), max_profiles);
2476 stop = max_profiles;
2483 if (profile.Number != 0)
2484 GSM->GetProfile(&profile);
2486 fprintf(stdout, "%d. \"%s\"\n", profile.Number + 1, profile.Name);
2487 if (profile.DefaultName == -1) fprintf(stdout, _(" (name defined)\n"));
2489 fprintf(stdout, _("Incoming call alert: %s\n"), GetProfileCallAlertString(profile.CallAlert));
2491 /* For different phones different ringtones names */
2493 if (!strcmp(model, "NSE-3"))
2494 fprintf(stdout, _("Ringing tone: %s (%d)\n"), RingingTones[profile.Ringtone], profile.Ringtone);
2496 fprintf(stdout, _("Ringtone number: %d\n"), profile.Ringtone);
2498 fprintf(stdout, _("Ringing volume: %s\n"), GetProfileVolumeString(profile.Volume));
2500 fprintf(stdout, _("Message alert tone: %s\n"), GetProfileMessageToneString(profile.MessageTone));
2502 fprintf(stdout, _("Keypad tones: %s\n"), GetProfileKeypadToneString(profile.KeypadTone));
2504 fprintf(stdout, _("Warning and game tones: %s\n"), GetProfileWarningToneString(profile.WarningTone));
2506 /* FIXME: Light settings is only used for Car */
2507 if (profile.Number == (max_profiles - 2)) fprintf(stdout, _("Lights: %s\n"), profile.Lights ? _("On") : _("Automatic"));
2509 fprintf(stdout, _("Vibration: %s\n"), GetProfileVibrationString(profile.Vibration));
2511 /* FIXME: it will be nice to add here reading caller group name. */
2512 if (max_profiles != 3) fprintf(stdout, _("Caller groups: 0x%02x\n"), profile.CallerGroups);
2514 /* FIXME: Automatic answer is only used for Car and Headset. */
2515 if (profile.Number >= (max_profiles - 2)) fprintf(stdout, _("Automatic answer: %s\n"), profile.AutomaticAnswer ? _("On") : _("Off"));
2517 fprintf(stdout, "\n");
2522 if (error == GE_NOTIMPLEMENTED) {
2523 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2527 fprintf(stderr, _("Unspecified error\n"));
2537 /* Get requested range of memory storage entries and output to stdout in
2538 easy-to-parse format */
2539 int getmemory(int argc, char *argv[])
2541 GSM_PhonebookEntry entry;
2544 char *memory_type_string;
2547 GSM_Statemachine *sm = &State;
2549 /* Handle command line args that set type, start and end locations. */
2550 memory_type_string = argv[0];
2551 entry.MemoryType = StrToMemoryType(memory_type_string);
2552 if (entry.MemoryType == GMT_XX) {
2553 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
2557 start_entry = atoi (argv[1]);
2558 if (argc > 2) end_entry = atoi (argv[2]);
2559 else end_entry = start_entry;
2561 /* Now retrieve the requested entries. */
2562 for (count = start_entry; count <= end_entry; count ++) {
2564 entry.Location = count;
2566 data.PhonebookEntry=&entry;
2567 error=SM_Functions(GOP_ReadPhonebook,&data,sm);
2569 if (error == GE_NONE) {
2570 fprintf(stdout, "%s;%s;%s;%d;%d\n", entry.Name, entry.Number, memory_type_string, entry.Location, entry.Group);
2571 if (entry.MemoryType == GMT_MC || entry.MemoryType == GMT_DC || entry.MemoryType == GMT_RC)
2572 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);
2575 if (error == GE_NOTIMPLEMENTED) {
2576 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2579 else if (error == GE_INVALIDMEMORYTYPE) {
2580 fprintf(stderr, _("Memory type %s not supported!\n"), memory_type_string);
2584 fprintf(stdout, _("%s|%d|Bad location or other error!(%d)\n"), memory_type_string, count, error);
2590 /* Read data from stdin, parse and write to phone. The parsing is relatively
2591 crude and doesn't allow for much variation from the stipulated format. */
2592 /* FIXME: I guess there's *very* similar code in xgnokii */
2593 int writephonebook(int argc, char *args[])
2595 GSM_PhonebookEntry entry;
2597 char *memory_type_string;
2601 char *Line, OLine[100], BackLine[100];
2604 /* Check argument */
2605 if (argc && (strcmp("-i", args[0])))
2610 /* Go through data from stdin. */
2611 while (GetLine(stdin, Line, 99)) {
2612 strcpy(BackLine, Line);
2615 ptr = strtok(Line, ";");
2616 if (ptr) strcpy(entry.Name, ptr);
2617 else entry.Name[0] = 0;
2619 ptr = strtok(NULL, ";");
2620 if (ptr) strcpy(entry.Number, ptr);
2621 else entry.Number[0] = 0;
2623 ptr = strtok(NULL, ";");
2626 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2631 if (!strncmp(ptr,"ME", 2)) {
2632 memory_type_string = "int";
2633 entry.MemoryType = GMT_ME;
2635 if (!strncmp(ptr,"SM", 2)) {
2636 memory_type_string = "sim";
2637 entry.MemoryType = GMT_SM;
2639 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2644 ptr = strtok(NULL, ";");
2645 if (ptr) entry.Location = atoi(ptr);
2646 else entry.Location = 0;
2648 ptr = strtok(NULL, ";");
2649 if (ptr) entry.Group = atoi(ptr);
2650 else entry.Group = 0;
2653 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2657 for (subentry = 0; ; subentry++) {
2658 ptr = strtok(NULL, ";");
2660 if (ptr && *ptr != 0)
2661 entry.SubEntries[subentry].EntryType = atoi(ptr);
2665 ptr = strtok(NULL, ";");
2667 entry.SubEntries[subentry].NumberType=atoi(ptr);
2669 /* Phone Numbers need to have a number type. */
2670 if (!ptr && entry.SubEntries[subentry].EntryType == GSM_Number) {
2671 fprintf(stderr, _("Missing phone number type on line %d"
2672 " entry %d [%s]\n"), line_count, subentry, BackLine);
2677 ptr = strtok(NULL, ";");
2679 entry.SubEntries[subentry].BlockNumber=atoi(ptr);
2681 ptr = strtok(NULL, ";");
2683 /* 0x13 Date Type; it is only for Dailed Numbers, etc.
2684 we don't store to this memories so it's an error to use it. */
2685 if (!ptr || entry.SubEntries[subentry].EntryType == GSM_Date) {
2686 fprintf(stdout, _("There is no phone number on line %d entry %d [%s]\n"),
2687 line_count, subentry, BackLine);
2691 strcpy(entry.SubEntries[subentry].data.Number, ptr);
2694 entry.SubEntriesCount = subentry;
2696 /* This is to send other exports (like from 6110) to 7110 */
2697 if (!entry.SubEntriesCount) {
2698 entry.SubEntriesCount = 1;
2699 entry.SubEntries[subentry].EntryType = GSM_Number;
2700 entry.SubEntries[subentry].NumberType = GSM_General;
2701 entry.SubEntries[subentry].BlockNumber = 2;
2702 strcpy(entry.SubEntries[subentry].data.Number, entry.Number);
2708 GSM_PhonebookEntry aux;
2710 aux.Location = entry.Location;
2711 error = GSM->GetMemoryLocation(&aux);
2713 if (error == GE_NONE) {
2718 fprintf(stdout, _("Location busy. "));
2719 while (confirm < 0) {
2720 fprintf(stdout, _("Overwrite? (yes/no) "));
2721 GetLine(stdin, ans, 7);
2722 if (!strcmp(ans, _("yes"))) confirm = 1;
2723 else if (!strcmp(ans, _("no"))) confirm = 0;
2725 if (!confirm) continue;
2728 fprintf(stderr, _("Unknown error (%d)\n"), error);
2734 /* Do write and report success/failure. */
2735 error = GSM->WritePhonebookLocation(&entry);
2737 if (error == GE_NONE)
2738 fprintf (stdout, _("Write Succeeded: memory type: %s, loc: %d, name: %s, number: %s\n"), memory_type_string, entry.Location, entry.Name, entry.Number);
2740 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);
2748 /* Getting speed dials. */
2749 int getspeeddial(char *Number)
2751 GSM_SpeedDial SpeedDial;
2755 SpeedDial.Number = atoi(Number);
2757 if (GSM && GSM->GetSpeedDial && GSM->Terminate) {
2758 error = GSM->GetSpeedDial(&SpeedDial);
2761 GSM_DataClear(&data);
2762 data.SpeedDial = &SpeedDial;
2764 error = SM_Functions(GOP_GetSpeedDial, &data, &State);
2769 fprintf(stdout, _("SpeedDial nr. %d: %d:%d\n"), SpeedDial.Number, SpeedDial.MemoryType, SpeedDial.Location);
2771 case GE_NOTIMPLEMENTED:
2772 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2775 fprintf(stdout, _("Internal error\n"));
2782 /* Setting speed dials. */
2783 int setspeeddial(char *argv[])
2785 GSM_SpeedDial entry;
2787 char *memory_type_string;
2789 /* Handle command line args that set type, start and end locations. */
2791 if (strcmp(argv[1], "ME") == 0) {
2792 entry.MemoryType = 0x02;
2793 memory_type_string = "ME";
2794 } else if (strcmp(argv[1], "SM") == 0) {
2795 entry.MemoryType = 0x03;
2796 memory_type_string = "SM";
2798 fprintf(stderr, _("Unknown memory type %s!\n"), argv[1]);
2802 entry.Number = atoi(argv[0]);
2803 entry.Location = atoi(argv[2]);
2805 if (GSM->SetSpeedDial(&entry) == GE_NONE) {
2806 fprintf(stdout, _("Succesfully written!\n"));
2813 /* Getting the status of the display. */
2814 int getdisplaystatus(void)
2818 GSM->GetDisplayStatus(&Status);
2820 fprintf(stdout, _("Call in progress: %s\n"), Status & (1<<DS_Call_In_Progress)?_("on"):_("off"));
2821 fprintf(stdout, _("Unknown: %s\n"), Status & (1<<DS_Unknown)?_("on"):_("off"));
2822 fprintf(stdout, _("Unread SMS: %s\n"), Status & (1<<DS_Unread_SMS)?_("on"):_("off"));
2823 fprintf(stdout, _("Voice call: %s\n"), Status & (1<<DS_Voice_Call)?_("on"):_("off"));
2824 fprintf(stdout, _("Fax call active: %s\n"), Status & (1<<DS_Fax_Call)?_("on"):_("off"));
2825 fprintf(stdout, _("Data call active: %s\n"), Status & (1<<DS_Data_Call)?_("on"):_("off"));
2826 fprintf(stdout, _("Keyboard lock: %s\n"), Status & (1<<DS_Keyboard_Lock)?_("on"):_("off"));
2827 fprintf(stdout, _("SMS storage full: %s\n"), Status & (1<<DS_SMS_Storage_Full)?_("on"):_("off"));
2833 int netmonitor(char *Mode)
2835 unsigned char mode = atoi(Mode);
2838 if (!strcmp(Mode, "reset"))
2840 else if (!strcmp(Mode, "off"))
2842 else if (!strcmp(Mode, "field"))
2844 else if (!strcmp(Mode, "devel"))
2846 else if (!strcmp(Mode, "next"))
2849 memset(&Screen, 0, 50);
2850 GSM->NetMonitor(mode, Screen);
2853 fprintf(stdout, "%s\n", Screen);
2861 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2862 char imei[64], model[64], rev[64], manufacturer[64];
2863 GSM_Statemachine *sm = &State;
2865 data.Manufacturer=manufacturer;
2870 /* Retrying is bad idea: what if function is simply not implemented?
2871 Anyway let's wait 2 seconds for the right packet from the phone. */
2874 strcpy(imei, "(unknown)");
2875 strcpy(manufacturer, "(unknown)");
2876 strcpy(model, "(unknown)");
2877 strcpy(rev, "(unknown)");
2879 SM_Functions(GOP_Identify, &data, sm);
2881 fprintf(stdout, _("IMEI: %s\n"), imei);
2882 fprintf(stdout, _("Manufacturer: %s\n"), manufacturer);
2883 fprintf(stdout, _("Model: %s\n"), model);
2884 fprintf(stdout, _("Revision: %s\n"), rev);
2891 int senddtmf(char *String)
2893 GSM->SendDTMF(String);
2898 /* Resets the phone */
2899 int reset( char *type)
2901 unsigned char _type = 0x03;
2904 if(!strcmp(type, "soft"))
2907 if(!strcmp(type, "hard"))
2910 fprintf(stderr, _("What kind of reset do you want??\n"));
2921 /* pmon allows fbus code to run in a passive state - it doesn't worry about
2922 whether comms are established with the phone. A debugging/development
2928 GSM_ConnectionType connection=GCT_Serial;
2929 GSM_Statemachine sm;
2931 /* Initialise the code for the GSM interface. */
2932 error = GSM_Initialise(model, Port, Initlength, connection, NULL, &sm);
2934 if (error != GE_NONE) {
2935 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
2946 int sendringtone(int argc, char *argv[])
2948 GSM_Ringtone ringtone;
2951 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2952 fprintf(stdout, _("Failed to load ringtone.\n"));
2956 error = GSM->SendRingtone(&ringtone,argv[1]);
2958 if (error == GE_NONE)
2959 fprintf(stdout, _("Send succeeded!\n"));
2961 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
2969 int setringtone(int argc, char *argv[])
2971 GSM_Ringtone ringtone;
2974 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2975 fprintf(stdout, _("Failed to load ringtone.\n"));
2979 error = GSM->SetRingtone(&ringtone);
2981 if (error == GE_NONE)
2982 fprintf(stdout, _("Send succeeded!\n"));
2984 fprintf(stdout, _("Send failed\n"));
2991 int presskeysequence(void)
2997 memset(&buf[0], 0, 102);
2998 while (read(0, buf, 100) > 0) {
2999 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
3000 if (GSM->HandleString(buf) != GE_NONE)
3001 fprintf(stdout, _("Key press simulation failed.\n"));
3002 memset(buf, 0, 102);
3009 /* This is a "convenience" function to allow quick test of new API stuff which
3010 doesn't warrant a "proper" command line function. */
3012 int foogle(char *argv[])
3014 /* Initialise the code for the GSM interface. */
3016 // Fill in what you would like to test here...