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.12.1 2001/11/27 23:34:48 short
23 Update: orig2001_11_27_05_17 -> orig2001_11_27_22_58
25 Revision 1.1.1.1.8.1 2001/11/27 23:06:09 short
26 Update: orig2001_11_27_05_17 -> orig2001_11_27_22_58
28 Revision 1.1.1.1.2.1 2001/11/27 22:48:37 short
29 Update: orig2001_11_27_05_17 -> orig2001_11_27_22_58
31 Revision 1.1.1.2 2001/11/27 22:01:25 short
32 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Nov 27 22:58 CET 2001
34 Revision 1.152 2001/11/27 12:23:11 pkot
35 Specifying SMSC number in --sendsms works again
37 Revision 1.151 2001/11/22 17:56:53 pkot
38 smslib update. sms sending
40 Revision 1.150 2001/11/20 16:22:22 pkot
41 First attempt to read Picture Messages. They should appear when you enable DEBUG. Nokia seems to break own standards. :/ (Markus Plail)
43 Revision 1.149 2001/11/19 16:00:15 pkot
46 Revision 1.148 2001/11/19 13:46:43 pkot
47 reading unread SMS in 6210 from Inbox. Folder updates (Markus Plail)
49 Revision 1.147 2001/11/18 00:54:32 pkot
50 Bugfixes. I18n of the user responses. UDH support in libsms. Business Card UDH Type
52 Revision 1.146 2001/11/17 20:18:33 pkot
53 Added dau9p connection type for 6210/7110
55 Revision 1.145 2001/11/14 10:46:12 pkot
56 Small cleanup with __unices__
58 Revision 1.144 2001/11/08 16:34:19 pkot
59 Updates to work with new libsms
61 Revision 1.143 2001/09/14 13:30:07 pkot
62 Fixed bugs introduced during 0.3.3 merge
64 Revision 1.142 2001/09/14 13:02:03 pkot
65 Gnokii calendar changes from 0.3.3
67 Revision 1.141 2001/09/14 12:53:00 pkot
70 Set valid operator on logos xgnokii screen.
72 Revision 1.140 2001/07/27 00:02:21 pkot
73 Generic AT support for the new structure (Manfred Jonsson)
75 Revision 1.139 2001/07/01 23:16:45 pkot
76 Fixed a typo in gnokii.c avoiding saving logo (Jan Havelka)
78 Revision 1.138 2001/06/28 00:28:45 pkot
79 Small docs updates (Pawel Kot)
81 Revision 1.137 2001/06/27 23:52:50 pkot
82 7110/6210 updates (Marian Jancar)
84 Revision 1.136 2001/06/10 23:49:49 pkot
85 Small fixes to hide compilation warnings and allow gnokii.c to compile
87 Revision 1.135 2001/06/10 11:42:26 machek
88 Cleanup: some formating, made Statemachine global, converted to new
89 structure w.r.t. SMS-es
91 Revision 1.134 2001/05/24 20:47:30 chris
92 More updating of 7110 code and some of xgnokii_lowlevel changed over.
94 Revision 1.133 2001/04/23 17:20:01 pkot
95 Added possibility for viewing logos (currently nol and ngg) on console (Bartek Klepacz)
97 Revision 1.132 2001/03/21 23:36:06 chris
98 Added the statemachine
99 This will break gnokii --identify and --monitor except for 6210/7110
101 Revision 1.131 2001/03/19 23:43:46 pkot
102 Solaris / BSD '#if defined' cleanup
104 Revision 1.130 2001/03/13 01:23:18 pkot
105 Windows updates (Manfred Jonsson)
107 Revision 1.129 2001/03/13 01:21:39 pkot
108 *BSD updates (Bert Driehuis)
110 Revision 1.128 2001/03/08 00:49:06 pkot
111 Fixed bug (introduced by me) in getmemory function. Now gnokii.c should compile
113 Revision 1.127 2001/03/08 00:18:13 pkot
114 Fixed writephonebook once again. Someone kick me please...
116 Revision 1.126 2001/03/07 21:46:12 pkot
117 Fixed writephonebook patch
119 Revision 1.125 2001/03/06 22:19:14 pkot
120 Cleanups and fixes in gnokii.c:
122 - fixed bug reported by Gabriele Zappi
123 - fixed small bugs introduced by Pavel Machek
125 Revision 1.124 2001/02/28 21:42:00 machek
126 Possibility to force overwrite in --getsms (-F). Possibility to get
127 multiple files (use --getsms -f xyzzy%d), cleanup.
129 Revision 1.123 2001/02/20 21:55:11 pkot
130 Small #include updates
132 Revision 1.122 2001/02/16 14:29:53 chris
133 Restructure of common/. Fixed a problem in fbus-phonet.c
134 Lots of dprintfs for Marcin
135 Any size xpm can now be loaded (eg for 7110 startup logos)
136 nk7110 code detects 7110/6210 and alters startup logo size to suit
137 Moved Marcin's extended phonebook code into gnokii.c
139 Revision 1.121 2001/02/06 21:15:35 chris
140 Preliminary irda support for 7110 etc. Not well tested!
142 Revision 1.120 2001/02/06 08:13:32 pkot
143 One more include in gnokii.c needed
145 Revision 1.119 2001/02/05 12:29:37 pkot
146 Changes needed to let unicode work
148 Revision 1.118 2001/02/01 15:17:33 pkot
149 Fixed --identify and added Manfred's manufacturer patch
151 Revision 1.117 2001/01/31 23:45:27 pkot
152 --identify should work ok now
154 Revision 1.116 2001/01/24 20:19:55 machek
155 Do not retry identification, if it is not implemented, it is bad idea.
157 Revision 1.115 2001/01/22 01:25:10 hugh
158 Tweaks for 3810 series, datacalls seem to be broken so need to do
159 some more debugging...
161 Revision 1.114 2001/01/17 02:54:55 chris
162 More 7110 work. Use with care! (eg it is not possible to delete phonebook entries)
163 I can now edit my phonebook in xgnokii but it is 'work in progress'.
165 Revision 1.113 2001/01/15 17:00:49 pkot
166 Initial keypress sequence support. Disable compilation warning
168 Revision 1.112 2001/01/12 14:09:13 pkot
169 More cleanups. This time mainly in the code.
171 Revision 1.111 2001/01/10 16:32:18 pkot
172 Documentation updates.
173 FreeBSD fix for 3810 code.
174 Added possibility for deleting SMS just after reading it in gnokii.
178 Revision 1.110 2001/01/08 15:11:37 pkot
179 Documentation updates.
180 Fixed some bugs and removed FIXMEs.
181 We need to move some stuff from configure.in to aclocal.m4
183 Revision 1.109 2000/12/29 15:39:07 pkot
184 Reverted a change in fbus-3810.c which broke compling with --enable-debug.
185 Small fixes in gnokii.c
187 Revision 1.108 2000/12/19 16:18:16 pkot
188 configure script updates and added shared function for configfile reading
200 # include <strings.h> /* for memset */
203 #include <sys/types.h>
204 #include <sys/stat.h>
209 #define sleep(x) Sleep((x) * 1000)
210 #define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
212 #include "win32/getopt.h"
227 #include "gsm-common.h"
229 #include "gsm-networks.h"
230 #include "cfgreader.h"
232 #include "gsm-filetypes.h"
233 #include "gsm-bitmaps.h"
234 #include "gsm-ringtones.h"
235 #include "gsm-statemachine.h"
237 char *model; /* Model from .gnokiirc file. */
238 char *Port; /* Serial port from .gnokiirc file */
239 char *Initlength; /* Init length from .gnokiirc file */
240 char *Connection; /* Connection type from .gnokiirc file */
241 char *BinDir; /* Binaries directory from .gnokiirc file - not used here yet */
242 /* Local variables */
244 char *GetProfileCallAlertString(int code)
247 case PROFILE_CALLALERT_RINGING: return "Ringing";
248 case PROFILE_CALLALERT_ASCENDING: return "Ascending";
249 case PROFILE_CALLALERT_RINGONCE: return "Ring once";
250 case PROFILE_CALLALERT_BEEPONCE: return "Beep once";
251 case PROFILE_CALLALERT_CALLERGROUPS: return "Caller groups";
252 case PROFILE_CALLALERT_OFF: return "Off";
253 default: return "Unknown";
257 char *GetProfileVolumeString(int code)
260 case PROFILE_VOLUME_LEVEL1: return "Level 1";
261 case PROFILE_VOLUME_LEVEL2: return "Level 2";
262 case PROFILE_VOLUME_LEVEL3: return "Level 3";
263 case PROFILE_VOLUME_LEVEL4: return "Level 4";
264 case PROFILE_VOLUME_LEVEL5: return "Level 5";
265 default: return "Unknown";
269 char *GetProfileKeypadToneString(int code)
272 case PROFILE_KEYPAD_OFF: return "Off";
273 case PROFILE_KEYPAD_LEVEL1: return "Level 1";
274 case PROFILE_KEYPAD_LEVEL2: return "Level 2";
275 case PROFILE_KEYPAD_LEVEL3: return "Level 3";
276 default: return "Unknown";
280 char *GetProfileMessageToneString(int code)
283 case PROFILE_MESSAGE_NOTONE: return "No tone";
284 case PROFILE_MESSAGE_STANDARD: return "Standard";
285 case PROFILE_MESSAGE_SPECIAL: return "Special";
286 case PROFILE_MESSAGE_BEEPONCE: return "Beep once";
287 case PROFILE_MESSAGE_ASCENDING: return "Ascending";
288 default: return "Unknown";
292 char *GetProfileWarningToneString(int code)
295 case PROFILE_WARNING_OFF: return "Off";
296 case PROFILE_WARNING_ON: return "On";
297 default: return "Unknown";
301 char *GetProfileVibrationString(int code)
304 case PROFILE_VIBRATION_OFF: return "Off";
305 case PROFILE_VIBRATION_ON: return "On";
306 default: return "Unknown";
310 /* This function shows the copyright and some informations usefull for
315 fprintf(stdout, _("GNOKII Version %s\n"
316 "Copyright (C) Hugh Blemings <hugh@blemings.org>, 1999, 2000\n"
317 "Copyright (C) Pavel Janík ml. <Pavel.Janik@suse.cz>, 1999, 2000\n"
318 "Copyright (C) Pavel Machek <pavel@ucw.cz>, 2001\n"
319 "Copyright (C) Pawe³ Kot <pkot@linuxnews.pl>, 2001\n"
320 "gnokii is free software, covered by the GNU General Public License, and you are\n"
321 "welcome to change it and/or distribute copies of it under certain conditions.\n"
322 "There is absolutely no warranty for gnokii. See GPL for details.\n"
323 "Built %s %s for %s on %s \n"), VERSION, __TIME__, __DATE__, model, Port);
327 /* The function usage is only informative - it prints this program's usage and
328 command-line options. */
332 fprintf(stdout, _(" usage: gnokii [--help|--monitor|--version]\n"
333 " gnokii --getmemory memory_type start [end]\n"
334 " gnokii --writephonebook [-i]\n"
335 " gnokii --getspeeddial number\n"
336 " gnokii --setspeeddial number memory_type location\n"
337 " gnokii --getsms memory_type start [end] [-f file] [-F file] [-d]\n"
338 " gnokii --deletesms memory_type start [end]\n"
339 " gnokii --sendsms destination [--smsc message_center_number |\n"
340 " --smscno message_center_index] [-r] [-C n] [-v n]\n"
342 " gnokii --savesms [-m] [-l n] [-i]\n"
343 " gnokii --getsmsc message_center_number\n"
344 " gnokii --setdatetime [YYYY [MM [DD [HH [MM]]]]]\n"
345 " gnokii --getdatetime\n"
346 " gnokii --setalarm HH MM\n"
347 " gnokii --getalarm\n"
348 " gnokii --dialvoice number\n"
349 " gnokii --getcalendarnote start [end] [-v]\n"
350 " gnokii --writecalendarnote vcardfile number\n"
351 " gnokii --deletecalendarnote start [end]\n"
352 " gnokii --getdisplaystatus\n"
353 " gnokii --netmonitor {reset|off|field|devel|next|nr}\n"
354 " gnokii --identify\n"
355 " gnokii --senddtmf string\n"
356 " gnokii --sendlogo {caller|op} destination logofile [network code]\n"
357 " gnokii --sendringtone destination rtttlfile\n"
358 " gnokii --setlogo op [logofile] [network code]\n"
359 " gnokii --setlogo startup [logofile]\n"
360 " gnokii --setlogo caller [logofile] [caller group number] [group name]\n"
361 " gnokii --setlogo {dealer|text} [text]\n"
362 " gnokii --getlogo op [logofile] [network code]\n"
363 " gnokii --getlogo startup [logofile] [network code]\n"
364 " gnokii --getlogo caller [logofile][caller group number][network code]\n"
365 " gnokii --getlogo {dealer|text}\n"
366 " gnokii --viewlogo logofile\n"
367 " gnokii --setringtone rtttlfile\n"
368 " gnokii --reset [soft|hard]\n"
369 " gnokii --getprofile [number]\n"
370 " gnokii --displayoutput\n"
371 " gnokii --keysequence\n"
375 " gnokii --entersecuritycode PIN|PIN2|PUK|PUK2\n"
376 " gnokii --getsecuritycodestatus\n"
382 /* fbusinit is the generic function which waits for the FBUS link. The limit
383 is 10 seconds. After 10 seconds we quit. */
385 static GSM_Statemachine State;
386 static GSM_Data data;
388 void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame))
392 GSM_ConnectionType connection = GCT_Serial;
394 GSM_DataClear(&data);
396 if (!strcasecmp(Connection, "dau9p")) connection = GCT_DAU9P;
397 if (!strcasecmp(Connection, "infrared")) connection = GCT_Infrared;
398 if (!strcasecmp(Connection, "irda")) connection = GCT_Irda;
400 /* Initialise the code for the GSM interface. */
402 error = GSM_Initialise(model, Port, Initlength, connection, rlp_handler, &State);
404 if (error != GE_NONE) {
405 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
409 /* First (and important!) wait for GSM link to be active. We allow 10
412 while (count++ < 200 && *GSM_LinkOK == false)
415 if (*GSM_LinkOK == false) {
416 fprintf (stderr, _("Hmmm... GSM_LinkOK never went true. Quitting.\n"));
421 /* This function checks that the argument count for a given options is withing
423 int checkargs(int opt, struct gnokii_arg_len gals[], int argc)
427 /* Walk through the whole array with options requiring arguments. */
428 for (i = 0; !(gals[i].gal_min == 0 && gals[i].gal_max == 0); i++) {
430 /* Current option. */
431 if (gals[i].gal_opt == opt) {
433 /* Argument count checking. */
434 if (gals[i].gal_flags == GAL_XOR) {
435 if (gals[i].gal_min == argc || gals[i].gal_max == argc)
438 if (gals[i].gal_min <= argc && gals[i].gal_max >= argc)
446 /* We do not have options without arguments in the array, so check them. */
447 if (argc == 0) return 0;
451 /* Main function - handles command line arguments, passes them to separate
452 functions accordingly. */
453 int main(int argc, char *argv[])
459 /* Every option should be in this array. */
460 static struct option long_options[] =
462 /* FIXME: these comments are nice, but they would be more usefull as docs for the user */
464 { "help", no_argument, NULL, OPT_HELP },
466 // Display version and build information.
467 { "version", no_argument, NULL, OPT_VERSION },
470 { "monitor", no_argument, NULL, OPT_MONITOR },
474 // Enter Security Code mode
475 { "entersecuritycode", required_argument, NULL, OPT_ENTERSECURITYCODE },
477 // Get Security Code status
478 { "getsecuritycodestatus", no_argument, NULL, OPT_GETSECURITYCODESTATUS },
483 { "setdatetime", optional_argument, NULL, OPT_SETDATETIME },
485 // Get date and time mode
486 { "getdatetime", no_argument, NULL, OPT_GETDATETIME },
489 { "setalarm", required_argument, NULL, OPT_SETALARM },
492 { "getalarm", no_argument, NULL, OPT_GETALARM },
495 { "dialvoice", required_argument, NULL, OPT_DIALVOICE },
497 // Get calendar note mode
498 { "getcalendarnote", required_argument, NULL, OPT_GETCALENDARNOTE },
500 // Write calendar note mode
501 { "writecalendarnote", required_argument, NULL, OPT_WRITECALENDARNOTE },
503 // Delete calendar note mode
504 { "deletecalendarnote", required_argument, NULL, OPT_DELCALENDARNOTE },
506 // Get display status mode
507 { "getdisplaystatus", no_argument, NULL, OPT_GETDISPLAYSTATUS },
510 { "getmemory", required_argument, NULL, OPT_GETMEMORY },
512 // Write phonebook (memory) mode
513 { "writephonebook", optional_argument, NULL, OPT_WRITEPHONEBOOK },
515 // Get speed dial mode
516 { "getspeeddial", required_argument, NULL, OPT_GETSPEEDDIAL },
518 // Set speed dial mode
519 { "setspeeddial", required_argument, NULL, OPT_SETSPEEDDIAL },
521 // Get SMS message mode
522 { "getsms", required_argument, NULL, OPT_GETSMS },
524 // Delete SMS message mode
525 { "deletesms", required_argument, NULL, OPT_DELETESMS },
527 // Send SMS message mode
528 { "sendsms", required_argument, NULL, OPT_SENDSMS },
530 // Ssve SMS message mode
531 { "savesms", optional_argument, NULL, OPT_SAVESMS },
533 // Send logo as SMS message mode
534 { "sendlogo", required_argument, NULL, OPT_SENDLOGO },
536 // Send ringtone as SMS message
537 { "sendringtone", required_argument, NULL, OPT_SENDRINGTONE },
540 { "setringtone", required_argument, NULL, OPT_SETRINGTONE },
542 // Get SMS center number mode
543 { "getsmsc", required_argument, NULL, OPT_GETSMSC },
545 // For development purposes: run in passive monitoring mode
546 { "pmon", no_argument, NULL, OPT_PMON },
549 { "netmonitor", required_argument, NULL, OPT_NETMONITOR },
552 { "identify", no_argument, NULL, OPT_IDENTIFY },
554 // Send DTMF sequence
555 { "senddtmf", required_argument, NULL, OPT_SENDDTMF },
558 { "reset", optional_argument, NULL, OPT_RESET },
561 { "setlogo", optional_argument, NULL, OPT_SETLOGO },
564 { "getlogo", required_argument, NULL, OPT_GETLOGO },
567 { "viewlogo", required_argument, NULL, OPT_VIEWLOGO },
570 { "getprofile", optional_argument, NULL, OPT_GETPROFILE },
572 // Show texts from phone's display
573 { "displayoutput", no_argument, NULL, OPT_DISPLAYOUTPUT },
575 // Simulate pressing the keys
576 { "keysequence", no_argument, NULL, OPT_KEYPRESS },
578 // For development purposes: insert you function calls here
579 { "foogle", no_argument, NULL, OPT_FOOGLE },
584 /* Every command which requires arguments should have an appropriate entry
586 struct gnokii_arg_len gals[] =
590 { OPT_ENTERSECURITYCODE, 1, 1, 0 },
593 { OPT_SETDATETIME, 0, 5, 0 },
594 { OPT_SETALARM, 2, 2, 0 },
595 { OPT_DIALVOICE, 1, 1, 0 },
596 { OPT_GETCALENDARNOTE, 1, 3, 0 },
597 { OPT_WRITECALENDARNOTE, 2, 2, 0 },
598 { OPT_DELCALENDARNOTE, 1, 2, 0 },
599 { OPT_GETMEMORY, 2, 3, 0 },
600 { OPT_GETSPEEDDIAL, 1, 1, 0 },
601 { OPT_SETSPEEDDIAL, 3, 3, 0 },
602 { OPT_GETSMS, 2, 5, 0 },
603 { OPT_DELETESMS, 2, 3, 0 },
604 { OPT_SENDSMS, 1, 10, 0 },
605 { OPT_SAVESMS, 0, 6, 0 },
606 { OPT_SENDLOGO, 3, 4, GAL_XOR },
607 { OPT_SENDRINGTONE, 2, 2, 0 },
608 { OPT_GETSMSC, 1, 1, 0 },
609 { OPT_GETWELCOMENOTE, 1, 1, 0 },
610 { OPT_SETWELCOMENOTE, 1, 1, 0 },
611 { OPT_NETMONITOR, 1, 1, 0 },
612 { OPT_SENDDTMF, 1, 1, 0 },
613 { OPT_SETLOGO, 1, 4, 0 },
614 { OPT_GETLOGO, 1, 4, 0 },
615 { OPT_VIEWLOGO, 1, 1, 0 },
616 { OPT_SETRINGTONE, 1, 1, 0 },
617 { OPT_RESET, 0, 1, 0 },
618 { OPT_GETPROFILE, 0, 1, 0 },
619 { OPT_WRITEPHONEBOOK, 0, 1, 0 },
626 /* For GNU gettext */
628 textdomain("gnokii");
629 setlocale(LC_ALL, "");
632 /* Read config file */
633 if (readconfig(&model, &Port, &Initlength, &Connection, &BinDir) < 0) {
637 /* Handle command line arguments. */
638 c = getopt_long(argc, argv, "", long_options, NULL);
639 if (c == -1) /* No argument given - we should display usage. */
643 // First, error conditions
646 fprintf(stderr, _("Use '%s --help' for usage informations.\n"), argv[0]);
648 // Then, options with no arguments
655 /* We have to build an array of the arguments which will be passed to the
656 functions. Please note that every text after the --command will be
657 passed as arguments. A syntax like gnokii --cmd1 args --cmd2 args will
658 not work as expected; instead args --cmd2 args is passed as a
660 if ((nargv = malloc(sizeof(char *) * argc)) != NULL) {
661 for (i = 2; i < argc; i++)
662 nargv[i-2] = argv[i];
664 if (checkargs(c, gals, nargc)) {
665 free(nargv); /* Wrong number of arguments - we should display usage. */
670 /* have to ignore SIGALARM */
674 /* Initialise the code for the GSM interface. */
682 case OPT_ENTERSECURITYCODE:
683 rc = entersecuritycode(optarg);
685 case OPT_GETSECURITYCODESTATUS:
686 rc = getsecuritycodestatus();
689 case OPT_GETDATETIME:
695 case OPT_GETDISPLAYSTATUS:
696 rc = getdisplaystatus();
701 case OPT_WRITEPHONEBOOK:
702 rc = writephonebook(nargc, nargv);
704 // Now, options with arguments
705 case OPT_SETDATETIME:
706 rc = setdatetime(nargc, nargv);
709 rc = setalarm(nargv);
712 rc = dialvoice(optarg);
714 case OPT_GETCALENDARNOTE:
715 rc = getcalendarnote(nargc, nargv);
717 case OPT_DELCALENDARNOTE:
718 rc = deletecalendarnote(nargc, nargv);
720 case OPT_WRITECALENDARNOTE:
721 rc = writecalendarnote(nargv);
724 rc = getmemory(nargc, nargv);
726 case OPT_GETSPEEDDIAL:
727 rc = getspeeddial(optarg);
729 case OPT_SETSPEEDDIAL:
730 rc = setspeeddial(nargv);
733 rc = getsms(argc, argv);
736 rc = deletesms(nargc, nargv);
739 rc = sendsms(nargc, nargv);
742 rc = savesms(argc, argv);
745 rc = sendlogo(nargc, nargv);
748 rc = getsmsc(optarg);
751 rc = netmonitor(optarg);
757 rc = setlogo(nargc, nargv);
760 rc = getlogo(nargc, nargv);
763 rc = viewlogo(optarg);
765 case OPT_SETRINGTONE:
766 rc = setringtone(nargc, nargv);
768 case OPT_SENDRINGTONE:
769 rc = sendringtone(nargc, nargv);
772 rc = getprofile(nargc, nargv);
774 case OPT_DISPLAYOUTPUT:
775 rc = displayoutput();
778 rc = presskeysequence();
786 rc = senddtmf(optarg);
792 fprintf(stderr, _("Unknown option: %d\n"), c);
799 fprintf(stderr, _("Wrong number of arguments\n"));
803 /* Send SMS messages. */
804 int sendsms(int argc, char *argv[])
808 // char UDH[GSM_MAX_USER_DATA_HEADER_LENGTH];
809 /* The maximum length of an uncompressed concatenated short message is
810 255 * 153 = 39015 default alphabet characters */
811 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
812 int input_len, chars_read;
813 int i; /*, offset, nr_msg, aux;*/
815 struct option options[] = {
816 { "smsc", required_argument, NULL, '1'},
817 { "smscno", required_argument, NULL, '2'},
818 { "long", required_argument, NULL, '3'},
822 input_len = GSM_MAX_SMS_LENGTH;
830 - message validity for 3 days
831 - unset user data header indicator
834 memset(&SMS, 0, sizeof(GSM_SMSMessage));
836 SMS.Type = SMS_Submit;
837 SMS.DCS.Type = SMS_GeneralDataCoding;
838 SMS.DCS.u.General.Compressed = false;
839 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
840 SMS.DCS.u.General.Class = 0;
841 SMS.MessageCenter.No = 1;
842 SMS.Validity.VPF = SMS_RelativeFormat;
843 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
846 strcpy(SMS.RemoteNumber.number, argv[0]);
847 if (SMS.RemoteNumber.number[0] == '+') SMS.RemoteNumber.type = SMS_International;
848 else SMS.RemoteNumber.type = SMS_Unknown;
853 while ((i = getopt_long(argc, argv, "r8cC:v:", options, NULL)) != -1) {
854 switch (i) { // -8 is for 8-bit data, -c for compression. both are not yet implemented.
855 case '1': /* SMSC number */
856 SMS.MessageCenter.No = 0;
857 strcpy(SMS.MessageCenter.Number, optarg);
858 if (SMS.MessageCenter.Number[0] == '+') SMS.MessageCenter.Type = SMS_International;
859 else SMS.MessageCenter.Type = SMS_Unknown;
861 case '2': /* SMSC number index in phone memory */
862 SMS.MessageCenter.No = atoi(optarg);
864 if (SMS.MessageCenter.No < 1 || SMS.MessageCenter.No > 5)
866 data.MessageCenter = &SMS.MessageCenter;
867 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
869 case '3': /* we send long message */
870 input_len = atoi(optarg);
871 if (input_len > 255 * GSM_MAX_SMS_LENGTH) {
872 fprintf(stderr, _("Input too long!\n"));
876 case 'r': /* request for delivery report */
877 SMS.Type = SMS_Delivery_Report;
879 case 'C': /* class Message */
882 SMS.DCS.u.General.Class = 1;
885 SMS.DCS.u.General.Class = 2;
888 SMS.DCS.u.General.Class = 3;
891 SMS.DCS.u.General.Class = 4;
898 SMS.Validity.u.Relative = atoi(optarg);
901 usage(); /* Would be better to have an sendsms_usage() here. */
905 /* Get message text from stdin. */
906 chars_read = fread(message_buffer, 1, input_len, stdin);
908 if (chars_read == 0) {
909 fprintf(stderr, _("Couldn't read from stdin!\n"));
911 } else if (chars_read > input_len) {
912 fprintf(stderr, _("Input too long!\n"));
916 /* Null terminate. */
917 message_buffer[chars_read] = 0x00;
918 strncpy(SMS.MessageText, message_buffer, chars_read);
919 data.SMSMessage = &SMS;
921 /* Send the message. */
922 error = SM_Functions(GOP_SendSMS, &data, &State);
924 if (error == GE_SMSSENDOK) {
925 fprintf(stdout, _("Send succeeded!\n"));
927 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
930 if (GSM && GSM->Terminate) GSM->Terminate();
935 int savesms(int argc, char *argv[])
939 /* The maximum length of an uncompressed concatenated short message is
940 255 * 153 = 39015 default alphabet characters */
941 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
942 int input_len, chars_read;
948 SMS.Type = SMS_Deliver;
949 SMS.DCS.Type = SMS_GeneralDataCoding;
950 SMS.DCS.u.General.Compressed = false;
951 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
952 SMS.DCS.u.General.Class = 0;
953 SMS.MessageCenter.No = 1;
954 SMS.Validity.VPF = SMS_RelativeFormat;
955 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
957 SMS.Status = SMS_Unsent;
960 input_len = GSM_MAX_SMS_LENGTH;
963 while ((i = getopt(argc, argv, "ml:in:s:c:")) != -1) {
965 case 'm': /* mark the message as sent */
966 SMS.Status = SMS_Sent;
968 case 'l': /* Specify the location */
969 SMS.Number = atoi(optarg);
971 case 'i': /* Ask before overwriting */
974 case 'n': /* Specify the from number */
976 case 's': /* Specify the smsc number */
978 case 'c': /* Specify the smsc location */
989 aux.Number = SMS.Number;
990 data.SMSMessage = &aux;
991 error = SM_Functions(GOP_GetSMS, &data, &State);
994 fprintf(stderr, _("Message at specified location exists. "));
995 while (confirm < 0) {
996 fprintf(stderr, _("Overwrite? (yes/no) "));
997 GetLine(stdin, ans, 7);
998 if (!strcmp(ans, _("yes"))) confirm = 1;
999 else if (!strcmp(ans, _("no"))) confirm = 0;
1001 if (!confirm) { GSM->Terminate(); return 0; }
1003 case GE_INVALIDSMSLOCATION:
1004 fprintf(stderr, _("Invalid location\n"));
1008 /* FIXME: Remove this fprintf when the function is thoroughly tested */
1010 fprintf(stderr, _("Location %d empty. Saving\n"), SMS.Number);
1015 chars_read = fread(message_buffer, 1, input_len, stdin);
1017 if (chars_read == 0) {
1019 fprintf(stderr, _("Couldn't read from stdin!\n"));
1022 } else if (chars_read > input_len) {
1024 fprintf(stderr, _("Input too long!\n"));
1029 strncpy (SMS.MessageText, message_buffer, chars_read);
1030 SMS.MessageText[chars_read] = 0;
1032 error = GSM->SaveSMSMessage(&SMS);
1034 if (error == GE_NONE) {
1035 fprintf(stdout, _("Saved!\n"));
1037 fprintf(stdout, _("Saving failed (error=%d)\n"), error);
1045 /* Get SMSC number */
1046 int getsmsc(char *MessageCenterNumber)
1048 SMS_MessageCenter MessageCenter;
1052 memset(&MessageCenter, 0, sizeof(MessageCenter));
1053 MessageCenter.No=atoi(MessageCenterNumber);
1055 if (GSM && GSM->GetSMSCenter && GSM->Terminate) {
1056 error = GSM->GetSMSCenter(&MessageCenter);
1059 GSM_DataClear(&data);
1060 data.MessageCenter = &MessageCenter;
1061 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
1066 fprintf(stdout, _("%d. SMS center (%s) number is %s\n"), MessageCenter.No, MessageCenter.Name, MessageCenter.Number);
1067 fprintf(stdout, _("Default recipient number is %s\n"), MessageCenter.Recipient);
1068 fprintf(stdout, _("Messages sent as "));
1070 switch (MessageCenter.Format) {
1072 fprintf(stdout, _("Text"));
1075 fprintf(stdout, _("VoiceMail"));
1078 fprintf(stdout, _("Fax"));
1082 fprintf(stdout, _("Email"));
1085 fprintf(stdout, _("ERMES"));
1088 fprintf(stdout, _("X.400"));
1091 fprintf(stdout, _("Unknown"));
1096 fprintf(stdout, _("Message validity is "));
1098 switch (MessageCenter.Validity) {
1100 fprintf(stdout, _("1 hour"));
1103 fprintf(stdout, _("6 hours"));
1106 fprintf(stdout, _("24 hours"));
1109 fprintf(stdout, _("72 hours"));
1112 fprintf(stdout, _("1 week"));
1115 fprintf(stdout, _("Maximum time"));
1118 fprintf(stdout, _("Unknown"));
1122 fprintf(stdout, "\n");
1125 case GE_NOTIMPLEMENTED:
1126 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1129 fprintf(stdout, _("SMS center can not be found :-(\n"));
1136 /* Get SMS messages. */
1137 int getsms(int argc, char *argv[])
1141 SMS_FolderList folderlist;
1142 GSM_SMSMessage message;
1143 char *memory_type_string;
1144 int start_message, end_message, count, mode = 1;
1151 /* Handle command line args that set type, start and end locations. */
1152 memory_type_string = argv[2];
1153 message.MemoryType = StrToMemoryType(memory_type_string);
1154 if (message.MemoryType == GMT_XX) {
1155 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[2]);
1159 memset(&filename, 0, 64);
1161 start_message = end_message = atoi(argv[3]);
1165 /* [end] can be only argv[4] */
1166 if (argv[4][0] != '-') {
1167 end_message = atoi(argv[4]);
1170 /* parse all options (beginning with '-' */
1171 while ((i = getopt(argc, argv, "f:F:d")) != -1) {
1180 dprintf("Saving into %s\n", optarg);
1181 strncpy(filename, optarg, 64);
1182 if (strlen(optarg) > 63) {
1183 fprintf(stderr, _("Filename too long - will be truncated to 63 characters.\n"));
1186 filename[strlen(optarg)] = 0;
1195 data.SMSFolderList = &folderlist;
1196 folder.FolderID = 0;
1197 data.SMSFolder = &folder;
1198 /* Now retrieve the requested entries. */
1199 for (count = start_message; count <= end_message; count ++) {
1202 message.Number = count;
1203 data.SMSMessage = &message;
1204 dprintf("MemoryType (gnokii.c) : %i\n", data.SMSMessage->MemoryType);
1205 error = SM_Functions(GOP_GetSMS, &data, &State);
1209 switch (message.Type) {
1211 fprintf(stdout, _("%d. MO Message "), message.Number);
1213 fprintf(stdout, _("(sent)\n"));
1214 fprintf(stdout, _("%d. MO Message "), message.Number);
1216 fprintf(stdout, _("(not sent)\n"));
1217 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1219 case SMS_Delivery_Report:
1220 fprintf(stdout, _("%d. Delivery Report "), message.Number);
1222 fprintf(stdout, _("(read)\n"));
1224 fprintf(stdout, _("(not read)\n"));
1225 fprintf(stdout, _("Sending date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1226 message.Time.Day, message.Time.Month, message.Time.Year, \
1227 message.Time.Hour, message.Time.Minute, message.Time.Second);
1228 if (message.Time.Timezone) {
1229 if (message.Time.Timezone > 0)
1230 fprintf(stdout,_("+%02d00"), message.Time.Timezone);
1232 fprintf(stdout,_("%02d00"), message.Time.Timezone);
1234 fprintf(stdout, "\n");
1235 fprintf(stdout, _("Response date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1236 message.SMSCTime.Day, message.SMSCTime.Month, message.SMSCTime.Year, \
1237 message.SMSCTime.Hour, message.SMSCTime.Minute, message.SMSCTime.Second);
1238 if (message.SMSCTime.Timezone) {
1239 if (message.SMSCTime.Timezone > 0)
1240 fprintf(stdout,_("+%02d00"),message.SMSCTime.Timezone);
1242 fprintf(stdout,_("%02d00"),message.SMSCTime.Timezone);
1244 fprintf(stdout, "\n");
1245 fprintf(stdout, _("Receiver: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1246 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1249 fprintf(stdout, _("%d. Inbox Message "), message.Number);
1251 fprintf(stdout, _("(read)\n"));
1253 fprintf(stdout, _("(not read)\n"));
1254 fprintf(stdout, _("Date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1255 message.Time.Day, message.Time.Month, message.Time.Year, \
1256 message.Time.Hour, message.Time.Minute, message.Time.Second);
1257 if (message.Time.Timezone) {
1258 if (message.Time.Timezone > 0)
1259 fprintf(stdout,_("+%02d00"),message.Time.Timezone);
1261 fprintf(stdout,_("%02d00"),message.Time.Timezone);
1263 fprintf(stdout, "\n");
1264 fprintf(stdout, _("Sender: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1265 switch (message.UDH[0].Type) {
1267 fprintf(stdout, _("GSM operator logo for %s (%s) network.\n"), bitmap.netcode, GSM_GetNetworkName(bitmap.netcode));
1268 if (!strcmp(message.RemoteNumber.number, "+998000005") && !strcmp(message.MessageCenter.Number, "+886935074443")) dprintf(_("Saved by Logo Express\n"));
1269 if (!strcmp(message.RemoteNumber.number, "+998000002") || !strcmp(message.RemoteNumber.number, "+998000003")) dprintf(_("Saved by Operator Logo Uploader by Thomas Kessler\n"));
1271 case SMS_CallerIDLogo:
1272 fprintf(stdout, ("Logo:\n"));
1273 /* put bitmap into bitmap structure */
1274 GSM_ReadSMSBitmap(message.UDH[0].Type, message.MessageText+2+offset, message.MessageText, &bitmap);
1275 GSM_PrintBitmap(&bitmap);
1278 if ((stat(filename, &buf) == 0)) {
1279 fprintf(stdout, _("File %s exists.\n"), filename);
1280 fprintf(stderr, _("Overwrite? (yes/no) "));
1281 GetLine(stdin, ans, 4);
1282 if (!strcmp(ans, _("yes"))) {
1283 error = GSM_SaveBitmapFile(filename, &bitmap);
1285 } else error = GSM_SaveBitmapFile(filename, &bitmap);
1286 if (error != GE_NONE) fprintf(stderr, _("Couldn't save logofile %s!\n"), filename);
1290 fprintf(stdout, _("Ringtone\n"));
1292 case SMS_ConcatenatedMessages:
1293 fprintf(stdout, _("Linked (%d/%d):\n"),
1294 message.UDH[0].u.ConcatenatedShortMessage.CurrentNumber,
1295 message.UDH[0].u.ConcatenatedShortMessage.MaximumNumber);
1297 fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText);
1298 if ((mode != -1) && *filename) {
1300 sprintf(buf, "%s%d", filename, count);
1301 mode = GSM_SaveTextFile(buf, message.MessageText, mode);
1304 case SMS_BusinessCard:
1305 fprintf(stdout, _("Business Card:\n%s"), message.MessageText);
1308 fprintf(stderr, _("Unknown\n"));
1314 data.SMSMessage = &message;
1315 if (GE_NONE != SM_Functions(GOP_DeleteSMS, &data, &State))
1316 fprintf(stdout, _("(delete failed)\n"));
1318 fprintf(stdout, _("(message deleted)\n"));
1321 case GE_NOTIMPLEMENTED:
1322 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1323 if (GSM && GSM->Terminate) GSM->Terminate();
1325 case GE_INVALIDSMSLOCATION:
1326 fprintf(stderr, _("Invalid location: %s %d\n"), memory_type_string, count);
1328 case GE_EMPTYSMSLOCATION:
1329 fprintf(stderr, _("SMS location %s %d empty.\n"), memory_type_string, count);
1332 fprintf(stdout, _("GetSMS %s %d failed!(%s)\n\n"), memory_type_string, count, print_error(error));
1337 if (GSM && GSM->Terminate) GSM->Terminate();
1342 /* Delete SMS messages. */
1343 int deletesms(int argc, char *argv[])
1345 GSM_SMSMessage message;
1346 char *memory_type_string;
1347 int start_message, end_message, count;
1350 /* Handle command line args that set type, start and end locations. */
1351 memory_type_string = argv[0];
1352 message.MemoryType = StrToMemoryType(memory_type_string);
1353 if (message.MemoryType == GMT_XX) {
1354 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
1358 start_message = end_message = atoi (argv[1]);
1359 if (argc > 2) end_message = atoi (argv[2]);
1361 /* Now delete the requested entries. */
1362 for (count = start_message; count <= end_message; count ++) {
1364 message.Number = count;
1365 data.SMSMessage = &message;
1366 error = SM_Functions(GOP_DeleteSMS, &data, &State);
1368 if (error == GE_NONE)
1369 fprintf(stdout, _("Deleted SMS %s %d\n"), memory_type_string, count);
1371 if (error == GE_NOTIMPLEMENTED) {
1372 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1376 fprintf(stdout, _("DeleteSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
1385 static volatile bool bshutdown = false;
1387 /* SIGINT signal handler. */
1388 static void interrupted(int sig)
1390 signal(sig, SIG_IGN);
1396 /* In this mode we get the code from the keyboard and send it to the mobile
1398 int entersecuritycode(char *type)
1401 GSM_SecurityCode SecurityCode;
1403 if (!strcmp(type,"PIN"))
1404 SecurityCode.Type=GSCT_Pin;
1405 else if (!strcmp(type,"PUK"))
1406 SecurityCode.Type=GSCT_Puk;
1407 else if (!strcmp(type,"PIN2"))
1408 SecurityCode.Type=GSCT_Pin2;
1409 else if (!strcmp(type,"PUK2"))
1410 SecurityCode.Type=GSCT_Puk2;
1411 // FIXME: Entering of SecurityCode does not work :-(
1412 // else if (!strcmp(type,"SecurityCode"))
1413 // SecurityCode.Type=GSCT_SecurityCode;
1418 printf("Enter your code: ");
1419 gets(SecurityCode.Code);
1421 strcpy(SecurityCode.Code,getpass(_("Enter your code: ")));
1424 test = GSM->EnterSecurityCode(SecurityCode);
1425 if (test == GE_INVALIDSECURITYCODE)
1426 fprintf(stdout, _("Error: invalid code.\n"));
1427 else if (test == GE_NONE)
1428 fprintf(stdout, _("Code ok.\n"));
1429 else if (test == GE_NOTIMPLEMENTED)
1430 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1432 fprintf(stdout, _("Other error.\n"));
1439 int getsecuritycodestatus(void)
1443 if (GSM->GetSecurityCodeStatus(&Status) == GE_NONE) {
1445 fprintf(stdout, _("Security code status: "));
1448 case GSCT_SecurityCode:
1449 fprintf(stdout, _("waiting for Security Code.\n"));
1452 fprintf(stdout, _("waiting for PIN.\n"));
1455 fprintf(stdout, _("waiting for PIN2.\n"));
1458 fprintf(stdout, _("waiting for PUK.\n"));
1461 fprintf(stdout, _("waiting for PUK2.\n"));
1464 fprintf(stdout, _("nothing to enter.\n"));
1467 fprintf(stdout, _("Unknown!\n"));
1480 /* Voice dialing mode. */
1481 int dialvoice(char *Number)
1483 GSM->DialVoice(Number);
1490 /* The following function allows to send logos using SMS */
1491 int sendlogo(int argc, char *argv[])
1497 char UserDataHeader[7] = { 0x06, /* UDH Length */
1498 0x05, /* IEI: application port addressing scheme, 16 bit address */
1499 0x04, /* IEI length */
1500 0x15, /* destination address: high byte */
1501 0x00, /* destination address: low byte */
1502 0x00, /* originator address */
1505 char Data[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1509 /* Default settings for SMS message:
1510 - no delivery report
1516 - set UserDataHeaderIndicator
1518 SMS.Type = SMS_Submit;
1519 SMS.DCS.Type = SMS_GeneralDataCoding;
1520 SMS.DCS.u.General.Compressed = false;
1521 SMS.DCS.u.General.Alphabet = SMS_8bit;
1522 SMS.DCS.u.General.Class = 2;
1523 SMS.MessageCenter.No = 1;
1524 SMS.Validity.VPF = SMS_RelativeFormat;
1525 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
1527 /* The first argument is the type of the logo. */
1528 if (!strcmp(argv[0], "op")) {
1529 SMS.UDH[0].Type = SMS_OpLogo;
1530 UserDataHeader[4] = 0x82; /* NBS port 0x1582 */
1531 fprintf(stdout, _("Sending operator logo.\n"));
1532 } else if (!strcmp(argv[0], "caller")) {
1533 SMS.UDH[0].Type = SMS_CallerIDLogo;
1534 UserDataHeader[4] = 0x83; /* NBS port 0x1583 */
1535 fprintf(stdout, _("Sending caller line identification logo.\n"));
1537 fprintf(stderr, _("You should specify what kind of logo to send!\n"));
1541 /* The second argument is the destination, ie the phone number of recipient. */
1542 SMS.MemoryType = atoi(argv[1]);
1544 /* The third argument is the bitmap file. */
1545 GSM_ReadBitmapFile(argv[2], &bitmap);
1547 /* If we are sending op logo we can rewrite network code. */
1548 if (!strcmp(argv[0], "op")) {
1550 * The fourth argument, if present, is the Network code of the operator.
1551 * Network code is in this format: "xxx yy".
1554 strcpy(bitmap.netcode, argv[3]);
1556 fprintf(stdout, _("Operator code: %s\n"), argv[3]);
1560 /* Set the network code */
1561 Data[current++] = ((bitmap.netcode[1] & 0x0f) << 4) | (bitmap.netcode[0] & 0xf);
1562 Data[current++] = 0xf0 | (bitmap.netcode[2] & 0x0f);
1563 Data[current++] = ((bitmap.netcode[5] & 0x0f) << 4) | (bitmap.netcode[4] & 0xf);
1566 /* Set the logo size */
1568 Data[current++] = bitmap.width;
1569 Data[current++] = bitmap.height;
1571 Data[current++] = 0x01;
1573 memcpy(SMS.MessageText, UserDataHeader, 7);
1574 memcpy(SMS.MessageText, Data, current);
1575 memcpy(SMS.MessageText+current, bitmap.bitmap, bitmap.size);
1577 /* Send the message. */
1578 error = GSM->SendSMSMessage(&SMS,current+bitmap.size);
1580 if (error == GE_SMSSENDOK)
1581 fprintf(stdout, _("Send succeeded!\n"));
1583 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
1589 /* Getting logos. */
1590 GSM_Error SaveBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1597 /* Ask before overwriting */
1598 while (stat(FileName, &buf) == 0) {
1601 fprintf(stderr, _("Saving logo. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "), FileName);
1602 GetLine(stdin, ans, 4);
1603 if (!strcmp(ans, "O") || !strcmp(ans, "o")) confirm = 1;
1604 if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm = 2;
1605 if (!strcmp(ans, "S") || !strcmp(ans, "s")) return GE_USERCANCELED;
1607 if (confirm == 1) break;
1609 fprintf(stderr, _("Enter name of new file: "));
1610 GetLine(stdin, FileName, 50);
1611 if (!FileName || (*FileName == 0)) return GE_USERCANCELED;
1615 error = GSM_SaveBitmapFile(FileName, bitmap);
1618 case GE_CANTOPENFILE:
1619 fprintf(stderr, _("Failed to write file \"%s\"\n"), FileName);
1628 int getlogo(int argc, char *argv[])
1632 GSM_Statemachine *sm = &State;
1634 bitmap.type=GSM_None;
1636 if (!strcmp(argv[0], "op"))
1637 bitmap.type = GSM_OperatorLogo;
1639 if (!strcmp(argv[0], "caller")) {
1640 /* There is caller group number missing in argument list. */
1642 bitmap.number=argv[2][0]-'0';
1643 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1647 bitmap.type = GSM_CallerLogo;
1650 if (!strcmp(argv[0],"startup"))
1651 bitmap.type = GSM_StartupLogo;
1652 else if (!strcmp(argv[0], "dealer"))
1653 bitmap.type = GSM_DealerNoteText;
1654 else if (!strcmp(argv[0], "text"))
1655 bitmap.type=GSM_WelcomeNoteText;
1657 if (bitmap.type != GSM_None) {
1659 fprintf(stdout, _("Getting Logo\n"));
1661 data.Bitmap=&bitmap;
1662 error=SM_Functions(GOP_GetBitmap, &data, sm);
1666 if (bitmap.type == GSM_DealerNoteText) fprintf(stdout, _("Dealer welcome note "));
1667 if (bitmap.type == GSM_WelcomeNoteText) fprintf(stdout, _("Welcome note "));
1668 if (bitmap.type == GSM_DealerNoteText || bitmap.type==GSM_WelcomeNoteText) {
1669 if (bitmap.text[0]) {
1670 fprintf(stdout, _("currently set to \"%s\"\n"), bitmap.text);
1672 fprintf(stdout, _("currently empty\n"));
1676 switch (bitmap.type) {
1677 case GSM_OperatorLogo:
1678 fprintf(stdout,"Operator logo for %s (%s) network got succesfully\n",bitmap.netcode,GSM_GetNetworkName(bitmap.netcode));
1680 strncpy(bitmap.netcode,argv[2], 7);
1681 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1682 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1687 case GSM_StartupLogo:
1688 fprintf(stdout, "Startup logo got successfully\n");
1690 strncpy(bitmap.netcode,argv[2], 7);
1691 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1692 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1697 case GSM_CallerLogo:
1698 fprintf(stdout,"Caller logo got successfully\n");
1700 strncpy(bitmap.netcode,argv[3],7);
1701 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1702 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1708 fprintf(stdout,"Unknown bitmap type.\n");
1712 if (SaveBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) return (-1);
1715 fprintf(stdout,"Your phone doesn't have logo uploaded !\n");
1720 case GE_NOTIMPLEMENTED:
1721 fprintf(stderr, _("Function not implemented !\n"));
1723 case GE_NOTSUPPORTED:
1724 fprintf(stderr, _("This kind of logo is not supported !\n"));
1727 fprintf(stderr, _("Error getting logo !\n"));
1731 fprintf(stderr, _("What kind of logo do you want to get ?\n"));
1739 /* Sending logos. */
1740 GSM_Error ReadBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1744 error = GSM_ReadBitmapFile(FileName, bitmap);
1747 case GE_CANTOPENFILE:
1748 fprintf(stderr, _("Failed to read file \"%s\"\n"), FileName);
1750 case GE_WRONGNUMBEROFCOLORS:
1751 fprintf(stderr, _("Wrong number of colors in \"%s\" logofile (accepted only 2-colors files) !\n"), FileName);
1753 case GE_WRONGCOLORS:
1754 fprintf(stderr, _("Wrong colors in \"%s\" logofile !\n"), FileName);
1756 case GE_INVALIDFILEFORMAT:
1757 fprintf(stderr, _("Invalid format of \"%s\" logofile !\n"), FileName);
1759 case GE_SUBFORMATNOTSUPPORTED:
1760 fprintf(stderr, _("Sorry, gnokii doesn't support used subformat in file \"%s\" !\n"), FileName);
1762 case GE_FILETOOSHORT:
1763 fprintf(stderr, _("\"%s\" logofile is too short !\n"), FileName);
1765 case GE_INVALIDIMAGESIZE:
1766 fprintf(stderr, _("Bitmap size doesn't supported by fileformat or different from 72x14, 84x48 and 72x28 !\n"));
1776 int setlogo(int argc, char *argv[])
1778 GSM_Bitmap bitmap,oldbit;
1779 GSM_NetworkInfo NetworkInfo;
1785 if (!strcmp(argv[0],"text") || !strcmp(argv[0],"dealer")) {
1786 if (!strcmp(argv[0], "text")) bitmap.type = GSM_WelcomeNoteText;
1787 else bitmap.type = GSM_DealerNoteText;
1788 bitmap.text[0] = 0x00;
1789 if (argc > 1) strncpy(bitmap.text, argv[1], 255);
1791 if (!strcmp(argv[0], "op") || !strcmp(argv[0], "startup") || !strcmp(argv[0], "caller")) {
1793 if (ReadBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) {
1798 if (!strcmp(argv[0], "op")) {
1799 if (bitmap.type != GSM_OperatorLogo || argc < 3) {
1800 if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode, NetworkInfo.NetworkCode, 7);
1802 GSM_ResizeBitmap(&bitmap, GSM_OperatorLogo, GSM_Info);
1804 strncpy(bitmap.netcode, argv[2], 7);
1805 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1806 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1811 if (!strcmp(argv[0], "startup")) {
1812 GSM_ResizeBitmap(&bitmap, GSM_StartupLogo, GSM_Info);
1814 if (!strcmp(argv[0],"caller")) {
1815 GSM_ResizeBitmap(&bitmap, GSM_CallerLogo, GSM_Info);
1817 bitmap.number = argv[2][0] - '0';
1818 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1822 oldbit.type = GSM_CallerLogo;
1823 oldbit.number = bitmap.number;
1824 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1825 /* We have to get the old name and ringtone!! */
1826 bitmap.ringtone = oldbit.ringtone;
1827 strncpy(bitmap.text, oldbit.text, 255);
1829 if (argc > 3) strncpy(bitmap.text, argv[3], 255);
1831 fprintf(stdout, _("Setting Logo.\n"));
1833 /* FIX ME: is it possible to permanently remove op logo ? */
1834 if (!strcmp(argv[0], "op"))
1836 bitmap.type = GSM_OperatorLogo;
1837 strncpy(bitmap.netcode, "000 00", 7);
1840 bitmap.size = bitmap.width * bitmap.height / 8;
1841 GSM_ClearBitmap(&bitmap);
1843 /* FIX ME: how to remove startup and group logos ? */
1844 fprintf(stdout, _("Removing Logo.\n"));
1847 fprintf(stderr, _("What kind of logo do you want to set ?\n"));
1853 error=GSM->SetBitmap(&bitmap);
1857 oldbit.type = bitmap.type;
1858 oldbit.number = bitmap.number;
1859 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1860 if (bitmap.type == GSM_WelcomeNoteText ||
1861 bitmap.type == GSM_DealerNoteText) {
1862 if (strcmp(bitmap.text, oldbit.text)) {
1863 fprintf(stderr, _("Error setting"));
1864 if (bitmap.type == GSM_DealerNoteText) fprintf(stderr, _(" dealer"));
1865 fprintf(stderr, _(" welcome note - "));
1867 /* I know, it looks horrible, but... */
1868 /* I set it to the short string - if it won't be set */
1869 /* it means, PIN is required. If it will be correct, previous */
1870 /* (user) text was too long */
1872 /* Without it, I could have such thing: */
1873 /* user set text to very short string (for example, "Marcin") */
1874 /* then enable phone without PIN and try to set it to the very long (too long for phone) */
1875 /* string (which start with "Marcin"). If we compare them as only length different, we could think, */
1876 /* that phone accepts strings 6 chars length only (length of "Marcin") */
1877 /* When we make it correct, we don't have this mistake */
1879 strcpy(oldbit.text, "!\0");
1880 GSM->SetBitmap(&oldbit);
1881 GSM->GetBitmap(&oldbit);
1882 if (oldbit.text[0]!='!') {
1883 fprintf(stderr, _("SIM card and PIN is required\n"));
1885 GSM->SetBitmap(&bitmap);
1886 GSM->GetBitmap(&oldbit);
1887 fprintf(stderr, _("too long, truncated to \"%s\" (length %i)\n"),oldbit.text,strlen(oldbit.text));
1892 if (bitmap.type == GSM_StartupLogo) {
1893 for (i = 0; i < oldbit.size; i++) {
1894 if (oldbit.bitmap[i] != bitmap.bitmap[i]) {
1895 fprintf(stderr, _("Error setting startup logo - SIM card and PIN is required\n"));
1903 if (ok) fprintf(stdout, _("Done.\n"));
1905 case GE_NOTIMPLEMENTED:
1906 fprintf(stderr, _("Function not implemented.\n"));
1908 case GE_NOTSUPPORTED:
1909 fprintf(stderr, _("This kind of logo is not supported.\n"));
1912 fprintf(stderr, _("Error !\n"));
1922 int viewlogo(char *filename)
1926 error = GSM_ShowBitmapFile(filename);
1930 /* Calendar notes receiving. */
1931 int getcalendarnote(int argc, char *argv[])
1933 GSM_CalendarNote CalendarNote;
1935 GSM_Error error = GE_NONE;
1936 int i, first_location, last_location;
1939 struct option options[] = {
1940 { "vCard", optional_argument, NULL, '1'},
1947 first_location = last_location = atoi(argv[0]);
1948 if ((argc > 1) && (argv[1][0] != '-')) {
1949 last_location = atoi(argv[1]);
1952 while ((i = getopt_long(argc, argv, "v", options, NULL)) != -1) {
1958 usage(); /* Would be better to have an calendar_usage() here. */
1964 for (i = first_location; i <= last_location; i++) {
1965 CalendarNote.Location = i;
1966 if (GSM && GSM->GetCalendarNote && GSM->Terminate) {
1967 error = GSM->GetCalendarNote(&CalendarNote);
1970 GSM_DataClear(&data);
1971 data.CalendarNote = &CalendarNote;
1973 error = SM_Functions(GOP_GetCalendarNote, &data, &State);
1978 fprintf(stdout, "BEGIN:VCALENDAR\n");
1979 fprintf(stdout, "VERSION:1.0\n");
1980 fprintf(stdout, "BEGIN:VEVENT\n");
1981 fprintf(stdout, "CATEGORIES:");
1982 switch (CalendarNote.Type) {
1984 fprintf(stdout, "MISCELLANEOUS\n");
1987 fprintf(stdout, "PHONE CALL\n");
1990 fprintf(stdout, "MEETING\n");
1993 fprintf(stdout, "SPECIAL OCCASION\n");
1996 fprintf(stdout, "UNKNOWN\n");
1999 fprintf(stdout, "SUMMARY:%s\n",CalendarNote.Text);
2000 fprintf(stdout, "DTSTART:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Time.Year,
2001 CalendarNote.Time.Month, CalendarNote.Time.Day, CalendarNote.Time.Hour,
2002 CalendarNote.Time.Minute, CalendarNote.Time.Second);
2003 if (CalendarNote.Alarm.Year!=0) {
2004 fprintf(stdout, "DALARM:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Alarm.Year,
2005 CalendarNote.Alarm.Month, CalendarNote.Alarm.Day, CalendarNote.Alarm.Hour,
2006 CalendarNote.Alarm.Minute, CalendarNote.Alarm.Second);
2008 fprintf(stdout, "END:VEVENT\n");
2009 fprintf(stdout, "END:VCALENDAR\n");
2011 } else { /* not vCal */
2012 fprintf(stdout, _(" Type of the note: "));
2014 switch (CalendarNote.Type) {
2016 fprintf(stdout, _("Reminder\n"));
2019 fprintf(stdout, _("Call\n"));
2022 fprintf(stdout, _("Meeting\n"));
2025 fprintf(stdout, _("Birthday\n"));
2028 fprintf(stdout, _("Unknown\n"));
2032 fprintf(stdout, _(" Date: %d-%02d-%02d\n"), CalendarNote.Time.Year,
2033 CalendarNote.Time.Month,
2034 CalendarNote.Time.Day);
2036 fprintf(stdout, _(" Time: %02d:%02d:%02d\n"), CalendarNote.Time.Hour,
2037 CalendarNote.Time.Minute,
2038 CalendarNote.Time.Second);
2040 if (CalendarNote.Alarm.AlarmEnabled == 1) {
2041 fprintf(stdout, _(" Alarm date: %d-%02d-%02d\n"), CalendarNote.Alarm.Year,
2042 CalendarNote.Alarm.Month,
2043 CalendarNote.Alarm.Day);
2045 fprintf(stdout, _(" Alarm time: %02d:%02d:%02d\n"), CalendarNote.Alarm.Hour,
2046 CalendarNote.Alarm.Minute,
2047 CalendarNote.Alarm.Second);
2050 fprintf(stdout, _(" Text: %s\n"), CalendarNote.Text);
2052 if (CalendarNote.Type == GCN_CALL)
2053 fprintf(stdout, _(" Phone: %s\n"), CalendarNote.Phone);
2056 case GE_NOTIMPLEMENTED:
2057 fprintf(stderr, _("Function not implemented.\n"));
2060 fprintf(stderr, _("The calendar note can not be read\n"));
2069 /* Writing calendar notes. */
2070 int writecalendarnote(char *argv[])
2072 GSM_CalendarNote CalendarNote;
2074 if (GSM_ReadVCalendarFile(argv[0], &CalendarNote, atoi(argv[1]))) {
2075 fprintf(stdout, _("Failed to load vCalendar file.\n"));
2079 /* Error 22=Calendar full ;-) */
2080 if ((GSM->WriteCalendarNote(&CalendarNote)) == GE_NONE)
2081 fprintf(stdout, _("Succesfully written!\n"));
2083 fprintf(stdout, _("Failed to write calendar note!\n"));
2090 /* Calendar note deleting. */
2091 int deletecalendarnote(int argc, char *argv[])
2093 GSM_CalendarNote CalendarNote;
2094 int i, first_location, last_location;
2096 first_location = last_location = atoi(argv[0]);
2097 if (argc > 1) last_location = atoi(argv[1]);
2099 for (i = first_location; i <= last_location; i++) {
2101 CalendarNote.Location = i;
2103 if (GSM->DeleteCalendarNote(&CalendarNote) == GE_NONE) {
2104 fprintf(stdout, _(" Calendar note deleted.\n"));
2106 fprintf(stderr, _("The calendar note can not be deleted\n"));
2116 /* Setting the date and time. */
2117 int setdatetime(int argc, char *argv[])
2124 now = localtime(&nowh);
2126 Date.Year = now->tm_year;
2127 Date.Month = now->tm_mon+1;
2128 Date.Day = now->tm_mday;
2129 Date.Hour = now->tm_hour;
2130 Date.Minute = now->tm_min;
2131 Date.Second = now->tm_sec;
2133 if (argc > 0) Date.Year = atoi (argv[0]);
2134 if (argc > 1) Date.Month = atoi (argv[1]);
2135 if (argc > 2) Date.Day = atoi (argv[2]);
2136 if (argc > 3) Date.Hour = atoi (argv[3]);
2137 if (argc > 4) Date.Minute = atoi (argv[4]);
2139 if (Date.Year < 1900) {
2141 /* Well, this thing is copyrighted in U.S. This technique is known as
2142 Windowing and you can read something about it in LinuxWeekly News:
2143 http://lwn.net/1999/features/Windowing.phtml. This thing is beeing
2144 written in Czech republic and Poland where algorithms are not allowed
2148 Date.Year = Date.Year + 1900;
2150 Date.Year = Date.Year + 2000;
2153 /* FIXME: Error checking should be here. */
2154 GSM->SetDateTime(&Date);
2161 /* In this mode we receive the date and time from mobile phone. */
2162 int getdatetime(void) {
2164 GSM_DateTime date_time;
2167 if (GSM && GSM->GetDateTime && GSM->Terminate) {
2168 error = GSM->GetDateTime(&date_time);
2171 GSM_DataClear(&data);
2172 data.DateTime = &date_time;
2174 error = SM_Functions(GOP_GetDateTime, &data, &State);
2179 fprintf(stdout, _("Date: %4d/%02d/%02d\n"), date_time.Year, date_time.Month, date_time.Day);
2180 fprintf(stdout, _("Time: %02d:%02d:%02d\n"), date_time.Hour, date_time.Minute, date_time.Second);
2182 case GE_NOTIMPLEMENTED:
2183 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2186 fprintf(stdout, _("Internal error\n"));
2193 /* Setting the alarm. */
2194 int setalarm(char *argv[])
2198 Date.Hour = atoi(argv[0]);
2199 Date.Minute = atoi(argv[1]);
2201 GSM->SetAlarm(1, &Date);
2208 /* Getting the alarm. */
2213 GSM_DateTime date_time;
2215 if (GSM && GSM->GetAlarm && GSM->Terminate) {
2216 error = GSM->GetAlarm(0, &date_time);
2219 GSM_DataClear(&data);
2220 data.DateTime = &date_time;
2222 error = SM_Functions(GOP_GetAlarm, &data, &State);
2227 fprintf(stdout, _("Alarm: %s\n"), (date_time.AlarmEnabled==0)?"off":"on");
2228 fprintf(stdout, _("Time: %02d:%02d\n"), date_time.Hour, date_time.Minute);
2230 case GE_NOTIMPLEMENTED:
2231 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2234 fprintf(stdout, _("Internal error\n"));
2241 /* In monitor mode we don't do much, we just initialise the fbus code.
2242 Note that the fbus code no longer has an internal monitor mode switch,
2243 instead compile with DEBUG enabled to get all the gumpf. */
2244 int monitormode(void)
2246 float rflevel = -1, batterylevel = -1;
2247 // GSM_PowerSource powersource = -1;
2248 GSM_RFUnits rf_units = GRF_Arbitrary;
2249 GSM_BatteryUnits batt_units = GBU_Arbitrary;
2250 GSM_Statemachine *sm = &State;
2253 // GSM_NetworkInfo NetworkInfo;
2254 // GSM_CBMessage CBMessage;
2256 GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0};
2257 GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0};
2258 GSM_MemoryStatus DC_MemoryStatus = {GMT_DC, 0, 0};
2259 GSM_MemoryStatus EN_MemoryStatus = {GMT_EN, 0, 0};
2260 GSM_MemoryStatus FD_MemoryStatus = {GMT_FD, 0, 0};
2261 GSM_MemoryStatus LD_MemoryStatus = {GMT_LD, 0, 0};
2262 GSM_MemoryStatus MC_MemoryStatus = {GMT_MC, 0, 0};
2263 GSM_MemoryStatus ON_MemoryStatus = {GMT_ON, 0, 0};
2264 GSM_MemoryStatus RC_MemoryStatus = {GMT_RC, 0, 0};
2266 // GSM_SMSStatus SMSStatus = {0, 0};
2270 GSM_DataClear(&data);
2272 /* We do not want to monitor serial line forever - press Ctrl+C to stop the
2274 signal(SIGINT, interrupted);
2276 fprintf (stderr, _("Entering monitor mode...\n"));
2279 //GSM->EnableCellBroadcast();
2281 /* Loop here indefinitely - allows you to see messages from GSM code in
2282 response to unknown messages etc. The loops ends after pressing the
2284 data.RFUnits=&rf_units;
2285 data.RFLevel=&rflevel;
2286 data.BatteryUnits=&batt_units;
2287 data.BatteryLevel=&batterylevel;
2289 while (!bshutdown) {
2290 if (SM_Functions(GOP_GetRFLevel,&data,sm) == GE_NONE)
2291 fprintf(stdout, _("RFLevel: %d\n"), (int)rflevel);
2293 if (SM_Functions(GOP_GetBatteryLevel,&data,sm) == GE_NONE)
2294 fprintf(stdout, _("Battery: %d\n"), (int)batterylevel);
2296 // if (GSM->GetPowerSource(&powersource) == GE_NONE)
2297 // fprintf(stdout, _("Power Source: %s\n"), (powersource==GPS_ACDC)?_("AC/DC"):_("battery"));
2299 data.MemoryStatus=&SIMMemoryStatus;
2300 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2301 fprintf(stdout, _("SIM: Used %d, Free %d\n"), SIMMemoryStatus.Used, SIMMemoryStatus.Free);
2303 data.MemoryStatus=&PhoneMemoryStatus;
2304 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2305 fprintf(stdout, _("Phone: Used %d, Free %d\n"), PhoneMemoryStatus.Used, PhoneMemoryStatus.Free);
2307 data.MemoryStatus=&DC_MemoryStatus;
2308 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2309 fprintf(stdout, _("DC: Used %d, Free %d\n"), DC_MemoryStatus.Used, DC_MemoryStatus.Free);
2311 data.MemoryStatus=&EN_MemoryStatus;
2312 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2313 fprintf(stdout, _("EN: Used %d, Free %d\n"), EN_MemoryStatus.Used, EN_MemoryStatus.Free);
2315 data.MemoryStatus=&FD_MemoryStatus;
2316 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2317 fprintf(stdout, _("FD: Used %d, Free %d\n"), FD_MemoryStatus.Used, FD_MemoryStatus.Free);
2319 data.MemoryStatus=&LD_MemoryStatus;
2320 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2321 fprintf(stdout, _("LD: Used %d, Free %d\n"), LD_MemoryStatus.Used, LD_MemoryStatus.Free);
2323 data.MemoryStatus=&MC_MemoryStatus;
2324 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2325 fprintf(stdout, _("MC: Used %d, Free %d\n"), MC_MemoryStatus.Used, MC_MemoryStatus.Free);
2327 data.MemoryStatus=&ON_MemoryStatus;
2328 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2329 fprintf(stdout, _("ON: Used %d, Free %d\n"), ON_MemoryStatus.Used, ON_MemoryStatus.Free);
2331 data.MemoryStatus=&RC_MemoryStatus;
2332 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2333 fprintf(stdout, _("RC: Used %d, Free %d\n"), RC_MemoryStatus.Used, RC_MemoryStatus.Free);
2335 // if (GSM->GetSMSStatus(&SMSStatus) == GE_NONE)
2336 // fprintf(stdout, _("SMS Messages: UnRead %d, Number %d\n"), SMSStatus.UnRead, SMSStatus.Number);
2338 // if (GSM->GetIncomingCallNr(Number) == GE_NONE)
2339 // fprintf(stdout, _("Incoming call: %s\n"), Number);
2341 // if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE)
2342 // fprintf(stdout, _("Network: %s (%s), LAC: %s, CellID: %s\n"), GSM_GetNetworkName (NetworkInfo.NetworkCode), GSM_GetCountryName(NetworkInfo.NetworkCode), NetworkInfo.LAC, NetworkInfo.CellID);
2344 // if (GSM->ReadCellBroadcast(&CBMessage) == GE_NONE)
2345 // fprintf(stdout, _("Cell broadcast received on channel %d: %s\n"), CBMessage.Channel, CBMessage.Message);
2350 fprintf (stderr, _("Leaving monitor mode...\n"));
2360 static GSM_Error PrettyOutputFn(char *Display, char *Indicators)
2363 printf(ESC "[10;0H Display is:\n%s\n", Display);
2365 printf(ESC "[9;0H Indicators: %s \n", Indicators);
2366 printf(ESC "[1;1H");
2371 // Uncomment it if used
2372 static GSM_Error OutputFn(char *Display, char *Indicators)
2375 printf("New display is:\n%s\n", Display);
2377 printf("Indicators: %s\n", Indicators);
2382 void console_raw(void)
2387 tcgetattr(fileno(stdin), &it);
2388 it.c_lflag &= ~(ICANON);
2389 //it.c_iflag &= ~(INPCK|ISTRIP|IXON);
2393 tcsetattr(fileno(stdin), TCSANOW, &it);
2397 int displayoutput(void)
2400 GSM_Statemachine *sm = &State;
2403 data.OutputFn = PrettyOutputFn;
2405 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2407 fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
2409 if (error == GE_NONE) {
2411 /* We do not want to see texts forever - press Ctrl+C to stop. */
2412 signal(SIGINT, interrupted);
2414 fprintf (stderr, _("Entered display monitoring mode...\n"));
2415 fprintf (stderr, ESC "c" );
2417 /* Loop here indefinitely - allows you to read texts from phone's
2418 display. The loops ends after pressing the Ctrl+C. */
2419 while (!bshutdown) {
2421 memset(&buf[0], 0, 102);
2422 while (read(0, buf, 100) > 0) {
2423 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
2424 if (GSM->HandleString(buf) != GE_NONE)
2425 fprintf(stdout, _("Key press simulation failed.\n"));
2426 memset(buf, 0, 102);
2430 fprintf (stderr, "Shutting down\n");
2432 fprintf (stderr, _("Leaving display monitor mode...\n"));
2433 data.OutputFn = NULL;
2435 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2436 if (error != GE_NONE)
2437 fprintf (stderr, _("Error!\n"));
2439 fprintf (stderr, _("Error!\n"));
2445 /* Reads profile from phone and displays its' settings */
2446 int getprofile(int argc, char *argv[])
2450 GSM_Profile profile;
2453 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2457 error = GSM->GetProfile(&profile);
2459 if (error == GE_NONE) {
2461 while (GSM->GetModel(model) != GE_NONE)
2464 max_profiles = 7; /* This is correct for 6110 (at least my). How do we get
2465 the number of profiles? */
2468 /*FIX ME: It should be set to 3 for N5130 and 3210 too*/
2469 if (!strcmp(model, "NSE-1"))
2473 profile.Number = atoi(argv[0]) - 1;
2474 start = profile.Number;
2477 if (profile.Number < 0) {
2478 fprintf(stderr, _("Profile number must be value from 1 to %d!\n"), max_profiles);
2483 if (profile.Number >= max_profiles) {
2484 fprintf(stderr, _("This phone supports only %d profiles!\n"), max_profiles);
2490 stop = max_profiles;
2497 if (profile.Number != 0)
2498 GSM->GetProfile(&profile);
2500 fprintf(stdout, "%d. \"%s\"\n", profile.Number + 1, profile.Name);
2501 if (profile.DefaultName == -1) fprintf(stdout, _(" (name defined)\n"));
2503 fprintf(stdout, _("Incoming call alert: %s\n"), GetProfileCallAlertString(profile.CallAlert));
2505 /* For different phones different ringtones names */
2507 if (!strcmp(model, "NSE-3"))
2508 fprintf(stdout, _("Ringing tone: %s (%d)\n"), RingingTones[profile.Ringtone], profile.Ringtone);
2510 fprintf(stdout, _("Ringtone number: %d\n"), profile.Ringtone);
2512 fprintf(stdout, _("Ringing volume: %s\n"), GetProfileVolumeString(profile.Volume));
2514 fprintf(stdout, _("Message alert tone: %s\n"), GetProfileMessageToneString(profile.MessageTone));
2516 fprintf(stdout, _("Keypad tones: %s\n"), GetProfileKeypadToneString(profile.KeypadTone));
2518 fprintf(stdout, _("Warning and game tones: %s\n"), GetProfileWarningToneString(profile.WarningTone));
2520 /* FIXME: Light settings is only used for Car */
2521 if (profile.Number == (max_profiles - 2)) fprintf(stdout, _("Lights: %s\n"), profile.Lights ? _("On") : _("Automatic"));
2523 fprintf(stdout, _("Vibration: %s\n"), GetProfileVibrationString(profile.Vibration));
2525 /* FIXME: it will be nice to add here reading caller group name. */
2526 if (max_profiles != 3) fprintf(stdout, _("Caller groups: 0x%02x\n"), profile.CallerGroups);
2528 /* FIXME: Automatic answer is only used for Car and Headset. */
2529 if (profile.Number >= (max_profiles - 2)) fprintf(stdout, _("Automatic answer: %s\n"), profile.AutomaticAnswer ? _("On") : _("Off"));
2531 fprintf(stdout, "\n");
2536 if (error == GE_NOTIMPLEMENTED) {
2537 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2541 fprintf(stderr, _("Unspecified error\n"));
2551 /* Get requested range of memory storage entries and output to stdout in
2552 easy-to-parse format */
2553 int getmemory(int argc, char *argv[])
2555 GSM_PhonebookEntry entry;
2558 char *memory_type_string;
2561 GSM_Statemachine *sm = &State;
2563 /* Handle command line args that set type, start and end locations. */
2564 memory_type_string = argv[0];
2565 entry.MemoryType = StrToMemoryType(memory_type_string);
2566 if (entry.MemoryType == GMT_XX) {
2567 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
2571 start_entry = atoi (argv[1]);
2572 if (argc > 2) end_entry = atoi (argv[2]);
2573 else end_entry = start_entry;
2575 /* Now retrieve the requested entries. */
2576 for (count = start_entry; count <= end_entry; count ++) {
2578 entry.Location = count;
2580 data.PhonebookEntry=&entry;
2581 error=SM_Functions(GOP_ReadPhonebook,&data,sm);
2583 if (error == GE_NONE) {
2584 fprintf(stdout, "%s;%s;%s;%d;%d\n", entry.Name, entry.Number, memory_type_string, entry.Location, entry.Group);
2585 if (entry.MemoryType == GMT_MC || entry.MemoryType == GMT_DC || entry.MemoryType == GMT_RC)
2586 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);
2589 if (error == GE_NOTIMPLEMENTED) {
2590 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2593 else if (error == GE_INVALIDMEMORYTYPE) {
2594 fprintf(stderr, _("Memory type %s not supported!\n"), memory_type_string);
2598 fprintf(stdout, _("%s|%d|Bad location or other error!(%d)\n"), memory_type_string, count, error);
2604 /* Read data from stdin, parse and write to phone. The parsing is relatively
2605 crude and doesn't allow for much variation from the stipulated format. */
2606 /* FIXME: I guess there's *very* similar code in xgnokii */
2607 int writephonebook(int argc, char *args[])
2609 GSM_PhonebookEntry entry;
2611 char *memory_type_string;
2615 char *Line, OLine[100], BackLine[100];
2618 /* Check argument */
2619 if (argc && (strcmp("-i", args[0])))
2624 /* Go through data from stdin. */
2625 while (GetLine(stdin, Line, 99)) {
2626 strcpy(BackLine, Line);
2629 ptr = strtok(Line, ";");
2630 if (ptr) strcpy(entry.Name, ptr);
2631 else entry.Name[0] = 0;
2633 ptr = strtok(NULL, ";");
2634 if (ptr) strcpy(entry.Number, ptr);
2635 else entry.Number[0] = 0;
2637 ptr = strtok(NULL, ";");
2640 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2645 if (!strncmp(ptr,"ME", 2)) {
2646 memory_type_string = "int";
2647 entry.MemoryType = GMT_ME;
2649 if (!strncmp(ptr,"SM", 2)) {
2650 memory_type_string = "sim";
2651 entry.MemoryType = GMT_SM;
2653 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2658 ptr = strtok(NULL, ";");
2659 if (ptr) entry.Location = atoi(ptr);
2660 else entry.Location = 0;
2662 ptr = strtok(NULL, ";");
2663 if (ptr) entry.Group = atoi(ptr);
2664 else entry.Group = 0;
2667 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2671 for (subentry = 0; ; subentry++) {
2672 ptr = strtok(NULL, ";");
2674 if (ptr && *ptr != 0)
2675 entry.SubEntries[subentry].EntryType = atoi(ptr);
2679 ptr = strtok(NULL, ";");
2681 entry.SubEntries[subentry].NumberType=atoi(ptr);
2683 /* Phone Numbers need to have a number type. */
2684 if (!ptr && entry.SubEntries[subentry].EntryType == GSM_Number) {
2685 fprintf(stderr, _("Missing phone number type on line %d"
2686 " entry %d [%s]\n"), line_count, subentry, BackLine);
2691 ptr = strtok(NULL, ";");
2693 entry.SubEntries[subentry].BlockNumber=atoi(ptr);
2695 ptr = strtok(NULL, ";");
2697 /* 0x13 Date Type; it is only for Dailed Numbers, etc.
2698 we don't store to this memories so it's an error to use it. */
2699 if (!ptr || entry.SubEntries[subentry].EntryType == GSM_Date) {
2700 fprintf(stdout, _("There is no phone number on line %d entry %d [%s]\n"),
2701 line_count, subentry, BackLine);
2705 strcpy(entry.SubEntries[subentry].data.Number, ptr);
2708 entry.SubEntriesCount = subentry;
2710 /* This is to send other exports (like from 6110) to 7110 */
2711 if (!entry.SubEntriesCount) {
2712 entry.SubEntriesCount = 1;
2713 entry.SubEntries[subentry].EntryType = GSM_Number;
2714 entry.SubEntries[subentry].NumberType = GSM_General;
2715 entry.SubEntries[subentry].BlockNumber = 2;
2716 strcpy(entry.SubEntries[subentry].data.Number, entry.Number);
2722 GSM_PhonebookEntry aux;
2724 aux.Location = entry.Location;
2725 error = GSM->GetMemoryLocation(&aux);
2727 if (error == GE_NONE) {
2732 fprintf(stdout, _("Location busy. "));
2733 while (confirm < 0) {
2734 fprintf(stdout, _("Overwrite? (yes/no) "));
2735 GetLine(stdin, ans, 7);
2736 if (!strcmp(ans, _("yes"))) confirm = 1;
2737 else if (!strcmp(ans, _("no"))) confirm = 0;
2739 if (!confirm) continue;
2742 fprintf(stderr, _("Unknown error (%d)\n"), error);
2748 /* Do write and report success/failure. */
2749 error = GSM->WritePhonebookLocation(&entry);
2751 if (error == GE_NONE)
2752 fprintf (stdout, _("Write Succeeded: memory type: %s, loc: %d, name: %s, number: %s\n"), memory_type_string, entry.Location, entry.Name, entry.Number);
2754 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);
2762 /* Getting speed dials. */
2763 int getspeeddial(char *Number)
2765 GSM_SpeedDial SpeedDial;
2769 SpeedDial.Number = atoi(Number);
2771 if (GSM && GSM->GetSpeedDial && GSM->Terminate) {
2772 error = GSM->GetSpeedDial(&SpeedDial);
2775 GSM_DataClear(&data);
2776 data.SpeedDial = &SpeedDial;
2778 error = SM_Functions(GOP_GetSpeedDial, &data, &State);
2783 fprintf(stdout, _("SpeedDial nr. %d: %d:%d\n"), SpeedDial.Number, SpeedDial.MemoryType, SpeedDial.Location);
2785 case GE_NOTIMPLEMENTED:
2786 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2789 fprintf(stdout, _("Internal error\n"));
2796 /* Setting speed dials. */
2797 int setspeeddial(char *argv[])
2799 GSM_SpeedDial entry;
2801 char *memory_type_string;
2803 /* Handle command line args that set type, start and end locations. */
2805 if (strcmp(argv[1], "ME") == 0) {
2806 entry.MemoryType = 0x02;
2807 memory_type_string = "ME";
2808 } else if (strcmp(argv[1], "SM") == 0) {
2809 entry.MemoryType = 0x03;
2810 memory_type_string = "SM";
2812 fprintf(stderr, _("Unknown memory type %s!\n"), argv[1]);
2816 entry.Number = atoi(argv[0]);
2817 entry.Location = atoi(argv[2]);
2819 if (GSM->SetSpeedDial(&entry) == GE_NONE) {
2820 fprintf(stdout, _("Succesfully written!\n"));
2827 /* Getting the status of the display. */
2828 int getdisplaystatus(void)
2832 GSM->GetDisplayStatus(&Status);
2834 fprintf(stdout, _("Call in progress: %s\n"), Status & (1<<DS_Call_In_Progress)?_("on"):_("off"));
2835 fprintf(stdout, _("Unknown: %s\n"), Status & (1<<DS_Unknown)?_("on"):_("off"));
2836 fprintf(stdout, _("Unread SMS: %s\n"), Status & (1<<DS_Unread_SMS)?_("on"):_("off"));
2837 fprintf(stdout, _("Voice call: %s\n"), Status & (1<<DS_Voice_Call)?_("on"):_("off"));
2838 fprintf(stdout, _("Fax call active: %s\n"), Status & (1<<DS_Fax_Call)?_("on"):_("off"));
2839 fprintf(stdout, _("Data call active: %s\n"), Status & (1<<DS_Data_Call)?_("on"):_("off"));
2840 fprintf(stdout, _("Keyboard lock: %s\n"), Status & (1<<DS_Keyboard_Lock)?_("on"):_("off"));
2841 fprintf(stdout, _("SMS storage full: %s\n"), Status & (1<<DS_SMS_Storage_Full)?_("on"):_("off"));
2847 int netmonitor(char *Mode)
2849 unsigned char mode = atoi(Mode);
2852 if (!strcmp(Mode, "reset"))
2854 else if (!strcmp(Mode, "off"))
2856 else if (!strcmp(Mode, "field"))
2858 else if (!strcmp(Mode, "devel"))
2860 else if (!strcmp(Mode, "next"))
2863 memset(&Screen, 0, 50);
2864 GSM->NetMonitor(mode, Screen);
2867 fprintf(stdout, "%s\n", Screen);
2875 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2876 char imei[64], model[64], rev[64], manufacturer[64];
2877 GSM_Statemachine *sm = &State;
2879 data.Manufacturer=manufacturer;
2884 /* Retrying is bad idea: what if function is simply not implemented?
2885 Anyway let's wait 2 seconds for the right packet from the phone. */
2888 strcpy(imei, "(unknown)");
2889 strcpy(manufacturer, "(unknown)");
2890 strcpy(model, "(unknown)");
2891 strcpy(rev, "(unknown)");
2893 SM_Functions(GOP_Identify, &data, sm);
2895 fprintf(stdout, _("IMEI: %s\n"), imei);
2896 fprintf(stdout, _("Manufacturer: %s\n"), manufacturer);
2897 fprintf(stdout, _("Model: %s\n"), model);
2898 fprintf(stdout, _("Revision: %s\n"), rev);
2905 int senddtmf(char *String)
2907 GSM->SendDTMF(String);
2912 /* Resets the phone */
2913 int reset( char *type)
2915 unsigned char _type = 0x03;
2918 if(!strcmp(type, "soft"))
2921 if(!strcmp(type, "hard"))
2924 fprintf(stderr, _("What kind of reset do you want??\n"));
2935 /* pmon allows fbus code to run in a passive state - it doesn't worry about
2936 whether comms are established with the phone. A debugging/development
2942 GSM_ConnectionType connection=GCT_Serial;
2943 GSM_Statemachine sm;
2945 /* Initialise the code for the GSM interface. */
2946 error = GSM_Initialise(model, Port, Initlength, connection, NULL, &sm);
2948 if (error != GE_NONE) {
2949 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
2960 int sendringtone(int argc, char *argv[])
2962 GSM_Ringtone ringtone;
2965 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2966 fprintf(stdout, _("Failed to load ringtone.\n"));
2970 error = GSM->SendRingtone(&ringtone,argv[1]);
2972 if (error == GE_NONE)
2973 fprintf(stdout, _("Send succeeded!\n"));
2975 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
2983 int setringtone(int argc, char *argv[])
2985 GSM_Ringtone ringtone;
2988 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2989 fprintf(stdout, _("Failed to load ringtone.\n"));
2993 error = GSM->SetRingtone(&ringtone);
2995 if (error == GE_NONE)
2996 fprintf(stdout, _("Send succeeded!\n"));
2998 fprintf(stdout, _("Send failed\n"));
3005 int presskeysequence(void)
3011 memset(&buf[0], 0, 102);
3012 while (read(0, buf, 100) > 0) {
3013 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
3014 if (GSM->HandleString(buf) != GE_NONE)
3015 fprintf(stdout, _("Key press simulation failed.\n"));
3016 memset(buf, 0, 102);
3023 /* This is a "convenience" function to allow quick test of new API stuff which
3024 doesn't warrant a "proper" command line function. */
3026 int foogle(char *argv[])
3028 /* Initialise the code for the GSM interface. */
3030 // Fill in what you would like to test here...