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.8.1 2001/11/27 23:06:09 short
23 Update: orig2001_11_27_05_17 -> orig2001_11_27_22_58
25 Revision 1.1.1.1.2.1 2001/11/27 22:48:37 short
26 Update: orig2001_11_27_05_17 -> orig2001_11_27_22_58
28 Revision 1.1.1.2 2001/11/27 22:01:25 short
29 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Nov 27 22:58 CET 2001
31 Revision 1.152 2001/11/27 12:23:11 pkot
32 Specifying SMSC number in --sendsms works again
34 Revision 1.151 2001/11/22 17:56:53 pkot
35 smslib update. sms sending
37 Revision 1.150 2001/11/20 16:22:22 pkot
38 First attempt to read Picture Messages. They should appear when you enable DEBUG. Nokia seems to break own standards. :/ (Markus Plail)
40 Revision 1.149 2001/11/19 16:00:15 pkot
43 Revision 1.148 2001/11/19 13:46:43 pkot
44 reading unread SMS in 6210 from Inbox. Folder updates (Markus Plail)
46 Revision 1.147 2001/11/18 00:54:32 pkot
47 Bugfixes. I18n of the user responses. UDH support in libsms. Business Card UDH Type
49 Revision 1.146 2001/11/17 20:18:33 pkot
50 Added dau9p connection type for 6210/7110
52 Revision 1.145 2001/11/14 10:46:12 pkot
53 Small cleanup with __unices__
55 Revision 1.144 2001/11/08 16:34:19 pkot
56 Updates to work with new libsms
58 Revision 1.143 2001/09/14 13:30:07 pkot
59 Fixed bugs introduced during 0.3.3 merge
61 Revision 1.142 2001/09/14 13:02:03 pkot
62 Gnokii calendar changes from 0.3.3
64 Revision 1.141 2001/09/14 12:53:00 pkot
67 Set valid operator on logos xgnokii screen.
69 Revision 1.140 2001/07/27 00:02:21 pkot
70 Generic AT support for the new structure (Manfred Jonsson)
72 Revision 1.139 2001/07/01 23:16:45 pkot
73 Fixed a typo in gnokii.c avoiding saving logo (Jan Havelka)
75 Revision 1.138 2001/06/28 00:28:45 pkot
76 Small docs updates (Pawel Kot)
78 Revision 1.137 2001/06/27 23:52:50 pkot
79 7110/6210 updates (Marian Jancar)
81 Revision 1.136 2001/06/10 23:49:49 pkot
82 Small fixes to hide compilation warnings and allow gnokii.c to compile
84 Revision 1.135 2001/06/10 11:42:26 machek
85 Cleanup: some formating, made Statemachine global, converted to new
86 structure w.r.t. SMS-es
88 Revision 1.134 2001/05/24 20:47:30 chris
89 More updating of 7110 code and some of xgnokii_lowlevel changed over.
91 Revision 1.133 2001/04/23 17:20:01 pkot
92 Added possibility for viewing logos (currently nol and ngg) on console (Bartek Klepacz)
94 Revision 1.132 2001/03/21 23:36:06 chris
95 Added the statemachine
96 This will break gnokii --identify and --monitor except for 6210/7110
98 Revision 1.131 2001/03/19 23:43:46 pkot
99 Solaris / BSD '#if defined' cleanup
101 Revision 1.130 2001/03/13 01:23:18 pkot
102 Windows updates (Manfred Jonsson)
104 Revision 1.129 2001/03/13 01:21:39 pkot
105 *BSD updates (Bert Driehuis)
107 Revision 1.128 2001/03/08 00:49:06 pkot
108 Fixed bug (introduced by me) in getmemory function. Now gnokii.c should compile
110 Revision 1.127 2001/03/08 00:18:13 pkot
111 Fixed writephonebook once again. Someone kick me please...
113 Revision 1.126 2001/03/07 21:46:12 pkot
114 Fixed writephonebook patch
116 Revision 1.125 2001/03/06 22:19:14 pkot
117 Cleanups and fixes in gnokii.c:
119 - fixed bug reported by Gabriele Zappi
120 - fixed small bugs introduced by Pavel Machek
122 Revision 1.124 2001/02/28 21:42:00 machek
123 Possibility to force overwrite in --getsms (-F). Possibility to get
124 multiple files (use --getsms -f xyzzy%d), cleanup.
126 Revision 1.123 2001/02/20 21:55:11 pkot
127 Small #include updates
129 Revision 1.122 2001/02/16 14:29:53 chris
130 Restructure of common/. Fixed a problem in fbus-phonet.c
131 Lots of dprintfs for Marcin
132 Any size xpm can now be loaded (eg for 7110 startup logos)
133 nk7110 code detects 7110/6210 and alters startup logo size to suit
134 Moved Marcin's extended phonebook code into gnokii.c
136 Revision 1.121 2001/02/06 21:15:35 chris
137 Preliminary irda support for 7110 etc. Not well tested!
139 Revision 1.120 2001/02/06 08:13:32 pkot
140 One more include in gnokii.c needed
142 Revision 1.119 2001/02/05 12:29:37 pkot
143 Changes needed to let unicode work
145 Revision 1.118 2001/02/01 15:17:33 pkot
146 Fixed --identify and added Manfred's manufacturer patch
148 Revision 1.117 2001/01/31 23:45:27 pkot
149 --identify should work ok now
151 Revision 1.116 2001/01/24 20:19:55 machek
152 Do not retry identification, if it is not implemented, it is bad idea.
154 Revision 1.115 2001/01/22 01:25:10 hugh
155 Tweaks for 3810 series, datacalls seem to be broken so need to do
156 some more debugging...
158 Revision 1.114 2001/01/17 02:54:55 chris
159 More 7110 work. Use with care! (eg it is not possible to delete phonebook entries)
160 I can now edit my phonebook in xgnokii but it is 'work in progress'.
162 Revision 1.113 2001/01/15 17:00:49 pkot
163 Initial keypress sequence support. Disable compilation warning
165 Revision 1.112 2001/01/12 14:09:13 pkot
166 More cleanups. This time mainly in the code.
168 Revision 1.111 2001/01/10 16:32:18 pkot
169 Documentation updates.
170 FreeBSD fix for 3810 code.
171 Added possibility for deleting SMS just after reading it in gnokii.
175 Revision 1.110 2001/01/08 15:11:37 pkot
176 Documentation updates.
177 Fixed some bugs and removed FIXMEs.
178 We need to move some stuff from configure.in to aclocal.m4
180 Revision 1.109 2000/12/29 15:39:07 pkot
181 Reverted a change in fbus-3810.c which broke compling with --enable-debug.
182 Small fixes in gnokii.c
184 Revision 1.108 2000/12/19 16:18:16 pkot
185 configure script updates and added shared function for configfile reading
197 # include <strings.h> /* for memset */
200 #include <sys/types.h>
201 #include <sys/stat.h>
206 #define sleep(x) Sleep((x) * 1000)
207 #define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
209 #include "win32/getopt.h"
224 #include "gsm-common.h"
226 #include "gsm-networks.h"
227 #include "cfgreader.h"
229 #include "gsm-filetypes.h"
230 #include "gsm-bitmaps.h"
231 #include "gsm-ringtones.h"
232 #include "gsm-statemachine.h"
234 char *model; /* Model from .gnokiirc file. */
235 char *Port; /* Serial port from .gnokiirc file */
236 char *Initlength; /* Init length from .gnokiirc file */
237 char *Connection; /* Connection type from .gnokiirc file */
238 char *BinDir; /* Binaries directory from .gnokiirc file - not used here yet */
239 /* Local variables */
241 char *GetProfileCallAlertString(int code)
244 case PROFILE_CALLALERT_RINGING: return "Ringing";
245 case PROFILE_CALLALERT_ASCENDING: return "Ascending";
246 case PROFILE_CALLALERT_RINGONCE: return "Ring once";
247 case PROFILE_CALLALERT_BEEPONCE: return "Beep once";
248 case PROFILE_CALLALERT_CALLERGROUPS: return "Caller groups";
249 case PROFILE_CALLALERT_OFF: return "Off";
250 default: return "Unknown";
254 char *GetProfileVolumeString(int code)
257 case PROFILE_VOLUME_LEVEL1: return "Level 1";
258 case PROFILE_VOLUME_LEVEL2: return "Level 2";
259 case PROFILE_VOLUME_LEVEL3: return "Level 3";
260 case PROFILE_VOLUME_LEVEL4: return "Level 4";
261 case PROFILE_VOLUME_LEVEL5: return "Level 5";
262 default: return "Unknown";
266 char *GetProfileKeypadToneString(int code)
269 case PROFILE_KEYPAD_OFF: return "Off";
270 case PROFILE_KEYPAD_LEVEL1: return "Level 1";
271 case PROFILE_KEYPAD_LEVEL2: return "Level 2";
272 case PROFILE_KEYPAD_LEVEL3: return "Level 3";
273 default: return "Unknown";
277 char *GetProfileMessageToneString(int code)
280 case PROFILE_MESSAGE_NOTONE: return "No tone";
281 case PROFILE_MESSAGE_STANDARD: return "Standard";
282 case PROFILE_MESSAGE_SPECIAL: return "Special";
283 case PROFILE_MESSAGE_BEEPONCE: return "Beep once";
284 case PROFILE_MESSAGE_ASCENDING: return "Ascending";
285 default: return "Unknown";
289 char *GetProfileWarningToneString(int code)
292 case PROFILE_WARNING_OFF: return "Off";
293 case PROFILE_WARNING_ON: return "On";
294 default: return "Unknown";
298 char *GetProfileVibrationString(int code)
301 case PROFILE_VIBRATION_OFF: return "Off";
302 case PROFILE_VIBRATION_ON: return "On";
303 default: return "Unknown";
307 /* This function shows the copyright and some informations usefull for
312 fprintf(stdout, _("GNOKII Version %s\n"
313 "Copyright (C) Hugh Blemings <hugh@blemings.org>, 1999, 2000\n"
314 "Copyright (C) Pavel Janík ml. <Pavel.Janik@suse.cz>, 1999, 2000\n"
315 "Copyright (C) Pavel Machek <pavel@ucw.cz>, 2001\n"
316 "Copyright (C) Pawe³ Kot <pkot@linuxnews.pl>, 2001\n"
317 "gnokii is free software, covered by the GNU General Public License, and you are\n"
318 "welcome to change it and/or distribute copies of it under certain conditions.\n"
319 "There is absolutely no warranty for gnokii. See GPL for details.\n"
320 "Built %s %s for %s on %s \n"), VERSION, __TIME__, __DATE__, model, Port);
324 /* The function usage is only informative - it prints this program's usage and
325 command-line options. */
329 fprintf(stdout, _(" usage: gnokii [--help|--monitor|--version]\n"
330 " gnokii --getmemory memory_type start [end]\n"
331 " gnokii --writephonebook [-i]\n"
332 " gnokii --getspeeddial number\n"
333 " gnokii --setspeeddial number memory_type location\n"
334 " gnokii --getsms memory_type start [end] [-f file] [-F file] [-d]\n"
335 " gnokii --deletesms memory_type start [end]\n"
336 " gnokii --sendsms destination [--smsc message_center_number |\n"
337 " --smscno message_center_index] [-r] [-C n] [-v n]\n"
339 " gnokii --savesms [-m] [-l n] [-i]\n"
340 " gnokii --getsmsc message_center_number\n"
341 " gnokii --setdatetime [YYYY [MM [DD [HH [MM]]]]]\n"
342 " gnokii --getdatetime\n"
343 " gnokii --setalarm HH MM\n"
344 " gnokii --getalarm\n"
345 " gnokii --dialvoice number\n"
346 " gnokii --getcalendarnote start [end] [-v]\n"
347 " gnokii --writecalendarnote vcardfile number\n"
348 " gnokii --deletecalendarnote start [end]\n"
349 " gnokii --getdisplaystatus\n"
350 " gnokii --netmonitor {reset|off|field|devel|next|nr}\n"
351 " gnokii --identify\n"
352 " gnokii --senddtmf string\n"
353 " gnokii --sendlogo {caller|op} destination logofile [network code]\n"
354 " gnokii --sendringtone destination rtttlfile\n"
355 " gnokii --setlogo op [logofile] [network code]\n"
356 " gnokii --setlogo startup [logofile]\n"
357 " gnokii --setlogo caller [logofile] [caller group number] [group name]\n"
358 " gnokii --setlogo {dealer|text} [text]\n"
359 " gnokii --getlogo op [logofile] [network code]\n"
360 " gnokii --getlogo startup [logofile] [network code]\n"
361 " gnokii --getlogo caller [logofile][caller group number][network code]\n"
362 " gnokii --getlogo {dealer|text}\n"
363 " gnokii --viewlogo logofile\n"
364 " gnokii --setringtone rtttlfile\n"
365 " gnokii --reset [soft|hard]\n"
366 " gnokii --getprofile [number]\n"
367 " gnokii --displayoutput\n"
368 " gnokii --keysequence\n"
372 " gnokii --entersecuritycode PIN|PIN2|PUK|PUK2\n"
373 " gnokii --getsecuritycodestatus\n"
379 /* fbusinit is the generic function which waits for the FBUS link. The limit
380 is 10 seconds. After 10 seconds we quit. */
382 static GSM_Statemachine State;
383 static GSM_Data data;
385 void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame))
389 GSM_ConnectionType connection = GCT_Serial;
391 GSM_DataClear(&data);
393 if (!strcasecmp(Connection, "dau9p")) connection = GCT_DAU9P;
394 if (!strcasecmp(Connection, "infrared")) connection = GCT_Infrared;
395 if (!strcasecmp(Connection, "irda")) connection = GCT_Irda;
397 /* Initialise the code for the GSM interface. */
399 error = GSM_Initialise(model, Port, Initlength, connection, rlp_handler, &State);
401 if (error != GE_NONE) {
402 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
406 /* First (and important!) wait for GSM link to be active. We allow 10
409 while (count++ < 200 && *GSM_LinkOK == false)
412 if (*GSM_LinkOK == false) {
413 fprintf (stderr, _("Hmmm... GSM_LinkOK never went true. Quitting.\n"));
418 /* This function checks that the argument count for a given options is withing
420 int checkargs(int opt, struct gnokii_arg_len gals[], int argc)
424 /* Walk through the whole array with options requiring arguments. */
425 for (i = 0; !(gals[i].gal_min == 0 && gals[i].gal_max == 0); i++) {
427 /* Current option. */
428 if (gals[i].gal_opt == opt) {
430 /* Argument count checking. */
431 if (gals[i].gal_flags == GAL_XOR) {
432 if (gals[i].gal_min == argc || gals[i].gal_max == argc)
435 if (gals[i].gal_min <= argc && gals[i].gal_max >= argc)
443 /* We do not have options without arguments in the array, so check them. */
444 if (argc == 0) return 0;
448 /* Main function - handles command line arguments, passes them to separate
449 functions accordingly. */
450 int main(int argc, char *argv[])
456 /* Every option should be in this array. */
457 static struct option long_options[] =
459 /* FIXME: these comments are nice, but they would be more usefull as docs for the user */
461 { "help", no_argument, NULL, OPT_HELP },
463 // Display version and build information.
464 { "version", no_argument, NULL, OPT_VERSION },
467 { "monitor", no_argument, NULL, OPT_MONITOR },
471 // Enter Security Code mode
472 { "entersecuritycode", required_argument, NULL, OPT_ENTERSECURITYCODE },
474 // Get Security Code status
475 { "getsecuritycodestatus", no_argument, NULL, OPT_GETSECURITYCODESTATUS },
480 { "setdatetime", optional_argument, NULL, OPT_SETDATETIME },
482 // Get date and time mode
483 { "getdatetime", no_argument, NULL, OPT_GETDATETIME },
486 { "setalarm", required_argument, NULL, OPT_SETALARM },
489 { "getalarm", no_argument, NULL, OPT_GETALARM },
492 { "dialvoice", required_argument, NULL, OPT_DIALVOICE },
494 // Get calendar note mode
495 { "getcalendarnote", required_argument, NULL, OPT_GETCALENDARNOTE },
497 // Write calendar note mode
498 { "writecalendarnote", required_argument, NULL, OPT_WRITECALENDARNOTE },
500 // Delete calendar note mode
501 { "deletecalendarnote", required_argument, NULL, OPT_DELCALENDARNOTE },
503 // Get display status mode
504 { "getdisplaystatus", no_argument, NULL, OPT_GETDISPLAYSTATUS },
507 { "getmemory", required_argument, NULL, OPT_GETMEMORY },
509 // Write phonebook (memory) mode
510 { "writephonebook", optional_argument, NULL, OPT_WRITEPHONEBOOK },
512 // Get speed dial mode
513 { "getspeeddial", required_argument, NULL, OPT_GETSPEEDDIAL },
515 // Set speed dial mode
516 { "setspeeddial", required_argument, NULL, OPT_SETSPEEDDIAL },
518 // Get SMS message mode
519 { "getsms", required_argument, NULL, OPT_GETSMS },
521 // Delete SMS message mode
522 { "deletesms", required_argument, NULL, OPT_DELETESMS },
524 // Send SMS message mode
525 { "sendsms", required_argument, NULL, OPT_SENDSMS },
527 // Ssve SMS message mode
528 { "savesms", optional_argument, NULL, OPT_SAVESMS },
530 // Send logo as SMS message mode
531 { "sendlogo", required_argument, NULL, OPT_SENDLOGO },
533 // Send ringtone as SMS message
534 { "sendringtone", required_argument, NULL, OPT_SENDRINGTONE },
537 { "setringtone", required_argument, NULL, OPT_SETRINGTONE },
539 // Get SMS center number mode
540 { "getsmsc", required_argument, NULL, OPT_GETSMSC },
542 // For development purposes: run in passive monitoring mode
543 { "pmon", no_argument, NULL, OPT_PMON },
546 { "netmonitor", required_argument, NULL, OPT_NETMONITOR },
549 { "identify", no_argument, NULL, OPT_IDENTIFY },
551 // Send DTMF sequence
552 { "senddtmf", required_argument, NULL, OPT_SENDDTMF },
555 { "reset", optional_argument, NULL, OPT_RESET },
558 { "setlogo", optional_argument, NULL, OPT_SETLOGO },
561 { "getlogo", required_argument, NULL, OPT_GETLOGO },
564 { "viewlogo", required_argument, NULL, OPT_VIEWLOGO },
567 { "getprofile", optional_argument, NULL, OPT_GETPROFILE },
569 // Show texts from phone's display
570 { "displayoutput", no_argument, NULL, OPT_DISPLAYOUTPUT },
572 // Simulate pressing the keys
573 { "keysequence", no_argument, NULL, OPT_KEYPRESS },
575 // For development purposes: insert you function calls here
576 { "foogle", no_argument, NULL, OPT_FOOGLE },
581 /* Every command which requires arguments should have an appropriate entry
583 struct gnokii_arg_len gals[] =
587 { OPT_ENTERSECURITYCODE, 1, 1, 0 },
590 { OPT_SETDATETIME, 0, 5, 0 },
591 { OPT_SETALARM, 2, 2, 0 },
592 { OPT_DIALVOICE, 1, 1, 0 },
593 { OPT_GETCALENDARNOTE, 1, 3, 0 },
594 { OPT_WRITECALENDARNOTE, 2, 2, 0 },
595 { OPT_DELCALENDARNOTE, 1, 2, 0 },
596 { OPT_GETMEMORY, 2, 3, 0 },
597 { OPT_GETSPEEDDIAL, 1, 1, 0 },
598 { OPT_SETSPEEDDIAL, 3, 3, 0 },
599 { OPT_GETSMS, 2, 5, 0 },
600 { OPT_DELETESMS, 2, 3, 0 },
601 { OPT_SENDSMS, 1, 10, 0 },
602 { OPT_SAVESMS, 0, 6, 0 },
603 { OPT_SENDLOGO, 3, 4, GAL_XOR },
604 { OPT_SENDRINGTONE, 2, 2, 0 },
605 { OPT_GETSMSC, 1, 1, 0 },
606 { OPT_GETWELCOMENOTE, 1, 1, 0 },
607 { OPT_SETWELCOMENOTE, 1, 1, 0 },
608 { OPT_NETMONITOR, 1, 1, 0 },
609 { OPT_SENDDTMF, 1, 1, 0 },
610 { OPT_SETLOGO, 1, 4, 0 },
611 { OPT_GETLOGO, 1, 4, 0 },
612 { OPT_VIEWLOGO, 1, 1, 0 },
613 { OPT_SETRINGTONE, 1, 1, 0 },
614 { OPT_RESET, 0, 1, 0 },
615 { OPT_GETPROFILE, 0, 1, 0 },
616 { OPT_WRITEPHONEBOOK, 0, 1, 0 },
623 /* For GNU gettext */
625 textdomain("gnokii");
626 setlocale(LC_ALL, "");
629 /* Read config file */
630 if (readconfig(&model, &Port, &Initlength, &Connection, &BinDir) < 0) {
634 /* Handle command line arguments. */
635 c = getopt_long(argc, argv, "", long_options, NULL);
636 if (c == -1) /* No argument given - we should display usage. */
640 // First, error conditions
643 fprintf(stderr, _("Use '%s --help' for usage informations.\n"), argv[0]);
645 // Then, options with no arguments
652 /* We have to build an array of the arguments which will be passed to the
653 functions. Please note that every text after the --command will be
654 passed as arguments. A syntax like gnokii --cmd1 args --cmd2 args will
655 not work as expected; instead args --cmd2 args is passed as a
657 if ((nargv = malloc(sizeof(char *) * argc)) != NULL) {
658 for (i = 2; i < argc; i++)
659 nargv[i-2] = argv[i];
661 if (checkargs(c, gals, nargc)) {
662 free(nargv); /* Wrong number of arguments - we should display usage. */
667 /* have to ignore SIGALARM */
671 /* Initialise the code for the GSM interface. */
679 case OPT_ENTERSECURITYCODE:
680 rc = entersecuritycode(optarg);
682 case OPT_GETSECURITYCODESTATUS:
683 rc = getsecuritycodestatus();
686 case OPT_GETDATETIME:
692 case OPT_GETDISPLAYSTATUS:
693 rc = getdisplaystatus();
698 case OPT_WRITEPHONEBOOK:
699 rc = writephonebook(nargc, nargv);
701 // Now, options with arguments
702 case OPT_SETDATETIME:
703 rc = setdatetime(nargc, nargv);
706 rc = setalarm(nargv);
709 rc = dialvoice(optarg);
711 case OPT_GETCALENDARNOTE:
712 rc = getcalendarnote(nargc, nargv);
714 case OPT_DELCALENDARNOTE:
715 rc = deletecalendarnote(nargc, nargv);
717 case OPT_WRITECALENDARNOTE:
718 rc = writecalendarnote(nargv);
721 rc = getmemory(nargc, nargv);
723 case OPT_GETSPEEDDIAL:
724 rc = getspeeddial(optarg);
726 case OPT_SETSPEEDDIAL:
727 rc = setspeeddial(nargv);
730 rc = getsms(argc, argv);
733 rc = deletesms(nargc, nargv);
736 rc = sendsms(nargc, nargv);
739 rc = savesms(argc, argv);
742 rc = sendlogo(nargc, nargv);
745 rc = getsmsc(optarg);
748 rc = netmonitor(optarg);
754 rc = setlogo(nargc, nargv);
757 rc = getlogo(nargc, nargv);
760 rc = viewlogo(optarg);
762 case OPT_SETRINGTONE:
763 rc = setringtone(nargc, nargv);
765 case OPT_SENDRINGTONE:
766 rc = sendringtone(nargc, nargv);
769 rc = getprofile(nargc, nargv);
771 case OPT_DISPLAYOUTPUT:
772 rc = displayoutput();
775 rc = presskeysequence();
783 rc = senddtmf(optarg);
789 fprintf(stderr, _("Unknown option: %d\n"), c);
796 fprintf(stderr, _("Wrong number of arguments\n"));
800 /* Send SMS messages. */
801 int sendsms(int argc, char *argv[])
805 // char UDH[GSM_MAX_USER_DATA_HEADER_LENGTH];
806 /* The maximum length of an uncompressed concatenated short message is
807 255 * 153 = 39015 default alphabet characters */
808 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
809 int input_len, chars_read;
810 int i; /*, offset, nr_msg, aux;*/
812 struct option options[] = {
813 { "smsc", required_argument, NULL, '1'},
814 { "smscno", required_argument, NULL, '2'},
815 { "long", required_argument, NULL, '3'},
819 input_len = GSM_MAX_SMS_LENGTH;
827 - message validity for 3 days
828 - unset user data header indicator
831 memset(&SMS, 0, sizeof(GSM_SMSMessage));
833 SMS.Type = SMS_Submit;
834 SMS.DCS.Type = SMS_GeneralDataCoding;
835 SMS.DCS.u.General.Compressed = false;
836 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
837 SMS.DCS.u.General.Class = 0;
838 SMS.MessageCenter.No = 1;
839 SMS.Validity.VPF = SMS_RelativeFormat;
840 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
843 strcpy(SMS.RemoteNumber.number, argv[0]);
844 if (SMS.RemoteNumber.number[0] == '+') SMS.RemoteNumber.type = SMS_International;
845 else SMS.RemoteNumber.type = SMS_Unknown;
850 while ((i = getopt_long(argc, argv, "r8cC:v:", options, NULL)) != -1) {
851 switch (i) { // -8 is for 8-bit data, -c for compression. both are not yet implemented.
852 case '1': /* SMSC number */
853 SMS.MessageCenter.No = 0;
854 strcpy(SMS.MessageCenter.Number, optarg);
855 if (SMS.MessageCenter.Number[0] == '+') SMS.MessageCenter.Type = SMS_International;
856 else SMS.MessageCenter.Type = SMS_Unknown;
858 case '2': /* SMSC number index in phone memory */
859 SMS.MessageCenter.No = atoi(optarg);
861 if (SMS.MessageCenter.No < 1 || SMS.MessageCenter.No > 5)
863 data.MessageCenter = &SMS.MessageCenter;
864 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
866 case '3': /* we send long message */
867 input_len = atoi(optarg);
868 if (input_len > 255 * GSM_MAX_SMS_LENGTH) {
869 fprintf(stderr, _("Input too long!\n"));
873 case 'r': /* request for delivery report */
874 SMS.Type = SMS_Delivery_Report;
876 case 'C': /* class Message */
879 SMS.DCS.u.General.Class = 1;
882 SMS.DCS.u.General.Class = 2;
885 SMS.DCS.u.General.Class = 3;
888 SMS.DCS.u.General.Class = 4;
895 SMS.Validity.u.Relative = atoi(optarg);
898 usage(); /* Would be better to have an sendsms_usage() here. */
902 /* Get message text from stdin. */
903 chars_read = fread(message_buffer, 1, input_len, stdin);
905 if (chars_read == 0) {
906 fprintf(stderr, _("Couldn't read from stdin!\n"));
908 } else if (chars_read > input_len) {
909 fprintf(stderr, _("Input too long!\n"));
913 /* Null terminate. */
914 message_buffer[chars_read] = 0x00;
915 strncpy(SMS.MessageText, message_buffer, chars_read);
916 data.SMSMessage = &SMS;
918 /* Send the message. */
919 error = SM_Functions(GOP_SendSMS, &data, &State);
921 if (error == GE_SMSSENDOK) {
922 fprintf(stdout, _("Send succeeded!\n"));
924 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
927 if (GSM && GSM->Terminate) GSM->Terminate();
932 int savesms(int argc, char *argv[])
936 /* The maximum length of an uncompressed concatenated short message is
937 255 * 153 = 39015 default alphabet characters */
938 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
939 int input_len, chars_read;
945 SMS.Type = SMS_Deliver;
946 SMS.DCS.Type = SMS_GeneralDataCoding;
947 SMS.DCS.u.General.Compressed = false;
948 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
949 SMS.DCS.u.General.Class = 0;
950 SMS.MessageCenter.No = 1;
951 SMS.Validity.VPF = SMS_RelativeFormat;
952 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
954 SMS.Status = SMS_Unsent;
957 input_len = GSM_MAX_SMS_LENGTH;
960 while ((i = getopt(argc, argv, "ml:in:s:c:")) != -1) {
962 case 'm': /* mark the message as sent */
963 SMS.Status = SMS_Sent;
965 case 'l': /* Specify the location */
966 SMS.Number = atoi(optarg);
968 case 'i': /* Ask before overwriting */
971 case 'n': /* Specify the from number */
973 case 's': /* Specify the smsc number */
975 case 'c': /* Specify the smsc location */
986 aux.Number = SMS.Number;
987 data.SMSMessage = &aux;
988 error = SM_Functions(GOP_GetSMS, &data, &State);
991 fprintf(stderr, _("Message at specified location exists. "));
992 while (confirm < 0) {
993 fprintf(stderr, _("Overwrite? (yes/no) "));
994 GetLine(stdin, ans, 7);
995 if (!strcmp(ans, _("yes"))) confirm = 1;
996 else if (!strcmp(ans, _("no"))) confirm = 0;
998 if (!confirm) { GSM->Terminate(); return 0; }
1000 case GE_INVALIDSMSLOCATION:
1001 fprintf(stderr, _("Invalid location\n"));
1005 /* FIXME: Remove this fprintf when the function is thoroughly tested */
1007 fprintf(stderr, _("Location %d empty. Saving\n"), SMS.Number);
1012 chars_read = fread(message_buffer, 1, input_len, stdin);
1014 if (chars_read == 0) {
1016 fprintf(stderr, _("Couldn't read from stdin!\n"));
1019 } else if (chars_read > input_len) {
1021 fprintf(stderr, _("Input too long!\n"));
1026 strncpy (SMS.MessageText, message_buffer, chars_read);
1027 SMS.MessageText[chars_read] = 0;
1029 error = GSM->SaveSMSMessage(&SMS);
1031 if (error == GE_NONE) {
1032 fprintf(stdout, _("Saved!\n"));
1034 fprintf(stdout, _("Saving failed (error=%d)\n"), error);
1042 /* Get SMSC number */
1043 int getsmsc(char *MessageCenterNumber)
1045 SMS_MessageCenter MessageCenter;
1049 memset(&MessageCenter, 0, sizeof(MessageCenter));
1050 MessageCenter.No=atoi(MessageCenterNumber);
1052 if (GSM && GSM->GetSMSCenter && GSM->Terminate) {
1053 error = GSM->GetSMSCenter(&MessageCenter);
1056 GSM_DataClear(&data);
1057 data.MessageCenter = &MessageCenter;
1058 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
1063 fprintf(stdout, _("%d. SMS center (%s) number is %s\n"), MessageCenter.No, MessageCenter.Name, MessageCenter.Number);
1064 fprintf(stdout, _("Default recipient number is %s\n"), MessageCenter.Recipient);
1065 fprintf(stdout, _("Messages sent as "));
1067 switch (MessageCenter.Format) {
1069 fprintf(stdout, _("Text"));
1072 fprintf(stdout, _("VoiceMail"));
1075 fprintf(stdout, _("Fax"));
1079 fprintf(stdout, _("Email"));
1082 fprintf(stdout, _("ERMES"));
1085 fprintf(stdout, _("X.400"));
1088 fprintf(stdout, _("Unknown"));
1093 fprintf(stdout, _("Message validity is "));
1095 switch (MessageCenter.Validity) {
1097 fprintf(stdout, _("1 hour"));
1100 fprintf(stdout, _("6 hours"));
1103 fprintf(stdout, _("24 hours"));
1106 fprintf(stdout, _("72 hours"));
1109 fprintf(stdout, _("1 week"));
1112 fprintf(stdout, _("Maximum time"));
1115 fprintf(stdout, _("Unknown"));
1119 fprintf(stdout, "\n");
1122 case GE_NOTIMPLEMENTED:
1123 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1126 fprintf(stdout, _("SMS center can not be found :-(\n"));
1133 /* Get SMS messages. */
1134 int getsms(int argc, char *argv[])
1138 SMS_FolderList folderlist;
1139 GSM_SMSMessage message;
1140 char *memory_type_string;
1141 int start_message, end_message, count, mode = 1;
1148 /* Handle command line args that set type, start and end locations. */
1149 memory_type_string = argv[2];
1150 message.MemoryType = StrToMemoryType(memory_type_string);
1151 if (message.MemoryType == GMT_XX) {
1152 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[2]);
1156 memset(&filename, 0, 64);
1158 start_message = end_message = atoi(argv[3]);
1162 /* [end] can be only argv[4] */
1163 if (argv[4][0] != '-') {
1164 end_message = atoi(argv[4]);
1167 /* parse all options (beginning with '-' */
1168 while ((i = getopt(argc, argv, "f:F:d")) != -1) {
1177 dprintf("Saving into %s\n", optarg);
1178 strncpy(filename, optarg, 64);
1179 if (strlen(optarg) > 63) {
1180 fprintf(stderr, _("Filename too long - will be truncated to 63 characters.\n"));
1183 filename[strlen(optarg)] = 0;
1192 data.SMSFolderList = &folderlist;
1193 folder.FolderID = 0;
1194 data.SMSFolder = &folder;
1195 /* Now retrieve the requested entries. */
1196 for (count = start_message; count <= end_message; count ++) {
1199 message.Number = count;
1200 data.SMSMessage = &message;
1201 dprintf("MemoryType (gnokii.c) : %i\n", data.SMSMessage->MemoryType);
1202 error = SM_Functions(GOP_GetSMS, &data, &State);
1206 switch (message.Type) {
1208 fprintf(stdout, _("%d. MO Message "), message.Number);
1210 fprintf(stdout, _("(sent)\n"));
1211 fprintf(stdout, _("%d. MO Message "), message.Number);
1213 fprintf(stdout, _("(not sent)\n"));
1214 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1216 case SMS_Delivery_Report:
1217 fprintf(stdout, _("%d. Delivery Report "), message.Number);
1219 fprintf(stdout, _("(read)\n"));
1221 fprintf(stdout, _("(not read)\n"));
1222 fprintf(stdout, _("Sending date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1223 message.Time.Day, message.Time.Month, message.Time.Year, \
1224 message.Time.Hour, message.Time.Minute, message.Time.Second);
1225 if (message.Time.Timezone) {
1226 if (message.Time.Timezone > 0)
1227 fprintf(stdout,_("+%02d00"), message.Time.Timezone);
1229 fprintf(stdout,_("%02d00"), message.Time.Timezone);
1231 fprintf(stdout, "\n");
1232 fprintf(stdout, _("Response date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1233 message.SMSCTime.Day, message.SMSCTime.Month, message.SMSCTime.Year, \
1234 message.SMSCTime.Hour, message.SMSCTime.Minute, message.SMSCTime.Second);
1235 if (message.SMSCTime.Timezone) {
1236 if (message.SMSCTime.Timezone > 0)
1237 fprintf(stdout,_("+%02d00"),message.SMSCTime.Timezone);
1239 fprintf(stdout,_("%02d00"),message.SMSCTime.Timezone);
1241 fprintf(stdout, "\n");
1242 fprintf(stdout, _("Receiver: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1243 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1246 fprintf(stdout, _("%d. Inbox Message "), message.Number);
1248 fprintf(stdout, _("(read)\n"));
1250 fprintf(stdout, _("(not read)\n"));
1251 fprintf(stdout, _("Date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1252 message.Time.Day, message.Time.Month, message.Time.Year, \
1253 message.Time.Hour, message.Time.Minute, message.Time.Second);
1254 if (message.Time.Timezone) {
1255 if (message.Time.Timezone > 0)
1256 fprintf(stdout,_("+%02d00"),message.Time.Timezone);
1258 fprintf(stdout,_("%02d00"),message.Time.Timezone);
1260 fprintf(stdout, "\n");
1261 fprintf(stdout, _("Sender: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1262 switch (message.UDH[0].Type) {
1264 fprintf(stdout, _("GSM operator logo for %s (%s) network.\n"), bitmap.netcode, GSM_GetNetworkName(bitmap.netcode));
1265 if (!strcmp(message.RemoteNumber.number, "+998000005") && !strcmp(message.MessageCenter.Number, "+886935074443")) dprintf(_("Saved by Logo Express\n"));
1266 if (!strcmp(message.RemoteNumber.number, "+998000002") || !strcmp(message.RemoteNumber.number, "+998000003")) dprintf(_("Saved by Operator Logo Uploader by Thomas Kessler\n"));
1268 case SMS_CallerIDLogo:
1269 fprintf(stdout, ("Logo:\n"));
1270 /* put bitmap into bitmap structure */
1271 GSM_ReadSMSBitmap(message.UDH[0].Type, message.MessageText+2+offset, message.MessageText, &bitmap);
1272 GSM_PrintBitmap(&bitmap);
1275 if ((stat(filename, &buf) == 0)) {
1276 fprintf(stdout, _("File %s exists.\n"), filename);
1277 fprintf(stderr, _("Overwrite? (yes/no) "));
1278 GetLine(stdin, ans, 4);
1279 if (!strcmp(ans, _("yes"))) {
1280 error = GSM_SaveBitmapFile(filename, &bitmap);
1282 } else error = GSM_SaveBitmapFile(filename, &bitmap);
1283 if (error != GE_NONE) fprintf(stderr, _("Couldn't save logofile %s!\n"), filename);
1287 fprintf(stdout, _("Ringtone\n"));
1289 case SMS_ConcatenatedMessages:
1290 fprintf(stdout, _("Linked (%d/%d):\n"),
1291 message.UDH[0].u.ConcatenatedShortMessage.CurrentNumber,
1292 message.UDH[0].u.ConcatenatedShortMessage.MaximumNumber);
1294 fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText);
1295 if ((mode != -1) && *filename) {
1297 sprintf(buf, "%s%d", filename, count);
1298 mode = GSM_SaveTextFile(buf, message.MessageText, mode);
1301 case SMS_BusinessCard:
1302 fprintf(stdout, _("Business Card:\n%s"), message.MessageText);
1305 fprintf(stderr, _("Unknown\n"));
1311 data.SMSMessage = &message;
1312 if (GE_NONE != SM_Functions(GOP_DeleteSMS, &data, &State))
1313 fprintf(stdout, _("(delete failed)\n"));
1315 fprintf(stdout, _("(message deleted)\n"));
1318 case GE_NOTIMPLEMENTED:
1319 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1320 if (GSM && GSM->Terminate) GSM->Terminate();
1322 case GE_INVALIDSMSLOCATION:
1323 fprintf(stderr, _("Invalid location: %s %d\n"), memory_type_string, count);
1325 case GE_EMPTYSMSLOCATION:
1326 fprintf(stderr, _("SMS location %s %d empty.\n"), memory_type_string, count);
1329 fprintf(stdout, _("GetSMS %s %d failed!(%s)\n\n"), memory_type_string, count, print_error(error));
1334 if (GSM && GSM->Terminate) GSM->Terminate();
1339 /* Delete SMS messages. */
1340 int deletesms(int argc, char *argv[])
1342 GSM_SMSMessage message;
1343 char *memory_type_string;
1344 int start_message, end_message, count;
1347 /* Handle command line args that set type, start and end locations. */
1348 memory_type_string = argv[0];
1349 message.MemoryType = StrToMemoryType(memory_type_string);
1350 if (message.MemoryType == GMT_XX) {
1351 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
1355 start_message = end_message = atoi (argv[1]);
1356 if (argc > 2) end_message = atoi (argv[2]);
1358 /* Now delete the requested entries. */
1359 for (count = start_message; count <= end_message; count ++) {
1361 message.Number = count;
1362 data.SMSMessage = &message;
1363 error = SM_Functions(GOP_DeleteSMS, &data, &State);
1365 if (error == GE_NONE)
1366 fprintf(stdout, _("Deleted SMS %s %d\n"), memory_type_string, count);
1368 if (error == GE_NOTIMPLEMENTED) {
1369 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1373 fprintf(stdout, _("DeleteSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
1382 static volatile bool bshutdown = false;
1384 /* SIGINT signal handler. */
1385 static void interrupted(int sig)
1387 signal(sig, SIG_IGN);
1393 /* In this mode we get the code from the keyboard and send it to the mobile
1395 int entersecuritycode(char *type)
1398 GSM_SecurityCode SecurityCode;
1400 if (!strcmp(type,"PIN"))
1401 SecurityCode.Type=GSCT_Pin;
1402 else if (!strcmp(type,"PUK"))
1403 SecurityCode.Type=GSCT_Puk;
1404 else if (!strcmp(type,"PIN2"))
1405 SecurityCode.Type=GSCT_Pin2;
1406 else if (!strcmp(type,"PUK2"))
1407 SecurityCode.Type=GSCT_Puk2;
1408 // FIXME: Entering of SecurityCode does not work :-(
1409 // else if (!strcmp(type,"SecurityCode"))
1410 // SecurityCode.Type=GSCT_SecurityCode;
1415 printf("Enter your code: ");
1416 gets(SecurityCode.Code);
1418 strcpy(SecurityCode.Code,getpass(_("Enter your code: ")));
1421 test = GSM->EnterSecurityCode(SecurityCode);
1422 if (test == GE_INVALIDSECURITYCODE)
1423 fprintf(stdout, _("Error: invalid code.\n"));
1424 else if (test == GE_NONE)
1425 fprintf(stdout, _("Code ok.\n"));
1426 else if (test == GE_NOTIMPLEMENTED)
1427 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1429 fprintf(stdout, _("Other error.\n"));
1436 int getsecuritycodestatus(void)
1440 if (GSM->GetSecurityCodeStatus(&Status) == GE_NONE) {
1442 fprintf(stdout, _("Security code status: "));
1445 case GSCT_SecurityCode:
1446 fprintf(stdout, _("waiting for Security Code.\n"));
1449 fprintf(stdout, _("waiting for PIN.\n"));
1452 fprintf(stdout, _("waiting for PIN2.\n"));
1455 fprintf(stdout, _("waiting for PUK.\n"));
1458 fprintf(stdout, _("waiting for PUK2.\n"));
1461 fprintf(stdout, _("nothing to enter.\n"));
1464 fprintf(stdout, _("Unknown!\n"));
1477 /* Voice dialing mode. */
1478 int dialvoice(char *Number)
1480 GSM->DialVoice(Number);
1487 /* The following function allows to send logos using SMS */
1488 int sendlogo(int argc, char *argv[])
1494 char UserDataHeader[7] = { 0x06, /* UDH Length */
1495 0x05, /* IEI: application port addressing scheme, 16 bit address */
1496 0x04, /* IEI length */
1497 0x15, /* destination address: high byte */
1498 0x00, /* destination address: low byte */
1499 0x00, /* originator address */
1502 char Data[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1506 /* Default settings for SMS message:
1507 - no delivery report
1513 - set UserDataHeaderIndicator
1515 SMS.Type = SMS_Submit;
1516 SMS.DCS.Type = SMS_GeneralDataCoding;
1517 SMS.DCS.u.General.Compressed = false;
1518 SMS.DCS.u.General.Alphabet = SMS_8bit;
1519 SMS.DCS.u.General.Class = 2;
1520 SMS.MessageCenter.No = 1;
1521 SMS.Validity.VPF = SMS_RelativeFormat;
1522 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
1524 /* The first argument is the type of the logo. */
1525 if (!strcmp(argv[0], "op")) {
1526 SMS.UDH[0].Type = SMS_OpLogo;
1527 UserDataHeader[4] = 0x82; /* NBS port 0x1582 */
1528 fprintf(stdout, _("Sending operator logo.\n"));
1529 } else if (!strcmp(argv[0], "caller")) {
1530 SMS.UDH[0].Type = SMS_CallerIDLogo;
1531 UserDataHeader[4] = 0x83; /* NBS port 0x1583 */
1532 fprintf(stdout, _("Sending caller line identification logo.\n"));
1534 fprintf(stderr, _("You should specify what kind of logo to send!\n"));
1538 /* The second argument is the destination, ie the phone number of recipient. */
1539 SMS.MemoryType = atoi(argv[1]);
1541 /* The third argument is the bitmap file. */
1542 GSM_ReadBitmapFile(argv[2], &bitmap);
1544 /* If we are sending op logo we can rewrite network code. */
1545 if (!strcmp(argv[0], "op")) {
1547 * The fourth argument, if present, is the Network code of the operator.
1548 * Network code is in this format: "xxx yy".
1551 strcpy(bitmap.netcode, argv[3]);
1553 fprintf(stdout, _("Operator code: %s\n"), argv[3]);
1557 /* Set the network code */
1558 Data[current++] = ((bitmap.netcode[1] & 0x0f) << 4) | (bitmap.netcode[0] & 0xf);
1559 Data[current++] = 0xf0 | (bitmap.netcode[2] & 0x0f);
1560 Data[current++] = ((bitmap.netcode[5] & 0x0f) << 4) | (bitmap.netcode[4] & 0xf);
1563 /* Set the logo size */
1565 Data[current++] = bitmap.width;
1566 Data[current++] = bitmap.height;
1568 Data[current++] = 0x01;
1570 memcpy(SMS.MessageText, UserDataHeader, 7);
1571 memcpy(SMS.MessageText, Data, current);
1572 memcpy(SMS.MessageText+current, bitmap.bitmap, bitmap.size);
1574 /* Send the message. */
1575 error = GSM->SendSMSMessage(&SMS,current+bitmap.size);
1577 if (error == GE_SMSSENDOK)
1578 fprintf(stdout, _("Send succeeded!\n"));
1580 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
1586 /* Getting logos. */
1587 GSM_Error SaveBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1594 /* Ask before overwriting */
1595 while (stat(FileName, &buf) == 0) {
1598 fprintf(stderr, _("Saving logo. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "), FileName);
1599 GetLine(stdin, ans, 4);
1600 if (!strcmp(ans, "O") || !strcmp(ans, "o")) confirm = 1;
1601 if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm = 2;
1602 if (!strcmp(ans, "S") || !strcmp(ans, "s")) return GE_USERCANCELED;
1604 if (confirm == 1) break;
1606 fprintf(stderr, _("Enter name of new file: "));
1607 GetLine(stdin, FileName, 50);
1608 if (!FileName || (*FileName == 0)) return GE_USERCANCELED;
1612 error = GSM_SaveBitmapFile(FileName, bitmap);
1615 case GE_CANTOPENFILE:
1616 fprintf(stderr, _("Failed to write file \"%s\"\n"), FileName);
1625 int getlogo(int argc, char *argv[])
1629 GSM_Statemachine *sm = &State;
1631 bitmap.type=GSM_None;
1633 if (!strcmp(argv[0], "op"))
1634 bitmap.type = GSM_OperatorLogo;
1636 if (!strcmp(argv[0], "caller")) {
1637 /* There is caller group number missing in argument list. */
1639 bitmap.number=argv[2][0]-'0';
1640 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1644 bitmap.type = GSM_CallerLogo;
1647 if (!strcmp(argv[0],"startup"))
1648 bitmap.type = GSM_StartupLogo;
1649 else if (!strcmp(argv[0], "dealer"))
1650 bitmap.type = GSM_DealerNoteText;
1651 else if (!strcmp(argv[0], "text"))
1652 bitmap.type=GSM_WelcomeNoteText;
1654 if (bitmap.type != GSM_None) {
1656 fprintf(stdout, _("Getting Logo\n"));
1658 data.Bitmap=&bitmap;
1659 error=SM_Functions(GOP_GetBitmap, &data, sm);
1663 if (bitmap.type == GSM_DealerNoteText) fprintf(stdout, _("Dealer welcome note "));
1664 if (bitmap.type == GSM_WelcomeNoteText) fprintf(stdout, _("Welcome note "));
1665 if (bitmap.type == GSM_DealerNoteText || bitmap.type==GSM_WelcomeNoteText) {
1666 if (bitmap.text[0]) {
1667 fprintf(stdout, _("currently set to \"%s\"\n"), bitmap.text);
1669 fprintf(stdout, _("currently empty\n"));
1673 switch (bitmap.type) {
1674 case GSM_OperatorLogo:
1675 fprintf(stdout,"Operator logo for %s (%s) network got succesfully\n",bitmap.netcode,GSM_GetNetworkName(bitmap.netcode));
1677 strncpy(bitmap.netcode,argv[2], 7);
1678 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1679 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1684 case GSM_StartupLogo:
1685 fprintf(stdout, "Startup logo got successfully\n");
1687 strncpy(bitmap.netcode,argv[2], 7);
1688 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1689 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1694 case GSM_CallerLogo:
1695 fprintf(stdout,"Caller logo got successfully\n");
1697 strncpy(bitmap.netcode,argv[3],7);
1698 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1699 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1705 fprintf(stdout,"Unknown bitmap type.\n");
1709 if (SaveBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) return (-1);
1712 fprintf(stdout,"Your phone doesn't have logo uploaded !\n");
1717 case GE_NOTIMPLEMENTED:
1718 fprintf(stderr, _("Function not implemented !\n"));
1720 case GE_NOTSUPPORTED:
1721 fprintf(stderr, _("This kind of logo is not supported !\n"));
1724 fprintf(stderr, _("Error getting logo !\n"));
1728 fprintf(stderr, _("What kind of logo do you want to get ?\n"));
1736 /* Sending logos. */
1737 GSM_Error ReadBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1741 error = GSM_ReadBitmapFile(FileName, bitmap);
1744 case GE_CANTOPENFILE:
1745 fprintf(stderr, _("Failed to read file \"%s\"\n"), FileName);
1747 case GE_WRONGNUMBEROFCOLORS:
1748 fprintf(stderr, _("Wrong number of colors in \"%s\" logofile (accepted only 2-colors files) !\n"), FileName);
1750 case GE_WRONGCOLORS:
1751 fprintf(stderr, _("Wrong colors in \"%s\" logofile !\n"), FileName);
1753 case GE_INVALIDFILEFORMAT:
1754 fprintf(stderr, _("Invalid format of \"%s\" logofile !\n"), FileName);
1756 case GE_SUBFORMATNOTSUPPORTED:
1757 fprintf(stderr, _("Sorry, gnokii doesn't support used subformat in file \"%s\" !\n"), FileName);
1759 case GE_FILETOOSHORT:
1760 fprintf(stderr, _("\"%s\" logofile is too short !\n"), FileName);
1762 case GE_INVALIDIMAGESIZE:
1763 fprintf(stderr, _("Bitmap size doesn't supported by fileformat or different from 72x14, 84x48 and 72x28 !\n"));
1773 int setlogo(int argc, char *argv[])
1775 GSM_Bitmap bitmap,oldbit;
1776 GSM_NetworkInfo NetworkInfo;
1782 if (!strcmp(argv[0],"text") || !strcmp(argv[0],"dealer")) {
1783 if (!strcmp(argv[0], "text")) bitmap.type = GSM_WelcomeNoteText;
1784 else bitmap.type = GSM_DealerNoteText;
1785 bitmap.text[0] = 0x00;
1786 if (argc > 1) strncpy(bitmap.text, argv[1], 255);
1788 if (!strcmp(argv[0], "op") || !strcmp(argv[0], "startup") || !strcmp(argv[0], "caller")) {
1790 if (ReadBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) {
1795 if (!strcmp(argv[0], "op")) {
1796 if (bitmap.type != GSM_OperatorLogo || argc < 3) {
1797 if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode, NetworkInfo.NetworkCode, 7);
1799 GSM_ResizeBitmap(&bitmap, GSM_OperatorLogo, GSM_Info);
1801 strncpy(bitmap.netcode, argv[2], 7);
1802 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1803 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1808 if (!strcmp(argv[0], "startup")) {
1809 GSM_ResizeBitmap(&bitmap, GSM_StartupLogo, GSM_Info);
1811 if (!strcmp(argv[0],"caller")) {
1812 GSM_ResizeBitmap(&bitmap, GSM_CallerLogo, GSM_Info);
1814 bitmap.number = argv[2][0] - '0';
1815 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1819 oldbit.type = GSM_CallerLogo;
1820 oldbit.number = bitmap.number;
1821 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1822 /* We have to get the old name and ringtone!! */
1823 bitmap.ringtone = oldbit.ringtone;
1824 strncpy(bitmap.text, oldbit.text, 255);
1826 if (argc > 3) strncpy(bitmap.text, argv[3], 255);
1828 fprintf(stdout, _("Setting Logo.\n"));
1830 /* FIX ME: is it possible to permanently remove op logo ? */
1831 if (!strcmp(argv[0], "op"))
1833 bitmap.type = GSM_OperatorLogo;
1834 strncpy(bitmap.netcode, "000 00", 7);
1837 bitmap.size = bitmap.width * bitmap.height / 8;
1838 GSM_ClearBitmap(&bitmap);
1840 /* FIX ME: how to remove startup and group logos ? */
1841 fprintf(stdout, _("Removing Logo.\n"));
1844 fprintf(stderr, _("What kind of logo do you want to set ?\n"));
1850 error=GSM->SetBitmap(&bitmap);
1854 oldbit.type = bitmap.type;
1855 oldbit.number = bitmap.number;
1856 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1857 if (bitmap.type == GSM_WelcomeNoteText ||
1858 bitmap.type == GSM_DealerNoteText) {
1859 if (strcmp(bitmap.text, oldbit.text)) {
1860 fprintf(stderr, _("Error setting"));
1861 if (bitmap.type == GSM_DealerNoteText) fprintf(stderr, _(" dealer"));
1862 fprintf(stderr, _(" welcome note - "));
1864 /* I know, it looks horrible, but... */
1865 /* I set it to the short string - if it won't be set */
1866 /* it means, PIN is required. If it will be correct, previous */
1867 /* (user) text was too long */
1869 /* Without it, I could have such thing: */
1870 /* user set text to very short string (for example, "Marcin") */
1871 /* then enable phone without PIN and try to set it to the very long (too long for phone) */
1872 /* string (which start with "Marcin"). If we compare them as only length different, we could think, */
1873 /* that phone accepts strings 6 chars length only (length of "Marcin") */
1874 /* When we make it correct, we don't have this mistake */
1876 strcpy(oldbit.text, "!\0");
1877 GSM->SetBitmap(&oldbit);
1878 GSM->GetBitmap(&oldbit);
1879 if (oldbit.text[0]!='!') {
1880 fprintf(stderr, _("SIM card and PIN is required\n"));
1882 GSM->SetBitmap(&bitmap);
1883 GSM->GetBitmap(&oldbit);
1884 fprintf(stderr, _("too long, truncated to \"%s\" (length %i)\n"),oldbit.text,strlen(oldbit.text));
1889 if (bitmap.type == GSM_StartupLogo) {
1890 for (i = 0; i < oldbit.size; i++) {
1891 if (oldbit.bitmap[i] != bitmap.bitmap[i]) {
1892 fprintf(stderr, _("Error setting startup logo - SIM card and PIN is required\n"));
1900 if (ok) fprintf(stdout, _("Done.\n"));
1902 case GE_NOTIMPLEMENTED:
1903 fprintf(stderr, _("Function not implemented.\n"));
1905 case GE_NOTSUPPORTED:
1906 fprintf(stderr, _("This kind of logo is not supported.\n"));
1909 fprintf(stderr, _("Error !\n"));
1919 int viewlogo(char *filename)
1923 error = GSM_ShowBitmapFile(filename);
1927 /* Calendar notes receiving. */
1928 int getcalendarnote(int argc, char *argv[])
1930 GSM_CalendarNote CalendarNote;
1932 GSM_Error error = GE_NONE;
1933 int i, first_location, last_location;
1936 struct option options[] = {
1937 { "vCard", optional_argument, NULL, '1'},
1944 first_location = last_location = atoi(argv[0]);
1945 if ((argc > 1) && (argv[1][0] != '-')) {
1946 last_location = atoi(argv[1]);
1949 while ((i = getopt_long(argc, argv, "v", options, NULL)) != -1) {
1955 usage(); /* Would be better to have an calendar_usage() here. */
1961 for (i = first_location; i <= last_location; i++) {
1962 CalendarNote.Location = i;
1963 if (GSM && GSM->GetCalendarNote && GSM->Terminate) {
1964 error = GSM->GetCalendarNote(&CalendarNote);
1967 GSM_DataClear(&data);
1968 data.CalendarNote = &CalendarNote;
1970 error = SM_Functions(GOP_GetCalendarNote, &data, &State);
1975 fprintf(stdout, "BEGIN:VCALENDAR\n");
1976 fprintf(stdout, "VERSION:1.0\n");
1977 fprintf(stdout, "BEGIN:VEVENT\n");
1978 fprintf(stdout, "CATEGORIES:");
1979 switch (CalendarNote.Type) {
1981 fprintf(stdout, "MISCELLANEOUS\n");
1984 fprintf(stdout, "PHONE CALL\n");
1987 fprintf(stdout, "MEETING\n");
1990 fprintf(stdout, "SPECIAL OCCASION\n");
1993 fprintf(stdout, "UNKNOWN\n");
1996 fprintf(stdout, "SUMMARY:%s\n",CalendarNote.Text);
1997 fprintf(stdout, "DTSTART:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Time.Year,
1998 CalendarNote.Time.Month, CalendarNote.Time.Day, CalendarNote.Time.Hour,
1999 CalendarNote.Time.Minute, CalendarNote.Time.Second);
2000 if (CalendarNote.Alarm.Year!=0) {
2001 fprintf(stdout, "DALARM:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Alarm.Year,
2002 CalendarNote.Alarm.Month, CalendarNote.Alarm.Day, CalendarNote.Alarm.Hour,
2003 CalendarNote.Alarm.Minute, CalendarNote.Alarm.Second);
2005 fprintf(stdout, "END:VEVENT\n");
2006 fprintf(stdout, "END:VCALENDAR\n");
2008 } else { /* not vCal */
2009 fprintf(stdout, _(" Type of the note: "));
2011 switch (CalendarNote.Type) {
2013 fprintf(stdout, _("Reminder\n"));
2016 fprintf(stdout, _("Call\n"));
2019 fprintf(stdout, _("Meeting\n"));
2022 fprintf(stdout, _("Birthday\n"));
2025 fprintf(stdout, _("Unknown\n"));
2029 fprintf(stdout, _(" Date: %d-%02d-%02d\n"), CalendarNote.Time.Year,
2030 CalendarNote.Time.Month,
2031 CalendarNote.Time.Day);
2033 fprintf(stdout, _(" Time: %02d:%02d:%02d\n"), CalendarNote.Time.Hour,
2034 CalendarNote.Time.Minute,
2035 CalendarNote.Time.Second);
2037 if (CalendarNote.Alarm.AlarmEnabled == 1) {
2038 fprintf(stdout, _(" Alarm date: %d-%02d-%02d\n"), CalendarNote.Alarm.Year,
2039 CalendarNote.Alarm.Month,
2040 CalendarNote.Alarm.Day);
2042 fprintf(stdout, _(" Alarm time: %02d:%02d:%02d\n"), CalendarNote.Alarm.Hour,
2043 CalendarNote.Alarm.Minute,
2044 CalendarNote.Alarm.Second);
2047 fprintf(stdout, _(" Text: %s\n"), CalendarNote.Text);
2049 if (CalendarNote.Type == GCN_CALL)
2050 fprintf(stdout, _(" Phone: %s\n"), CalendarNote.Phone);
2053 case GE_NOTIMPLEMENTED:
2054 fprintf(stderr, _("Function not implemented.\n"));
2057 fprintf(stderr, _("The calendar note can not be read\n"));
2066 /* Writing calendar notes. */
2067 int writecalendarnote(char *argv[])
2069 GSM_CalendarNote CalendarNote;
2071 if (GSM_ReadVCalendarFile(argv[0], &CalendarNote, atoi(argv[1]))) {
2072 fprintf(stdout, _("Failed to load vCalendar file.\n"));
2076 /* Error 22=Calendar full ;-) */
2077 if ((GSM->WriteCalendarNote(&CalendarNote)) == GE_NONE)
2078 fprintf(stdout, _("Succesfully written!\n"));
2080 fprintf(stdout, _("Failed to write calendar note!\n"));
2087 /* Calendar note deleting. */
2088 int deletecalendarnote(int argc, char *argv[])
2090 GSM_CalendarNote CalendarNote;
2091 int i, first_location, last_location;
2093 first_location = last_location = atoi(argv[0]);
2094 if (argc > 1) last_location = atoi(argv[1]);
2096 for (i = first_location; i <= last_location; i++) {
2098 CalendarNote.Location = i;
2100 if (GSM->DeleteCalendarNote(&CalendarNote) == GE_NONE) {
2101 fprintf(stdout, _(" Calendar note deleted.\n"));
2103 fprintf(stderr, _("The calendar note can not be deleted\n"));
2113 /* Setting the date and time. */
2114 int setdatetime(int argc, char *argv[])
2121 now = localtime(&nowh);
2123 Date.Year = now->tm_year;
2124 Date.Month = now->tm_mon+1;
2125 Date.Day = now->tm_mday;
2126 Date.Hour = now->tm_hour;
2127 Date.Minute = now->tm_min;
2128 Date.Second = now->tm_sec;
2130 if (argc > 0) Date.Year = atoi (argv[0]);
2131 if (argc > 1) Date.Month = atoi (argv[1]);
2132 if (argc > 2) Date.Day = atoi (argv[2]);
2133 if (argc > 3) Date.Hour = atoi (argv[3]);
2134 if (argc > 4) Date.Minute = atoi (argv[4]);
2136 if (Date.Year < 1900) {
2138 /* Well, this thing is copyrighted in U.S. This technique is known as
2139 Windowing and you can read something about it in LinuxWeekly News:
2140 http://lwn.net/1999/features/Windowing.phtml. This thing is beeing
2141 written in Czech republic and Poland where algorithms are not allowed
2145 Date.Year = Date.Year + 1900;
2147 Date.Year = Date.Year + 2000;
2150 /* FIXME: Error checking should be here. */
2151 GSM->SetDateTime(&Date);
2158 /* In this mode we receive the date and time from mobile phone. */
2159 int getdatetime(void) {
2161 GSM_DateTime date_time;
2164 if (GSM && GSM->GetDateTime && GSM->Terminate) {
2165 error = GSM->GetDateTime(&date_time);
2168 GSM_DataClear(&data);
2169 data.DateTime = &date_time;
2171 error = SM_Functions(GOP_GetDateTime, &data, &State);
2176 fprintf(stdout, _("Date: %4d/%02d/%02d\n"), date_time.Year, date_time.Month, date_time.Day);
2177 fprintf(stdout, _("Time: %02d:%02d:%02d\n"), date_time.Hour, date_time.Minute, date_time.Second);
2179 case GE_NOTIMPLEMENTED:
2180 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2183 fprintf(stdout, _("Internal error\n"));
2190 /* Setting the alarm. */
2191 int setalarm(char *argv[])
2195 Date.Hour = atoi(argv[0]);
2196 Date.Minute = atoi(argv[1]);
2198 GSM->SetAlarm(1, &Date);
2205 /* Getting the alarm. */
2210 GSM_DateTime date_time;
2212 if (GSM && GSM->GetAlarm && GSM->Terminate) {
2213 error = GSM->GetAlarm(0, &date_time);
2216 GSM_DataClear(&data);
2217 data.DateTime = &date_time;
2219 error = SM_Functions(GOP_GetAlarm, &data, &State);
2224 fprintf(stdout, _("Alarm: %s\n"), (date_time.AlarmEnabled==0)?"off":"on");
2225 fprintf(stdout, _("Time: %02d:%02d\n"), date_time.Hour, date_time.Minute);
2227 case GE_NOTIMPLEMENTED:
2228 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2231 fprintf(stdout, _("Internal error\n"));
2238 /* In monitor mode we don't do much, we just initialise the fbus code.
2239 Note that the fbus code no longer has an internal monitor mode switch,
2240 instead compile with DEBUG enabled to get all the gumpf. */
2241 int monitormode(void)
2243 float rflevel = -1, batterylevel = -1;
2244 // GSM_PowerSource powersource = -1;
2245 GSM_RFUnits rf_units = GRF_Arbitrary;
2246 GSM_BatteryUnits batt_units = GBU_Arbitrary;
2247 GSM_Statemachine *sm = &State;
2250 // GSM_NetworkInfo NetworkInfo;
2251 // GSM_CBMessage CBMessage;
2253 GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0};
2254 GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0};
2255 GSM_MemoryStatus DC_MemoryStatus = {GMT_DC, 0, 0};
2256 GSM_MemoryStatus EN_MemoryStatus = {GMT_EN, 0, 0};
2257 GSM_MemoryStatus FD_MemoryStatus = {GMT_FD, 0, 0};
2258 GSM_MemoryStatus LD_MemoryStatus = {GMT_LD, 0, 0};
2259 GSM_MemoryStatus MC_MemoryStatus = {GMT_MC, 0, 0};
2260 GSM_MemoryStatus ON_MemoryStatus = {GMT_ON, 0, 0};
2261 GSM_MemoryStatus RC_MemoryStatus = {GMT_RC, 0, 0};
2263 // GSM_SMSStatus SMSStatus = {0, 0};
2267 GSM_DataClear(&data);
2269 /* We do not want to monitor serial line forever - press Ctrl+C to stop the
2271 signal(SIGINT, interrupted);
2273 fprintf (stderr, _("Entering monitor mode...\n"));
2276 //GSM->EnableCellBroadcast();
2278 /* Loop here indefinitely - allows you to see messages from GSM code in
2279 response to unknown messages etc. The loops ends after pressing the
2281 data.RFUnits=&rf_units;
2282 data.RFLevel=&rflevel;
2283 data.BatteryUnits=&batt_units;
2284 data.BatteryLevel=&batterylevel;
2286 while (!bshutdown) {
2287 if (SM_Functions(GOP_GetRFLevel,&data,sm) == GE_NONE)
2288 fprintf(stdout, _("RFLevel: %d\n"), (int)rflevel);
2290 if (SM_Functions(GOP_GetBatteryLevel,&data,sm) == GE_NONE)
2291 fprintf(stdout, _("Battery: %d\n"), (int)batterylevel);
2293 // if (GSM->GetPowerSource(&powersource) == GE_NONE)
2294 // fprintf(stdout, _("Power Source: %s\n"), (powersource==GPS_ACDC)?_("AC/DC"):_("battery"));
2296 data.MemoryStatus=&SIMMemoryStatus;
2297 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2298 fprintf(stdout, _("SIM: Used %d, Free %d\n"), SIMMemoryStatus.Used, SIMMemoryStatus.Free);
2300 data.MemoryStatus=&PhoneMemoryStatus;
2301 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2302 fprintf(stdout, _("Phone: Used %d, Free %d\n"), PhoneMemoryStatus.Used, PhoneMemoryStatus.Free);
2304 data.MemoryStatus=&DC_MemoryStatus;
2305 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2306 fprintf(stdout, _("DC: Used %d, Free %d\n"), DC_MemoryStatus.Used, DC_MemoryStatus.Free);
2308 data.MemoryStatus=&EN_MemoryStatus;
2309 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2310 fprintf(stdout, _("EN: Used %d, Free %d\n"), EN_MemoryStatus.Used, EN_MemoryStatus.Free);
2312 data.MemoryStatus=&FD_MemoryStatus;
2313 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2314 fprintf(stdout, _("FD: Used %d, Free %d\n"), FD_MemoryStatus.Used, FD_MemoryStatus.Free);
2316 data.MemoryStatus=&LD_MemoryStatus;
2317 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2318 fprintf(stdout, _("LD: Used %d, Free %d\n"), LD_MemoryStatus.Used, LD_MemoryStatus.Free);
2320 data.MemoryStatus=&MC_MemoryStatus;
2321 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2322 fprintf(stdout, _("MC: Used %d, Free %d\n"), MC_MemoryStatus.Used, MC_MemoryStatus.Free);
2324 data.MemoryStatus=&ON_MemoryStatus;
2325 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2326 fprintf(stdout, _("ON: Used %d, Free %d\n"), ON_MemoryStatus.Used, ON_MemoryStatus.Free);
2328 data.MemoryStatus=&RC_MemoryStatus;
2329 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2330 fprintf(stdout, _("RC: Used %d, Free %d\n"), RC_MemoryStatus.Used, RC_MemoryStatus.Free);
2332 // if (GSM->GetSMSStatus(&SMSStatus) == GE_NONE)
2333 // fprintf(stdout, _("SMS Messages: UnRead %d, Number %d\n"), SMSStatus.UnRead, SMSStatus.Number);
2335 // if (GSM->GetIncomingCallNr(Number) == GE_NONE)
2336 // fprintf(stdout, _("Incoming call: %s\n"), Number);
2338 // if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE)
2339 // fprintf(stdout, _("Network: %s (%s), LAC: %s, CellID: %s\n"), GSM_GetNetworkName (NetworkInfo.NetworkCode), GSM_GetCountryName(NetworkInfo.NetworkCode), NetworkInfo.LAC, NetworkInfo.CellID);
2341 // if (GSM->ReadCellBroadcast(&CBMessage) == GE_NONE)
2342 // fprintf(stdout, _("Cell broadcast received on channel %d: %s\n"), CBMessage.Channel, CBMessage.Message);
2347 fprintf (stderr, _("Leaving monitor mode...\n"));
2357 static GSM_Error PrettyOutputFn(char *Display, char *Indicators)
2360 printf(ESC "[10;0H Display is:\n%s\n", Display);
2362 printf(ESC "[9;0H Indicators: %s \n", Indicators);
2363 printf(ESC "[1;1H");
2368 // Uncomment it if used
2369 static GSM_Error OutputFn(char *Display, char *Indicators)
2372 printf("New display is:\n%s\n", Display);
2374 printf("Indicators: %s\n", Indicators);
2379 void console_raw(void)
2384 tcgetattr(fileno(stdin), &it);
2385 it.c_lflag &= ~(ICANON);
2386 //it.c_iflag &= ~(INPCK|ISTRIP|IXON);
2390 tcsetattr(fileno(stdin), TCSANOW, &it);
2394 int displayoutput(void)
2397 GSM_Statemachine *sm = &State;
2400 data.OutputFn = PrettyOutputFn;
2402 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2404 fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
2406 if (error == GE_NONE) {
2408 /* We do not want to see texts forever - press Ctrl+C to stop. */
2409 signal(SIGINT, interrupted);
2411 fprintf (stderr, _("Entered display monitoring mode...\n"));
2412 fprintf (stderr, ESC "c" );
2414 /* Loop here indefinitely - allows you to read texts from phone's
2415 display. The loops ends after pressing the Ctrl+C. */
2416 while (!bshutdown) {
2418 memset(&buf[0], 0, 102);
2419 while (read(0, buf, 100) > 0) {
2420 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
2421 if (GSM->HandleString(buf) != GE_NONE)
2422 fprintf(stdout, _("Key press simulation failed.\n"));
2423 memset(buf, 0, 102);
2427 fprintf (stderr, "Shutting down\n");
2429 fprintf (stderr, _("Leaving display monitor mode...\n"));
2430 data.OutputFn = NULL;
2432 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2433 if (error != GE_NONE)
2434 fprintf (stderr, _("Error!\n"));
2436 fprintf (stderr, _("Error!\n"));
2442 /* Reads profile from phone and displays its' settings */
2443 int getprofile(int argc, char *argv[])
2447 GSM_Profile profile;
2450 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2454 error = GSM->GetProfile(&profile);
2456 if (error == GE_NONE) {
2458 while (GSM->GetModel(model) != GE_NONE)
2461 max_profiles = 7; /* This is correct for 6110 (at least my). How do we get
2462 the number of profiles? */
2465 /*FIX ME: It should be set to 3 for N5130 and 3210 too*/
2466 if (!strcmp(model, "NSE-1"))
2470 profile.Number = atoi(argv[0]) - 1;
2471 start = profile.Number;
2474 if (profile.Number < 0) {
2475 fprintf(stderr, _("Profile number must be value from 1 to %d!\n"), max_profiles);
2480 if (profile.Number >= max_profiles) {
2481 fprintf(stderr, _("This phone supports only %d profiles!\n"), max_profiles);
2487 stop = max_profiles;
2494 if (profile.Number != 0)
2495 GSM->GetProfile(&profile);
2497 fprintf(stdout, "%d. \"%s\"\n", profile.Number + 1, profile.Name);
2498 if (profile.DefaultName == -1) fprintf(stdout, _(" (name defined)\n"));
2500 fprintf(stdout, _("Incoming call alert: %s\n"), GetProfileCallAlertString(profile.CallAlert));
2502 /* For different phones different ringtones names */
2504 if (!strcmp(model, "NSE-3"))
2505 fprintf(stdout, _("Ringing tone: %s (%d)\n"), RingingTones[profile.Ringtone], profile.Ringtone);
2507 fprintf(stdout, _("Ringtone number: %d\n"), profile.Ringtone);
2509 fprintf(stdout, _("Ringing volume: %s\n"), GetProfileVolumeString(profile.Volume));
2511 fprintf(stdout, _("Message alert tone: %s\n"), GetProfileMessageToneString(profile.MessageTone));
2513 fprintf(stdout, _("Keypad tones: %s\n"), GetProfileKeypadToneString(profile.KeypadTone));
2515 fprintf(stdout, _("Warning and game tones: %s\n"), GetProfileWarningToneString(profile.WarningTone));
2517 /* FIXME: Light settings is only used for Car */
2518 if (profile.Number == (max_profiles - 2)) fprintf(stdout, _("Lights: %s\n"), profile.Lights ? _("On") : _("Automatic"));
2520 fprintf(stdout, _("Vibration: %s\n"), GetProfileVibrationString(profile.Vibration));
2522 /* FIXME: it will be nice to add here reading caller group name. */
2523 if (max_profiles != 3) fprintf(stdout, _("Caller groups: 0x%02x\n"), profile.CallerGroups);
2525 /* FIXME: Automatic answer is only used for Car and Headset. */
2526 if (profile.Number >= (max_profiles - 2)) fprintf(stdout, _("Automatic answer: %s\n"), profile.AutomaticAnswer ? _("On") : _("Off"));
2528 fprintf(stdout, "\n");
2533 if (error == GE_NOTIMPLEMENTED) {
2534 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2538 fprintf(stderr, _("Unspecified error\n"));
2548 /* Get requested range of memory storage entries and output to stdout in
2549 easy-to-parse format */
2550 int getmemory(int argc, char *argv[])
2552 GSM_PhonebookEntry entry;
2555 char *memory_type_string;
2558 GSM_Statemachine *sm = &State;
2560 /* Handle command line args that set type, start and end locations. */
2561 memory_type_string = argv[0];
2562 entry.MemoryType = StrToMemoryType(memory_type_string);
2563 if (entry.MemoryType == GMT_XX) {
2564 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
2568 start_entry = atoi (argv[1]);
2569 if (argc > 2) end_entry = atoi (argv[2]);
2570 else end_entry = start_entry;
2572 /* Now retrieve the requested entries. */
2573 for (count = start_entry; count <= end_entry; count ++) {
2575 entry.Location = count;
2577 data.PhonebookEntry=&entry;
2578 error=SM_Functions(GOP_ReadPhonebook,&data,sm);
2580 if (error == GE_NONE) {
2581 fprintf(stdout, "%s;%s;%s;%d;%d\n", entry.Name, entry.Number, memory_type_string, entry.Location, entry.Group);
2582 if (entry.MemoryType == GMT_MC || entry.MemoryType == GMT_DC || entry.MemoryType == GMT_RC)
2583 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);
2586 if (error == GE_NOTIMPLEMENTED) {
2587 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2590 else if (error == GE_INVALIDMEMORYTYPE) {
2591 fprintf(stderr, _("Memory type %s not supported!\n"), memory_type_string);
2595 fprintf(stdout, _("%s|%d|Bad location or other error!(%d)\n"), memory_type_string, count, error);
2601 /* Read data from stdin, parse and write to phone. The parsing is relatively
2602 crude and doesn't allow for much variation from the stipulated format. */
2603 /* FIXME: I guess there's *very* similar code in xgnokii */
2604 int writephonebook(int argc, char *args[])
2606 GSM_PhonebookEntry entry;
2608 char *memory_type_string;
2612 char *Line, OLine[100], BackLine[100];
2615 /* Check argument */
2616 if (argc && (strcmp("-i", args[0])))
2621 /* Go through data from stdin. */
2622 while (GetLine(stdin, Line, 99)) {
2623 strcpy(BackLine, Line);
2626 ptr = strtok(Line, ";");
2627 if (ptr) strcpy(entry.Name, ptr);
2628 else entry.Name[0] = 0;
2630 ptr = strtok(NULL, ";");
2631 if (ptr) strcpy(entry.Number, ptr);
2632 else entry.Number[0] = 0;
2634 ptr = strtok(NULL, ";");
2637 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2642 if (!strncmp(ptr,"ME", 2)) {
2643 memory_type_string = "int";
2644 entry.MemoryType = GMT_ME;
2646 if (!strncmp(ptr,"SM", 2)) {
2647 memory_type_string = "sim";
2648 entry.MemoryType = GMT_SM;
2650 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2655 ptr = strtok(NULL, ";");
2656 if (ptr) entry.Location = atoi(ptr);
2657 else entry.Location = 0;
2659 ptr = strtok(NULL, ";");
2660 if (ptr) entry.Group = atoi(ptr);
2661 else entry.Group = 0;
2664 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2668 for (subentry = 0; ; subentry++) {
2669 ptr = strtok(NULL, ";");
2671 if (ptr && *ptr != 0)
2672 entry.SubEntries[subentry].EntryType = atoi(ptr);
2676 ptr = strtok(NULL, ";");
2678 entry.SubEntries[subentry].NumberType=atoi(ptr);
2680 /* Phone Numbers need to have a number type. */
2681 if (!ptr && entry.SubEntries[subentry].EntryType == GSM_Number) {
2682 fprintf(stderr, _("Missing phone number type on line %d"
2683 " entry %d [%s]\n"), line_count, subentry, BackLine);
2688 ptr = strtok(NULL, ";");
2690 entry.SubEntries[subentry].BlockNumber=atoi(ptr);
2692 ptr = strtok(NULL, ";");
2694 /* 0x13 Date Type; it is only for Dailed Numbers, etc.
2695 we don't store to this memories so it's an error to use it. */
2696 if (!ptr || entry.SubEntries[subentry].EntryType == GSM_Date) {
2697 fprintf(stdout, _("There is no phone number on line %d entry %d [%s]\n"),
2698 line_count, subentry, BackLine);
2702 strcpy(entry.SubEntries[subentry].data.Number, ptr);
2705 entry.SubEntriesCount = subentry;
2707 /* This is to send other exports (like from 6110) to 7110 */
2708 if (!entry.SubEntriesCount) {
2709 entry.SubEntriesCount = 1;
2710 entry.SubEntries[subentry].EntryType = GSM_Number;
2711 entry.SubEntries[subentry].NumberType = GSM_General;
2712 entry.SubEntries[subentry].BlockNumber = 2;
2713 strcpy(entry.SubEntries[subentry].data.Number, entry.Number);
2719 GSM_PhonebookEntry aux;
2721 aux.Location = entry.Location;
2722 error = GSM->GetMemoryLocation(&aux);
2724 if (error == GE_NONE) {
2729 fprintf(stdout, _("Location busy. "));
2730 while (confirm < 0) {
2731 fprintf(stdout, _("Overwrite? (yes/no) "));
2732 GetLine(stdin, ans, 7);
2733 if (!strcmp(ans, _("yes"))) confirm = 1;
2734 else if (!strcmp(ans, _("no"))) confirm = 0;
2736 if (!confirm) continue;
2739 fprintf(stderr, _("Unknown error (%d)\n"), error);
2745 /* Do write and report success/failure. */
2746 error = GSM->WritePhonebookLocation(&entry);
2748 if (error == GE_NONE)
2749 fprintf (stdout, _("Write Succeeded: memory type: %s, loc: %d, name: %s, number: %s\n"), memory_type_string, entry.Location, entry.Name, entry.Number);
2751 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);
2759 /* Getting speed dials. */
2760 int getspeeddial(char *Number)
2762 GSM_SpeedDial SpeedDial;
2766 SpeedDial.Number = atoi(Number);
2768 if (GSM && GSM->GetSpeedDial && GSM->Terminate) {
2769 error = GSM->GetSpeedDial(&SpeedDial);
2772 GSM_DataClear(&data);
2773 data.SpeedDial = &SpeedDial;
2775 error = SM_Functions(GOP_GetSpeedDial, &data, &State);
2780 fprintf(stdout, _("SpeedDial nr. %d: %d:%d\n"), SpeedDial.Number, SpeedDial.MemoryType, SpeedDial.Location);
2782 case GE_NOTIMPLEMENTED:
2783 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2786 fprintf(stdout, _("Internal error\n"));
2793 /* Setting speed dials. */
2794 int setspeeddial(char *argv[])
2796 GSM_SpeedDial entry;
2798 char *memory_type_string;
2800 /* Handle command line args that set type, start and end locations. */
2802 if (strcmp(argv[1], "ME") == 0) {
2803 entry.MemoryType = 0x02;
2804 memory_type_string = "ME";
2805 } else if (strcmp(argv[1], "SM") == 0) {
2806 entry.MemoryType = 0x03;
2807 memory_type_string = "SM";
2809 fprintf(stderr, _("Unknown memory type %s!\n"), argv[1]);
2813 entry.Number = atoi(argv[0]);
2814 entry.Location = atoi(argv[2]);
2816 if (GSM->SetSpeedDial(&entry) == GE_NONE) {
2817 fprintf(stdout, _("Succesfully written!\n"));
2824 /* Getting the status of the display. */
2825 int getdisplaystatus(void)
2829 GSM->GetDisplayStatus(&Status);
2831 fprintf(stdout, _("Call in progress: %s\n"), Status & (1<<DS_Call_In_Progress)?_("on"):_("off"));
2832 fprintf(stdout, _("Unknown: %s\n"), Status & (1<<DS_Unknown)?_("on"):_("off"));
2833 fprintf(stdout, _("Unread SMS: %s\n"), Status & (1<<DS_Unread_SMS)?_("on"):_("off"));
2834 fprintf(stdout, _("Voice call: %s\n"), Status & (1<<DS_Voice_Call)?_("on"):_("off"));
2835 fprintf(stdout, _("Fax call active: %s\n"), Status & (1<<DS_Fax_Call)?_("on"):_("off"));
2836 fprintf(stdout, _("Data call active: %s\n"), Status & (1<<DS_Data_Call)?_("on"):_("off"));
2837 fprintf(stdout, _("Keyboard lock: %s\n"), Status & (1<<DS_Keyboard_Lock)?_("on"):_("off"));
2838 fprintf(stdout, _("SMS storage full: %s\n"), Status & (1<<DS_SMS_Storage_Full)?_("on"):_("off"));
2844 int netmonitor(char *Mode)
2846 unsigned char mode = atoi(Mode);
2849 if (!strcmp(Mode, "reset"))
2851 else if (!strcmp(Mode, "off"))
2853 else if (!strcmp(Mode, "field"))
2855 else if (!strcmp(Mode, "devel"))
2857 else if (!strcmp(Mode, "next"))
2860 memset(&Screen, 0, 50);
2861 GSM->NetMonitor(mode, Screen);
2864 fprintf(stdout, "%s\n", Screen);
2872 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2873 char imei[64], model[64], rev[64], manufacturer[64];
2874 GSM_Statemachine *sm = &State;
2876 data.Manufacturer=manufacturer;
2881 /* Retrying is bad idea: what if function is simply not implemented?
2882 Anyway let's wait 2 seconds for the right packet from the phone. */
2885 strcpy(imei, "(unknown)");
2886 strcpy(manufacturer, "(unknown)");
2887 strcpy(model, "(unknown)");
2888 strcpy(rev, "(unknown)");
2890 SM_Functions(GOP_Identify, &data, sm);
2892 fprintf(stdout, _("IMEI: %s\n"), imei);
2893 fprintf(stdout, _("Manufacturer: %s\n"), manufacturer);
2894 fprintf(stdout, _("Model: %s\n"), model);
2895 fprintf(stdout, _("Revision: %s\n"), rev);
2902 int senddtmf(char *String)
2904 GSM->SendDTMF(String);
2909 /* Resets the phone */
2910 int reset( char *type)
2912 unsigned char _type = 0x03;
2915 if(!strcmp(type, "soft"))
2918 if(!strcmp(type, "hard"))
2921 fprintf(stderr, _("What kind of reset do you want??\n"));
2932 /* pmon allows fbus code to run in a passive state - it doesn't worry about
2933 whether comms are established with the phone. A debugging/development
2939 GSM_ConnectionType connection=GCT_Serial;
2940 GSM_Statemachine sm;
2942 /* Initialise the code for the GSM interface. */
2943 error = GSM_Initialise(model, Port, Initlength, connection, NULL, &sm);
2945 if (error != GE_NONE) {
2946 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
2957 int sendringtone(int argc, char *argv[])
2959 GSM_Ringtone ringtone;
2962 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2963 fprintf(stdout, _("Failed to load ringtone.\n"));
2967 error = GSM->SendRingtone(&ringtone,argv[1]);
2969 if (error == GE_NONE)
2970 fprintf(stdout, _("Send succeeded!\n"));
2972 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
2980 int setringtone(int argc, char *argv[])
2982 GSM_Ringtone ringtone;
2985 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2986 fprintf(stdout, _("Failed to load ringtone.\n"));
2990 error = GSM->SetRingtone(&ringtone);
2992 if (error == GE_NONE)
2993 fprintf(stdout, _("Send succeeded!\n"));
2995 fprintf(stdout, _("Send failed\n"));
3002 int presskeysequence(void)
3008 memset(&buf[0], 0, 102);
3009 while (read(0, buf, 100) > 0) {
3010 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
3011 if (GSM->HandleString(buf) != GE_NONE)
3012 fprintf(stdout, _("Key press simulation failed.\n"));
3013 memset(buf, 0, 102);
3020 /* This is a "convenience" function to allow quick test of new API stuff which
3021 doesn't warrant a "proper" command line function. */
3023 int foogle(char *argv[])
3025 /* Initialise the code for the GSM interface. */
3027 // Fill in what you would like to test here...