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.2.1 2001/11/27 22:48:37 short
23 Update: orig2001_11_27_05_17 -> orig2001_11_27_22_58
25 Revision 1.1.1.2 2001/11/27 22:01:25 short
26 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Nov 27 22:58 CET 2001
28 Revision 1.152 2001/11/27 12:23:11 pkot
29 Specifying SMSC number in --sendsms works again
31 Revision 1.151 2001/11/22 17:56:53 pkot
32 smslib update. sms sending
34 Revision 1.150 2001/11/20 16:22:22 pkot
35 First attempt to read Picture Messages. They should appear when you enable DEBUG. Nokia seems to break own standards. :/ (Markus Plail)
37 Revision 1.149 2001/11/19 16:00:15 pkot
40 Revision 1.148 2001/11/19 13:46:43 pkot
41 reading unread SMS in 6210 from Inbox. Folder updates (Markus Plail)
43 Revision 1.147 2001/11/18 00:54:32 pkot
44 Bugfixes. I18n of the user responses. UDH support in libsms. Business Card UDH Type
46 Revision 1.146 2001/11/17 20:18:33 pkot
47 Added dau9p connection type for 6210/7110
49 Revision 1.145 2001/11/14 10:46:12 pkot
50 Small cleanup with __unices__
52 Revision 1.144 2001/11/08 16:34:19 pkot
53 Updates to work with new libsms
55 Revision 1.143 2001/09/14 13:30:07 pkot
56 Fixed bugs introduced during 0.3.3 merge
58 Revision 1.142 2001/09/14 13:02:03 pkot
59 Gnokii calendar changes from 0.3.3
61 Revision 1.141 2001/09/14 12:53:00 pkot
64 Set valid operator on logos xgnokii screen.
66 Revision 1.140 2001/07/27 00:02:21 pkot
67 Generic AT support for the new structure (Manfred Jonsson)
69 Revision 1.139 2001/07/01 23:16:45 pkot
70 Fixed a typo in gnokii.c avoiding saving logo (Jan Havelka)
72 Revision 1.138 2001/06/28 00:28:45 pkot
73 Small docs updates (Pawel Kot)
75 Revision 1.137 2001/06/27 23:52:50 pkot
76 7110/6210 updates (Marian Jancar)
78 Revision 1.136 2001/06/10 23:49:49 pkot
79 Small fixes to hide compilation warnings and allow gnokii.c to compile
81 Revision 1.135 2001/06/10 11:42:26 machek
82 Cleanup: some formating, made Statemachine global, converted to new
83 structure w.r.t. SMS-es
85 Revision 1.134 2001/05/24 20:47:30 chris
86 More updating of 7110 code and some of xgnokii_lowlevel changed over.
88 Revision 1.133 2001/04/23 17:20:01 pkot
89 Added possibility for viewing logos (currently nol and ngg) on console (Bartek Klepacz)
91 Revision 1.132 2001/03/21 23:36:06 chris
92 Added the statemachine
93 This will break gnokii --identify and --monitor except for 6210/7110
95 Revision 1.131 2001/03/19 23:43:46 pkot
96 Solaris / BSD '#if defined' cleanup
98 Revision 1.130 2001/03/13 01:23:18 pkot
99 Windows updates (Manfred Jonsson)
101 Revision 1.129 2001/03/13 01:21:39 pkot
102 *BSD updates (Bert Driehuis)
104 Revision 1.128 2001/03/08 00:49:06 pkot
105 Fixed bug (introduced by me) in getmemory function. Now gnokii.c should compile
107 Revision 1.127 2001/03/08 00:18:13 pkot
108 Fixed writephonebook once again. Someone kick me please...
110 Revision 1.126 2001/03/07 21:46:12 pkot
111 Fixed writephonebook patch
113 Revision 1.125 2001/03/06 22:19:14 pkot
114 Cleanups and fixes in gnokii.c:
116 - fixed bug reported by Gabriele Zappi
117 - fixed small bugs introduced by Pavel Machek
119 Revision 1.124 2001/02/28 21:42:00 machek
120 Possibility to force overwrite in --getsms (-F). Possibility to get
121 multiple files (use --getsms -f xyzzy%d), cleanup.
123 Revision 1.123 2001/02/20 21:55:11 pkot
124 Small #include updates
126 Revision 1.122 2001/02/16 14:29:53 chris
127 Restructure of common/. Fixed a problem in fbus-phonet.c
128 Lots of dprintfs for Marcin
129 Any size xpm can now be loaded (eg for 7110 startup logos)
130 nk7110 code detects 7110/6210 and alters startup logo size to suit
131 Moved Marcin's extended phonebook code into gnokii.c
133 Revision 1.121 2001/02/06 21:15:35 chris
134 Preliminary irda support for 7110 etc. Not well tested!
136 Revision 1.120 2001/02/06 08:13:32 pkot
137 One more include in gnokii.c needed
139 Revision 1.119 2001/02/05 12:29:37 pkot
140 Changes needed to let unicode work
142 Revision 1.118 2001/02/01 15:17:33 pkot
143 Fixed --identify and added Manfred's manufacturer patch
145 Revision 1.117 2001/01/31 23:45:27 pkot
146 --identify should work ok now
148 Revision 1.116 2001/01/24 20:19:55 machek
149 Do not retry identification, if it is not implemented, it is bad idea.
151 Revision 1.115 2001/01/22 01:25:10 hugh
152 Tweaks for 3810 series, datacalls seem to be broken so need to do
153 some more debugging...
155 Revision 1.114 2001/01/17 02:54:55 chris
156 More 7110 work. Use with care! (eg it is not possible to delete phonebook entries)
157 I can now edit my phonebook in xgnokii but it is 'work in progress'.
159 Revision 1.113 2001/01/15 17:00:49 pkot
160 Initial keypress sequence support. Disable compilation warning
162 Revision 1.112 2001/01/12 14:09:13 pkot
163 More cleanups. This time mainly in the code.
165 Revision 1.111 2001/01/10 16:32:18 pkot
166 Documentation updates.
167 FreeBSD fix for 3810 code.
168 Added possibility for deleting SMS just after reading it in gnokii.
172 Revision 1.110 2001/01/08 15:11:37 pkot
173 Documentation updates.
174 Fixed some bugs and removed FIXMEs.
175 We need to move some stuff from configure.in to aclocal.m4
177 Revision 1.109 2000/12/29 15:39:07 pkot
178 Reverted a change in fbus-3810.c which broke compling with --enable-debug.
179 Small fixes in gnokii.c
181 Revision 1.108 2000/12/19 16:18:16 pkot
182 configure script updates and added shared function for configfile reading
194 # include <strings.h> /* for memset */
197 #include <sys/types.h>
198 #include <sys/stat.h>
203 #define sleep(x) Sleep((x) * 1000)
204 #define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
206 #include "win32/getopt.h"
221 #include "gsm-common.h"
223 #include "gsm-networks.h"
224 #include "cfgreader.h"
226 #include "gsm-filetypes.h"
227 #include "gsm-bitmaps.h"
228 #include "gsm-ringtones.h"
229 #include "gsm-statemachine.h"
231 char *model; /* Model from .gnokiirc file. */
232 char *Port; /* Serial port from .gnokiirc file */
233 char *Initlength; /* Init length from .gnokiirc file */
234 char *Connection; /* Connection type from .gnokiirc file */
235 char *BinDir; /* Binaries directory from .gnokiirc file - not used here yet */
236 /* Local variables */
238 char *GetProfileCallAlertString(int code)
241 case PROFILE_CALLALERT_RINGING: return "Ringing";
242 case PROFILE_CALLALERT_ASCENDING: return "Ascending";
243 case PROFILE_CALLALERT_RINGONCE: return "Ring once";
244 case PROFILE_CALLALERT_BEEPONCE: return "Beep once";
245 case PROFILE_CALLALERT_CALLERGROUPS: return "Caller groups";
246 case PROFILE_CALLALERT_OFF: return "Off";
247 default: return "Unknown";
251 char *GetProfileVolumeString(int code)
254 case PROFILE_VOLUME_LEVEL1: return "Level 1";
255 case PROFILE_VOLUME_LEVEL2: return "Level 2";
256 case PROFILE_VOLUME_LEVEL3: return "Level 3";
257 case PROFILE_VOLUME_LEVEL4: return "Level 4";
258 case PROFILE_VOLUME_LEVEL5: return "Level 5";
259 default: return "Unknown";
263 char *GetProfileKeypadToneString(int code)
266 case PROFILE_KEYPAD_OFF: return "Off";
267 case PROFILE_KEYPAD_LEVEL1: return "Level 1";
268 case PROFILE_KEYPAD_LEVEL2: return "Level 2";
269 case PROFILE_KEYPAD_LEVEL3: return "Level 3";
270 default: return "Unknown";
274 char *GetProfileMessageToneString(int code)
277 case PROFILE_MESSAGE_NOTONE: return "No tone";
278 case PROFILE_MESSAGE_STANDARD: return "Standard";
279 case PROFILE_MESSAGE_SPECIAL: return "Special";
280 case PROFILE_MESSAGE_BEEPONCE: return "Beep once";
281 case PROFILE_MESSAGE_ASCENDING: return "Ascending";
282 default: return "Unknown";
286 char *GetProfileWarningToneString(int code)
289 case PROFILE_WARNING_OFF: return "Off";
290 case PROFILE_WARNING_ON: return "On";
291 default: return "Unknown";
295 char *GetProfileVibrationString(int code)
298 case PROFILE_VIBRATION_OFF: return "Off";
299 case PROFILE_VIBRATION_ON: return "On";
300 default: return "Unknown";
304 /* This function shows the copyright and some informations usefull for
309 fprintf(stdout, _("GNOKII Version %s\n"
310 "Copyright (C) Hugh Blemings <hugh@blemings.org>, 1999, 2000\n"
311 "Copyright (C) Pavel Janík ml. <Pavel.Janik@suse.cz>, 1999, 2000\n"
312 "Copyright (C) Pavel Machek <pavel@ucw.cz>, 2001\n"
313 "Copyright (C) Pawe³ Kot <pkot@linuxnews.pl>, 2001\n"
314 "gnokii is free software, covered by the GNU General Public License, and you are\n"
315 "welcome to change it and/or distribute copies of it under certain conditions.\n"
316 "There is absolutely no warranty for gnokii. See GPL for details.\n"
317 "Built %s %s for %s on %s \n"), VERSION, __TIME__, __DATE__, model, Port);
321 /* The function usage is only informative - it prints this program's usage and
322 command-line options. */
326 fprintf(stdout, _(" usage: gnokii [--help|--monitor|--version]\n"
327 " gnokii --getmemory memory_type start [end]\n"
328 " gnokii --writephonebook [-i]\n"
329 " gnokii --getspeeddial number\n"
330 " gnokii --setspeeddial number memory_type location\n"
331 " gnokii --getsms memory_type start [end] [-f file] [-F file] [-d]\n"
332 " gnokii --deletesms memory_type start [end]\n"
333 " gnokii --sendsms destination [--smsc message_center_number |\n"
334 " --smscno message_center_index] [-r] [-C n] [-v n]\n"
336 " gnokii --savesms [-m] [-l n] [-i]\n"
337 " gnokii --getsmsc message_center_number\n"
338 " gnokii --setdatetime [YYYY [MM [DD [HH [MM]]]]]\n"
339 " gnokii --getdatetime\n"
340 " gnokii --setalarm HH MM\n"
341 " gnokii --getalarm\n"
342 " gnokii --dialvoice number\n"
343 " gnokii --getcalendarnote start [end] [-v]\n"
344 " gnokii --writecalendarnote vcardfile number\n"
345 " gnokii --deletecalendarnote start [end]\n"
346 " gnokii --getdisplaystatus\n"
347 " gnokii --netmonitor {reset|off|field|devel|next|nr}\n"
348 " gnokii --identify\n"
349 " gnokii --senddtmf string\n"
350 " gnokii --sendlogo {caller|op} destination logofile [network code]\n"
351 " gnokii --sendringtone destination rtttlfile\n"
352 " gnokii --setlogo op [logofile] [network code]\n"
353 " gnokii --setlogo startup [logofile]\n"
354 " gnokii --setlogo caller [logofile] [caller group number] [group name]\n"
355 " gnokii --setlogo {dealer|text} [text]\n"
356 " gnokii --getlogo op [logofile] [network code]\n"
357 " gnokii --getlogo startup [logofile] [network code]\n"
358 " gnokii --getlogo caller [logofile][caller group number][network code]\n"
359 " gnokii --getlogo {dealer|text}\n"
360 " gnokii --viewlogo logofile\n"
361 " gnokii --setringtone rtttlfile\n"
362 " gnokii --reset [soft|hard]\n"
363 " gnokii --getprofile [number]\n"
364 " gnokii --displayoutput\n"
365 " gnokii --keysequence\n"
369 " gnokii --entersecuritycode PIN|PIN2|PUK|PUK2\n"
370 " gnokii --getsecuritycodestatus\n"
376 /* fbusinit is the generic function which waits for the FBUS link. The limit
377 is 10 seconds. After 10 seconds we quit. */
379 static GSM_Statemachine State;
380 static GSM_Data data;
382 void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame))
386 GSM_ConnectionType connection = GCT_Serial;
388 GSM_DataClear(&data);
390 if (!strcasecmp(Connection, "dau9p")) connection = GCT_DAU9P;
391 if (!strcasecmp(Connection, "infrared")) connection = GCT_Infrared;
392 if (!strcasecmp(Connection, "irda")) connection = GCT_Irda;
394 /* Initialise the code for the GSM interface. */
396 error = GSM_Initialise(model, Port, Initlength, connection, rlp_handler, &State);
398 if (error != GE_NONE) {
399 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
403 /* First (and important!) wait for GSM link to be active. We allow 10
406 while (count++ < 200 && *GSM_LinkOK == false)
409 if (*GSM_LinkOK == false) {
410 fprintf (stderr, _("Hmmm... GSM_LinkOK never went true. Quitting.\n"));
415 /* This function checks that the argument count for a given options is withing
417 int checkargs(int opt, struct gnokii_arg_len gals[], int argc)
421 /* Walk through the whole array with options requiring arguments. */
422 for (i = 0; !(gals[i].gal_min == 0 && gals[i].gal_max == 0); i++) {
424 /* Current option. */
425 if (gals[i].gal_opt == opt) {
427 /* Argument count checking. */
428 if (gals[i].gal_flags == GAL_XOR) {
429 if (gals[i].gal_min == argc || gals[i].gal_max == argc)
432 if (gals[i].gal_min <= argc && gals[i].gal_max >= argc)
440 /* We do not have options without arguments in the array, so check them. */
441 if (argc == 0) return 0;
445 /* Main function - handles command line arguments, passes them to separate
446 functions accordingly. */
447 int main(int argc, char *argv[])
453 /* Every option should be in this array. */
454 static struct option long_options[] =
456 /* FIXME: these comments are nice, but they would be more usefull as docs for the user */
458 { "help", no_argument, NULL, OPT_HELP },
460 // Display version and build information.
461 { "version", no_argument, NULL, OPT_VERSION },
464 { "monitor", no_argument, NULL, OPT_MONITOR },
468 // Enter Security Code mode
469 { "entersecuritycode", required_argument, NULL, OPT_ENTERSECURITYCODE },
471 // Get Security Code status
472 { "getsecuritycodestatus", no_argument, NULL, OPT_GETSECURITYCODESTATUS },
477 { "setdatetime", optional_argument, NULL, OPT_SETDATETIME },
479 // Get date and time mode
480 { "getdatetime", no_argument, NULL, OPT_GETDATETIME },
483 { "setalarm", required_argument, NULL, OPT_SETALARM },
486 { "getalarm", no_argument, NULL, OPT_GETALARM },
489 { "dialvoice", required_argument, NULL, OPT_DIALVOICE },
491 // Get calendar note mode
492 { "getcalendarnote", required_argument, NULL, OPT_GETCALENDARNOTE },
494 // Write calendar note mode
495 { "writecalendarnote", required_argument, NULL, OPT_WRITECALENDARNOTE },
497 // Delete calendar note mode
498 { "deletecalendarnote", required_argument, NULL, OPT_DELCALENDARNOTE },
500 // Get display status mode
501 { "getdisplaystatus", no_argument, NULL, OPT_GETDISPLAYSTATUS },
504 { "getmemory", required_argument, NULL, OPT_GETMEMORY },
506 // Write phonebook (memory) mode
507 { "writephonebook", optional_argument, NULL, OPT_WRITEPHONEBOOK },
509 // Get speed dial mode
510 { "getspeeddial", required_argument, NULL, OPT_GETSPEEDDIAL },
512 // Set speed dial mode
513 { "setspeeddial", required_argument, NULL, OPT_SETSPEEDDIAL },
515 // Get SMS message mode
516 { "getsms", required_argument, NULL, OPT_GETSMS },
518 // Delete SMS message mode
519 { "deletesms", required_argument, NULL, OPT_DELETESMS },
521 // Send SMS message mode
522 { "sendsms", required_argument, NULL, OPT_SENDSMS },
524 // Ssve SMS message mode
525 { "savesms", optional_argument, NULL, OPT_SAVESMS },
527 // Send logo as SMS message mode
528 { "sendlogo", required_argument, NULL, OPT_SENDLOGO },
530 // Send ringtone as SMS message
531 { "sendringtone", required_argument, NULL, OPT_SENDRINGTONE },
534 { "setringtone", required_argument, NULL, OPT_SETRINGTONE },
536 // Get SMS center number mode
537 { "getsmsc", required_argument, NULL, OPT_GETSMSC },
539 // For development purposes: run in passive monitoring mode
540 { "pmon", no_argument, NULL, OPT_PMON },
543 { "netmonitor", required_argument, NULL, OPT_NETMONITOR },
546 { "identify", no_argument, NULL, OPT_IDENTIFY },
548 // Send DTMF sequence
549 { "senddtmf", required_argument, NULL, OPT_SENDDTMF },
552 { "reset", optional_argument, NULL, OPT_RESET },
555 { "setlogo", optional_argument, NULL, OPT_SETLOGO },
558 { "getlogo", required_argument, NULL, OPT_GETLOGO },
561 { "viewlogo", required_argument, NULL, OPT_VIEWLOGO },
564 { "getprofile", optional_argument, NULL, OPT_GETPROFILE },
566 // Show texts from phone's display
567 { "displayoutput", no_argument, NULL, OPT_DISPLAYOUTPUT },
569 // Simulate pressing the keys
570 { "keysequence", no_argument, NULL, OPT_KEYPRESS },
572 // For development purposes: insert you function calls here
573 { "foogle", no_argument, NULL, OPT_FOOGLE },
578 /* Every command which requires arguments should have an appropriate entry
580 struct gnokii_arg_len gals[] =
584 { OPT_ENTERSECURITYCODE, 1, 1, 0 },
587 { OPT_SETDATETIME, 0, 5, 0 },
588 { OPT_SETALARM, 2, 2, 0 },
589 { OPT_DIALVOICE, 1, 1, 0 },
590 { OPT_GETCALENDARNOTE, 1, 3, 0 },
591 { OPT_WRITECALENDARNOTE, 2, 2, 0 },
592 { OPT_DELCALENDARNOTE, 1, 2, 0 },
593 { OPT_GETMEMORY, 2, 3, 0 },
594 { OPT_GETSPEEDDIAL, 1, 1, 0 },
595 { OPT_SETSPEEDDIAL, 3, 3, 0 },
596 { OPT_GETSMS, 2, 5, 0 },
597 { OPT_DELETESMS, 2, 3, 0 },
598 { OPT_SENDSMS, 1, 10, 0 },
599 { OPT_SAVESMS, 0, 6, 0 },
600 { OPT_SENDLOGO, 3, 4, GAL_XOR },
601 { OPT_SENDRINGTONE, 2, 2, 0 },
602 { OPT_GETSMSC, 1, 1, 0 },
603 { OPT_GETWELCOMENOTE, 1, 1, 0 },
604 { OPT_SETWELCOMENOTE, 1, 1, 0 },
605 { OPT_NETMONITOR, 1, 1, 0 },
606 { OPT_SENDDTMF, 1, 1, 0 },
607 { OPT_SETLOGO, 1, 4, 0 },
608 { OPT_GETLOGO, 1, 4, 0 },
609 { OPT_VIEWLOGO, 1, 1, 0 },
610 { OPT_SETRINGTONE, 1, 1, 0 },
611 { OPT_RESET, 0, 1, 0 },
612 { OPT_GETPROFILE, 0, 1, 0 },
613 { OPT_WRITEPHONEBOOK, 0, 1, 0 },
620 /* For GNU gettext */
622 textdomain("gnokii");
623 setlocale(LC_ALL, "");
626 /* Read config file */
627 if (readconfig(&model, &Port, &Initlength, &Connection, &BinDir) < 0) {
631 /* Handle command line arguments. */
632 c = getopt_long(argc, argv, "", long_options, NULL);
633 if (c == -1) /* No argument given - we should display usage. */
637 // First, error conditions
640 fprintf(stderr, _("Use '%s --help' for usage informations.\n"), argv[0]);
642 // Then, options with no arguments
649 /* We have to build an array of the arguments which will be passed to the
650 functions. Please note that every text after the --command will be
651 passed as arguments. A syntax like gnokii --cmd1 args --cmd2 args will
652 not work as expected; instead args --cmd2 args is passed as a
654 if ((nargv = malloc(sizeof(char *) * argc)) != NULL) {
655 for (i = 2; i < argc; i++)
656 nargv[i-2] = argv[i];
658 if (checkargs(c, gals, nargc)) {
659 free(nargv); /* Wrong number of arguments - we should display usage. */
664 /* have to ignore SIGALARM */
668 /* Initialise the code for the GSM interface. */
676 case OPT_ENTERSECURITYCODE:
677 rc = entersecuritycode(optarg);
679 case OPT_GETSECURITYCODESTATUS:
680 rc = getsecuritycodestatus();
683 case OPT_GETDATETIME:
689 case OPT_GETDISPLAYSTATUS:
690 rc = getdisplaystatus();
695 case OPT_WRITEPHONEBOOK:
696 rc = writephonebook(nargc, nargv);
698 // Now, options with arguments
699 case OPT_SETDATETIME:
700 rc = setdatetime(nargc, nargv);
703 rc = setalarm(nargv);
706 rc = dialvoice(optarg);
708 case OPT_GETCALENDARNOTE:
709 rc = getcalendarnote(nargc, nargv);
711 case OPT_DELCALENDARNOTE:
712 rc = deletecalendarnote(nargc, nargv);
714 case OPT_WRITECALENDARNOTE:
715 rc = writecalendarnote(nargv);
718 rc = getmemory(nargc, nargv);
720 case OPT_GETSPEEDDIAL:
721 rc = getspeeddial(optarg);
723 case OPT_SETSPEEDDIAL:
724 rc = setspeeddial(nargv);
727 rc = getsms(argc, argv);
730 rc = deletesms(nargc, nargv);
733 rc = sendsms(nargc, nargv);
736 rc = savesms(argc, argv);
739 rc = sendlogo(nargc, nargv);
742 rc = getsmsc(optarg);
745 rc = netmonitor(optarg);
751 rc = setlogo(nargc, nargv);
754 rc = getlogo(nargc, nargv);
757 rc = viewlogo(optarg);
759 case OPT_SETRINGTONE:
760 rc = setringtone(nargc, nargv);
762 case OPT_SENDRINGTONE:
763 rc = sendringtone(nargc, nargv);
766 rc = getprofile(nargc, nargv);
768 case OPT_DISPLAYOUTPUT:
769 rc = displayoutput();
772 rc = presskeysequence();
780 rc = senddtmf(optarg);
786 fprintf(stderr, _("Unknown option: %d\n"), c);
793 fprintf(stderr, _("Wrong number of arguments\n"));
797 /* Send SMS messages. */
798 int sendsms(int argc, char *argv[])
802 // char UDH[GSM_MAX_USER_DATA_HEADER_LENGTH];
803 /* The maximum length of an uncompressed concatenated short message is
804 255 * 153 = 39015 default alphabet characters */
805 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
806 int input_len, chars_read;
807 int i; /*, offset, nr_msg, aux;*/
809 struct option options[] = {
810 { "smsc", required_argument, NULL, '1'},
811 { "smscno", required_argument, NULL, '2'},
812 { "long", required_argument, NULL, '3'},
816 input_len = GSM_MAX_SMS_LENGTH;
824 - message validity for 3 days
825 - unset user data header indicator
828 memset(&SMS, 0, sizeof(GSM_SMSMessage));
830 SMS.Type = SMS_Submit;
831 SMS.DCS.Type = SMS_GeneralDataCoding;
832 SMS.DCS.u.General.Compressed = false;
833 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
834 SMS.DCS.u.General.Class = 0;
835 SMS.MessageCenter.No = 1;
836 SMS.Validity.VPF = SMS_RelativeFormat;
837 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
840 strcpy(SMS.RemoteNumber.number, argv[0]);
841 if (SMS.RemoteNumber.number[0] == '+') SMS.RemoteNumber.type = SMS_International;
842 else SMS.RemoteNumber.type = SMS_Unknown;
847 while ((i = getopt_long(argc, argv, "r8cC:v:", options, NULL)) != -1) {
848 switch (i) { // -8 is for 8-bit data, -c for compression. both are not yet implemented.
849 case '1': /* SMSC number */
850 SMS.MessageCenter.No = 0;
851 strcpy(SMS.MessageCenter.Number, optarg);
852 if (SMS.MessageCenter.Number[0] == '+') SMS.MessageCenter.Type = SMS_International;
853 else SMS.MessageCenter.Type = SMS_Unknown;
855 case '2': /* SMSC number index in phone memory */
856 SMS.MessageCenter.No = atoi(optarg);
858 if (SMS.MessageCenter.No < 1 || SMS.MessageCenter.No > 5)
860 data.MessageCenter = &SMS.MessageCenter;
861 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
863 case '3': /* we send long message */
864 input_len = atoi(optarg);
865 if (input_len > 255 * GSM_MAX_SMS_LENGTH) {
866 fprintf(stderr, _("Input too long!\n"));
870 case 'r': /* request for delivery report */
871 SMS.Type = SMS_Delivery_Report;
873 case 'C': /* class Message */
876 SMS.DCS.u.General.Class = 1;
879 SMS.DCS.u.General.Class = 2;
882 SMS.DCS.u.General.Class = 3;
885 SMS.DCS.u.General.Class = 4;
892 SMS.Validity.u.Relative = atoi(optarg);
895 usage(); /* Would be better to have an sendsms_usage() here. */
899 /* Get message text from stdin. */
900 chars_read = fread(message_buffer, 1, input_len, stdin);
902 if (chars_read == 0) {
903 fprintf(stderr, _("Couldn't read from stdin!\n"));
905 } else if (chars_read > input_len) {
906 fprintf(stderr, _("Input too long!\n"));
910 /* Null terminate. */
911 message_buffer[chars_read] = 0x00;
912 strncpy(SMS.MessageText, message_buffer, chars_read);
913 data.SMSMessage = &SMS;
915 /* Send the message. */
916 error = SM_Functions(GOP_SendSMS, &data, &State);
918 if (error == GE_SMSSENDOK) {
919 fprintf(stdout, _("Send succeeded!\n"));
921 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
924 if (GSM && GSM->Terminate) GSM->Terminate();
929 int savesms(int argc, char *argv[])
933 /* The maximum length of an uncompressed concatenated short message is
934 255 * 153 = 39015 default alphabet characters */
935 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
936 int input_len, chars_read;
942 SMS.Type = SMS_Deliver;
943 SMS.DCS.Type = SMS_GeneralDataCoding;
944 SMS.DCS.u.General.Compressed = false;
945 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
946 SMS.DCS.u.General.Class = 0;
947 SMS.MessageCenter.No = 1;
948 SMS.Validity.VPF = SMS_RelativeFormat;
949 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
951 SMS.Status = SMS_Unsent;
954 input_len = GSM_MAX_SMS_LENGTH;
957 while ((i = getopt(argc, argv, "ml:in:s:c:")) != -1) {
959 case 'm': /* mark the message as sent */
960 SMS.Status = SMS_Sent;
962 case 'l': /* Specify the location */
963 SMS.Number = atoi(optarg);
965 case 'i': /* Ask before overwriting */
968 case 'n': /* Specify the from number */
970 case 's': /* Specify the smsc number */
972 case 'c': /* Specify the smsc location */
983 aux.Number = SMS.Number;
984 data.SMSMessage = &aux;
985 error = SM_Functions(GOP_GetSMS, &data, &State);
988 fprintf(stderr, _("Message at specified location exists. "));
989 while (confirm < 0) {
990 fprintf(stderr, _("Overwrite? (yes/no) "));
991 GetLine(stdin, ans, 7);
992 if (!strcmp(ans, _("yes"))) confirm = 1;
993 else if (!strcmp(ans, _("no"))) confirm = 0;
995 if (!confirm) { GSM->Terminate(); return 0; }
997 case GE_INVALIDSMSLOCATION:
998 fprintf(stderr, _("Invalid location\n"));
1002 /* FIXME: Remove this fprintf when the function is thoroughly tested */
1004 fprintf(stderr, _("Location %d empty. Saving\n"), SMS.Number);
1009 chars_read = fread(message_buffer, 1, input_len, stdin);
1011 if (chars_read == 0) {
1013 fprintf(stderr, _("Couldn't read from stdin!\n"));
1016 } else if (chars_read > input_len) {
1018 fprintf(stderr, _("Input too long!\n"));
1023 strncpy (SMS.MessageText, message_buffer, chars_read);
1024 SMS.MessageText[chars_read] = 0;
1026 error = GSM->SaveSMSMessage(&SMS);
1028 if (error == GE_NONE) {
1029 fprintf(stdout, _("Saved!\n"));
1031 fprintf(stdout, _("Saving failed (error=%d)\n"), error);
1039 /* Get SMSC number */
1040 int getsmsc(char *MessageCenterNumber)
1042 SMS_MessageCenter MessageCenter;
1046 memset(&MessageCenter, 0, sizeof(MessageCenter));
1047 MessageCenter.No=atoi(MessageCenterNumber);
1049 if (GSM && GSM->GetSMSCenter && GSM->Terminate) {
1050 error = GSM->GetSMSCenter(&MessageCenter);
1053 GSM_DataClear(&data);
1054 data.MessageCenter = &MessageCenter;
1055 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
1060 fprintf(stdout, _("%d. SMS center (%s) number is %s\n"), MessageCenter.No, MessageCenter.Name, MessageCenter.Number);
1061 fprintf(stdout, _("Default recipient number is %s\n"), MessageCenter.Recipient);
1062 fprintf(stdout, _("Messages sent as "));
1064 switch (MessageCenter.Format) {
1066 fprintf(stdout, _("Text"));
1069 fprintf(stdout, _("VoiceMail"));
1072 fprintf(stdout, _("Fax"));
1076 fprintf(stdout, _("Email"));
1079 fprintf(stdout, _("ERMES"));
1082 fprintf(stdout, _("X.400"));
1085 fprintf(stdout, _("Unknown"));
1090 fprintf(stdout, _("Message validity is "));
1092 switch (MessageCenter.Validity) {
1094 fprintf(stdout, _("1 hour"));
1097 fprintf(stdout, _("6 hours"));
1100 fprintf(stdout, _("24 hours"));
1103 fprintf(stdout, _("72 hours"));
1106 fprintf(stdout, _("1 week"));
1109 fprintf(stdout, _("Maximum time"));
1112 fprintf(stdout, _("Unknown"));
1116 fprintf(stdout, "\n");
1119 case GE_NOTIMPLEMENTED:
1120 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1123 fprintf(stdout, _("SMS center can not be found :-(\n"));
1130 /* Get SMS messages. */
1131 int getsms(int argc, char *argv[])
1135 SMS_FolderList folderlist;
1136 GSM_SMSMessage message;
1137 char *memory_type_string;
1138 int start_message, end_message, count, mode = 1;
1145 /* Handle command line args that set type, start and end locations. */
1146 memory_type_string = argv[2];
1147 message.MemoryType = StrToMemoryType(memory_type_string);
1148 if (message.MemoryType == GMT_XX) {
1149 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[2]);
1153 memset(&filename, 0, 64);
1155 start_message = end_message = atoi(argv[3]);
1159 /* [end] can be only argv[4] */
1160 if (argv[4][0] != '-') {
1161 end_message = atoi(argv[4]);
1164 /* parse all options (beginning with '-' */
1165 while ((i = getopt(argc, argv, "f:F:d")) != -1) {
1174 dprintf("Saving into %s\n", optarg);
1175 strncpy(filename, optarg, 64);
1176 if (strlen(optarg) > 63) {
1177 fprintf(stderr, _("Filename too long - will be truncated to 63 characters.\n"));
1180 filename[strlen(optarg)] = 0;
1189 data.SMSFolderList = &folderlist;
1190 folder.FolderID = 0;
1191 data.SMSFolder = &folder;
1192 /* Now retrieve the requested entries. */
1193 for (count = start_message; count <= end_message; count ++) {
1196 message.Number = count;
1197 data.SMSMessage = &message;
1198 dprintf("MemoryType (gnokii.c) : %i\n", data.SMSMessage->MemoryType);
1199 error = SM_Functions(GOP_GetSMS, &data, &State);
1203 switch (message.Type) {
1205 fprintf(stdout, _("%d. MO Message "), message.Number);
1207 fprintf(stdout, _("(sent)\n"));
1208 fprintf(stdout, _("%d. MO Message "), message.Number);
1210 fprintf(stdout, _("(not sent)\n"));
1211 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1213 case SMS_Delivery_Report:
1214 fprintf(stdout, _("%d. Delivery Report "), message.Number);
1216 fprintf(stdout, _("(read)\n"));
1218 fprintf(stdout, _("(not read)\n"));
1219 fprintf(stdout, _("Sending date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1220 message.Time.Day, message.Time.Month, message.Time.Year, \
1221 message.Time.Hour, message.Time.Minute, message.Time.Second);
1222 if (message.Time.Timezone) {
1223 if (message.Time.Timezone > 0)
1224 fprintf(stdout,_("+%02d00"), message.Time.Timezone);
1226 fprintf(stdout,_("%02d00"), message.Time.Timezone);
1228 fprintf(stdout, "\n");
1229 fprintf(stdout, _("Response date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1230 message.SMSCTime.Day, message.SMSCTime.Month, message.SMSCTime.Year, \
1231 message.SMSCTime.Hour, message.SMSCTime.Minute, message.SMSCTime.Second);
1232 if (message.SMSCTime.Timezone) {
1233 if (message.SMSCTime.Timezone > 0)
1234 fprintf(stdout,_("+%02d00"),message.SMSCTime.Timezone);
1236 fprintf(stdout,_("%02d00"),message.SMSCTime.Timezone);
1238 fprintf(stdout, "\n");
1239 fprintf(stdout, _("Receiver: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1240 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1243 fprintf(stdout, _("%d. Inbox Message "), message.Number);
1245 fprintf(stdout, _("(read)\n"));
1247 fprintf(stdout, _("(not read)\n"));
1248 fprintf(stdout, _("Date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1249 message.Time.Day, message.Time.Month, message.Time.Year, \
1250 message.Time.Hour, message.Time.Minute, message.Time.Second);
1251 if (message.Time.Timezone) {
1252 if (message.Time.Timezone > 0)
1253 fprintf(stdout,_("+%02d00"),message.Time.Timezone);
1255 fprintf(stdout,_("%02d00"),message.Time.Timezone);
1257 fprintf(stdout, "\n");
1258 fprintf(stdout, _("Sender: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1259 switch (message.UDH[0].Type) {
1261 fprintf(stdout, _("GSM operator logo for %s (%s) network.\n"), bitmap.netcode, GSM_GetNetworkName(bitmap.netcode));
1262 if (!strcmp(message.RemoteNumber.number, "+998000005") && !strcmp(message.MessageCenter.Number, "+886935074443")) dprintf(_("Saved by Logo Express\n"));
1263 if (!strcmp(message.RemoteNumber.number, "+998000002") || !strcmp(message.RemoteNumber.number, "+998000003")) dprintf(_("Saved by Operator Logo Uploader by Thomas Kessler\n"));
1265 case SMS_CallerIDLogo:
1266 fprintf(stdout, ("Logo:\n"));
1267 /* put bitmap into bitmap structure */
1268 GSM_ReadSMSBitmap(message.UDH[0].Type, message.MessageText+2+offset, message.MessageText, &bitmap);
1269 GSM_PrintBitmap(&bitmap);
1272 if ((stat(filename, &buf) == 0)) {
1273 fprintf(stdout, _("File %s exists.\n"), filename);
1274 fprintf(stderr, _("Overwrite? (yes/no) "));
1275 GetLine(stdin, ans, 4);
1276 if (!strcmp(ans, _("yes"))) {
1277 error = GSM_SaveBitmapFile(filename, &bitmap);
1279 } else error = GSM_SaveBitmapFile(filename, &bitmap);
1280 if (error != GE_NONE) fprintf(stderr, _("Couldn't save logofile %s!\n"), filename);
1284 fprintf(stdout, _("Ringtone\n"));
1286 case SMS_ConcatenatedMessages:
1287 fprintf(stdout, _("Linked (%d/%d):\n"),
1288 message.UDH[0].u.ConcatenatedShortMessage.CurrentNumber,
1289 message.UDH[0].u.ConcatenatedShortMessage.MaximumNumber);
1291 fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText);
1292 if ((mode != -1) && *filename) {
1294 sprintf(buf, "%s%d", filename, count);
1295 mode = GSM_SaveTextFile(buf, message.MessageText, mode);
1298 case SMS_BusinessCard:
1299 fprintf(stdout, _("Business Card:\n%s"), message.MessageText);
1302 fprintf(stderr, _("Unknown\n"));
1308 data.SMSMessage = &message;
1309 if (GE_NONE != SM_Functions(GOP_DeleteSMS, &data, &State))
1310 fprintf(stdout, _("(delete failed)\n"));
1312 fprintf(stdout, _("(message deleted)\n"));
1315 case GE_NOTIMPLEMENTED:
1316 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1317 if (GSM && GSM->Terminate) GSM->Terminate();
1319 case GE_INVALIDSMSLOCATION:
1320 fprintf(stderr, _("Invalid location: %s %d\n"), memory_type_string, count);
1322 case GE_EMPTYSMSLOCATION:
1323 fprintf(stderr, _("SMS location %s %d empty.\n"), memory_type_string, count);
1326 fprintf(stdout, _("GetSMS %s %d failed!(%s)\n\n"), memory_type_string, count, print_error(error));
1331 if (GSM && GSM->Terminate) GSM->Terminate();
1336 /* Delete SMS messages. */
1337 int deletesms(int argc, char *argv[])
1339 GSM_SMSMessage message;
1340 char *memory_type_string;
1341 int start_message, end_message, count;
1344 /* Handle command line args that set type, start and end locations. */
1345 memory_type_string = argv[0];
1346 message.MemoryType = StrToMemoryType(memory_type_string);
1347 if (message.MemoryType == GMT_XX) {
1348 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
1352 start_message = end_message = atoi (argv[1]);
1353 if (argc > 2) end_message = atoi (argv[2]);
1355 /* Now delete the requested entries. */
1356 for (count = start_message; count <= end_message; count ++) {
1358 message.Number = count;
1359 data.SMSMessage = &message;
1360 error = SM_Functions(GOP_DeleteSMS, &data, &State);
1362 if (error == GE_NONE)
1363 fprintf(stdout, _("Deleted SMS %s %d\n"), memory_type_string, count);
1365 if (error == GE_NOTIMPLEMENTED) {
1366 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1370 fprintf(stdout, _("DeleteSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
1379 static volatile bool bshutdown = false;
1381 /* SIGINT signal handler. */
1382 static void interrupted(int sig)
1384 signal(sig, SIG_IGN);
1390 /* In this mode we get the code from the keyboard and send it to the mobile
1392 int entersecuritycode(char *type)
1395 GSM_SecurityCode SecurityCode;
1397 if (!strcmp(type,"PIN"))
1398 SecurityCode.Type=GSCT_Pin;
1399 else if (!strcmp(type,"PUK"))
1400 SecurityCode.Type=GSCT_Puk;
1401 else if (!strcmp(type,"PIN2"))
1402 SecurityCode.Type=GSCT_Pin2;
1403 else if (!strcmp(type,"PUK2"))
1404 SecurityCode.Type=GSCT_Puk2;
1405 // FIXME: Entering of SecurityCode does not work :-(
1406 // else if (!strcmp(type,"SecurityCode"))
1407 // SecurityCode.Type=GSCT_SecurityCode;
1412 printf("Enter your code: ");
1413 gets(SecurityCode.Code);
1415 strcpy(SecurityCode.Code,getpass(_("Enter your code: ")));
1418 test = GSM->EnterSecurityCode(SecurityCode);
1419 if (test == GE_INVALIDSECURITYCODE)
1420 fprintf(stdout, _("Error: invalid code.\n"));
1421 else if (test == GE_NONE)
1422 fprintf(stdout, _("Code ok.\n"));
1423 else if (test == GE_NOTIMPLEMENTED)
1424 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1426 fprintf(stdout, _("Other error.\n"));
1433 int getsecuritycodestatus(void)
1437 if (GSM->GetSecurityCodeStatus(&Status) == GE_NONE) {
1439 fprintf(stdout, _("Security code status: "));
1442 case GSCT_SecurityCode:
1443 fprintf(stdout, _("waiting for Security Code.\n"));
1446 fprintf(stdout, _("waiting for PIN.\n"));
1449 fprintf(stdout, _("waiting for PIN2.\n"));
1452 fprintf(stdout, _("waiting for PUK.\n"));
1455 fprintf(stdout, _("waiting for PUK2.\n"));
1458 fprintf(stdout, _("nothing to enter.\n"));
1461 fprintf(stdout, _("Unknown!\n"));
1474 /* Voice dialing mode. */
1475 int dialvoice(char *Number)
1477 GSM->DialVoice(Number);
1484 /* The following function allows to send logos using SMS */
1485 int sendlogo(int argc, char *argv[])
1491 char UserDataHeader[7] = { 0x06, /* UDH Length */
1492 0x05, /* IEI: application port addressing scheme, 16 bit address */
1493 0x04, /* IEI length */
1494 0x15, /* destination address: high byte */
1495 0x00, /* destination address: low byte */
1496 0x00, /* originator address */
1499 char Data[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1503 /* Default settings for SMS message:
1504 - no delivery report
1510 - set UserDataHeaderIndicator
1512 SMS.Type = SMS_Submit;
1513 SMS.DCS.Type = SMS_GeneralDataCoding;
1514 SMS.DCS.u.General.Compressed = false;
1515 SMS.DCS.u.General.Alphabet = SMS_8bit;
1516 SMS.DCS.u.General.Class = 2;
1517 SMS.MessageCenter.No = 1;
1518 SMS.Validity.VPF = SMS_RelativeFormat;
1519 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
1521 /* The first argument is the type of the logo. */
1522 if (!strcmp(argv[0], "op")) {
1523 SMS.UDH[0].Type = SMS_OpLogo;
1524 UserDataHeader[4] = 0x82; /* NBS port 0x1582 */
1525 fprintf(stdout, _("Sending operator logo.\n"));
1526 } else if (!strcmp(argv[0], "caller")) {
1527 SMS.UDH[0].Type = SMS_CallerIDLogo;
1528 UserDataHeader[4] = 0x83; /* NBS port 0x1583 */
1529 fprintf(stdout, _("Sending caller line identification logo.\n"));
1531 fprintf(stderr, _("You should specify what kind of logo to send!\n"));
1535 /* The second argument is the destination, ie the phone number of recipient. */
1536 SMS.MemoryType = atoi(argv[1]);
1538 /* The third argument is the bitmap file. */
1539 GSM_ReadBitmapFile(argv[2], &bitmap);
1541 /* If we are sending op logo we can rewrite network code. */
1542 if (!strcmp(argv[0], "op")) {
1544 * The fourth argument, if present, is the Network code of the operator.
1545 * Network code is in this format: "xxx yy".
1548 strcpy(bitmap.netcode, argv[3]);
1550 fprintf(stdout, _("Operator code: %s\n"), argv[3]);
1554 /* Set the network code */
1555 Data[current++] = ((bitmap.netcode[1] & 0x0f) << 4) | (bitmap.netcode[0] & 0xf);
1556 Data[current++] = 0xf0 | (bitmap.netcode[2] & 0x0f);
1557 Data[current++] = ((bitmap.netcode[5] & 0x0f) << 4) | (bitmap.netcode[4] & 0xf);
1560 /* Set the logo size */
1562 Data[current++] = bitmap.width;
1563 Data[current++] = bitmap.height;
1565 Data[current++] = 0x01;
1567 memcpy(SMS.MessageText, UserDataHeader, 7);
1568 memcpy(SMS.MessageText, Data, current);
1569 memcpy(SMS.MessageText+current, bitmap.bitmap, bitmap.size);
1571 /* Send the message. */
1572 error = GSM->SendSMSMessage(&SMS,current+bitmap.size);
1574 if (error == GE_SMSSENDOK)
1575 fprintf(stdout, _("Send succeeded!\n"));
1577 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
1583 /* Getting logos. */
1584 GSM_Error SaveBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1591 /* Ask before overwriting */
1592 while (stat(FileName, &buf) == 0) {
1595 fprintf(stderr, _("Saving logo. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "), FileName);
1596 GetLine(stdin, ans, 4);
1597 if (!strcmp(ans, "O") || !strcmp(ans, "o")) confirm = 1;
1598 if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm = 2;
1599 if (!strcmp(ans, "S") || !strcmp(ans, "s")) return GE_USERCANCELED;
1601 if (confirm == 1) break;
1603 fprintf(stderr, _("Enter name of new file: "));
1604 GetLine(stdin, FileName, 50);
1605 if (!FileName || (*FileName == 0)) return GE_USERCANCELED;
1609 error = GSM_SaveBitmapFile(FileName, bitmap);
1612 case GE_CANTOPENFILE:
1613 fprintf(stderr, _("Failed to write file \"%s\"\n"), FileName);
1622 int getlogo(int argc, char *argv[])
1626 GSM_Statemachine *sm = &State;
1628 bitmap.type=GSM_None;
1630 if (!strcmp(argv[0], "op"))
1631 bitmap.type = GSM_OperatorLogo;
1633 if (!strcmp(argv[0], "caller")) {
1634 /* There is caller group number missing in argument list. */
1636 bitmap.number=argv[2][0]-'0';
1637 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1641 bitmap.type = GSM_CallerLogo;
1644 if (!strcmp(argv[0],"startup"))
1645 bitmap.type = GSM_StartupLogo;
1646 else if (!strcmp(argv[0], "dealer"))
1647 bitmap.type = GSM_DealerNoteText;
1648 else if (!strcmp(argv[0], "text"))
1649 bitmap.type=GSM_WelcomeNoteText;
1651 if (bitmap.type != GSM_None) {
1653 fprintf(stdout, _("Getting Logo\n"));
1655 data.Bitmap=&bitmap;
1656 error=SM_Functions(GOP_GetBitmap, &data, sm);
1660 if (bitmap.type == GSM_DealerNoteText) fprintf(stdout, _("Dealer welcome note "));
1661 if (bitmap.type == GSM_WelcomeNoteText) fprintf(stdout, _("Welcome note "));
1662 if (bitmap.type == GSM_DealerNoteText || bitmap.type==GSM_WelcomeNoteText) {
1663 if (bitmap.text[0]) {
1664 fprintf(stdout, _("currently set to \"%s\"\n"), bitmap.text);
1666 fprintf(stdout, _("currently empty\n"));
1670 switch (bitmap.type) {
1671 case GSM_OperatorLogo:
1672 fprintf(stdout,"Operator logo for %s (%s) network got succesfully\n",bitmap.netcode,GSM_GetNetworkName(bitmap.netcode));
1674 strncpy(bitmap.netcode,argv[2], 7);
1675 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1676 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1681 case GSM_StartupLogo:
1682 fprintf(stdout, "Startup logo got successfully\n");
1684 strncpy(bitmap.netcode,argv[2], 7);
1685 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1686 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1691 case GSM_CallerLogo:
1692 fprintf(stdout,"Caller logo got successfully\n");
1694 strncpy(bitmap.netcode,argv[3],7);
1695 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1696 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1702 fprintf(stdout,"Unknown bitmap type.\n");
1706 if (SaveBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) return (-1);
1709 fprintf(stdout,"Your phone doesn't have logo uploaded !\n");
1714 case GE_NOTIMPLEMENTED:
1715 fprintf(stderr, _("Function not implemented !\n"));
1717 case GE_NOTSUPPORTED:
1718 fprintf(stderr, _("This kind of logo is not supported !\n"));
1721 fprintf(stderr, _("Error getting logo !\n"));
1725 fprintf(stderr, _("What kind of logo do you want to get ?\n"));
1733 /* Sending logos. */
1734 GSM_Error ReadBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1738 error = GSM_ReadBitmapFile(FileName, bitmap);
1741 case GE_CANTOPENFILE:
1742 fprintf(stderr, _("Failed to read file \"%s\"\n"), FileName);
1744 case GE_WRONGNUMBEROFCOLORS:
1745 fprintf(stderr, _("Wrong number of colors in \"%s\" logofile (accepted only 2-colors files) !\n"), FileName);
1747 case GE_WRONGCOLORS:
1748 fprintf(stderr, _("Wrong colors in \"%s\" logofile !\n"), FileName);
1750 case GE_INVALIDFILEFORMAT:
1751 fprintf(stderr, _("Invalid format of \"%s\" logofile !\n"), FileName);
1753 case GE_SUBFORMATNOTSUPPORTED:
1754 fprintf(stderr, _("Sorry, gnokii doesn't support used subformat in file \"%s\" !\n"), FileName);
1756 case GE_FILETOOSHORT:
1757 fprintf(stderr, _("\"%s\" logofile is too short !\n"), FileName);
1759 case GE_INVALIDIMAGESIZE:
1760 fprintf(stderr, _("Bitmap size doesn't supported by fileformat or different from 72x14, 84x48 and 72x28 !\n"));
1770 int setlogo(int argc, char *argv[])
1772 GSM_Bitmap bitmap,oldbit;
1773 GSM_NetworkInfo NetworkInfo;
1779 if (!strcmp(argv[0],"text") || !strcmp(argv[0],"dealer")) {
1780 if (!strcmp(argv[0], "text")) bitmap.type = GSM_WelcomeNoteText;
1781 else bitmap.type = GSM_DealerNoteText;
1782 bitmap.text[0] = 0x00;
1783 if (argc > 1) strncpy(bitmap.text, argv[1], 255);
1785 if (!strcmp(argv[0], "op") || !strcmp(argv[0], "startup") || !strcmp(argv[0], "caller")) {
1787 if (ReadBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) {
1792 if (!strcmp(argv[0], "op")) {
1793 if (bitmap.type != GSM_OperatorLogo || argc < 3) {
1794 if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode, NetworkInfo.NetworkCode, 7);
1796 GSM_ResizeBitmap(&bitmap, GSM_OperatorLogo, GSM_Info);
1798 strncpy(bitmap.netcode, argv[2], 7);
1799 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1800 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1805 if (!strcmp(argv[0], "startup")) {
1806 GSM_ResizeBitmap(&bitmap, GSM_StartupLogo, GSM_Info);
1808 if (!strcmp(argv[0],"caller")) {
1809 GSM_ResizeBitmap(&bitmap, GSM_CallerLogo, GSM_Info);
1811 bitmap.number = argv[2][0] - '0';
1812 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1816 oldbit.type = GSM_CallerLogo;
1817 oldbit.number = bitmap.number;
1818 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1819 /* We have to get the old name and ringtone!! */
1820 bitmap.ringtone = oldbit.ringtone;
1821 strncpy(bitmap.text, oldbit.text, 255);
1823 if (argc > 3) strncpy(bitmap.text, argv[3], 255);
1825 fprintf(stdout, _("Setting Logo.\n"));
1827 /* FIX ME: is it possible to permanently remove op logo ? */
1828 if (!strcmp(argv[0], "op"))
1830 bitmap.type = GSM_OperatorLogo;
1831 strncpy(bitmap.netcode, "000 00", 7);
1834 bitmap.size = bitmap.width * bitmap.height / 8;
1835 GSM_ClearBitmap(&bitmap);
1837 /* FIX ME: how to remove startup and group logos ? */
1838 fprintf(stdout, _("Removing Logo.\n"));
1841 fprintf(stderr, _("What kind of logo do you want to set ?\n"));
1847 error=GSM->SetBitmap(&bitmap);
1851 oldbit.type = bitmap.type;
1852 oldbit.number = bitmap.number;
1853 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1854 if (bitmap.type == GSM_WelcomeNoteText ||
1855 bitmap.type == GSM_DealerNoteText) {
1856 if (strcmp(bitmap.text, oldbit.text)) {
1857 fprintf(stderr, _("Error setting"));
1858 if (bitmap.type == GSM_DealerNoteText) fprintf(stderr, _(" dealer"));
1859 fprintf(stderr, _(" welcome note - "));
1861 /* I know, it looks horrible, but... */
1862 /* I set it to the short string - if it won't be set */
1863 /* it means, PIN is required. If it will be correct, previous */
1864 /* (user) text was too long */
1866 /* Without it, I could have such thing: */
1867 /* user set text to very short string (for example, "Marcin") */
1868 /* then enable phone without PIN and try to set it to the very long (too long for phone) */
1869 /* string (which start with "Marcin"). If we compare them as only length different, we could think, */
1870 /* that phone accepts strings 6 chars length only (length of "Marcin") */
1871 /* When we make it correct, we don't have this mistake */
1873 strcpy(oldbit.text, "!\0");
1874 GSM->SetBitmap(&oldbit);
1875 GSM->GetBitmap(&oldbit);
1876 if (oldbit.text[0]!='!') {
1877 fprintf(stderr, _("SIM card and PIN is required\n"));
1879 GSM->SetBitmap(&bitmap);
1880 GSM->GetBitmap(&oldbit);
1881 fprintf(stderr, _("too long, truncated to \"%s\" (length %i)\n"),oldbit.text,strlen(oldbit.text));
1886 if (bitmap.type == GSM_StartupLogo) {
1887 for (i = 0; i < oldbit.size; i++) {
1888 if (oldbit.bitmap[i] != bitmap.bitmap[i]) {
1889 fprintf(stderr, _("Error setting startup logo - SIM card and PIN is required\n"));
1897 if (ok) fprintf(stdout, _("Done.\n"));
1899 case GE_NOTIMPLEMENTED:
1900 fprintf(stderr, _("Function not implemented.\n"));
1902 case GE_NOTSUPPORTED:
1903 fprintf(stderr, _("This kind of logo is not supported.\n"));
1906 fprintf(stderr, _("Error !\n"));
1916 int viewlogo(char *filename)
1920 error = GSM_ShowBitmapFile(filename);
1924 /* Calendar notes receiving. */
1925 int getcalendarnote(int argc, char *argv[])
1927 GSM_CalendarNote CalendarNote;
1929 GSM_Error error = GE_NONE;
1930 int i, first_location, last_location;
1933 struct option options[] = {
1934 { "vCard", optional_argument, NULL, '1'},
1941 first_location = last_location = atoi(argv[0]);
1942 if ((argc > 1) && (argv[1][0] != '-')) {
1943 last_location = atoi(argv[1]);
1946 while ((i = getopt_long(argc, argv, "v", options, NULL)) != -1) {
1952 usage(); /* Would be better to have an calendar_usage() here. */
1958 for (i = first_location; i <= last_location; i++) {
1959 CalendarNote.Location = i;
1960 if (GSM && GSM->GetCalendarNote && GSM->Terminate) {
1961 error = GSM->GetCalendarNote(&CalendarNote);
1964 GSM_DataClear(&data);
1965 data.CalendarNote = &CalendarNote;
1967 error = SM_Functions(GOP_GetCalendarNote, &data, &State);
1972 fprintf(stdout, "BEGIN:VCALENDAR\n");
1973 fprintf(stdout, "VERSION:1.0\n");
1974 fprintf(stdout, "BEGIN:VEVENT\n");
1975 fprintf(stdout, "CATEGORIES:");
1976 switch (CalendarNote.Type) {
1978 fprintf(stdout, "MISCELLANEOUS\n");
1981 fprintf(stdout, "PHONE CALL\n");
1984 fprintf(stdout, "MEETING\n");
1987 fprintf(stdout, "SPECIAL OCCASION\n");
1990 fprintf(stdout, "UNKNOWN\n");
1993 fprintf(stdout, "SUMMARY:%s\n",CalendarNote.Text);
1994 fprintf(stdout, "DTSTART:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Time.Year,
1995 CalendarNote.Time.Month, CalendarNote.Time.Day, CalendarNote.Time.Hour,
1996 CalendarNote.Time.Minute, CalendarNote.Time.Second);
1997 if (CalendarNote.Alarm.Year!=0) {
1998 fprintf(stdout, "DALARM:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Alarm.Year,
1999 CalendarNote.Alarm.Month, CalendarNote.Alarm.Day, CalendarNote.Alarm.Hour,
2000 CalendarNote.Alarm.Minute, CalendarNote.Alarm.Second);
2002 fprintf(stdout, "END:VEVENT\n");
2003 fprintf(stdout, "END:VCALENDAR\n");
2005 } else { /* not vCal */
2006 fprintf(stdout, _(" Type of the note: "));
2008 switch (CalendarNote.Type) {
2010 fprintf(stdout, _("Reminder\n"));
2013 fprintf(stdout, _("Call\n"));
2016 fprintf(stdout, _("Meeting\n"));
2019 fprintf(stdout, _("Birthday\n"));
2022 fprintf(stdout, _("Unknown\n"));
2026 fprintf(stdout, _(" Date: %d-%02d-%02d\n"), CalendarNote.Time.Year,
2027 CalendarNote.Time.Month,
2028 CalendarNote.Time.Day);
2030 fprintf(stdout, _(" Time: %02d:%02d:%02d\n"), CalendarNote.Time.Hour,
2031 CalendarNote.Time.Minute,
2032 CalendarNote.Time.Second);
2034 if (CalendarNote.Alarm.AlarmEnabled == 1) {
2035 fprintf(stdout, _(" Alarm date: %d-%02d-%02d\n"), CalendarNote.Alarm.Year,
2036 CalendarNote.Alarm.Month,
2037 CalendarNote.Alarm.Day);
2039 fprintf(stdout, _(" Alarm time: %02d:%02d:%02d\n"), CalendarNote.Alarm.Hour,
2040 CalendarNote.Alarm.Minute,
2041 CalendarNote.Alarm.Second);
2044 fprintf(stdout, _(" Text: %s\n"), CalendarNote.Text);
2046 if (CalendarNote.Type == GCN_CALL)
2047 fprintf(stdout, _(" Phone: %s\n"), CalendarNote.Phone);
2050 case GE_NOTIMPLEMENTED:
2051 fprintf(stderr, _("Function not implemented.\n"));
2054 fprintf(stderr, _("The calendar note can not be read\n"));
2063 /* Writing calendar notes. */
2064 int writecalendarnote(char *argv[])
2066 GSM_CalendarNote CalendarNote;
2068 if (GSM_ReadVCalendarFile(argv[0], &CalendarNote, atoi(argv[1]))) {
2069 fprintf(stdout, _("Failed to load vCalendar file.\n"));
2073 /* Error 22=Calendar full ;-) */
2074 if ((GSM->WriteCalendarNote(&CalendarNote)) == GE_NONE)
2075 fprintf(stdout, _("Succesfully written!\n"));
2077 fprintf(stdout, _("Failed to write calendar note!\n"));
2084 /* Calendar note deleting. */
2085 int deletecalendarnote(int argc, char *argv[])
2087 GSM_CalendarNote CalendarNote;
2088 int i, first_location, last_location;
2090 first_location = last_location = atoi(argv[0]);
2091 if (argc > 1) last_location = atoi(argv[1]);
2093 for (i = first_location; i <= last_location; i++) {
2095 CalendarNote.Location = i;
2097 if (GSM->DeleteCalendarNote(&CalendarNote) == GE_NONE) {
2098 fprintf(stdout, _(" Calendar note deleted.\n"));
2100 fprintf(stderr, _("The calendar note can not be deleted\n"));
2110 /* Setting the date and time. */
2111 int setdatetime(int argc, char *argv[])
2118 now = localtime(&nowh);
2120 Date.Year = now->tm_year;
2121 Date.Month = now->tm_mon+1;
2122 Date.Day = now->tm_mday;
2123 Date.Hour = now->tm_hour;
2124 Date.Minute = now->tm_min;
2125 Date.Second = now->tm_sec;
2127 if (argc > 0) Date.Year = atoi (argv[0]);
2128 if (argc > 1) Date.Month = atoi (argv[1]);
2129 if (argc > 2) Date.Day = atoi (argv[2]);
2130 if (argc > 3) Date.Hour = atoi (argv[3]);
2131 if (argc > 4) Date.Minute = atoi (argv[4]);
2133 if (Date.Year < 1900) {
2135 /* Well, this thing is copyrighted in U.S. This technique is known as
2136 Windowing and you can read something about it in LinuxWeekly News:
2137 http://lwn.net/1999/features/Windowing.phtml. This thing is beeing
2138 written in Czech republic and Poland where algorithms are not allowed
2142 Date.Year = Date.Year + 1900;
2144 Date.Year = Date.Year + 2000;
2147 /* FIXME: Error checking should be here. */
2148 GSM->SetDateTime(&Date);
2155 /* In this mode we receive the date and time from mobile phone. */
2156 int getdatetime(void) {
2158 GSM_DateTime date_time;
2161 if (GSM && GSM->GetDateTime && GSM->Terminate) {
2162 error = GSM->GetDateTime(&date_time);
2165 GSM_DataClear(&data);
2166 data.DateTime = &date_time;
2168 error = SM_Functions(GOP_GetDateTime, &data, &State);
2173 fprintf(stdout, _("Date: %4d/%02d/%02d\n"), date_time.Year, date_time.Month, date_time.Day);
2174 fprintf(stdout, _("Time: %02d:%02d:%02d\n"), date_time.Hour, date_time.Minute, date_time.Second);
2176 case GE_NOTIMPLEMENTED:
2177 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2180 fprintf(stdout, _("Internal error\n"));
2187 /* Setting the alarm. */
2188 int setalarm(char *argv[])
2192 Date.Hour = atoi(argv[0]);
2193 Date.Minute = atoi(argv[1]);
2195 GSM->SetAlarm(1, &Date);
2202 /* Getting the alarm. */
2207 GSM_DateTime date_time;
2209 if (GSM && GSM->GetAlarm && GSM->Terminate) {
2210 error = GSM->GetAlarm(0, &date_time);
2213 GSM_DataClear(&data);
2214 data.DateTime = &date_time;
2216 error = SM_Functions(GOP_GetAlarm, &data, &State);
2221 fprintf(stdout, _("Alarm: %s\n"), (date_time.AlarmEnabled==0)?"off":"on");
2222 fprintf(stdout, _("Time: %02d:%02d\n"), date_time.Hour, date_time.Minute);
2224 case GE_NOTIMPLEMENTED:
2225 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2228 fprintf(stdout, _("Internal error\n"));
2235 /* In monitor mode we don't do much, we just initialise the fbus code.
2236 Note that the fbus code no longer has an internal monitor mode switch,
2237 instead compile with DEBUG enabled to get all the gumpf. */
2238 int monitormode(void)
2240 float rflevel = -1, batterylevel = -1;
2241 // GSM_PowerSource powersource = -1;
2242 GSM_RFUnits rf_units = GRF_Arbitrary;
2243 GSM_BatteryUnits batt_units = GBU_Arbitrary;
2244 GSM_Statemachine *sm = &State;
2247 // GSM_NetworkInfo NetworkInfo;
2248 // GSM_CBMessage CBMessage;
2250 GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0};
2251 GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0};
2252 GSM_MemoryStatus DC_MemoryStatus = {GMT_DC, 0, 0};
2253 GSM_MemoryStatus EN_MemoryStatus = {GMT_EN, 0, 0};
2254 GSM_MemoryStatus FD_MemoryStatus = {GMT_FD, 0, 0};
2255 GSM_MemoryStatus LD_MemoryStatus = {GMT_LD, 0, 0};
2256 GSM_MemoryStatus MC_MemoryStatus = {GMT_MC, 0, 0};
2257 GSM_MemoryStatus ON_MemoryStatus = {GMT_ON, 0, 0};
2258 GSM_MemoryStatus RC_MemoryStatus = {GMT_RC, 0, 0};
2260 // GSM_SMSStatus SMSStatus = {0, 0};
2264 GSM_DataClear(&data);
2266 /* We do not want to monitor serial line forever - press Ctrl+C to stop the
2268 signal(SIGINT, interrupted);
2270 fprintf (stderr, _("Entering monitor mode...\n"));
2273 //GSM->EnableCellBroadcast();
2275 /* Loop here indefinitely - allows you to see messages from GSM code in
2276 response to unknown messages etc. The loops ends after pressing the
2278 data.RFUnits=&rf_units;
2279 data.RFLevel=&rflevel;
2280 data.BatteryUnits=&batt_units;
2281 data.BatteryLevel=&batterylevel;
2283 while (!bshutdown) {
2284 if (SM_Functions(GOP_GetRFLevel,&data,sm) == GE_NONE)
2285 fprintf(stdout, _("RFLevel: %d\n"), (int)rflevel);
2287 if (SM_Functions(GOP_GetBatteryLevel,&data,sm) == GE_NONE)
2288 fprintf(stdout, _("Battery: %d\n"), (int)batterylevel);
2290 // if (GSM->GetPowerSource(&powersource) == GE_NONE)
2291 // fprintf(stdout, _("Power Source: %s\n"), (powersource==GPS_ACDC)?_("AC/DC"):_("battery"));
2293 data.MemoryStatus=&SIMMemoryStatus;
2294 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2295 fprintf(stdout, _("SIM: Used %d, Free %d\n"), SIMMemoryStatus.Used, SIMMemoryStatus.Free);
2297 data.MemoryStatus=&PhoneMemoryStatus;
2298 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2299 fprintf(stdout, _("Phone: Used %d, Free %d\n"), PhoneMemoryStatus.Used, PhoneMemoryStatus.Free);
2301 data.MemoryStatus=&DC_MemoryStatus;
2302 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2303 fprintf(stdout, _("DC: Used %d, Free %d\n"), DC_MemoryStatus.Used, DC_MemoryStatus.Free);
2305 data.MemoryStatus=&EN_MemoryStatus;
2306 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2307 fprintf(stdout, _("EN: Used %d, Free %d\n"), EN_MemoryStatus.Used, EN_MemoryStatus.Free);
2309 data.MemoryStatus=&FD_MemoryStatus;
2310 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2311 fprintf(stdout, _("FD: Used %d, Free %d\n"), FD_MemoryStatus.Used, FD_MemoryStatus.Free);
2313 data.MemoryStatus=&LD_MemoryStatus;
2314 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2315 fprintf(stdout, _("LD: Used %d, Free %d\n"), LD_MemoryStatus.Used, LD_MemoryStatus.Free);
2317 data.MemoryStatus=&MC_MemoryStatus;
2318 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2319 fprintf(stdout, _("MC: Used %d, Free %d\n"), MC_MemoryStatus.Used, MC_MemoryStatus.Free);
2321 data.MemoryStatus=&ON_MemoryStatus;
2322 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2323 fprintf(stdout, _("ON: Used %d, Free %d\n"), ON_MemoryStatus.Used, ON_MemoryStatus.Free);
2325 data.MemoryStatus=&RC_MemoryStatus;
2326 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2327 fprintf(stdout, _("RC: Used %d, Free %d\n"), RC_MemoryStatus.Used, RC_MemoryStatus.Free);
2329 // if (GSM->GetSMSStatus(&SMSStatus) == GE_NONE)
2330 // fprintf(stdout, _("SMS Messages: UnRead %d, Number %d\n"), SMSStatus.UnRead, SMSStatus.Number);
2332 // if (GSM->GetIncomingCallNr(Number) == GE_NONE)
2333 // fprintf(stdout, _("Incoming call: %s\n"), Number);
2335 // if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE)
2336 // fprintf(stdout, _("Network: %s (%s), LAC: %s, CellID: %s\n"), GSM_GetNetworkName (NetworkInfo.NetworkCode), GSM_GetCountryName(NetworkInfo.NetworkCode), NetworkInfo.LAC, NetworkInfo.CellID);
2338 // if (GSM->ReadCellBroadcast(&CBMessage) == GE_NONE)
2339 // fprintf(stdout, _("Cell broadcast received on channel %d: %s\n"), CBMessage.Channel, CBMessage.Message);
2344 fprintf (stderr, _("Leaving monitor mode...\n"));
2354 static GSM_Error PrettyOutputFn(char *Display, char *Indicators)
2357 printf(ESC "[10;0H Display is:\n%s\n", Display);
2359 printf(ESC "[9;0H Indicators: %s \n", Indicators);
2360 printf(ESC "[1;1H");
2365 // Uncomment it if used
2366 static GSM_Error OutputFn(char *Display, char *Indicators)
2369 printf("New display is:\n%s\n", Display);
2371 printf("Indicators: %s\n", Indicators);
2376 void console_raw(void)
2381 tcgetattr(fileno(stdin), &it);
2382 it.c_lflag &= ~(ICANON);
2383 //it.c_iflag &= ~(INPCK|ISTRIP|IXON);
2387 tcsetattr(fileno(stdin), TCSANOW, &it);
2391 int displayoutput(void)
2394 GSM_Statemachine *sm = &State;
2397 data.OutputFn = PrettyOutputFn;
2399 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2401 fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
2403 if (error == GE_NONE) {
2405 /* We do not want to see texts forever - press Ctrl+C to stop. */
2406 signal(SIGINT, interrupted);
2408 fprintf (stderr, _("Entered display monitoring mode...\n"));
2409 fprintf (stderr, ESC "c" );
2411 /* Loop here indefinitely - allows you to read texts from phone's
2412 display. The loops ends after pressing the Ctrl+C. */
2413 while (!bshutdown) {
2415 memset(&buf[0], 0, 102);
2416 while (read(0, buf, 100) > 0) {
2417 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
2418 if (GSM->HandleString(buf) != GE_NONE)
2419 fprintf(stdout, _("Key press simulation failed.\n"));
2420 memset(buf, 0, 102);
2424 fprintf (stderr, "Shutting down\n");
2426 fprintf (stderr, _("Leaving display monitor mode...\n"));
2427 data.OutputFn = NULL;
2429 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2430 if (error != GE_NONE)
2431 fprintf (stderr, _("Error!\n"));
2433 fprintf (stderr, _("Error!\n"));
2439 /* Reads profile from phone and displays its' settings */
2440 int getprofile(int argc, char *argv[])
2444 GSM_Profile profile;
2447 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2451 error = GSM->GetProfile(&profile);
2453 if (error == GE_NONE) {
2455 while (GSM->GetModel(model) != GE_NONE)
2458 max_profiles = 7; /* This is correct for 6110 (at least my). How do we get
2459 the number of profiles? */
2462 /*FIX ME: It should be set to 3 for N5130 and 3210 too*/
2463 if (!strcmp(model, "NSE-1"))
2467 profile.Number = atoi(argv[0]) - 1;
2468 start = profile.Number;
2471 if (profile.Number < 0) {
2472 fprintf(stderr, _("Profile number must be value from 1 to %d!\n"), max_profiles);
2477 if (profile.Number >= max_profiles) {
2478 fprintf(stderr, _("This phone supports only %d profiles!\n"), max_profiles);
2484 stop = max_profiles;
2491 if (profile.Number != 0)
2492 GSM->GetProfile(&profile);
2494 fprintf(stdout, "%d. \"%s\"\n", profile.Number + 1, profile.Name);
2495 if (profile.DefaultName == -1) fprintf(stdout, _(" (name defined)\n"));
2497 fprintf(stdout, _("Incoming call alert: %s\n"), GetProfileCallAlertString(profile.CallAlert));
2499 /* For different phones different ringtones names */
2501 if (!strcmp(model, "NSE-3"))
2502 fprintf(stdout, _("Ringing tone: %s (%d)\n"), RingingTones[profile.Ringtone], profile.Ringtone);
2504 fprintf(stdout, _("Ringtone number: %d\n"), profile.Ringtone);
2506 fprintf(stdout, _("Ringing volume: %s\n"), GetProfileVolumeString(profile.Volume));
2508 fprintf(stdout, _("Message alert tone: %s\n"), GetProfileMessageToneString(profile.MessageTone));
2510 fprintf(stdout, _("Keypad tones: %s\n"), GetProfileKeypadToneString(profile.KeypadTone));
2512 fprintf(stdout, _("Warning and game tones: %s\n"), GetProfileWarningToneString(profile.WarningTone));
2514 /* FIXME: Light settings is only used for Car */
2515 if (profile.Number == (max_profiles - 2)) fprintf(stdout, _("Lights: %s\n"), profile.Lights ? _("On") : _("Automatic"));
2517 fprintf(stdout, _("Vibration: %s\n"), GetProfileVibrationString(profile.Vibration));
2519 /* FIXME: it will be nice to add here reading caller group name. */
2520 if (max_profiles != 3) fprintf(stdout, _("Caller groups: 0x%02x\n"), profile.CallerGroups);
2522 /* FIXME: Automatic answer is only used for Car and Headset. */
2523 if (profile.Number >= (max_profiles - 2)) fprintf(stdout, _("Automatic answer: %s\n"), profile.AutomaticAnswer ? _("On") : _("Off"));
2525 fprintf(stdout, "\n");
2530 if (error == GE_NOTIMPLEMENTED) {
2531 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2535 fprintf(stderr, _("Unspecified error\n"));
2545 /* Get requested range of memory storage entries and output to stdout in
2546 easy-to-parse format */
2547 int getmemory(int argc, char *argv[])
2549 GSM_PhonebookEntry entry;
2552 char *memory_type_string;
2555 GSM_Statemachine *sm = &State;
2557 /* Handle command line args that set type, start and end locations. */
2558 memory_type_string = argv[0];
2559 entry.MemoryType = StrToMemoryType(memory_type_string);
2560 if (entry.MemoryType == GMT_XX) {
2561 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
2565 start_entry = atoi (argv[1]);
2566 if (argc > 2) end_entry = atoi (argv[2]);
2567 else end_entry = start_entry;
2569 /* Now retrieve the requested entries. */
2570 for (count = start_entry; count <= end_entry; count ++) {
2572 entry.Location = count;
2574 data.PhonebookEntry=&entry;
2575 error=SM_Functions(GOP_ReadPhonebook,&data,sm);
2577 if (error == GE_NONE) {
2578 fprintf(stdout, "%s;%s;%s;%d;%d\n", entry.Name, entry.Number, memory_type_string, entry.Location, entry.Group);
2579 if (entry.MemoryType == GMT_MC || entry.MemoryType == GMT_DC || entry.MemoryType == GMT_RC)
2580 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);
2583 if (error == GE_NOTIMPLEMENTED) {
2584 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2587 else if (error == GE_INVALIDMEMORYTYPE) {
2588 fprintf(stderr, _("Memory type %s not supported!\n"), memory_type_string);
2592 fprintf(stdout, _("%s|%d|Bad location or other error!(%d)\n"), memory_type_string, count, error);
2598 /* Read data from stdin, parse and write to phone. The parsing is relatively
2599 crude and doesn't allow for much variation from the stipulated format. */
2600 /* FIXME: I guess there's *very* similar code in xgnokii */
2601 int writephonebook(int argc, char *args[])
2603 GSM_PhonebookEntry entry;
2605 char *memory_type_string;
2609 char *Line, OLine[100], BackLine[100];
2612 /* Check argument */
2613 if (argc && (strcmp("-i", args[0])))
2618 /* Go through data from stdin. */
2619 while (GetLine(stdin, Line, 99)) {
2620 strcpy(BackLine, Line);
2623 ptr = strtok(Line, ";");
2624 if (ptr) strcpy(entry.Name, ptr);
2625 else entry.Name[0] = 0;
2627 ptr = strtok(NULL, ";");
2628 if (ptr) strcpy(entry.Number, ptr);
2629 else entry.Number[0] = 0;
2631 ptr = strtok(NULL, ";");
2634 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2639 if (!strncmp(ptr,"ME", 2)) {
2640 memory_type_string = "int";
2641 entry.MemoryType = GMT_ME;
2643 if (!strncmp(ptr,"SM", 2)) {
2644 memory_type_string = "sim";
2645 entry.MemoryType = GMT_SM;
2647 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2652 ptr = strtok(NULL, ";");
2653 if (ptr) entry.Location = atoi(ptr);
2654 else entry.Location = 0;
2656 ptr = strtok(NULL, ";");
2657 if (ptr) entry.Group = atoi(ptr);
2658 else entry.Group = 0;
2661 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2665 for (subentry = 0; ; subentry++) {
2666 ptr = strtok(NULL, ";");
2668 if (ptr && *ptr != 0)
2669 entry.SubEntries[subentry].EntryType = atoi(ptr);
2673 ptr = strtok(NULL, ";");
2675 entry.SubEntries[subentry].NumberType=atoi(ptr);
2677 /* Phone Numbers need to have a number type. */
2678 if (!ptr && entry.SubEntries[subentry].EntryType == GSM_Number) {
2679 fprintf(stderr, _("Missing phone number type on line %d"
2680 " entry %d [%s]\n"), line_count, subentry, BackLine);
2685 ptr = strtok(NULL, ";");
2687 entry.SubEntries[subentry].BlockNumber=atoi(ptr);
2689 ptr = strtok(NULL, ";");
2691 /* 0x13 Date Type; it is only for Dailed Numbers, etc.
2692 we don't store to this memories so it's an error to use it. */
2693 if (!ptr || entry.SubEntries[subentry].EntryType == GSM_Date) {
2694 fprintf(stdout, _("There is no phone number on line %d entry %d [%s]\n"),
2695 line_count, subentry, BackLine);
2699 strcpy(entry.SubEntries[subentry].data.Number, ptr);
2702 entry.SubEntriesCount = subentry;
2704 /* This is to send other exports (like from 6110) to 7110 */
2705 if (!entry.SubEntriesCount) {
2706 entry.SubEntriesCount = 1;
2707 entry.SubEntries[subentry].EntryType = GSM_Number;
2708 entry.SubEntries[subentry].NumberType = GSM_General;
2709 entry.SubEntries[subentry].BlockNumber = 2;
2710 strcpy(entry.SubEntries[subentry].data.Number, entry.Number);
2716 GSM_PhonebookEntry aux;
2718 aux.Location = entry.Location;
2719 error = GSM->GetMemoryLocation(&aux);
2721 if (error == GE_NONE) {
2726 fprintf(stdout, _("Location busy. "));
2727 while (confirm < 0) {
2728 fprintf(stdout, _("Overwrite? (yes/no) "));
2729 GetLine(stdin, ans, 7);
2730 if (!strcmp(ans, _("yes"))) confirm = 1;
2731 else if (!strcmp(ans, _("no"))) confirm = 0;
2733 if (!confirm) continue;
2736 fprintf(stderr, _("Unknown error (%d)\n"), error);
2742 /* Do write and report success/failure. */
2743 error = GSM->WritePhonebookLocation(&entry);
2745 if (error == GE_NONE)
2746 fprintf (stdout, _("Write Succeeded: memory type: %s, loc: %d, name: %s, number: %s\n"), memory_type_string, entry.Location, entry.Name, entry.Number);
2748 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);
2756 /* Getting speed dials. */
2757 int getspeeddial(char *Number)
2759 GSM_SpeedDial SpeedDial;
2763 SpeedDial.Number = atoi(Number);
2765 if (GSM && GSM->GetSpeedDial && GSM->Terminate) {
2766 error = GSM->GetSpeedDial(&SpeedDial);
2769 GSM_DataClear(&data);
2770 data.SpeedDial = &SpeedDial;
2772 error = SM_Functions(GOP_GetSpeedDial, &data, &State);
2777 fprintf(stdout, _("SpeedDial nr. %d: %d:%d\n"), SpeedDial.Number, SpeedDial.MemoryType, SpeedDial.Location);
2779 case GE_NOTIMPLEMENTED:
2780 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2783 fprintf(stdout, _("Internal error\n"));
2790 /* Setting speed dials. */
2791 int setspeeddial(char *argv[])
2793 GSM_SpeedDial entry;
2795 char *memory_type_string;
2797 /* Handle command line args that set type, start and end locations. */
2799 if (strcmp(argv[1], "ME") == 0) {
2800 entry.MemoryType = 0x02;
2801 memory_type_string = "ME";
2802 } else if (strcmp(argv[1], "SM") == 0) {
2803 entry.MemoryType = 0x03;
2804 memory_type_string = "SM";
2806 fprintf(stderr, _("Unknown memory type %s!\n"), argv[1]);
2810 entry.Number = atoi(argv[0]);
2811 entry.Location = atoi(argv[2]);
2813 if (GSM->SetSpeedDial(&entry) == GE_NONE) {
2814 fprintf(stdout, _("Succesfully written!\n"));
2821 /* Getting the status of the display. */
2822 int getdisplaystatus(void)
2826 GSM->GetDisplayStatus(&Status);
2828 fprintf(stdout, _("Call in progress: %s\n"), Status & (1<<DS_Call_In_Progress)?_("on"):_("off"));
2829 fprintf(stdout, _("Unknown: %s\n"), Status & (1<<DS_Unknown)?_("on"):_("off"));
2830 fprintf(stdout, _("Unread SMS: %s\n"), Status & (1<<DS_Unread_SMS)?_("on"):_("off"));
2831 fprintf(stdout, _("Voice call: %s\n"), Status & (1<<DS_Voice_Call)?_("on"):_("off"));
2832 fprintf(stdout, _("Fax call active: %s\n"), Status & (1<<DS_Fax_Call)?_("on"):_("off"));
2833 fprintf(stdout, _("Data call active: %s\n"), Status & (1<<DS_Data_Call)?_("on"):_("off"));
2834 fprintf(stdout, _("Keyboard lock: %s\n"), Status & (1<<DS_Keyboard_Lock)?_("on"):_("off"));
2835 fprintf(stdout, _("SMS storage full: %s\n"), Status & (1<<DS_SMS_Storage_Full)?_("on"):_("off"));
2841 int netmonitor(char *Mode)
2843 unsigned char mode = atoi(Mode);
2846 if (!strcmp(Mode, "reset"))
2848 else if (!strcmp(Mode, "off"))
2850 else if (!strcmp(Mode, "field"))
2852 else if (!strcmp(Mode, "devel"))
2854 else if (!strcmp(Mode, "next"))
2857 memset(&Screen, 0, 50);
2858 GSM->NetMonitor(mode, Screen);
2861 fprintf(stdout, "%s\n", Screen);
2869 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2870 char imei[64], model[64], rev[64], manufacturer[64];
2871 GSM_Statemachine *sm = &State;
2873 data.Manufacturer=manufacturer;
2878 /* Retrying is bad idea: what if function is simply not implemented?
2879 Anyway let's wait 2 seconds for the right packet from the phone. */
2882 strcpy(imei, "(unknown)");
2883 strcpy(manufacturer, "(unknown)");
2884 strcpy(model, "(unknown)");
2885 strcpy(rev, "(unknown)");
2887 SM_Functions(GOP_Identify, &data, sm);
2889 fprintf(stdout, _("IMEI: %s\n"), imei);
2890 fprintf(stdout, _("Manufacturer: %s\n"), manufacturer);
2891 fprintf(stdout, _("Model: %s\n"), model);
2892 fprintf(stdout, _("Revision: %s\n"), rev);
2899 int senddtmf(char *String)
2901 GSM->SendDTMF(String);
2906 /* Resets the phone */
2907 int reset( char *type)
2909 unsigned char _type = 0x03;
2912 if(!strcmp(type, "soft"))
2915 if(!strcmp(type, "hard"))
2918 fprintf(stderr, _("What kind of reset do you want??\n"));
2929 /* pmon allows fbus code to run in a passive state - it doesn't worry about
2930 whether comms are established with the phone. A debugging/development
2936 GSM_ConnectionType connection=GCT_Serial;
2937 GSM_Statemachine sm;
2939 /* Initialise the code for the GSM interface. */
2940 error = GSM_Initialise(model, Port, Initlength, connection, NULL, &sm);
2942 if (error != GE_NONE) {
2943 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
2954 int sendringtone(int argc, char *argv[])
2956 GSM_Ringtone ringtone;
2959 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2960 fprintf(stdout, _("Failed to load ringtone.\n"));
2964 error = GSM->SendRingtone(&ringtone,argv[1]);
2966 if (error == GE_NONE)
2967 fprintf(stdout, _("Send succeeded!\n"));
2969 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
2977 int setringtone(int argc, char *argv[])
2979 GSM_Ringtone ringtone;
2982 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2983 fprintf(stdout, _("Failed to load ringtone.\n"));
2987 error = GSM->SetRingtone(&ringtone);
2989 if (error == GE_NONE)
2990 fprintf(stdout, _("Send succeeded!\n"));
2992 fprintf(stdout, _("Send failed\n"));
2999 int presskeysequence(void)
3005 memset(&buf[0], 0, 102);
3006 while (read(0, buf, 100) > 0) {
3007 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
3008 if (GSM->HandleString(buf) != GE_NONE)
3009 fprintf(stdout, _("Key press simulation failed.\n"));
3010 memset(buf, 0, 102);
3017 /* This is a "convenience" function to allow quick test of new API stuff which
3018 doesn't warrant a "proper" command line function. */
3020 int foogle(char *argv[])
3022 /* Initialise the code for the GSM interface. */
3024 // Fill in what you would like to test here...