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.2 2001/11/27 22:01:25 short
23 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Nov 27 22:58 CET 2001
25 Revision 1.152 2001/11/27 12:23:11 pkot
26 Specifying SMSC number in --sendsms works again
28 Revision 1.151 2001/11/22 17:56:53 pkot
29 smslib update. sms sending
31 Revision 1.150 2001/11/20 16:22:22 pkot
32 First attempt to read Picture Messages. They should appear when you enable DEBUG. Nokia seems to break own standards. :/ (Markus Plail)
34 Revision 1.149 2001/11/19 16:00:15 pkot
37 Revision 1.148 2001/11/19 13:46:43 pkot
38 reading unread SMS in 6210 from Inbox. Folder updates (Markus Plail)
40 Revision 1.147 2001/11/18 00:54:32 pkot
41 Bugfixes. I18n of the user responses. UDH support in libsms. Business Card UDH Type
43 Revision 1.146 2001/11/17 20:18:33 pkot
44 Added dau9p connection type for 6210/7110
46 Revision 1.145 2001/11/14 10:46:12 pkot
47 Small cleanup with __unices__
49 Revision 1.144 2001/11/08 16:34:19 pkot
50 Updates to work with new libsms
52 Revision 1.143 2001/09/14 13:30:07 pkot
53 Fixed bugs introduced during 0.3.3 merge
55 Revision 1.142 2001/09/14 13:02:03 pkot
56 Gnokii calendar changes from 0.3.3
58 Revision 1.141 2001/09/14 12:53:00 pkot
61 Set valid operator on logos xgnokii screen.
63 Revision 1.140 2001/07/27 00:02:21 pkot
64 Generic AT support for the new structure (Manfred Jonsson)
66 Revision 1.139 2001/07/01 23:16:45 pkot
67 Fixed a typo in gnokii.c avoiding saving logo (Jan Havelka)
69 Revision 1.138 2001/06/28 00:28:45 pkot
70 Small docs updates (Pawel Kot)
72 Revision 1.137 2001/06/27 23:52:50 pkot
73 7110/6210 updates (Marian Jancar)
75 Revision 1.136 2001/06/10 23:49:49 pkot
76 Small fixes to hide compilation warnings and allow gnokii.c to compile
78 Revision 1.135 2001/06/10 11:42:26 machek
79 Cleanup: some formating, made Statemachine global, converted to new
80 structure w.r.t. SMS-es
82 Revision 1.134 2001/05/24 20:47:30 chris
83 More updating of 7110 code and some of xgnokii_lowlevel changed over.
85 Revision 1.133 2001/04/23 17:20:01 pkot
86 Added possibility for viewing logos (currently nol and ngg) on console (Bartek Klepacz)
88 Revision 1.132 2001/03/21 23:36:06 chris
89 Added the statemachine
90 This will break gnokii --identify and --monitor except for 6210/7110
92 Revision 1.131 2001/03/19 23:43:46 pkot
93 Solaris / BSD '#if defined' cleanup
95 Revision 1.130 2001/03/13 01:23:18 pkot
96 Windows updates (Manfred Jonsson)
98 Revision 1.129 2001/03/13 01:21:39 pkot
99 *BSD updates (Bert Driehuis)
101 Revision 1.128 2001/03/08 00:49:06 pkot
102 Fixed bug (introduced by me) in getmemory function. Now gnokii.c should compile
104 Revision 1.127 2001/03/08 00:18:13 pkot
105 Fixed writephonebook once again. Someone kick me please...
107 Revision 1.126 2001/03/07 21:46:12 pkot
108 Fixed writephonebook patch
110 Revision 1.125 2001/03/06 22:19:14 pkot
111 Cleanups and fixes in gnokii.c:
113 - fixed bug reported by Gabriele Zappi
114 - fixed small bugs introduced by Pavel Machek
116 Revision 1.124 2001/02/28 21:42:00 machek
117 Possibility to force overwrite in --getsms (-F). Possibility to get
118 multiple files (use --getsms -f xyzzy%d), cleanup.
120 Revision 1.123 2001/02/20 21:55:11 pkot
121 Small #include updates
123 Revision 1.122 2001/02/16 14:29:53 chris
124 Restructure of common/. Fixed a problem in fbus-phonet.c
125 Lots of dprintfs for Marcin
126 Any size xpm can now be loaded (eg for 7110 startup logos)
127 nk7110 code detects 7110/6210 and alters startup logo size to suit
128 Moved Marcin's extended phonebook code into gnokii.c
130 Revision 1.121 2001/02/06 21:15:35 chris
131 Preliminary irda support for 7110 etc. Not well tested!
133 Revision 1.120 2001/02/06 08:13:32 pkot
134 One more include in gnokii.c needed
136 Revision 1.119 2001/02/05 12:29:37 pkot
137 Changes needed to let unicode work
139 Revision 1.118 2001/02/01 15:17:33 pkot
140 Fixed --identify and added Manfred's manufacturer patch
142 Revision 1.117 2001/01/31 23:45:27 pkot
143 --identify should work ok now
145 Revision 1.116 2001/01/24 20:19:55 machek
146 Do not retry identification, if it is not implemented, it is bad idea.
148 Revision 1.115 2001/01/22 01:25:10 hugh
149 Tweaks for 3810 series, datacalls seem to be broken so need to do
150 some more debugging...
152 Revision 1.114 2001/01/17 02:54:55 chris
153 More 7110 work. Use with care! (eg it is not possible to delete phonebook entries)
154 I can now edit my phonebook in xgnokii but it is 'work in progress'.
156 Revision 1.113 2001/01/15 17:00:49 pkot
157 Initial keypress sequence support. Disable compilation warning
159 Revision 1.112 2001/01/12 14:09:13 pkot
160 More cleanups. This time mainly in the code.
162 Revision 1.111 2001/01/10 16:32:18 pkot
163 Documentation updates.
164 FreeBSD fix for 3810 code.
165 Added possibility for deleting SMS just after reading it in gnokii.
169 Revision 1.110 2001/01/08 15:11:37 pkot
170 Documentation updates.
171 Fixed some bugs and removed FIXMEs.
172 We need to move some stuff from configure.in to aclocal.m4
174 Revision 1.109 2000/12/29 15:39:07 pkot
175 Reverted a change in fbus-3810.c which broke compling with --enable-debug.
176 Small fixes in gnokii.c
178 Revision 1.108 2000/12/19 16:18:16 pkot
179 configure script updates and added shared function for configfile reading
191 # include <strings.h> /* for memset */
194 #include <sys/types.h>
195 #include <sys/stat.h>
200 #define sleep(x) Sleep((x) * 1000)
201 #define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
203 #include "win32/getopt.h"
218 #include "gsm-common.h"
220 #include "gsm-networks.h"
221 #include "cfgreader.h"
223 #include "gsm-filetypes.h"
224 #include "gsm-bitmaps.h"
225 #include "gsm-ringtones.h"
226 #include "gsm-statemachine.h"
228 char *model; /* Model from .gnokiirc file. */
229 char *Port; /* Serial port from .gnokiirc file */
230 char *Initlength; /* Init length from .gnokiirc file */
231 char *Connection; /* Connection type from .gnokiirc file */
232 char *BinDir; /* Binaries directory from .gnokiirc file - not used here yet */
233 /* Local variables */
235 char *GetProfileCallAlertString(int code)
238 case PROFILE_CALLALERT_RINGING: return "Ringing";
239 case PROFILE_CALLALERT_ASCENDING: return "Ascending";
240 case PROFILE_CALLALERT_RINGONCE: return "Ring once";
241 case PROFILE_CALLALERT_BEEPONCE: return "Beep once";
242 case PROFILE_CALLALERT_CALLERGROUPS: return "Caller groups";
243 case PROFILE_CALLALERT_OFF: return "Off";
244 default: return "Unknown";
248 char *GetProfileVolumeString(int code)
251 case PROFILE_VOLUME_LEVEL1: return "Level 1";
252 case PROFILE_VOLUME_LEVEL2: return "Level 2";
253 case PROFILE_VOLUME_LEVEL3: return "Level 3";
254 case PROFILE_VOLUME_LEVEL4: return "Level 4";
255 case PROFILE_VOLUME_LEVEL5: return "Level 5";
256 default: return "Unknown";
260 char *GetProfileKeypadToneString(int code)
263 case PROFILE_KEYPAD_OFF: return "Off";
264 case PROFILE_KEYPAD_LEVEL1: return "Level 1";
265 case PROFILE_KEYPAD_LEVEL2: return "Level 2";
266 case PROFILE_KEYPAD_LEVEL3: return "Level 3";
267 default: return "Unknown";
271 char *GetProfileMessageToneString(int code)
274 case PROFILE_MESSAGE_NOTONE: return "No tone";
275 case PROFILE_MESSAGE_STANDARD: return "Standard";
276 case PROFILE_MESSAGE_SPECIAL: return "Special";
277 case PROFILE_MESSAGE_BEEPONCE: return "Beep once";
278 case PROFILE_MESSAGE_ASCENDING: return "Ascending";
279 default: return "Unknown";
283 char *GetProfileWarningToneString(int code)
286 case PROFILE_WARNING_OFF: return "Off";
287 case PROFILE_WARNING_ON: return "On";
288 default: return "Unknown";
292 char *GetProfileVibrationString(int code)
295 case PROFILE_VIBRATION_OFF: return "Off";
296 case PROFILE_VIBRATION_ON: return "On";
297 default: return "Unknown";
301 /* This function shows the copyright and some informations usefull for
306 fprintf(stdout, _("GNOKII Version %s\n"
307 "Copyright (C) Hugh Blemings <hugh@blemings.org>, 1999, 2000\n"
308 "Copyright (C) Pavel Janík ml. <Pavel.Janik@suse.cz>, 1999, 2000\n"
309 "Copyright (C) Pavel Machek <pavel@ucw.cz>, 2001\n"
310 "Copyright (C) Pawe³ Kot <pkot@linuxnews.pl>, 2001\n"
311 "gnokii is free software, covered by the GNU General Public License, and you are\n"
312 "welcome to change it and/or distribute copies of it under certain conditions.\n"
313 "There is absolutely no warranty for gnokii. See GPL for details.\n"
314 "Built %s %s for %s on %s \n"), VERSION, __TIME__, __DATE__, model, Port);
318 /* The function usage is only informative - it prints this program's usage and
319 command-line options. */
323 fprintf(stdout, _(" usage: gnokii [--help|--monitor|--version]\n"
324 " gnokii --getmemory memory_type start [end]\n"
325 " gnokii --writephonebook [-i]\n"
326 " gnokii --getspeeddial number\n"
327 " gnokii --setspeeddial number memory_type location\n"
328 " gnokii --getsms memory_type start [end] [-f file] [-F file] [-d]\n"
329 " gnokii --deletesms memory_type start [end]\n"
330 " gnokii --sendsms destination [--smsc message_center_number |\n"
331 " --smscno message_center_index] [-r] [-C n] [-v n]\n"
333 " gnokii --savesms [-m] [-l n] [-i]\n"
334 " gnokii --getsmsc message_center_number\n"
335 " gnokii --setdatetime [YYYY [MM [DD [HH [MM]]]]]\n"
336 " gnokii --getdatetime\n"
337 " gnokii --setalarm HH MM\n"
338 " gnokii --getalarm\n"
339 " gnokii --dialvoice number\n"
340 " gnokii --getcalendarnote start [end] [-v]\n"
341 " gnokii --writecalendarnote vcardfile number\n"
342 " gnokii --deletecalendarnote start [end]\n"
343 " gnokii --getdisplaystatus\n"
344 " gnokii --netmonitor {reset|off|field|devel|next|nr}\n"
345 " gnokii --identify\n"
346 " gnokii --senddtmf string\n"
347 " gnokii --sendlogo {caller|op} destination logofile [network code]\n"
348 " gnokii --sendringtone destination rtttlfile\n"
349 " gnokii --setlogo op [logofile] [network code]\n"
350 " gnokii --setlogo startup [logofile]\n"
351 " gnokii --setlogo caller [logofile] [caller group number] [group name]\n"
352 " gnokii --setlogo {dealer|text} [text]\n"
353 " gnokii --getlogo op [logofile] [network code]\n"
354 " gnokii --getlogo startup [logofile] [network code]\n"
355 " gnokii --getlogo caller [logofile][caller group number][network code]\n"
356 " gnokii --getlogo {dealer|text}\n"
357 " gnokii --viewlogo logofile\n"
358 " gnokii --setringtone rtttlfile\n"
359 " gnokii --reset [soft|hard]\n"
360 " gnokii --getprofile [number]\n"
361 " gnokii --displayoutput\n"
362 " gnokii --keysequence\n"
366 " gnokii --entersecuritycode PIN|PIN2|PUK|PUK2\n"
367 " gnokii --getsecuritycodestatus\n"
373 /* fbusinit is the generic function which waits for the FBUS link. The limit
374 is 10 seconds. After 10 seconds we quit. */
376 static GSM_Statemachine State;
377 static GSM_Data data;
379 void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame))
383 GSM_ConnectionType connection = GCT_Serial;
385 GSM_DataClear(&data);
387 if (!strcasecmp(Connection, "dau9p")) connection = GCT_DAU9P;
388 if (!strcasecmp(Connection, "infrared")) connection = GCT_Infrared;
389 if (!strcasecmp(Connection, "irda")) connection = GCT_Irda;
391 /* Initialise the code for the GSM interface. */
393 error = GSM_Initialise(model, Port, Initlength, connection, rlp_handler, &State);
395 if (error != GE_NONE) {
396 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
400 /* First (and important!) wait for GSM link to be active. We allow 10
403 while (count++ < 200 && *GSM_LinkOK == false)
406 if (*GSM_LinkOK == false) {
407 fprintf (stderr, _("Hmmm... GSM_LinkOK never went true. Quitting.\n"));
412 /* This function checks that the argument count for a given options is withing
414 int checkargs(int opt, struct gnokii_arg_len gals[], int argc)
418 /* Walk through the whole array with options requiring arguments. */
419 for (i = 0; !(gals[i].gal_min == 0 && gals[i].gal_max == 0); i++) {
421 /* Current option. */
422 if (gals[i].gal_opt == opt) {
424 /* Argument count checking. */
425 if (gals[i].gal_flags == GAL_XOR) {
426 if (gals[i].gal_min == argc || gals[i].gal_max == argc)
429 if (gals[i].gal_min <= argc && gals[i].gal_max >= argc)
437 /* We do not have options without arguments in the array, so check them. */
438 if (argc == 0) return 0;
442 /* Main function - handles command line arguments, passes them to separate
443 functions accordingly. */
444 int main(int argc, char *argv[])
450 /* Every option should be in this array. */
451 static struct option long_options[] =
453 /* FIXME: these comments are nice, but they would be more usefull as docs for the user */
455 { "help", no_argument, NULL, OPT_HELP },
457 // Display version and build information.
458 { "version", no_argument, NULL, OPT_VERSION },
461 { "monitor", no_argument, NULL, OPT_MONITOR },
465 // Enter Security Code mode
466 { "entersecuritycode", required_argument, NULL, OPT_ENTERSECURITYCODE },
468 // Get Security Code status
469 { "getsecuritycodestatus", no_argument, NULL, OPT_GETSECURITYCODESTATUS },
474 { "setdatetime", optional_argument, NULL, OPT_SETDATETIME },
476 // Get date and time mode
477 { "getdatetime", no_argument, NULL, OPT_GETDATETIME },
480 { "setalarm", required_argument, NULL, OPT_SETALARM },
483 { "getalarm", no_argument, NULL, OPT_GETALARM },
486 { "dialvoice", required_argument, NULL, OPT_DIALVOICE },
488 // Get calendar note mode
489 { "getcalendarnote", required_argument, NULL, OPT_GETCALENDARNOTE },
491 // Write calendar note mode
492 { "writecalendarnote", required_argument, NULL, OPT_WRITECALENDARNOTE },
494 // Delete calendar note mode
495 { "deletecalendarnote", required_argument, NULL, OPT_DELCALENDARNOTE },
497 // Get display status mode
498 { "getdisplaystatus", no_argument, NULL, OPT_GETDISPLAYSTATUS },
501 { "getmemory", required_argument, NULL, OPT_GETMEMORY },
503 // Write phonebook (memory) mode
504 { "writephonebook", optional_argument, NULL, OPT_WRITEPHONEBOOK },
506 // Get speed dial mode
507 { "getspeeddial", required_argument, NULL, OPT_GETSPEEDDIAL },
509 // Set speed dial mode
510 { "setspeeddial", required_argument, NULL, OPT_SETSPEEDDIAL },
512 // Get SMS message mode
513 { "getsms", required_argument, NULL, OPT_GETSMS },
515 // Delete SMS message mode
516 { "deletesms", required_argument, NULL, OPT_DELETESMS },
518 // Send SMS message mode
519 { "sendsms", required_argument, NULL, OPT_SENDSMS },
521 // Ssve SMS message mode
522 { "savesms", optional_argument, NULL, OPT_SAVESMS },
524 // Send logo as SMS message mode
525 { "sendlogo", required_argument, NULL, OPT_SENDLOGO },
527 // Send ringtone as SMS message
528 { "sendringtone", required_argument, NULL, OPT_SENDRINGTONE },
531 { "setringtone", required_argument, NULL, OPT_SETRINGTONE },
533 // Get SMS center number mode
534 { "getsmsc", required_argument, NULL, OPT_GETSMSC },
536 // For development purposes: run in passive monitoring mode
537 { "pmon", no_argument, NULL, OPT_PMON },
540 { "netmonitor", required_argument, NULL, OPT_NETMONITOR },
543 { "identify", no_argument, NULL, OPT_IDENTIFY },
545 // Send DTMF sequence
546 { "senddtmf", required_argument, NULL, OPT_SENDDTMF },
549 { "reset", optional_argument, NULL, OPT_RESET },
552 { "setlogo", optional_argument, NULL, OPT_SETLOGO },
555 { "getlogo", required_argument, NULL, OPT_GETLOGO },
558 { "viewlogo", required_argument, NULL, OPT_VIEWLOGO },
561 { "getprofile", optional_argument, NULL, OPT_GETPROFILE },
563 // Show texts from phone's display
564 { "displayoutput", no_argument, NULL, OPT_DISPLAYOUTPUT },
566 // Simulate pressing the keys
567 { "keysequence", no_argument, NULL, OPT_KEYPRESS },
569 // For development purposes: insert you function calls here
570 { "foogle", no_argument, NULL, OPT_FOOGLE },
575 /* Every command which requires arguments should have an appropriate entry
577 struct gnokii_arg_len gals[] =
581 { OPT_ENTERSECURITYCODE, 1, 1, 0 },
584 { OPT_SETDATETIME, 0, 5, 0 },
585 { OPT_SETALARM, 2, 2, 0 },
586 { OPT_DIALVOICE, 1, 1, 0 },
587 { OPT_GETCALENDARNOTE, 1, 3, 0 },
588 { OPT_WRITECALENDARNOTE, 2, 2, 0 },
589 { OPT_DELCALENDARNOTE, 1, 2, 0 },
590 { OPT_GETMEMORY, 2, 3, 0 },
591 { OPT_GETSPEEDDIAL, 1, 1, 0 },
592 { OPT_SETSPEEDDIAL, 3, 3, 0 },
593 { OPT_GETSMS, 2, 5, 0 },
594 { OPT_DELETESMS, 2, 3, 0 },
595 { OPT_SENDSMS, 1, 10, 0 },
596 { OPT_SAVESMS, 0, 6, 0 },
597 { OPT_SENDLOGO, 3, 4, GAL_XOR },
598 { OPT_SENDRINGTONE, 2, 2, 0 },
599 { OPT_GETSMSC, 1, 1, 0 },
600 { OPT_GETWELCOMENOTE, 1, 1, 0 },
601 { OPT_SETWELCOMENOTE, 1, 1, 0 },
602 { OPT_NETMONITOR, 1, 1, 0 },
603 { OPT_SENDDTMF, 1, 1, 0 },
604 { OPT_SETLOGO, 1, 4, 0 },
605 { OPT_GETLOGO, 1, 4, 0 },
606 { OPT_VIEWLOGO, 1, 1, 0 },
607 { OPT_SETRINGTONE, 1, 1, 0 },
608 { OPT_RESET, 0, 1, 0 },
609 { OPT_GETPROFILE, 0, 1, 0 },
610 { OPT_WRITEPHONEBOOK, 0, 1, 0 },
617 /* For GNU gettext */
619 textdomain("gnokii");
620 setlocale(LC_ALL, "");
623 /* Read config file */
624 if (readconfig(&model, &Port, &Initlength, &Connection, &BinDir) < 0) {
628 /* Handle command line arguments. */
629 c = getopt_long(argc, argv, "", long_options, NULL);
630 if (c == -1) /* No argument given - we should display usage. */
634 // First, error conditions
637 fprintf(stderr, _("Use '%s --help' for usage informations.\n"), argv[0]);
639 // Then, options with no arguments
646 /* We have to build an array of the arguments which will be passed to the
647 functions. Please note that every text after the --command will be
648 passed as arguments. A syntax like gnokii --cmd1 args --cmd2 args will
649 not work as expected; instead args --cmd2 args is passed as a
651 if ((nargv = malloc(sizeof(char *) * argc)) != NULL) {
652 for (i = 2; i < argc; i++)
653 nargv[i-2] = argv[i];
655 if (checkargs(c, gals, nargc)) {
656 free(nargv); /* Wrong number of arguments - we should display usage. */
661 /* have to ignore SIGALARM */
665 /* Initialise the code for the GSM interface. */
673 case OPT_ENTERSECURITYCODE:
674 rc = entersecuritycode(optarg);
676 case OPT_GETSECURITYCODESTATUS:
677 rc = getsecuritycodestatus();
680 case OPT_GETDATETIME:
686 case OPT_GETDISPLAYSTATUS:
687 rc = getdisplaystatus();
692 case OPT_WRITEPHONEBOOK:
693 rc = writephonebook(nargc, nargv);
695 // Now, options with arguments
696 case OPT_SETDATETIME:
697 rc = setdatetime(nargc, nargv);
700 rc = setalarm(nargv);
703 rc = dialvoice(optarg);
705 case OPT_GETCALENDARNOTE:
706 rc = getcalendarnote(nargc, nargv);
708 case OPT_DELCALENDARNOTE:
709 rc = deletecalendarnote(nargc, nargv);
711 case OPT_WRITECALENDARNOTE:
712 rc = writecalendarnote(nargv);
715 rc = getmemory(nargc, nargv);
717 case OPT_GETSPEEDDIAL:
718 rc = getspeeddial(optarg);
720 case OPT_SETSPEEDDIAL:
721 rc = setspeeddial(nargv);
724 rc = getsms(argc, argv);
727 rc = deletesms(nargc, nargv);
730 rc = sendsms(nargc, nargv);
733 rc = savesms(argc, argv);
736 rc = sendlogo(nargc, nargv);
739 rc = getsmsc(optarg);
742 rc = netmonitor(optarg);
748 rc = setlogo(nargc, nargv);
751 rc = getlogo(nargc, nargv);
754 rc = viewlogo(optarg);
756 case OPT_SETRINGTONE:
757 rc = setringtone(nargc, nargv);
759 case OPT_SENDRINGTONE:
760 rc = sendringtone(nargc, nargv);
763 rc = getprofile(nargc, nargv);
765 case OPT_DISPLAYOUTPUT:
766 rc = displayoutput();
769 rc = presskeysequence();
777 rc = senddtmf(optarg);
783 fprintf(stderr, _("Unknown option: %d\n"), c);
790 fprintf(stderr, _("Wrong number of arguments\n"));
794 /* Send SMS messages. */
795 int sendsms(int argc, char *argv[])
799 // char UDH[GSM_MAX_USER_DATA_HEADER_LENGTH];
800 /* The maximum length of an uncompressed concatenated short message is
801 255 * 153 = 39015 default alphabet characters */
802 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
803 int input_len, chars_read;
804 int i; /*, offset, nr_msg, aux;*/
806 struct option options[] = {
807 { "smsc", required_argument, NULL, '1'},
808 { "smscno", required_argument, NULL, '2'},
809 { "long", required_argument, NULL, '3'},
813 input_len = GSM_MAX_SMS_LENGTH;
821 - message validity for 3 days
822 - unset user data header indicator
825 memset(&SMS, 0, sizeof(GSM_SMSMessage));
827 SMS.Type = SMS_Submit;
828 SMS.DCS.Type = SMS_GeneralDataCoding;
829 SMS.DCS.u.General.Compressed = false;
830 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
831 SMS.DCS.u.General.Class = 0;
832 SMS.MessageCenter.No = 1;
833 SMS.Validity.VPF = SMS_RelativeFormat;
834 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
837 strcpy(SMS.RemoteNumber.number, argv[0]);
838 if (SMS.RemoteNumber.number[0] == '+') SMS.RemoteNumber.type = SMS_International;
839 else SMS.RemoteNumber.type = SMS_Unknown;
844 while ((i = getopt_long(argc, argv, "r8cC:v:", options, NULL)) != -1) {
845 switch (i) { // -8 is for 8-bit data, -c for compression. both are not yet implemented.
846 case '1': /* SMSC number */
847 SMS.MessageCenter.No = 0;
848 strcpy(SMS.MessageCenter.Number, optarg);
849 if (SMS.MessageCenter.Number[0] == '+') SMS.MessageCenter.Type = SMS_International;
850 else SMS.MessageCenter.Type = SMS_Unknown;
852 case '2': /* SMSC number index in phone memory */
853 SMS.MessageCenter.No = atoi(optarg);
855 if (SMS.MessageCenter.No < 1 || SMS.MessageCenter.No > 5)
857 data.MessageCenter = &SMS.MessageCenter;
858 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
860 case '3': /* we send long message */
861 input_len = atoi(optarg);
862 if (input_len > 255 * GSM_MAX_SMS_LENGTH) {
863 fprintf(stderr, _("Input too long!\n"));
867 case 'r': /* request for delivery report */
868 SMS.Type = SMS_Delivery_Report;
870 case 'C': /* class Message */
873 SMS.DCS.u.General.Class = 1;
876 SMS.DCS.u.General.Class = 2;
879 SMS.DCS.u.General.Class = 3;
882 SMS.DCS.u.General.Class = 4;
889 SMS.Validity.u.Relative = atoi(optarg);
892 usage(); /* Would be better to have an sendsms_usage() here. */
896 /* Get message text from stdin. */
897 chars_read = fread(message_buffer, 1, input_len, stdin);
899 if (chars_read == 0) {
900 fprintf(stderr, _("Couldn't read from stdin!\n"));
902 } else if (chars_read > input_len) {
903 fprintf(stderr, _("Input too long!\n"));
907 /* Null terminate. */
908 message_buffer[chars_read] = 0x00;
909 strncpy(SMS.MessageText, message_buffer, chars_read);
910 data.SMSMessage = &SMS;
912 /* Send the message. */
913 error = SM_Functions(GOP_SendSMS, &data, &State);
915 if (error == GE_SMSSENDOK) {
916 fprintf(stdout, _("Send succeeded!\n"));
918 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
921 if (GSM && GSM->Terminate) GSM->Terminate();
926 int savesms(int argc, char *argv[])
930 /* The maximum length of an uncompressed concatenated short message is
931 255 * 153 = 39015 default alphabet characters */
932 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
933 int input_len, chars_read;
939 SMS.Type = SMS_Deliver;
940 SMS.DCS.Type = SMS_GeneralDataCoding;
941 SMS.DCS.u.General.Compressed = false;
942 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
943 SMS.DCS.u.General.Class = 0;
944 SMS.MessageCenter.No = 1;
945 SMS.Validity.VPF = SMS_RelativeFormat;
946 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
948 SMS.Status = SMS_Unsent;
951 input_len = GSM_MAX_SMS_LENGTH;
954 while ((i = getopt(argc, argv, "ml:in:s:c:")) != -1) {
956 case 'm': /* mark the message as sent */
957 SMS.Status = SMS_Sent;
959 case 'l': /* Specify the location */
960 SMS.Number = atoi(optarg);
962 case 'i': /* Ask before overwriting */
965 case 'n': /* Specify the from number */
967 case 's': /* Specify the smsc number */
969 case 'c': /* Specify the smsc location */
980 aux.Number = SMS.Number;
981 data.SMSMessage = &aux;
982 error = SM_Functions(GOP_GetSMS, &data, &State);
985 fprintf(stderr, _("Message at specified location exists. "));
986 while (confirm < 0) {
987 fprintf(stderr, _("Overwrite? (yes/no) "));
988 GetLine(stdin, ans, 7);
989 if (!strcmp(ans, _("yes"))) confirm = 1;
990 else if (!strcmp(ans, _("no"))) confirm = 0;
992 if (!confirm) { GSM->Terminate(); return 0; }
994 case GE_INVALIDSMSLOCATION:
995 fprintf(stderr, _("Invalid location\n"));
999 /* FIXME: Remove this fprintf when the function is thoroughly tested */
1001 fprintf(stderr, _("Location %d empty. Saving\n"), SMS.Number);
1006 chars_read = fread(message_buffer, 1, input_len, stdin);
1008 if (chars_read == 0) {
1010 fprintf(stderr, _("Couldn't read from stdin!\n"));
1013 } else if (chars_read > input_len) {
1015 fprintf(stderr, _("Input too long!\n"));
1020 strncpy (SMS.MessageText, message_buffer, chars_read);
1021 SMS.MessageText[chars_read] = 0;
1023 error = GSM->SaveSMSMessage(&SMS);
1025 if (error == GE_NONE) {
1026 fprintf(stdout, _("Saved!\n"));
1028 fprintf(stdout, _("Saving failed (error=%d)\n"), error);
1036 /* Get SMSC number */
1037 int getsmsc(char *MessageCenterNumber)
1039 SMS_MessageCenter MessageCenter;
1043 memset(&MessageCenter, 0, sizeof(MessageCenter));
1044 MessageCenter.No=atoi(MessageCenterNumber);
1046 if (GSM && GSM->GetSMSCenter && GSM->Terminate) {
1047 error = GSM->GetSMSCenter(&MessageCenter);
1050 GSM_DataClear(&data);
1051 data.MessageCenter = &MessageCenter;
1052 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
1057 fprintf(stdout, _("%d. SMS center (%s) number is %s\n"), MessageCenter.No, MessageCenter.Name, MessageCenter.Number);
1058 fprintf(stdout, _("Default recipient number is %s\n"), MessageCenter.Recipient);
1059 fprintf(stdout, _("Messages sent as "));
1061 switch (MessageCenter.Format) {
1063 fprintf(stdout, _("Text"));
1066 fprintf(stdout, _("VoiceMail"));
1069 fprintf(stdout, _("Fax"));
1073 fprintf(stdout, _("Email"));
1076 fprintf(stdout, _("ERMES"));
1079 fprintf(stdout, _("X.400"));
1082 fprintf(stdout, _("Unknown"));
1087 fprintf(stdout, _("Message validity is "));
1089 switch (MessageCenter.Validity) {
1091 fprintf(stdout, _("1 hour"));
1094 fprintf(stdout, _("6 hours"));
1097 fprintf(stdout, _("24 hours"));
1100 fprintf(stdout, _("72 hours"));
1103 fprintf(stdout, _("1 week"));
1106 fprintf(stdout, _("Maximum time"));
1109 fprintf(stdout, _("Unknown"));
1113 fprintf(stdout, "\n");
1116 case GE_NOTIMPLEMENTED:
1117 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1120 fprintf(stdout, _("SMS center can not be found :-(\n"));
1127 /* Get SMS messages. */
1128 int getsms(int argc, char *argv[])
1132 SMS_FolderList folderlist;
1133 GSM_SMSMessage message;
1134 char *memory_type_string;
1135 int start_message, end_message, count, mode = 1;
1142 /* Handle command line args that set type, start and end locations. */
1143 memory_type_string = argv[2];
1144 message.MemoryType = StrToMemoryType(memory_type_string);
1145 if (message.MemoryType == GMT_XX) {
1146 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[2]);
1150 memset(&filename, 0, 64);
1152 start_message = end_message = atoi(argv[3]);
1156 /* [end] can be only argv[4] */
1157 if (argv[4][0] != '-') {
1158 end_message = atoi(argv[4]);
1161 /* parse all options (beginning with '-' */
1162 while ((i = getopt(argc, argv, "f:F:d")) != -1) {
1171 dprintf("Saving into %s\n", optarg);
1172 strncpy(filename, optarg, 64);
1173 if (strlen(optarg) > 63) {
1174 fprintf(stderr, _("Filename too long - will be truncated to 63 characters.\n"));
1177 filename[strlen(optarg)] = 0;
1186 data.SMSFolderList = &folderlist;
1187 folder.FolderID = 0;
1188 data.SMSFolder = &folder;
1189 /* Now retrieve the requested entries. */
1190 for (count = start_message; count <= end_message; count ++) {
1193 message.Number = count;
1194 data.SMSMessage = &message;
1195 dprintf("MemoryType (gnokii.c) : %i\n", data.SMSMessage->MemoryType);
1196 error = SM_Functions(GOP_GetSMS, &data, &State);
1200 switch (message.Type) {
1202 fprintf(stdout, _("%d. MO Message "), message.Number);
1204 fprintf(stdout, _("(sent)\n"));
1205 fprintf(stdout, _("%d. MO Message "), message.Number);
1207 fprintf(stdout, _("(not sent)\n"));
1208 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1210 case SMS_Delivery_Report:
1211 fprintf(stdout, _("%d. Delivery Report "), message.Number);
1213 fprintf(stdout, _("(read)\n"));
1215 fprintf(stdout, _("(not read)\n"));
1216 fprintf(stdout, _("Sending date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1217 message.Time.Day, message.Time.Month, message.Time.Year, \
1218 message.Time.Hour, message.Time.Minute, message.Time.Second);
1219 if (message.Time.Timezone) {
1220 if (message.Time.Timezone > 0)
1221 fprintf(stdout,_("+%02d00"), message.Time.Timezone);
1223 fprintf(stdout,_("%02d00"), message.Time.Timezone);
1225 fprintf(stdout, "\n");
1226 fprintf(stdout, _("Response date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1227 message.SMSCTime.Day, message.SMSCTime.Month, message.SMSCTime.Year, \
1228 message.SMSCTime.Hour, message.SMSCTime.Minute, message.SMSCTime.Second);
1229 if (message.SMSCTime.Timezone) {
1230 if (message.SMSCTime.Timezone > 0)
1231 fprintf(stdout,_("+%02d00"),message.SMSCTime.Timezone);
1233 fprintf(stdout,_("%02d00"),message.SMSCTime.Timezone);
1235 fprintf(stdout, "\n");
1236 fprintf(stdout, _("Receiver: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1237 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1240 fprintf(stdout, _("%d. Inbox Message "), message.Number);
1242 fprintf(stdout, _("(read)\n"));
1244 fprintf(stdout, _("(not read)\n"));
1245 fprintf(stdout, _("Date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1246 message.Time.Day, message.Time.Month, message.Time.Year, \
1247 message.Time.Hour, message.Time.Minute, message.Time.Second);
1248 if (message.Time.Timezone) {
1249 if (message.Time.Timezone > 0)
1250 fprintf(stdout,_("+%02d00"),message.Time.Timezone);
1252 fprintf(stdout,_("%02d00"),message.Time.Timezone);
1254 fprintf(stdout, "\n");
1255 fprintf(stdout, _("Sender: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1256 switch (message.UDH[0].Type) {
1258 fprintf(stdout, _("GSM operator logo for %s (%s) network.\n"), bitmap.netcode, GSM_GetNetworkName(bitmap.netcode));
1259 if (!strcmp(message.RemoteNumber.number, "+998000005") && !strcmp(message.MessageCenter.Number, "+886935074443")) dprintf(_("Saved by Logo Express\n"));
1260 if (!strcmp(message.RemoteNumber.number, "+998000002") || !strcmp(message.RemoteNumber.number, "+998000003")) dprintf(_("Saved by Operator Logo Uploader by Thomas Kessler\n"));
1262 case SMS_CallerIDLogo:
1263 fprintf(stdout, ("Logo:\n"));
1264 /* put bitmap into bitmap structure */
1265 GSM_ReadSMSBitmap(message.UDH[0].Type, message.MessageText+2+offset, message.MessageText, &bitmap);
1266 GSM_PrintBitmap(&bitmap);
1269 if ((stat(filename, &buf) == 0)) {
1270 fprintf(stdout, _("File %s exists.\n"), filename);
1271 fprintf(stderr, _("Overwrite? (yes/no) "));
1272 GetLine(stdin, ans, 4);
1273 if (!strcmp(ans, _("yes"))) {
1274 error = GSM_SaveBitmapFile(filename, &bitmap);
1276 } else error = GSM_SaveBitmapFile(filename, &bitmap);
1277 if (error != GE_NONE) fprintf(stderr, _("Couldn't save logofile %s!\n"), filename);
1281 fprintf(stdout, _("Ringtone\n"));
1283 case SMS_ConcatenatedMessages:
1284 fprintf(stdout, _("Linked (%d/%d):\n"),
1285 message.UDH[0].u.ConcatenatedShortMessage.CurrentNumber,
1286 message.UDH[0].u.ConcatenatedShortMessage.MaximumNumber);
1288 fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText);
1289 if ((mode != -1) && *filename) {
1291 sprintf(buf, "%s%d", filename, count);
1292 mode = GSM_SaveTextFile(buf, message.MessageText, mode);
1295 case SMS_BusinessCard:
1296 fprintf(stdout, _("Business Card:\n%s"), message.MessageText);
1299 fprintf(stderr, _("Unknown\n"));
1305 data.SMSMessage = &message;
1306 if (GE_NONE != SM_Functions(GOP_DeleteSMS, &data, &State))
1307 fprintf(stdout, _("(delete failed)\n"));
1309 fprintf(stdout, _("(message deleted)\n"));
1312 case GE_NOTIMPLEMENTED:
1313 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1314 if (GSM && GSM->Terminate) GSM->Terminate();
1316 case GE_INVALIDSMSLOCATION:
1317 fprintf(stderr, _("Invalid location: %s %d\n"), memory_type_string, count);
1319 case GE_EMPTYSMSLOCATION:
1320 fprintf(stderr, _("SMS location %s %d empty.\n"), memory_type_string, count);
1323 fprintf(stdout, _("GetSMS %s %d failed!(%s)\n\n"), memory_type_string, count, print_error(error));
1328 if (GSM && GSM->Terminate) GSM->Terminate();
1333 /* Delete SMS messages. */
1334 int deletesms(int argc, char *argv[])
1336 GSM_SMSMessage message;
1337 char *memory_type_string;
1338 int start_message, end_message, count;
1341 /* Handle command line args that set type, start and end locations. */
1342 memory_type_string = argv[0];
1343 message.MemoryType = StrToMemoryType(memory_type_string);
1344 if (message.MemoryType == GMT_XX) {
1345 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
1349 start_message = end_message = atoi (argv[1]);
1350 if (argc > 2) end_message = atoi (argv[2]);
1352 /* Now delete the requested entries. */
1353 for (count = start_message; count <= end_message; count ++) {
1355 message.Number = count;
1356 data.SMSMessage = &message;
1357 error = SM_Functions(GOP_DeleteSMS, &data, &State);
1359 if (error == GE_NONE)
1360 fprintf(stdout, _("Deleted SMS %s %d\n"), memory_type_string, count);
1362 if (error == GE_NOTIMPLEMENTED) {
1363 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1367 fprintf(stdout, _("DeleteSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
1376 static volatile bool bshutdown = false;
1378 /* SIGINT signal handler. */
1379 static void interrupted(int sig)
1381 signal(sig, SIG_IGN);
1387 /* In this mode we get the code from the keyboard and send it to the mobile
1389 int entersecuritycode(char *type)
1392 GSM_SecurityCode SecurityCode;
1394 if (!strcmp(type,"PIN"))
1395 SecurityCode.Type=GSCT_Pin;
1396 else if (!strcmp(type,"PUK"))
1397 SecurityCode.Type=GSCT_Puk;
1398 else if (!strcmp(type,"PIN2"))
1399 SecurityCode.Type=GSCT_Pin2;
1400 else if (!strcmp(type,"PUK2"))
1401 SecurityCode.Type=GSCT_Puk2;
1402 // FIXME: Entering of SecurityCode does not work :-(
1403 // else if (!strcmp(type,"SecurityCode"))
1404 // SecurityCode.Type=GSCT_SecurityCode;
1409 printf("Enter your code: ");
1410 gets(SecurityCode.Code);
1412 strcpy(SecurityCode.Code,getpass(_("Enter your code: ")));
1415 test = GSM->EnterSecurityCode(SecurityCode);
1416 if (test == GE_INVALIDSECURITYCODE)
1417 fprintf(stdout, _("Error: invalid code.\n"));
1418 else if (test == GE_NONE)
1419 fprintf(stdout, _("Code ok.\n"));
1420 else if (test == GE_NOTIMPLEMENTED)
1421 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1423 fprintf(stdout, _("Other error.\n"));
1430 int getsecuritycodestatus(void)
1434 if (GSM->GetSecurityCodeStatus(&Status) == GE_NONE) {
1436 fprintf(stdout, _("Security code status: "));
1439 case GSCT_SecurityCode:
1440 fprintf(stdout, _("waiting for Security Code.\n"));
1443 fprintf(stdout, _("waiting for PIN.\n"));
1446 fprintf(stdout, _("waiting for PIN2.\n"));
1449 fprintf(stdout, _("waiting for PUK.\n"));
1452 fprintf(stdout, _("waiting for PUK2.\n"));
1455 fprintf(stdout, _("nothing to enter.\n"));
1458 fprintf(stdout, _("Unknown!\n"));
1471 /* Voice dialing mode. */
1472 int dialvoice(char *Number)
1474 GSM->DialVoice(Number);
1481 /* The following function allows to send logos using SMS */
1482 int sendlogo(int argc, char *argv[])
1488 char UserDataHeader[7] = { 0x06, /* UDH Length */
1489 0x05, /* IEI: application port addressing scheme, 16 bit address */
1490 0x04, /* IEI length */
1491 0x15, /* destination address: high byte */
1492 0x00, /* destination address: low byte */
1493 0x00, /* originator address */
1496 char Data[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1500 /* Default settings for SMS message:
1501 - no delivery report
1507 - set UserDataHeaderIndicator
1509 SMS.Type = SMS_Submit;
1510 SMS.DCS.Type = SMS_GeneralDataCoding;
1511 SMS.DCS.u.General.Compressed = false;
1512 SMS.DCS.u.General.Alphabet = SMS_8bit;
1513 SMS.DCS.u.General.Class = 2;
1514 SMS.MessageCenter.No = 1;
1515 SMS.Validity.VPF = SMS_RelativeFormat;
1516 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
1518 /* The first argument is the type of the logo. */
1519 if (!strcmp(argv[0], "op")) {
1520 SMS.UDH[0].Type = SMS_OpLogo;
1521 UserDataHeader[4] = 0x82; /* NBS port 0x1582 */
1522 fprintf(stdout, _("Sending operator logo.\n"));
1523 } else if (!strcmp(argv[0], "caller")) {
1524 SMS.UDH[0].Type = SMS_CallerIDLogo;
1525 UserDataHeader[4] = 0x83; /* NBS port 0x1583 */
1526 fprintf(stdout, _("Sending caller line identification logo.\n"));
1528 fprintf(stderr, _("You should specify what kind of logo to send!\n"));
1532 /* The second argument is the destination, ie the phone number of recipient. */
1533 SMS.MemoryType = atoi(argv[1]);
1535 /* The third argument is the bitmap file. */
1536 GSM_ReadBitmapFile(argv[2], &bitmap);
1538 /* If we are sending op logo we can rewrite network code. */
1539 if (!strcmp(argv[0], "op")) {
1541 * The fourth argument, if present, is the Network code of the operator.
1542 * Network code is in this format: "xxx yy".
1545 strcpy(bitmap.netcode, argv[3]);
1547 fprintf(stdout, _("Operator code: %s\n"), argv[3]);
1551 /* Set the network code */
1552 Data[current++] = ((bitmap.netcode[1] & 0x0f) << 4) | (bitmap.netcode[0] & 0xf);
1553 Data[current++] = 0xf0 | (bitmap.netcode[2] & 0x0f);
1554 Data[current++] = ((bitmap.netcode[5] & 0x0f) << 4) | (bitmap.netcode[4] & 0xf);
1557 /* Set the logo size */
1559 Data[current++] = bitmap.width;
1560 Data[current++] = bitmap.height;
1562 Data[current++] = 0x01;
1564 memcpy(SMS.MessageText, UserDataHeader, 7);
1565 memcpy(SMS.MessageText, Data, current);
1566 memcpy(SMS.MessageText+current, bitmap.bitmap, bitmap.size);
1568 /* Send the message. */
1569 error = GSM->SendSMSMessage(&SMS,current+bitmap.size);
1571 if (error == GE_SMSSENDOK)
1572 fprintf(stdout, _("Send succeeded!\n"));
1574 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
1580 /* Getting logos. */
1581 GSM_Error SaveBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1588 /* Ask before overwriting */
1589 while (stat(FileName, &buf) == 0) {
1592 fprintf(stderr, _("Saving logo. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "), FileName);
1593 GetLine(stdin, ans, 4);
1594 if (!strcmp(ans, "O") || !strcmp(ans, "o")) confirm = 1;
1595 if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm = 2;
1596 if (!strcmp(ans, "S") || !strcmp(ans, "s")) return GE_USERCANCELED;
1598 if (confirm == 1) break;
1600 fprintf(stderr, _("Enter name of new file: "));
1601 GetLine(stdin, FileName, 50);
1602 if (!FileName || (*FileName == 0)) return GE_USERCANCELED;
1606 error = GSM_SaveBitmapFile(FileName, bitmap);
1609 case GE_CANTOPENFILE:
1610 fprintf(stderr, _("Failed to write file \"%s\"\n"), FileName);
1619 int getlogo(int argc, char *argv[])
1623 GSM_Statemachine *sm = &State;
1625 bitmap.type=GSM_None;
1627 if (!strcmp(argv[0], "op"))
1628 bitmap.type = GSM_OperatorLogo;
1630 if (!strcmp(argv[0], "caller")) {
1631 /* There is caller group number missing in argument list. */
1633 bitmap.number=argv[2][0]-'0';
1634 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1638 bitmap.type = GSM_CallerLogo;
1641 if (!strcmp(argv[0],"startup"))
1642 bitmap.type = GSM_StartupLogo;
1643 else if (!strcmp(argv[0], "dealer"))
1644 bitmap.type = GSM_DealerNoteText;
1645 else if (!strcmp(argv[0], "text"))
1646 bitmap.type=GSM_WelcomeNoteText;
1648 if (bitmap.type != GSM_None) {
1650 fprintf(stdout, _("Getting Logo\n"));
1652 data.Bitmap=&bitmap;
1653 error=SM_Functions(GOP_GetBitmap, &data, sm);
1657 if (bitmap.type == GSM_DealerNoteText) fprintf(stdout, _("Dealer welcome note "));
1658 if (bitmap.type == GSM_WelcomeNoteText) fprintf(stdout, _("Welcome note "));
1659 if (bitmap.type == GSM_DealerNoteText || bitmap.type==GSM_WelcomeNoteText) {
1660 if (bitmap.text[0]) {
1661 fprintf(stdout, _("currently set to \"%s\"\n"), bitmap.text);
1663 fprintf(stdout, _("currently empty\n"));
1667 switch (bitmap.type) {
1668 case GSM_OperatorLogo:
1669 fprintf(stdout,"Operator logo for %s (%s) network got succesfully\n",bitmap.netcode,GSM_GetNetworkName(bitmap.netcode));
1671 strncpy(bitmap.netcode,argv[2], 7);
1672 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1673 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1678 case GSM_StartupLogo:
1679 fprintf(stdout, "Startup logo got successfully\n");
1681 strncpy(bitmap.netcode,argv[2], 7);
1682 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1683 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1688 case GSM_CallerLogo:
1689 fprintf(stdout,"Caller logo got successfully\n");
1691 strncpy(bitmap.netcode,argv[3],7);
1692 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1693 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1699 fprintf(stdout,"Unknown bitmap type.\n");
1703 if (SaveBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) return (-1);
1706 fprintf(stdout,"Your phone doesn't have logo uploaded !\n");
1711 case GE_NOTIMPLEMENTED:
1712 fprintf(stderr, _("Function not implemented !\n"));
1714 case GE_NOTSUPPORTED:
1715 fprintf(stderr, _("This kind of logo is not supported !\n"));
1718 fprintf(stderr, _("Error getting logo !\n"));
1722 fprintf(stderr, _("What kind of logo do you want to get ?\n"));
1730 /* Sending logos. */
1731 GSM_Error ReadBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1735 error = GSM_ReadBitmapFile(FileName, bitmap);
1738 case GE_CANTOPENFILE:
1739 fprintf(stderr, _("Failed to read file \"%s\"\n"), FileName);
1741 case GE_WRONGNUMBEROFCOLORS:
1742 fprintf(stderr, _("Wrong number of colors in \"%s\" logofile (accepted only 2-colors files) !\n"), FileName);
1744 case GE_WRONGCOLORS:
1745 fprintf(stderr, _("Wrong colors in \"%s\" logofile !\n"), FileName);
1747 case GE_INVALIDFILEFORMAT:
1748 fprintf(stderr, _("Invalid format of \"%s\" logofile !\n"), FileName);
1750 case GE_SUBFORMATNOTSUPPORTED:
1751 fprintf(stderr, _("Sorry, gnokii doesn't support used subformat in file \"%s\" !\n"), FileName);
1753 case GE_FILETOOSHORT:
1754 fprintf(stderr, _("\"%s\" logofile is too short !\n"), FileName);
1756 case GE_INVALIDIMAGESIZE:
1757 fprintf(stderr, _("Bitmap size doesn't supported by fileformat or different from 72x14, 84x48 and 72x28 !\n"));
1767 int setlogo(int argc, char *argv[])
1769 GSM_Bitmap bitmap,oldbit;
1770 GSM_NetworkInfo NetworkInfo;
1776 if (!strcmp(argv[0],"text") || !strcmp(argv[0],"dealer")) {
1777 if (!strcmp(argv[0], "text")) bitmap.type = GSM_WelcomeNoteText;
1778 else bitmap.type = GSM_DealerNoteText;
1779 bitmap.text[0] = 0x00;
1780 if (argc > 1) strncpy(bitmap.text, argv[1], 255);
1782 if (!strcmp(argv[0], "op") || !strcmp(argv[0], "startup") || !strcmp(argv[0], "caller")) {
1784 if (ReadBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) {
1789 if (!strcmp(argv[0], "op")) {
1790 if (bitmap.type != GSM_OperatorLogo || argc < 3) {
1791 if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode, NetworkInfo.NetworkCode, 7);
1793 GSM_ResizeBitmap(&bitmap, GSM_OperatorLogo, GSM_Info);
1795 strncpy(bitmap.netcode, argv[2], 7);
1796 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1797 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1802 if (!strcmp(argv[0], "startup")) {
1803 GSM_ResizeBitmap(&bitmap, GSM_StartupLogo, GSM_Info);
1805 if (!strcmp(argv[0],"caller")) {
1806 GSM_ResizeBitmap(&bitmap, GSM_CallerLogo, GSM_Info);
1808 bitmap.number = argv[2][0] - '0';
1809 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1813 oldbit.type = GSM_CallerLogo;
1814 oldbit.number = bitmap.number;
1815 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1816 /* We have to get the old name and ringtone!! */
1817 bitmap.ringtone = oldbit.ringtone;
1818 strncpy(bitmap.text, oldbit.text, 255);
1820 if (argc > 3) strncpy(bitmap.text, argv[3], 255);
1822 fprintf(stdout, _("Setting Logo.\n"));
1824 /* FIX ME: is it possible to permanently remove op logo ? */
1825 if (!strcmp(argv[0], "op"))
1827 bitmap.type = GSM_OperatorLogo;
1828 strncpy(bitmap.netcode, "000 00", 7);
1831 bitmap.size = bitmap.width * bitmap.height / 8;
1832 GSM_ClearBitmap(&bitmap);
1834 /* FIX ME: how to remove startup and group logos ? */
1835 fprintf(stdout, _("Removing Logo.\n"));
1838 fprintf(stderr, _("What kind of logo do you want to set ?\n"));
1844 error=GSM->SetBitmap(&bitmap);
1848 oldbit.type = bitmap.type;
1849 oldbit.number = bitmap.number;
1850 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1851 if (bitmap.type == GSM_WelcomeNoteText ||
1852 bitmap.type == GSM_DealerNoteText) {
1853 if (strcmp(bitmap.text, oldbit.text)) {
1854 fprintf(stderr, _("Error setting"));
1855 if (bitmap.type == GSM_DealerNoteText) fprintf(stderr, _(" dealer"));
1856 fprintf(stderr, _(" welcome note - "));
1858 /* I know, it looks horrible, but... */
1859 /* I set it to the short string - if it won't be set */
1860 /* it means, PIN is required. If it will be correct, previous */
1861 /* (user) text was too long */
1863 /* Without it, I could have such thing: */
1864 /* user set text to very short string (for example, "Marcin") */
1865 /* then enable phone without PIN and try to set it to the very long (too long for phone) */
1866 /* string (which start with "Marcin"). If we compare them as only length different, we could think, */
1867 /* that phone accepts strings 6 chars length only (length of "Marcin") */
1868 /* When we make it correct, we don't have this mistake */
1870 strcpy(oldbit.text, "!\0");
1871 GSM->SetBitmap(&oldbit);
1872 GSM->GetBitmap(&oldbit);
1873 if (oldbit.text[0]!='!') {
1874 fprintf(stderr, _("SIM card and PIN is required\n"));
1876 GSM->SetBitmap(&bitmap);
1877 GSM->GetBitmap(&oldbit);
1878 fprintf(stderr, _("too long, truncated to \"%s\" (length %i)\n"),oldbit.text,strlen(oldbit.text));
1883 if (bitmap.type == GSM_StartupLogo) {
1884 for (i = 0; i < oldbit.size; i++) {
1885 if (oldbit.bitmap[i] != bitmap.bitmap[i]) {
1886 fprintf(stderr, _("Error setting startup logo - SIM card and PIN is required\n"));
1894 if (ok) fprintf(stdout, _("Done.\n"));
1896 case GE_NOTIMPLEMENTED:
1897 fprintf(stderr, _("Function not implemented.\n"));
1899 case GE_NOTSUPPORTED:
1900 fprintf(stderr, _("This kind of logo is not supported.\n"));
1903 fprintf(stderr, _("Error !\n"));
1913 int viewlogo(char *filename)
1917 error = GSM_ShowBitmapFile(filename);
1921 /* Calendar notes receiving. */
1922 int getcalendarnote(int argc, char *argv[])
1924 GSM_CalendarNote CalendarNote;
1926 GSM_Error error = GE_NONE;
1927 int i, first_location, last_location;
1930 struct option options[] = {
1931 { "vCard", optional_argument, NULL, '1'},
1938 first_location = last_location = atoi(argv[0]);
1939 if ((argc > 1) && (argv[1][0] != '-')) {
1940 last_location = atoi(argv[1]);
1943 while ((i = getopt_long(argc, argv, "v", options, NULL)) != -1) {
1949 usage(); /* Would be better to have an calendar_usage() here. */
1955 for (i = first_location; i <= last_location; i++) {
1956 CalendarNote.Location = i;
1957 if (GSM && GSM->GetCalendarNote && GSM->Terminate) {
1958 error = GSM->GetCalendarNote(&CalendarNote);
1961 GSM_DataClear(&data);
1962 data.CalendarNote = &CalendarNote;
1964 error = SM_Functions(GOP_GetCalendarNote, &data, &State);
1969 fprintf(stdout, "BEGIN:VCALENDAR\n");
1970 fprintf(stdout, "VERSION:1.0\n");
1971 fprintf(stdout, "BEGIN:VEVENT\n");
1972 fprintf(stdout, "CATEGORIES:");
1973 switch (CalendarNote.Type) {
1975 fprintf(stdout, "MISCELLANEOUS\n");
1978 fprintf(stdout, "PHONE CALL\n");
1981 fprintf(stdout, "MEETING\n");
1984 fprintf(stdout, "SPECIAL OCCASION\n");
1987 fprintf(stdout, "UNKNOWN\n");
1990 fprintf(stdout, "SUMMARY:%s\n",CalendarNote.Text);
1991 fprintf(stdout, "DTSTART:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Time.Year,
1992 CalendarNote.Time.Month, CalendarNote.Time.Day, CalendarNote.Time.Hour,
1993 CalendarNote.Time.Minute, CalendarNote.Time.Second);
1994 if (CalendarNote.Alarm.Year!=0) {
1995 fprintf(stdout, "DALARM:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Alarm.Year,
1996 CalendarNote.Alarm.Month, CalendarNote.Alarm.Day, CalendarNote.Alarm.Hour,
1997 CalendarNote.Alarm.Minute, CalendarNote.Alarm.Second);
1999 fprintf(stdout, "END:VEVENT\n");
2000 fprintf(stdout, "END:VCALENDAR\n");
2002 } else { /* not vCal */
2003 fprintf(stdout, _(" Type of the note: "));
2005 switch (CalendarNote.Type) {
2007 fprintf(stdout, _("Reminder\n"));
2010 fprintf(stdout, _("Call\n"));
2013 fprintf(stdout, _("Meeting\n"));
2016 fprintf(stdout, _("Birthday\n"));
2019 fprintf(stdout, _("Unknown\n"));
2023 fprintf(stdout, _(" Date: %d-%02d-%02d\n"), CalendarNote.Time.Year,
2024 CalendarNote.Time.Month,
2025 CalendarNote.Time.Day);
2027 fprintf(stdout, _(" Time: %02d:%02d:%02d\n"), CalendarNote.Time.Hour,
2028 CalendarNote.Time.Minute,
2029 CalendarNote.Time.Second);
2031 if (CalendarNote.Alarm.AlarmEnabled == 1) {
2032 fprintf(stdout, _(" Alarm date: %d-%02d-%02d\n"), CalendarNote.Alarm.Year,
2033 CalendarNote.Alarm.Month,
2034 CalendarNote.Alarm.Day);
2036 fprintf(stdout, _(" Alarm time: %02d:%02d:%02d\n"), CalendarNote.Alarm.Hour,
2037 CalendarNote.Alarm.Minute,
2038 CalendarNote.Alarm.Second);
2041 fprintf(stdout, _(" Text: %s\n"), CalendarNote.Text);
2043 if (CalendarNote.Type == GCN_CALL)
2044 fprintf(stdout, _(" Phone: %s\n"), CalendarNote.Phone);
2047 case GE_NOTIMPLEMENTED:
2048 fprintf(stderr, _("Function not implemented.\n"));
2051 fprintf(stderr, _("The calendar note can not be read\n"));
2060 /* Writing calendar notes. */
2061 int writecalendarnote(char *argv[])
2063 GSM_CalendarNote CalendarNote;
2065 if (GSM_ReadVCalendarFile(argv[0], &CalendarNote, atoi(argv[1]))) {
2066 fprintf(stdout, _("Failed to load vCalendar file.\n"));
2070 /* Error 22=Calendar full ;-) */
2071 if ((GSM->WriteCalendarNote(&CalendarNote)) == GE_NONE)
2072 fprintf(stdout, _("Succesfully written!\n"));
2074 fprintf(stdout, _("Failed to write calendar note!\n"));
2081 /* Calendar note deleting. */
2082 int deletecalendarnote(int argc, char *argv[])
2084 GSM_CalendarNote CalendarNote;
2085 int i, first_location, last_location;
2087 first_location = last_location = atoi(argv[0]);
2088 if (argc > 1) last_location = atoi(argv[1]);
2090 for (i = first_location; i <= last_location; i++) {
2092 CalendarNote.Location = i;
2094 if (GSM->DeleteCalendarNote(&CalendarNote) == GE_NONE) {
2095 fprintf(stdout, _(" Calendar note deleted.\n"));
2097 fprintf(stderr, _("The calendar note can not be deleted\n"));
2107 /* Setting the date and time. */
2108 int setdatetime(int argc, char *argv[])
2115 now = localtime(&nowh);
2117 Date.Year = now->tm_year;
2118 Date.Month = now->tm_mon+1;
2119 Date.Day = now->tm_mday;
2120 Date.Hour = now->tm_hour;
2121 Date.Minute = now->tm_min;
2122 Date.Second = now->tm_sec;
2124 if (argc > 0) Date.Year = atoi (argv[0]);
2125 if (argc > 1) Date.Month = atoi (argv[1]);
2126 if (argc > 2) Date.Day = atoi (argv[2]);
2127 if (argc > 3) Date.Hour = atoi (argv[3]);
2128 if (argc > 4) Date.Minute = atoi (argv[4]);
2130 if (Date.Year < 1900) {
2132 /* Well, this thing is copyrighted in U.S. This technique is known as
2133 Windowing and you can read something about it in LinuxWeekly News:
2134 http://lwn.net/1999/features/Windowing.phtml. This thing is beeing
2135 written in Czech republic and Poland where algorithms are not allowed
2139 Date.Year = Date.Year + 1900;
2141 Date.Year = Date.Year + 2000;
2144 /* FIXME: Error checking should be here. */
2145 GSM->SetDateTime(&Date);
2152 /* In this mode we receive the date and time from mobile phone. */
2153 int getdatetime(void) {
2155 GSM_DateTime date_time;
2158 if (GSM && GSM->GetDateTime && GSM->Terminate) {
2159 error = GSM->GetDateTime(&date_time);
2162 GSM_DataClear(&data);
2163 data.DateTime = &date_time;
2165 error = SM_Functions(GOP_GetDateTime, &data, &State);
2170 fprintf(stdout, _("Date: %4d/%02d/%02d\n"), date_time.Year, date_time.Month, date_time.Day);
2171 fprintf(stdout, _("Time: %02d:%02d:%02d\n"), date_time.Hour, date_time.Minute, date_time.Second);
2173 case GE_NOTIMPLEMENTED:
2174 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2177 fprintf(stdout, _("Internal error\n"));
2184 /* Setting the alarm. */
2185 int setalarm(char *argv[])
2189 Date.Hour = atoi(argv[0]);
2190 Date.Minute = atoi(argv[1]);
2192 GSM->SetAlarm(1, &Date);
2199 /* Getting the alarm. */
2204 GSM_DateTime date_time;
2206 if (GSM && GSM->GetAlarm && GSM->Terminate) {
2207 error = GSM->GetAlarm(0, &date_time);
2210 GSM_DataClear(&data);
2211 data.DateTime = &date_time;
2213 error = SM_Functions(GOP_GetAlarm, &data, &State);
2218 fprintf(stdout, _("Alarm: %s\n"), (date_time.AlarmEnabled==0)?"off":"on");
2219 fprintf(stdout, _("Time: %02d:%02d\n"), date_time.Hour, date_time.Minute);
2221 case GE_NOTIMPLEMENTED:
2222 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2225 fprintf(stdout, _("Internal error\n"));
2232 /* In monitor mode we don't do much, we just initialise the fbus code.
2233 Note that the fbus code no longer has an internal monitor mode switch,
2234 instead compile with DEBUG enabled to get all the gumpf. */
2235 int monitormode(void)
2237 float rflevel = -1, batterylevel = -1;
2238 // GSM_PowerSource powersource = -1;
2239 GSM_RFUnits rf_units = GRF_Arbitrary;
2240 GSM_BatteryUnits batt_units = GBU_Arbitrary;
2241 GSM_Statemachine *sm = &State;
2244 // GSM_NetworkInfo NetworkInfo;
2245 // GSM_CBMessage CBMessage;
2247 GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0};
2248 GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0};
2249 GSM_MemoryStatus DC_MemoryStatus = {GMT_DC, 0, 0};
2250 GSM_MemoryStatus EN_MemoryStatus = {GMT_EN, 0, 0};
2251 GSM_MemoryStatus FD_MemoryStatus = {GMT_FD, 0, 0};
2252 GSM_MemoryStatus LD_MemoryStatus = {GMT_LD, 0, 0};
2253 GSM_MemoryStatus MC_MemoryStatus = {GMT_MC, 0, 0};
2254 GSM_MemoryStatus ON_MemoryStatus = {GMT_ON, 0, 0};
2255 GSM_MemoryStatus RC_MemoryStatus = {GMT_RC, 0, 0};
2257 // GSM_SMSStatus SMSStatus = {0, 0};
2261 GSM_DataClear(&data);
2263 /* We do not want to monitor serial line forever - press Ctrl+C to stop the
2265 signal(SIGINT, interrupted);
2267 fprintf (stderr, _("Entering monitor mode...\n"));
2270 //GSM->EnableCellBroadcast();
2272 /* Loop here indefinitely - allows you to see messages from GSM code in
2273 response to unknown messages etc. The loops ends after pressing the
2275 data.RFUnits=&rf_units;
2276 data.RFLevel=&rflevel;
2277 data.BatteryUnits=&batt_units;
2278 data.BatteryLevel=&batterylevel;
2280 while (!bshutdown) {
2281 if (SM_Functions(GOP_GetRFLevel,&data,sm) == GE_NONE)
2282 fprintf(stdout, _("RFLevel: %d\n"), (int)rflevel);
2284 if (SM_Functions(GOP_GetBatteryLevel,&data,sm) == GE_NONE)
2285 fprintf(stdout, _("Battery: %d\n"), (int)batterylevel);
2287 // if (GSM->GetPowerSource(&powersource) == GE_NONE)
2288 // fprintf(stdout, _("Power Source: %s\n"), (powersource==GPS_ACDC)?_("AC/DC"):_("battery"));
2290 data.MemoryStatus=&SIMMemoryStatus;
2291 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2292 fprintf(stdout, _("SIM: Used %d, Free %d\n"), SIMMemoryStatus.Used, SIMMemoryStatus.Free);
2294 data.MemoryStatus=&PhoneMemoryStatus;
2295 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2296 fprintf(stdout, _("Phone: Used %d, Free %d\n"), PhoneMemoryStatus.Used, PhoneMemoryStatus.Free);
2298 data.MemoryStatus=&DC_MemoryStatus;
2299 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2300 fprintf(stdout, _("DC: Used %d, Free %d\n"), DC_MemoryStatus.Used, DC_MemoryStatus.Free);
2302 data.MemoryStatus=&EN_MemoryStatus;
2303 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2304 fprintf(stdout, _("EN: Used %d, Free %d\n"), EN_MemoryStatus.Used, EN_MemoryStatus.Free);
2306 data.MemoryStatus=&FD_MemoryStatus;
2307 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2308 fprintf(stdout, _("FD: Used %d, Free %d\n"), FD_MemoryStatus.Used, FD_MemoryStatus.Free);
2310 data.MemoryStatus=&LD_MemoryStatus;
2311 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2312 fprintf(stdout, _("LD: Used %d, Free %d\n"), LD_MemoryStatus.Used, LD_MemoryStatus.Free);
2314 data.MemoryStatus=&MC_MemoryStatus;
2315 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2316 fprintf(stdout, _("MC: Used %d, Free %d\n"), MC_MemoryStatus.Used, MC_MemoryStatus.Free);
2318 data.MemoryStatus=&ON_MemoryStatus;
2319 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2320 fprintf(stdout, _("ON: Used %d, Free %d\n"), ON_MemoryStatus.Used, ON_MemoryStatus.Free);
2322 data.MemoryStatus=&RC_MemoryStatus;
2323 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2324 fprintf(stdout, _("RC: Used %d, Free %d\n"), RC_MemoryStatus.Used, RC_MemoryStatus.Free);
2326 // if (GSM->GetSMSStatus(&SMSStatus) == GE_NONE)
2327 // fprintf(stdout, _("SMS Messages: UnRead %d, Number %d\n"), SMSStatus.UnRead, SMSStatus.Number);
2329 // if (GSM->GetIncomingCallNr(Number) == GE_NONE)
2330 // fprintf(stdout, _("Incoming call: %s\n"), Number);
2332 // if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE)
2333 // fprintf(stdout, _("Network: %s (%s), LAC: %s, CellID: %s\n"), GSM_GetNetworkName (NetworkInfo.NetworkCode), GSM_GetCountryName(NetworkInfo.NetworkCode), NetworkInfo.LAC, NetworkInfo.CellID);
2335 // if (GSM->ReadCellBroadcast(&CBMessage) == GE_NONE)
2336 // fprintf(stdout, _("Cell broadcast received on channel %d: %s\n"), CBMessage.Channel, CBMessage.Message);
2341 fprintf (stderr, _("Leaving monitor mode...\n"));
2351 static GSM_Error PrettyOutputFn(char *Display, char *Indicators)
2354 printf(ESC "[10;0H Display is:\n%s\n", Display);
2356 printf(ESC "[9;0H Indicators: %s \n", Indicators);
2357 printf(ESC "[1;1H");
2362 // Uncomment it if used
2363 static GSM_Error OutputFn(char *Display, char *Indicators)
2366 printf("New display is:\n%s\n", Display);
2368 printf("Indicators: %s\n", Indicators);
2373 void console_raw(void)
2378 tcgetattr(fileno(stdin), &it);
2379 it.c_lflag &= ~(ICANON);
2380 //it.c_iflag &= ~(INPCK|ISTRIP|IXON);
2384 tcsetattr(fileno(stdin), TCSANOW, &it);
2388 int displayoutput(void)
2391 GSM_Statemachine *sm = &State;
2394 data.OutputFn = PrettyOutputFn;
2396 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2398 fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
2400 if (error == GE_NONE) {
2402 /* We do not want to see texts forever - press Ctrl+C to stop. */
2403 signal(SIGINT, interrupted);
2405 fprintf (stderr, _("Entered display monitoring mode...\n"));
2406 fprintf (stderr, ESC "c" );
2408 /* Loop here indefinitely - allows you to read texts from phone's
2409 display. The loops ends after pressing the Ctrl+C. */
2410 while (!bshutdown) {
2412 memset(&buf[0], 0, 102);
2413 while (read(0, buf, 100) > 0) {
2414 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
2415 if (GSM->HandleString(buf) != GE_NONE)
2416 fprintf(stdout, _("Key press simulation failed.\n"));
2417 memset(buf, 0, 102);
2421 fprintf (stderr, "Shutting down\n");
2423 fprintf (stderr, _("Leaving display monitor mode...\n"));
2424 data.OutputFn = NULL;
2426 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2427 if (error != GE_NONE)
2428 fprintf (stderr, _("Error!\n"));
2430 fprintf (stderr, _("Error!\n"));
2436 /* Reads profile from phone and displays its' settings */
2437 int getprofile(int argc, char *argv[])
2441 GSM_Profile profile;
2444 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2448 error = GSM->GetProfile(&profile);
2450 if (error == GE_NONE) {
2452 while (GSM->GetModel(model) != GE_NONE)
2455 max_profiles = 7; /* This is correct for 6110 (at least my). How do we get
2456 the number of profiles? */
2459 /*FIX ME: It should be set to 3 for N5130 and 3210 too*/
2460 if (!strcmp(model, "NSE-1"))
2464 profile.Number = atoi(argv[0]) - 1;
2465 start = profile.Number;
2468 if (profile.Number < 0) {
2469 fprintf(stderr, _("Profile number must be value from 1 to %d!\n"), max_profiles);
2474 if (profile.Number >= max_profiles) {
2475 fprintf(stderr, _("This phone supports only %d profiles!\n"), max_profiles);
2481 stop = max_profiles;
2488 if (profile.Number != 0)
2489 GSM->GetProfile(&profile);
2491 fprintf(stdout, "%d. \"%s\"\n", profile.Number + 1, profile.Name);
2492 if (profile.DefaultName == -1) fprintf(stdout, _(" (name defined)\n"));
2494 fprintf(stdout, _("Incoming call alert: %s\n"), GetProfileCallAlertString(profile.CallAlert));
2496 /* For different phones different ringtones names */
2498 if (!strcmp(model, "NSE-3"))
2499 fprintf(stdout, _("Ringing tone: %s (%d)\n"), RingingTones[profile.Ringtone], profile.Ringtone);
2501 fprintf(stdout, _("Ringtone number: %d\n"), profile.Ringtone);
2503 fprintf(stdout, _("Ringing volume: %s\n"), GetProfileVolumeString(profile.Volume));
2505 fprintf(stdout, _("Message alert tone: %s\n"), GetProfileMessageToneString(profile.MessageTone));
2507 fprintf(stdout, _("Keypad tones: %s\n"), GetProfileKeypadToneString(profile.KeypadTone));
2509 fprintf(stdout, _("Warning and game tones: %s\n"), GetProfileWarningToneString(profile.WarningTone));
2511 /* FIXME: Light settings is only used for Car */
2512 if (profile.Number == (max_profiles - 2)) fprintf(stdout, _("Lights: %s\n"), profile.Lights ? _("On") : _("Automatic"));
2514 fprintf(stdout, _("Vibration: %s\n"), GetProfileVibrationString(profile.Vibration));
2516 /* FIXME: it will be nice to add here reading caller group name. */
2517 if (max_profiles != 3) fprintf(stdout, _("Caller groups: 0x%02x\n"), profile.CallerGroups);
2519 /* FIXME: Automatic answer is only used for Car and Headset. */
2520 if (profile.Number >= (max_profiles - 2)) fprintf(stdout, _("Automatic answer: %s\n"), profile.AutomaticAnswer ? _("On") : _("Off"));
2522 fprintf(stdout, "\n");
2527 if (error == GE_NOTIMPLEMENTED) {
2528 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2532 fprintf(stderr, _("Unspecified error\n"));
2542 /* Get requested range of memory storage entries and output to stdout in
2543 easy-to-parse format */
2544 int getmemory(int argc, char *argv[])
2546 GSM_PhonebookEntry entry;
2549 char *memory_type_string;
2552 GSM_Statemachine *sm = &State;
2554 /* Handle command line args that set type, start and end locations. */
2555 memory_type_string = argv[0];
2556 entry.MemoryType = StrToMemoryType(memory_type_string);
2557 if (entry.MemoryType == GMT_XX) {
2558 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
2562 start_entry = atoi (argv[1]);
2563 if (argc > 2) end_entry = atoi (argv[2]);
2564 else end_entry = start_entry;
2566 /* Now retrieve the requested entries. */
2567 for (count = start_entry; count <= end_entry; count ++) {
2569 entry.Location = count;
2571 data.PhonebookEntry=&entry;
2572 error=SM_Functions(GOP_ReadPhonebook,&data,sm);
2574 if (error == GE_NONE) {
2575 fprintf(stdout, "%s;%s;%s;%d;%d\n", entry.Name, entry.Number, memory_type_string, entry.Location, entry.Group);
2576 if (entry.MemoryType == GMT_MC || entry.MemoryType == GMT_DC || entry.MemoryType == GMT_RC)
2577 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);
2580 if (error == GE_NOTIMPLEMENTED) {
2581 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2584 else if (error == GE_INVALIDMEMORYTYPE) {
2585 fprintf(stderr, _("Memory type %s not supported!\n"), memory_type_string);
2589 fprintf(stdout, _("%s|%d|Bad location or other error!(%d)\n"), memory_type_string, count, error);
2595 /* Read data from stdin, parse and write to phone. The parsing is relatively
2596 crude and doesn't allow for much variation from the stipulated format. */
2597 /* FIXME: I guess there's *very* similar code in xgnokii */
2598 int writephonebook(int argc, char *args[])
2600 GSM_PhonebookEntry entry;
2602 char *memory_type_string;
2606 char *Line, OLine[100], BackLine[100];
2609 /* Check argument */
2610 if (argc && (strcmp("-i", args[0])))
2615 /* Go through data from stdin. */
2616 while (GetLine(stdin, Line, 99)) {
2617 strcpy(BackLine, Line);
2620 ptr = strtok(Line, ";");
2621 if (ptr) strcpy(entry.Name, ptr);
2622 else entry.Name[0] = 0;
2624 ptr = strtok(NULL, ";");
2625 if (ptr) strcpy(entry.Number, ptr);
2626 else entry.Number[0] = 0;
2628 ptr = strtok(NULL, ";");
2631 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2636 if (!strncmp(ptr,"ME", 2)) {
2637 memory_type_string = "int";
2638 entry.MemoryType = GMT_ME;
2640 if (!strncmp(ptr,"SM", 2)) {
2641 memory_type_string = "sim";
2642 entry.MemoryType = GMT_SM;
2644 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2649 ptr = strtok(NULL, ";");
2650 if (ptr) entry.Location = atoi(ptr);
2651 else entry.Location = 0;
2653 ptr = strtok(NULL, ";");
2654 if (ptr) entry.Group = atoi(ptr);
2655 else entry.Group = 0;
2658 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2662 for (subentry = 0; ; subentry++) {
2663 ptr = strtok(NULL, ";");
2665 if (ptr && *ptr != 0)
2666 entry.SubEntries[subentry].EntryType = atoi(ptr);
2670 ptr = strtok(NULL, ";");
2672 entry.SubEntries[subentry].NumberType=atoi(ptr);
2674 /* Phone Numbers need to have a number type. */
2675 if (!ptr && entry.SubEntries[subentry].EntryType == GSM_Number) {
2676 fprintf(stderr, _("Missing phone number type on line %d"
2677 " entry %d [%s]\n"), line_count, subentry, BackLine);
2682 ptr = strtok(NULL, ";");
2684 entry.SubEntries[subentry].BlockNumber=atoi(ptr);
2686 ptr = strtok(NULL, ";");
2688 /* 0x13 Date Type; it is only for Dailed Numbers, etc.
2689 we don't store to this memories so it's an error to use it. */
2690 if (!ptr || entry.SubEntries[subentry].EntryType == GSM_Date) {
2691 fprintf(stdout, _("There is no phone number on line %d entry %d [%s]\n"),
2692 line_count, subentry, BackLine);
2696 strcpy(entry.SubEntries[subentry].data.Number, ptr);
2699 entry.SubEntriesCount = subentry;
2701 /* This is to send other exports (like from 6110) to 7110 */
2702 if (!entry.SubEntriesCount) {
2703 entry.SubEntriesCount = 1;
2704 entry.SubEntries[subentry].EntryType = GSM_Number;
2705 entry.SubEntries[subentry].NumberType = GSM_General;
2706 entry.SubEntries[subentry].BlockNumber = 2;
2707 strcpy(entry.SubEntries[subentry].data.Number, entry.Number);
2713 GSM_PhonebookEntry aux;
2715 aux.Location = entry.Location;
2716 error = GSM->GetMemoryLocation(&aux);
2718 if (error == GE_NONE) {
2723 fprintf(stdout, _("Location busy. "));
2724 while (confirm < 0) {
2725 fprintf(stdout, _("Overwrite? (yes/no) "));
2726 GetLine(stdin, ans, 7);
2727 if (!strcmp(ans, _("yes"))) confirm = 1;
2728 else if (!strcmp(ans, _("no"))) confirm = 0;
2730 if (!confirm) continue;
2733 fprintf(stderr, _("Unknown error (%d)\n"), error);
2739 /* Do write and report success/failure. */
2740 error = GSM->WritePhonebookLocation(&entry);
2742 if (error == GE_NONE)
2743 fprintf (stdout, _("Write Succeeded: memory type: %s, loc: %d, name: %s, number: %s\n"), memory_type_string, entry.Location, entry.Name, entry.Number);
2745 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);
2753 /* Getting speed dials. */
2754 int getspeeddial(char *Number)
2756 GSM_SpeedDial SpeedDial;
2760 SpeedDial.Number = atoi(Number);
2762 if (GSM && GSM->GetSpeedDial && GSM->Terminate) {
2763 error = GSM->GetSpeedDial(&SpeedDial);
2766 GSM_DataClear(&data);
2767 data.SpeedDial = &SpeedDial;
2769 error = SM_Functions(GOP_GetSpeedDial, &data, &State);
2774 fprintf(stdout, _("SpeedDial nr. %d: %d:%d\n"), SpeedDial.Number, SpeedDial.MemoryType, SpeedDial.Location);
2776 case GE_NOTIMPLEMENTED:
2777 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2780 fprintf(stdout, _("Internal error\n"));
2787 /* Setting speed dials. */
2788 int setspeeddial(char *argv[])
2790 GSM_SpeedDial entry;
2792 char *memory_type_string;
2794 /* Handle command line args that set type, start and end locations. */
2796 if (strcmp(argv[1], "ME") == 0) {
2797 entry.MemoryType = 0x02;
2798 memory_type_string = "ME";
2799 } else if (strcmp(argv[1], "SM") == 0) {
2800 entry.MemoryType = 0x03;
2801 memory_type_string = "SM";
2803 fprintf(stderr, _("Unknown memory type %s!\n"), argv[1]);
2807 entry.Number = atoi(argv[0]);
2808 entry.Location = atoi(argv[2]);
2810 if (GSM->SetSpeedDial(&entry) == GE_NONE) {
2811 fprintf(stdout, _("Succesfully written!\n"));
2818 /* Getting the status of the display. */
2819 int getdisplaystatus(void)
2823 GSM->GetDisplayStatus(&Status);
2825 fprintf(stdout, _("Call in progress: %s\n"), Status & (1<<DS_Call_In_Progress)?_("on"):_("off"));
2826 fprintf(stdout, _("Unknown: %s\n"), Status & (1<<DS_Unknown)?_("on"):_("off"));
2827 fprintf(stdout, _("Unread SMS: %s\n"), Status & (1<<DS_Unread_SMS)?_("on"):_("off"));
2828 fprintf(stdout, _("Voice call: %s\n"), Status & (1<<DS_Voice_Call)?_("on"):_("off"));
2829 fprintf(stdout, _("Fax call active: %s\n"), Status & (1<<DS_Fax_Call)?_("on"):_("off"));
2830 fprintf(stdout, _("Data call active: %s\n"), Status & (1<<DS_Data_Call)?_("on"):_("off"));
2831 fprintf(stdout, _("Keyboard lock: %s\n"), Status & (1<<DS_Keyboard_Lock)?_("on"):_("off"));
2832 fprintf(stdout, _("SMS storage full: %s\n"), Status & (1<<DS_SMS_Storage_Full)?_("on"):_("off"));
2838 int netmonitor(char *Mode)
2840 unsigned char mode = atoi(Mode);
2843 if (!strcmp(Mode, "reset"))
2845 else if (!strcmp(Mode, "off"))
2847 else if (!strcmp(Mode, "field"))
2849 else if (!strcmp(Mode, "devel"))
2851 else if (!strcmp(Mode, "next"))
2854 memset(&Screen, 0, 50);
2855 GSM->NetMonitor(mode, Screen);
2858 fprintf(stdout, "%s\n", Screen);
2866 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2867 char imei[64], model[64], rev[64], manufacturer[64];
2868 GSM_Statemachine *sm = &State;
2870 data.Manufacturer=manufacturer;
2875 /* Retrying is bad idea: what if function is simply not implemented?
2876 Anyway let's wait 2 seconds for the right packet from the phone. */
2879 strcpy(imei, "(unknown)");
2880 strcpy(manufacturer, "(unknown)");
2881 strcpy(model, "(unknown)");
2882 strcpy(rev, "(unknown)");
2884 SM_Functions(GOP_Identify, &data, sm);
2886 fprintf(stdout, _("IMEI: %s\n"), imei);
2887 fprintf(stdout, _("Manufacturer: %s\n"), manufacturer);
2888 fprintf(stdout, _("Model: %s\n"), model);
2889 fprintf(stdout, _("Revision: %s\n"), rev);
2896 int senddtmf(char *String)
2898 GSM->SendDTMF(String);
2903 /* Resets the phone */
2904 int reset( char *type)
2906 unsigned char _type = 0x03;
2909 if(!strcmp(type, "soft"))
2912 if(!strcmp(type, "hard"))
2915 fprintf(stderr, _("What kind of reset do you want??\n"));
2926 /* pmon allows fbus code to run in a passive state - it doesn't worry about
2927 whether comms are established with the phone. A debugging/development
2933 GSM_ConnectionType connection=GCT_Serial;
2934 GSM_Statemachine sm;
2936 /* Initialise the code for the GSM interface. */
2937 error = GSM_Initialise(model, Port, Initlength, connection, NULL, &sm);
2939 if (error != GE_NONE) {
2940 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
2951 int sendringtone(int argc, char *argv[])
2953 GSM_Ringtone ringtone;
2956 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2957 fprintf(stdout, _("Failed to load ringtone.\n"));
2961 error = GSM->SendRingtone(&ringtone,argv[1]);
2963 if (error == GE_NONE)
2964 fprintf(stdout, _("Send succeeded!\n"));
2966 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
2974 int setringtone(int argc, char *argv[])
2976 GSM_Ringtone ringtone;
2979 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2980 fprintf(stdout, _("Failed to load ringtone.\n"));
2984 error = GSM->SetRingtone(&ringtone);
2986 if (error == GE_NONE)
2987 fprintf(stdout, _("Send succeeded!\n"));
2989 fprintf(stdout, _("Send failed\n"));
2996 int presskeysequence(void)
3002 memset(&buf[0], 0, 102);
3003 while (read(0, buf, 100) > 0) {
3004 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
3005 if (GSM->HandleString(buf) != GE_NONE)
3006 fprintf(stdout, _("Key press simulation failed.\n"));
3007 memset(buf, 0, 102);
3014 /* This is a "convenience" function to allow quick test of new API stuff which
3015 doesn't warrant a "proper" command line function. */
3017 int foogle(char *argv[])
3019 /* Initialise the code for the GSM interface. */
3021 // Fill in what you would like to test here...