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.12 2002/04/03 01:44:15 short
23 Implemented connection type "tcp" (GCT_TCP), use <hostname>:<port> as "port"
25 Revision 1.1.1.11 2002/04/03 00:08:17 short
26 Found in "gnokii-working" directory, some November-patches version
28 Revision 1.143 2001/09/14 13:30:07 pkot
29 Fixed bugs introduced during 0.3.3 merge
31 Revision 1.142 2001/09/14 13:02:03 pkot
32 Gnokii calendar changes from 0.3.3
34 Revision 1.141 2001/09/14 12:53:00 pkot
37 Set valid operator on logos xgnokii screen.
39 Revision 1.140 2001/07/27 00:02:21 pkot
40 Generic AT support for the new structure (Manfred Jonsson)
42 Revision 1.139 2001/07/01 23:16:45 pkot
43 Fixed a typo in gnokii.c avoiding saving logo (Jan Havelka)
45 Revision 1.138 2001/06/28 00:28:45 pkot
46 Small docs updates (Pawel Kot)
48 Revision 1.137 2001/06/27 23:52:50 pkot
49 7110/6210 updates (Marian Jancar)
51 Revision 1.136 2001/06/10 23:49:49 pkot
52 Small fixes to hide compilation warnings and allow gnokii.c to compile
54 Revision 1.135 2001/06/10 11:42:26 machek
55 Cleanup: some formating, made Statemachine global, converted to new
56 structure w.r.t. SMS-es
58 Revision 1.134 2001/05/24 20:47:30 chris
59 More updating of 7110 code and some of xgnokii_lowlevel changed over.
61 Revision 1.133 2001/04/23 17:20:01 pkot
62 Added possibility for viewing logos (currently nol and ngg) on console (Bartek Klepacz)
64 Revision 1.132 2001/03/21 23:36:06 chris
65 Added the statemachine
66 This will break gnokii --identify and --monitor except for 6210/7110
68 Revision 1.131 2001/03/19 23:43:46 pkot
69 Solaris / BSD '#if defined' cleanup
71 Revision 1.130 2001/03/13 01:23:18 pkot
72 Windows updates (Manfred Jonsson)
74 Revision 1.129 2001/03/13 01:21:39 pkot
75 *BSD updates (Bert Driehuis)
77 Revision 1.128 2001/03/08 00:49:06 pkot
78 Fixed bug (introduced by me) in getmemory function. Now gnokii.c should compile
80 Revision 1.127 2001/03/08 00:18:13 pkot
81 Fixed writephonebook once again. Someone kick me please...
83 Revision 1.126 2001/03/07 21:46:12 pkot
84 Fixed writephonebook patch
86 Revision 1.125 2001/03/06 22:19:14 pkot
87 Cleanups and fixes in gnokii.c:
89 - fixed bug reported by Gabriele Zappi
90 - fixed small bugs introduced by Pavel Machek
92 Revision 1.124 2001/02/28 21:42:00 machek
93 Possibility to force overwrite in --getsms (-F). Possibility to get
94 multiple files (use --getsms -f xyzzy%d), cleanup.
96 Revision 1.123 2001/02/20 21:55:11 pkot
97 Small #include updates
99 Revision 1.122 2001/02/16 14:29:53 chris
100 Restructure of common/. Fixed a problem in fbus-phonet.c
101 Lots of dprintfs for Marcin
102 Any size xpm can now be loaded (eg for 7110 startup logos)
103 nk7110 code detects 7110/6210 and alters startup logo size to suit
104 Moved Marcin's extended phonebook code into gnokii.c
106 Revision 1.121 2001/02/06 21:15:35 chris
107 Preliminary irda support for 7110 etc. Not well tested!
109 Revision 1.120 2001/02/06 08:13:32 pkot
110 One more include in gnokii.c needed
112 Revision 1.119 2001/02/05 12:29:37 pkot
113 Changes needed to let unicode work
115 Revision 1.118 2001/02/01 15:17:33 pkot
116 Fixed --identify and added Manfred's manufacturer patch
118 Revision 1.117 2001/01/31 23:45:27 pkot
119 --identify should work ok now
121 Revision 1.116 2001/01/24 20:19:55 machek
122 Do not retry identification, if it is not implemented, it is bad idea.
124 Revision 1.115 2001/01/22 01:25:10 hugh
125 Tweaks for 3810 series, datacalls seem to be broken so need to do
126 some more debugging...
128 Revision 1.114 2001/01/17 02:54:55 chris
129 More 7110 work. Use with care! (eg it is not possible to delete phonebook entries)
130 I can now edit my phonebook in xgnokii but it is 'work in progress'.
132 Revision 1.113 2001/01/15 17:00:49 pkot
133 Initial keypress sequence support. Disable compilation warning
135 Revision 1.112 2001/01/12 14:09:13 pkot
136 More cleanups. This time mainly in the code.
138 Revision 1.111 2001/01/10 16:32:18 pkot
139 Documentation updates.
140 FreeBSD fix for 3810 code.
141 Added possibility for deleting SMS just after reading it in gnokii.
145 Revision 1.110 2001/01/08 15:11:37 pkot
146 Documentation updates.
147 Fixed some bugs and removed FIXMEs.
148 We need to move some stuff from configure.in to aclocal.m4
150 Revision 1.109 2000/12/29 15:39:07 pkot
151 Reverted a change in fbus-3810.c which broke compling with --enable-debug.
152 Small fixes in gnokii.c
154 Revision 1.108 2000/12/19 16:18:16 pkot
155 configure script updates and added shared function for configfile reading
168 # include <strings.h> /* for memset */
171 #include <sys/types.h>
172 #include <sys/stat.h>
177 #define sleep(x) Sleep((x) * 1000)
178 #define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
180 #include "win32/getopt.h"
195 #include "gsm-common.h"
197 #include "gsm-networks.h"
198 #include "cfgreader.h"
200 #include "gsm-filetypes.h"
201 #include "gsm-bitmaps.h"
202 #include "gsm-ringtones.h"
203 #include "gsm-statemachine.h"
205 char *model; /* Model from .gnokiirc file. */
206 char *Port; /* Serial port from .gnokiirc file */
207 char *Initlength; /* Init length from .gnokiirc file */
208 char *Connection; /* Connection type from .gnokiirc file */
209 char *BinDir; /* Binaries directory from .gnokiirc file - not used here yet */
210 /* Local variables */
212 char *GetProfileCallAlertString(int code)
215 case PROFILE_CALLALERT_RINGING: return "Ringing";
216 case PROFILE_CALLALERT_ASCENDING: return "Ascending";
217 case PROFILE_CALLALERT_RINGONCE: return "Ring once";
218 case PROFILE_CALLALERT_BEEPONCE: return "Beep once";
219 case PROFILE_CALLALERT_CALLERGROUPS: return "Caller groups";
220 case PROFILE_CALLALERT_OFF: return "Off";
221 default: return "Unknown";
225 char *GetProfileVolumeString(int code)
228 case PROFILE_VOLUME_LEVEL1: return "Level 1";
229 case PROFILE_VOLUME_LEVEL2: return "Level 2";
230 case PROFILE_VOLUME_LEVEL3: return "Level 3";
231 case PROFILE_VOLUME_LEVEL4: return "Level 4";
232 case PROFILE_VOLUME_LEVEL5: return "Level 5";
233 default: return "Unknown";
237 char *GetProfileKeypadToneString(int code)
240 case PROFILE_KEYPAD_OFF: return "Off";
241 case PROFILE_KEYPAD_LEVEL1: return "Level 1";
242 case PROFILE_KEYPAD_LEVEL2: return "Level 2";
243 case PROFILE_KEYPAD_LEVEL3: return "Level 3";
244 default: return "Unknown";
248 char *GetProfileMessageToneString(int code)
251 case PROFILE_MESSAGE_NOTONE: return "No tone";
252 case PROFILE_MESSAGE_STANDARD: return "Standard";
253 case PROFILE_MESSAGE_SPECIAL: return "Special";
254 case PROFILE_MESSAGE_BEEPONCE: return "Beep once";
255 case PROFILE_MESSAGE_ASCENDING: return "Ascending";
256 default: return "Unknown";
260 char *GetProfileWarningToneString(int code)
263 case PROFILE_WARNING_OFF: return "Off";
264 case PROFILE_WARNING_ON: return "On";
265 default: return "Unknown";
269 char *GetProfileVibrationString(int code)
272 case PROFILE_VIBRATION_OFF: return "Off";
273 case PROFILE_VIBRATION_ON: return "On";
274 default: return "Unknown";
278 /* This function shows the copyright and some informations usefull for
283 fprintf(stdout, _("GNOKII Version %s\n"
284 "Copyright (C) Hugh Blemings <hugh@blemings.org>, 1999, 2000\n"
285 "Copyright (C) Pavel Janík ml. <Pavel.Janik@suse.cz>, 1999, 2000\n"
286 "Copyright (C) Pavel Machek <pavel@ucw.cz>, 2001\n"
287 "Copyright (C) Pawe³ Kot <pkot@linuxnews.pl>, 2001\n"
288 "gnokii is free software, covered by the GNU General Public License, and you are\n"
289 "welcome to change it and/or distribute copies of it under certain conditions.\n"
290 "There is absolutely no warranty for gnokii. See GPL for details.\n"
291 "Built %s %s for %s on %s \n"), VERSION, __TIME__, __DATE__, model, Port);
295 /* The function usage is only informative - it prints this program's usage and
296 command-line options. */
300 fprintf(stdout, _(" usage: gnokii [--help|--monitor|--version]\n"
301 " gnokii --getmemory memory_type start [end]\n"
302 " gnokii --writephonebook [-i]\n"
303 " gnokii --getspeeddial number\n"
304 " gnokii --setspeeddial number memory_type location\n"
305 " gnokii --getsms memory_type start [end] [-f file] [-F file] [-d]\n"
306 " gnokii --deletesms memory_type start [end]\n"
307 " gnokii --sendsms destination [-r] [-C n] [-v n]\n"
308 " [--longtext|--longudh] [--udh] [-8]\n"
309 " [--smsc message_center_number | --smscno message_center_index]\n"
310 " gnokii --savesms [-m] [-l n] [-i]\n"
311 " gnokii --getsmsc message_center_number\n"
312 " gnokii --setdatetime [YYYY [MM [DD [HH [MM]]]]]\n"
313 " gnokii --getdatetime\n"
314 " gnokii --setalarm HH MM\n"
315 " gnokii --getalarm\n"
316 " gnokii --dialvoice number\n"
317 " gnokii --getcalendarnote start [end] [-v]\n"
318 " gnokii --writecalendarnote vcardfile number\n"
319 " gnokii --deletecalendarnote start [end]\n"
320 " gnokii --getdisplaystatus\n"
321 " gnokii --netmonitor {reset|off|field|devel|next|nr}\n"
322 " gnokii --identify\n"
323 " gnokii --senddtmf string\n"
324 " gnokii --sendlogo {caller|op} destination logofile [network code]\n"
325 " [--smsc message_center_number | --smscno message_center_index]\n"
326 " gnokii --sendringtone destination rtttlfile\n"
327 " [--smsc message_center_number | --smscno message_center_index]\n"
328 " gnokii --setlogo op [logofile] [network code]\n"
329 " gnokii --setlogo startup [logofile]\n"
330 " gnokii --setlogo caller [logofile] [caller group number] [group name]\n"
331 " gnokii --setlogo {dealer|text} [text]\n"
332 " gnokii --getlogo op [logofile] [network code]\n"
333 " gnokii --getlogo startup [logofile] [network code]\n"
334 " gnokii --getlogo caller [logofile][caller group number][network code]\n"
335 " gnokii --getlogo {dealer|text}\n"
336 " gnokii --viewlogo logofile\n"
337 " gnokii --setringtone rtttlfile\n"
338 " gnokii --reset [soft|hard]\n"
339 " gnokii --getprofile [number]\n"
340 " gnokii --displayoutput\n"
341 " gnokii --keysequence\n"
345 " gnokii --entersecuritycode PIN|PIN2|PUK|PUK2\n"
346 " gnokii --getsecuritycodestatus\n"
352 /* fbusinit is the generic function which waits for the FBUS link. The limit
353 is 10 seconds. After 10 seconds we quit. */
355 static GSM_Statemachine State;
356 static GSM_Data data;
358 void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame))
362 GSM_ConnectionType connection=GCT_Serial;
364 GSM_DataClear(&data);
366 if (!strcmp(Connection, "infrared")) connection=GCT_Infrared;
367 if (!strcmp(Connection, "irda")) connection=GCT_Irda;
368 if (!strcmp(Connection, "tcp")) connection=GCT_TCP;
370 /* Initialise the code for the GSM interface. */
372 error = GSM_Initialise(model, Port, Initlength, connection, rlp_handler, &State);
374 if (error != GE_NONE) {
375 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
379 /* First (and important!) wait for GSM link to be active. We allow 10
382 while (count++ < 200 && *GSM_LinkOK == false)
385 if (*GSM_LinkOK == false) {
386 fprintf (stderr, _("Hmmm... GSM_LinkOK never went true. Quitting.\n"));
391 /* This function checks that the argument count for a given options is withing
393 int checkargs(int opt, struct gnokii_arg_len gals[], int argc)
397 /* Walk through the whole array with options requiring arguments. */
398 for (i = 0; !(gals[i].gal_min == 0 && gals[i].gal_max == 0); i++) {
400 /* Current option. */
401 if (gals[i].gal_opt == opt) {
403 /* Argument count checking. */
404 if (gals[i].gal_flags == GAL_XOR) {
405 if (gals[i].gal_min == argc || gals[i].gal_max == argc)
408 if (gals[i].gal_min <= argc && gals[i].gal_max >= argc)
416 /* We do not have options without arguments in the array, so check them. */
417 if (argc == 0) return 0;
421 /* Main function - handles command line arguments, passes them to separate
422 functions accordingly. */
423 int main(int argc, char *argv[])
429 /* Every option should be in this array. */
430 static struct option long_options[] =
432 /* FIXME: these comments are nice, but they would be more usefull as docs for the user */
434 { "help", no_argument, NULL, OPT_HELP },
436 // Display version and build information.
437 { "version", no_argument, NULL, OPT_VERSION },
440 { "monitor", no_argument, NULL, OPT_MONITOR },
444 // Enter Security Code mode
445 { "entersecuritycode", required_argument, NULL, OPT_ENTERSECURITYCODE },
447 // Get Security Code status
448 { "getsecuritycodestatus", no_argument, NULL, OPT_GETSECURITYCODESTATUS },
453 { "setdatetime", optional_argument, NULL, OPT_SETDATETIME },
455 // Get date and time mode
456 { "getdatetime", no_argument, NULL, OPT_GETDATETIME },
459 { "setalarm", required_argument, NULL, OPT_SETALARM },
462 { "getalarm", no_argument, NULL, OPT_GETALARM },
465 { "dialvoice", required_argument, NULL, OPT_DIALVOICE },
467 // Get calendar note mode
468 { "getcalendarnote", required_argument, NULL, OPT_GETCALENDARNOTE },
470 // Write calendar note mode
471 { "writecalendarnote", required_argument, NULL, OPT_WRITECALENDARNOTE },
473 // Delete calendar note mode
474 { "deletecalendarnote", required_argument, NULL, OPT_DELCALENDARNOTE },
476 // Get display status mode
477 { "getdisplaystatus", no_argument, NULL, OPT_GETDISPLAYSTATUS },
480 { "getmemory", required_argument, NULL, OPT_GETMEMORY },
482 // Write phonebook (memory) mode
483 { "writephonebook", optional_argument, NULL, OPT_WRITEPHONEBOOK },
485 // Get speed dial mode
486 { "getspeeddial", required_argument, NULL, OPT_GETSPEEDDIAL },
488 // Set speed dial mode
489 { "setspeeddial", required_argument, NULL, OPT_SETSPEEDDIAL },
491 // Get SMS message mode
492 { "getsms", required_argument, NULL, OPT_GETSMS },
494 // Delete SMS message mode
495 { "deletesms", required_argument, NULL, OPT_DELETESMS },
497 // Send SMS message mode
498 { "sendsms", required_argument, NULL, OPT_SENDSMS },
500 // Save SMS message mode
501 { "savesms", optional_argument, NULL, OPT_SAVESMS },
503 // Send logo as SMS message mode
504 { "sendlogo", required_argument, NULL, OPT_SENDLOGO },
506 // Send ringtone as SMS message
507 { "sendringtone", required_argument, NULL, OPT_SENDRINGTONE },
510 { "setringtone", required_argument, NULL, OPT_SETRINGTONE },
512 // Get SMS center number mode
513 { "getsmsc", required_argument, NULL, OPT_GETSMSC },
515 // For development purposes: run in passive monitoring mode
516 { "pmon", no_argument, NULL, OPT_PMON },
519 { "netmonitor", required_argument, NULL, OPT_NETMONITOR },
522 { "identify", no_argument, NULL, OPT_IDENTIFY },
524 // Send DTMF sequence
525 { "senddtmf", required_argument, NULL, OPT_SENDDTMF },
528 { "reset", optional_argument, NULL, OPT_RESET },
531 { "setlogo", optional_argument, NULL, OPT_SETLOGO },
534 { "getlogo", required_argument, NULL, OPT_GETLOGO },
537 { "viewlogo", required_argument, NULL, OPT_VIEWLOGO },
540 { "getprofile", optional_argument, NULL, OPT_GETPROFILE },
542 // Show texts from phone's display
543 { "displayoutput", no_argument, NULL, OPT_DISPLAYOUTPUT },
545 // Simulate pressing the keys
546 { "keysequence", no_argument, NULL, OPT_KEYPRESS },
548 // For development purposes: insert you function calls here
549 { "foogle", no_argument, NULL, OPT_FOOGLE },
554 /* Every command which requires arguments should have an appropriate entry
556 struct gnokii_arg_len gals[] =
560 { OPT_ENTERSECURITYCODE, 1, 1, 0 },
563 { OPT_SETDATETIME, 0, 5, 0 },
564 { OPT_SETALARM, 2, 2, 0 },
565 { OPT_DIALVOICE, 1, 1, 0 },
566 { OPT_GETCALENDARNOTE, 1, 3, 0 },
567 { OPT_WRITECALENDARNOTE, 2, 2, 0 },
568 { OPT_DELCALENDARNOTE, 1, 2, 0 },
569 { OPT_GETMEMORY, 2, 3, 0 },
570 { OPT_GETSPEEDDIAL, 1, 1, 0 },
571 { OPT_SETSPEEDDIAL, 3, 3, 0 },
572 { OPT_GETSMS, 2, 5, 0 },
573 { OPT_DELETESMS, 2, 3, 0 },
574 { OPT_SENDSMS, 1, 10, 0 },
575 { OPT_SAVESMS, 0, 6, 0 },
576 { OPT_SENDLOGO, 3, 6, 0 },
577 { OPT_SENDRINGTONE, 2, 6, 0 },
578 { OPT_GETSMSC, 1, 1, 0 },
579 { OPT_GETWELCOMENOTE, 1, 1, 0 },
580 { OPT_SETWELCOMENOTE, 1, 1, 0 },
581 { OPT_NETMONITOR, 1, 1, 0 },
582 { OPT_SENDDTMF, 1, 1, 0 },
583 { OPT_SETLOGO, 1, 4, 0 },
584 { OPT_GETLOGO, 1, 4, 0 },
585 { OPT_VIEWLOGO, 1, 1, 0 },
586 { OPT_SETRINGTONE, 1, 1, 0 },
587 { OPT_RESET, 0, 1, 0 },
588 { OPT_GETPROFILE, 0, 1, 0 },
589 { OPT_WRITEPHONEBOOK, 0, 1, 0 },
596 /* For GNU gettext */
598 textdomain("gnokii");
599 setlocale(LC_ALL, "");
602 /* Read config file */
603 if (readconfig(&model, &Port, &Initlength, &Connection, &BinDir) < 0) {
607 /* Handle command line arguments. */
608 c = getopt_long(argc, argv, "", long_options, NULL);
609 if (c == -1) /* No argument given - we should display usage. */
613 // First, error conditions
616 fprintf(stderr, _("Use '%s --help' for usage informations.\n"), argv[0]);
618 // Then, options with no arguments
625 /* We have to build an array of the arguments which will be passed to the
626 functions. Please note that every text after the --command will be
627 passed as arguments. A syntax like gnokii --cmd1 args --cmd2 args will
628 not work as expected; instead args --cmd2 args is passed as a
630 if ((nargv = malloc(sizeof(char *) * argc)) != NULL) {
631 for (i = 2; i < argc; i++)
632 nargv[i-2] = argv[i];
634 if (checkargs(c, gals, nargc)) {
635 free(nargv); /* Wrong number of arguments - we should display usage. */
640 /* have to ignore SIGALARM */
644 /* Initialise the code for the GSM interface. */
652 case OPT_ENTERSECURITYCODE:
653 rc = entersecuritycode(optarg);
655 case OPT_GETSECURITYCODESTATUS:
656 rc = getsecuritycodestatus();
659 case OPT_GETDATETIME:
665 case OPT_GETDISPLAYSTATUS:
666 rc = getdisplaystatus();
671 case OPT_WRITEPHONEBOOK:
672 rc = writephonebook(nargc, nargv);
674 // Now, options with arguments
675 case OPT_SETDATETIME:
676 rc = setdatetime(nargc, nargv);
679 rc = setalarm(nargv);
682 rc = dialvoice(optarg);
684 case OPT_GETCALENDARNOTE:
685 rc = getcalendarnote(nargc, nargv);
687 case OPT_DELCALENDARNOTE:
688 rc = deletecalendarnote(nargc, nargv);
690 case OPT_WRITECALENDARNOTE:
691 rc = writecalendarnote(nargv);
694 rc = getmemory(nargc, nargv);
696 case OPT_GETSPEEDDIAL:
697 rc = getspeeddial(optarg);
699 case OPT_SETSPEEDDIAL:
700 rc = setspeeddial(nargv);
703 rc = getsms(argc, argv);
706 rc = deletesms(nargc, nargv);
709 rc = sendsms(nargc, nargv);
712 rc = savesms(argc, argv);
715 rc = sendlogo(nargc, nargv);
718 rc = getsmsc(optarg);
721 rc = netmonitor(optarg);
727 rc = setlogo(nargc, nargv);
730 rc = getlogo(nargc, nargv);
733 rc = viewlogo(optarg);
735 case OPT_SETRINGTONE:
736 rc = setringtone(nargc, nargv);
738 case OPT_SENDRINGTONE:
739 rc = sendringtone(argc, argv);
742 rc = getprofile(nargc, nargv);
744 case OPT_DISPLAYOUTPUT:
745 rc = displayoutput();
748 rc = presskeysequence();
756 rc = senddtmf(optarg);
762 fprintf(stderr, _("Unknown option: %d\n"), c);
769 fprintf(stderr, _("Wrong number of arguments\n"));
773 #define SMSC_SHORTCHAR_SMSC (0xF0)
774 #define SMSC_SHORTCHAR_SMSCNO (0xF1)
775 #define SMSC_OPTIONS \
776 { "smsc", required_argument, NULL, SMSC_SHORTCHAR_SMSC}, \
777 { "smscno", required_argument, NULL, SMSC_SHORTCHAR_SMSCNO}
779 /* RETURNS: Whether the options was found as ours (=>rerun getopt_long())
781 static bool smsc_options_parse(int option,GSM_SMSMessage *SMS)
785 case SMSC_SHORTCHAR_SMSC: /* SMSC number */
786 SMS->MessageCenter.No = 0;
787 strcpy(SMS->MessageCenter.Number,optarg);
790 case SMSC_SHORTCHAR_SMSCNO: /* SMSC number index in phone memory */
791 SMS->MessageCenter.No = atoi(optarg);
793 if (SMS->MessageCenter.No < 1 || SMS->MessageCenter.No > 5)
798 return(false); /* option not recognized */
801 return(true); /* option was successfuly processed */
806 bool sendsms_deconcatenated(GSM_SMSMessage *sms,char *buf,size_t buflen,bool useudh)
808 GSM_Deconcatenate_state SMS_Deconcatenate_state;
811 SMS_Deconcatenate_state.first=true;
812 while (SMS_Deconcatenate(&SMS_Deconcatenate_state,sms,buf,buflen,useudh)) {
813 /* Send the message. */
814 error = GSM->SendSMSMessage(sms);
816 if (error == GE_SMSSENDOK) {
817 fprintf(stdout, _("Send succeeded!\n"));
819 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
822 /* Here the sleep have no meaning.
823 * If it is required by some backend phone driver, it should be done THERE!
830 /* Send SMS messages. */
831 int sendsms(int argc, char *argv[])
834 /* The maximum length of an uncompressed concatenated short message is
835 255 * 153 = 39015 default alphabet characters */
836 char message_buffer[GSM_MAX_CONCATENATED_SMS_LENGTH];
837 int input_len, chars_read;
841 struct option options[] = {
843 { "longtext", no_argument, NULL, '3'},
844 { "longudh", no_argument, NULL, '4'},
845 { "udh", no_argument, NULL, '5'},
849 input_len = GSM_MAX_SMS_LENGTH;
857 - message validity for 3 days
858 - unset user data header indicator
863 SMS.Compression = false;
864 SMS.EightBit = false;
865 SMS.MessageCenter.No = 1;
866 SMS.Validity = 4320; /* 4320 minutes == 72 hours */
867 SMS.UDHPresent = false;
869 strcpy(SMS.Destination, argv[0]);
874 while ((i = getopt_long(argc, argv, "r8cC:v:", options, NULL)) != -1) {
875 if (smsc_options_parse(i,&SMS))
877 switch (i) { // -c for compression. not yet implemented.
878 case '3': /* we send long message in text format */
879 input_len = GSM_MAX_CONCATENATED_SMS_LENGTH;
882 case '4': /* we send long message in UDH format */
883 input_len = GSM_MAX_CONCATENATED_SMS_LENGTH;
886 case '5': /* UDH indication requested */
887 SMS.UDHPresent = true;
889 case 'r': /* request for delivery report */
892 case 'C': /* class Message */
910 case '8': /* 8-bit data */
914 SMS.Validity = atoi(optarg);
917 usage(); /* Would be better to have an sendsms_usage() here. */
921 /* Get message text from stdin. */
922 chars_read = fread(message_buffer, 1, input_len, stdin);
924 if (chars_read == 0) {
925 fprintf(stderr, _("Couldn't read from stdin!\n"));
927 } else if (chars_read > input_len) {
928 fprintf(stderr, _("Input too long!\n"));
932 if (SMS.UDHPresent) {
933 u8 UDHlen = 1 + message_buffer[0]; /* designifify */
935 if (chars_read < UDHlen || sizeof(SMS.UDH) < UDHlen) {
936 fprintf(stderr, _("Input too short to satisfy UDH!\n"));
939 memcpy(SMS.UDH, message_buffer, UDHlen);
941 memmove(message_buffer, message_buffer + UDHlen, chars_read);
944 /* Null terminate. */
945 message_buffer[chars_read] = 0x00;
947 sendsms_deconcatenated(&SMS,message_buffer,chars_read,useudh);
954 int savesms(int argc, char *argv[])
958 /* The maximum length of an uncompressed concatenated short message is
959 255 * 153 = 39015 default alphabet characters */
960 char message_buffer[GSM_MAX_CONCATENATED_SMS_LENGTH];
961 int input_len, chars_read;
968 SMS.Destination[0] = '\0';
970 SMS.Compression = false;
971 SMS.EightBit = false;
972 SMS.MessageCenter.No = 1;
973 SMS.Validity = 4320; /* 4320 minutes == 72 hours */
974 SMS.UDHPresent = false;
975 SMS.Status = GSS_NOTSENTREAD;
977 SMS.MemoryType = GMT_SM;
979 input_len = GSM_MAX_SMS_LENGTH;
982 while ((i = getopt(argc, argv, "ml:in:s:c:")) != -1) {
984 case 'm': /* mark the message as sent */
985 SMS.Status = GSS_SENTREAD;
987 case 'l': /* Specify the location */
988 SMS.Location = atoi(optarg);
990 case 'i': /* Ask before overwriting */
993 case 'n': /* Specify the from number */
995 case 's': /* Specify the smsc number */
997 case 'c': /* Specify the smsc location */
1008 aux.Location = SMS.Location;
1009 data.SMSMessage = &aux;
1010 error = SM_Functions(GOP_GetSMS, &data, &State);
1013 fprintf(stderr, _("Message at specified location exists. "));
1014 while (confirm < 0) {
1015 fprintf(stderr, _("Overwrite? (yes/no) "));
1016 GetLine(stdin, ans, 7);
1017 if (!strcmp(ans, "yes")) confirm = 1;
1018 else if (!strcmp(ans, "no")) confirm = 0;
1020 if (!confirm) { GSM->Terminate(); return 0; }
1022 case GE_INVALIDSMSLOCATION:
1023 fprintf(stderr, _("Invalid location\n"));
1027 /* FIXME: Remove this fprintf when the function is thoroughly tested */
1029 fprintf(stderr, _("Location %d empty. Saving\n"), SMS.Location);
1034 chars_read = fread(message_buffer, 1, input_len, stdin);
1036 if (chars_read == 0) {
1038 fprintf(stderr, _("Couldn't read from stdin!\n"));
1041 } else if (chars_read > input_len) {
1043 fprintf(stderr, _("Input too long!\n"));
1048 strncpy (SMS.MessageText, message_buffer, chars_read);
1049 SMS.MessageText[chars_read] = 0;
1050 SMS.MessageTextLength=chars_read;
1052 error = GSM->SaveSMSMessage(&SMS);
1054 if (error == GE_NONE) {
1055 fprintf(stdout, _("Saved!\n"));
1057 fprintf(stdout, _("Saving failed (error=%d)\n"), error);
1065 /* Get SMSC number */
1066 int getsmsc(char *MessageCenterNumber)
1068 GSM_MessageCenter MessageCenter;
1072 memset(&MessageCenter, 0, sizeof(MessageCenter));
1073 MessageCenter.No=atoi(MessageCenterNumber);
1075 if (GSM && GSM->GetSMSCenter && GSM->Terminate) {
1076 error = GSM->GetSMSCenter(&MessageCenter);
1079 GSM_DataClear(&data);
1080 data.MessageCenter = &MessageCenter;
1081 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
1086 fprintf(stdout, _("%d. SMS center (%s) number is %s\n"), MessageCenter.No, MessageCenter.Name, MessageCenter.Number);
1087 fprintf(stdout, _("Default recipient number is %s\n"), MessageCenter.Recipient);
1088 fprintf(stdout, _("Messages sent as "));
1090 switch (MessageCenter.Format) {
1092 fprintf(stdout, _("Text"));
1095 fprintf(stdout, _("Paging"));
1098 fprintf(stdout, _("Fax"));
1102 fprintf(stdout, _("Email"));
1105 fprintf(stdout, _("ERMES"));
1108 fprintf(stdout, _("X.400"));
1111 fprintf(stdout, _("Unknown"));
1116 fprintf(stdout, _("Message validity is "));
1118 switch (MessageCenter.Validity) {
1120 fprintf(stdout, _("1 hour"));
1123 fprintf(stdout, _("6 hours"));
1126 fprintf(stdout, _("24 hours"));
1129 fprintf(stdout, _("72 hours"));
1132 fprintf(stdout, _("1 week"));
1135 fprintf(stdout, _("Maximum time"));
1138 fprintf(stdout, _("Unknown"));
1142 fprintf(stdout, "\n");
1145 case GE_NOTIMPLEMENTED:
1146 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1149 fprintf(stdout, _("SMS center can not be found :-(\n"));
1156 /* Get SMS messages. */
1157 int getsms(int argc, char *argv[])
1160 GSM_SMSMessage message;
1161 char *memory_type_string;
1162 int start_message, end_message, count, mode = 1;
1169 /* Handle command line args that set type, start and end locations. */
1170 memory_type_string = argv[2];
1171 message.MemoryType = StrToMemoryType(memory_type_string);
1172 if (message.MemoryType == GMT_XX) {
1173 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[2]);
1177 memset(&filename, 0, 64);
1179 start_message = end_message = atoi(argv[3]);
1183 /* [end] can be only argv[4] */
1184 if (argv[4][0] != '-') {
1185 end_message = atoi(argv[4]);
1188 /* parse all options (beginning with '-' */
1189 while ((i = getopt(argc, argv, "f:F:d")) != -1) {
1198 dprintf(_("Saving into %s\n"), optarg);
1199 strncpy(filename, optarg, 64);
1200 if (strlen(optarg) > 63) {
1201 fprintf(stderr, _("Filename too long - will be truncated to 63 characters.\n"));
1204 filename[strlen(optarg)] = 0;
1214 /* Now retrieve the requested entries. */
1215 for (count = start_message; count <= end_message; count ++) {
1217 message.Location = count;
1218 data.SMSMessage = &message;
1219 error = SM_Functions(GOP_GetSMS, &data, &State);
1223 switch (message.Type) {
1225 fprintf(stdout, _("%d. Outbox Message "), message.MessageNumber);
1227 fprintf(stdout, _("(sent)\n"));
1229 fprintf(stdout, _("(not sent)\n"));
1230 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1233 fprintf(stdout, _("%d. Delivery Report "), message.MessageNumber);
1235 fprintf(stdout, _("(read)\n"));
1237 fprintf(stdout, _("(not read)\n"));
1238 fprintf(stdout, _("Sending date/time: %d/%d/%d %d:%02d:%02d "), \
1239 message.Time.Day, message.Time.Month, message.Time.Year, \
1240 message.Time.Hour, message.Time.Minute, message.Time.Second);
1241 if (message.Time.Timezone) {
1242 if (message.Time.Timezone > 0)
1243 fprintf(stdout,_("+%02d00"), message.Time.Timezone);
1245 fprintf(stdout,_("%02d00"), message.Time.Timezone);
1247 fprintf(stdout, "\n");
1248 fprintf(stdout, _("Response date/time: %d/%d/%d %d:%02d:%02d "), \
1249 message.SMSCTime.Day, message.SMSCTime.Month, message.SMSCTime.Year, \
1250 message.SMSCTime.Hour, message.SMSCTime.Minute, message.SMSCTime.Second);
1251 if (message.SMSCTime.Timezone) {
1252 if (message.SMSCTime.Timezone > 0)
1253 fprintf(stdout,_("+%02d00"),message.SMSCTime.Timezone);
1255 fprintf(stdout,_("%02d00"),message.SMSCTime.Timezone);
1257 fprintf(stdout, "\n");
1258 fprintf(stdout, _("Receiver: %s Msg Center: %s\n"), message.Sender, message.MessageCenter.Number);
1259 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1262 fprintf(stdout, _("%d. Inbox Message "), message.MessageNumber);
1264 fprintf(stdout, _("(read)\n"));
1266 fprintf(stdout, _("(not read)\n"));
1267 fprintf(stdout, _("Date/time: %d/%d/%d %d:%02d:%02d "), \
1268 message.Time.Day, message.Time.Month, message.Time.Year, \
1269 message.Time.Hour, message.Time.Minute, message.Time.Second);
1270 if (message.Time.Timezone) {
1271 if (message.Time.Timezone > 0)
1272 fprintf(stdout,_("+%02d00"),message.Time.Timezone);
1274 fprintf(stdout,_("%02d00"),message.Time.Timezone);
1276 fprintf(stdout, "\n");
1277 fprintf(stdout, _("Sender: %s Msg Center: %s\n"), message.Sender, message.MessageCenter.Number);
1278 switch (SMS_DetectUDH(&message)) {
1280 fprintf(stdout, _("GSM operator logo for %s (%s) network.\n"), bitmap.netcode, GSM_GetNetworkName(bitmap.netcode));
1281 if (!strcmp(message.Sender, "+998000005") && !strcmp(message.MessageCenter.Number, "+886935074443")) dprintf(_("Saved by Logo Express\n"));
1282 if (!strcmp(message.Sender, "+998000002") || !strcmp(message.Sender, "+998000003")) dprintf(_("Saved by Operator Logo Uploader by Thomas Kessler\n"));
1283 case GSM_CallerIDLogo:
1284 fprintf(stdout, ("Logo:\n"));
1285 /* put bitmap into bitmap structure */
1286 GSM_ReadSMSBitmap(&message, &bitmap);
1287 GSM_PrintBitmap(&bitmap);
1290 if ((stat(filename, &buf) == 0)) {
1291 fprintf(stdout, _("File %s exists.\n"), filename);
1292 fprintf(stderr, _("Overwrite? (yes/no) "));
1293 GetLine(stdin, ans, 4);
1294 if (!strcmp(ans, "yes")) {
1295 error = GSM_SaveBitmapFile(filename, &bitmap);
1297 } else error = GSM_SaveBitmapFile(filename, &bitmap);
1298 if (error!=GE_NONE) fprintf(stderr, _("Couldn't save logofile %s!\n"), filename);
1301 case GSM_RingtoneUDH:
1302 fprintf(stdout, ("Ringtone\n"));
1304 case GSM_ConcatenatedMessages:
1305 fprintf(stdout, _("Linked (%d/%d):\n"),message.UDH[5],message.UDH[4]);
1307 fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText);
1308 if ((mode != -1) && *filename) {
1310 sprintf(buf, "%s%d", filename, count);
1311 mode = GSM_SaveTextFile(buf, message.MessageText, mode);
1315 fprintf(stderr, _("Unknown\n"));
1321 data.SMSMessage = &message;
1322 if (GE_NONE != SM_Functions(GOP_DeleteSMS, &data, &State))
1323 fprintf(stdout, _("(delete failed)\n"));
1325 fprintf(stdout, _("(message deleted)\n"));
1328 case GE_NOTIMPLEMENTED:
1329 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1330 if (GSM && GSM->Terminate) GSM->Terminate();
1332 case GE_INVALIDSMSLOCATION:
1333 fprintf(stderr, _("Invalid location: %s %d\n"), memory_type_string, count);
1335 case GE_EMPTYSMSLOCATION:
1336 fprintf(stderr, _("SMS location %s %d empty.\n"), memory_type_string, count);
1339 fprintf(stdout, _("GetSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
1344 if (GSM && GSM->Terminate) GSM->Terminate();
1349 /* Delete SMS messages. */
1350 int deletesms(int argc, char *argv[])
1352 GSM_SMSMessage message;
1353 char *memory_type_string;
1354 int start_message, end_message, count;
1357 /* Handle command line args that set type, start and end locations. */
1358 memory_type_string = argv[0];
1359 message.MemoryType = StrToMemoryType(memory_type_string);
1360 if (message.MemoryType == GMT_XX) {
1361 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
1365 start_message = end_message = atoi (argv[1]);
1366 if (argc > 2) end_message = atoi (argv[2]);
1368 /* Now delete the requested entries. */
1369 for (count = start_message; count <= end_message; count ++) {
1371 message.Location = count;
1372 data.SMSMessage = &message;
1373 error = SM_Functions(GOP_DeleteSMS, &data, &State);
1375 if (error == GE_NONE)
1376 fprintf(stdout, _("Deleted SMS %s %d\n"), memory_type_string, count);
1378 if (error == GE_NOTIMPLEMENTED) {
1379 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1383 fprintf(stdout, _("DeleteSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
1392 static volatile bool bshutdown = false;
1394 /* SIGINT signal handler. */
1395 static void interrupted(int sig)
1397 signal(sig, SIG_IGN);
1403 /* In this mode we get the code from the keyboard and send it to the mobile
1405 int entersecuritycode(char *type)
1408 GSM_SecurityCode SecurityCode;
1410 if (!strcmp(type,"PIN"))
1411 SecurityCode.Type=GSCT_Pin;
1412 else if (!strcmp(type,"PUK"))
1413 SecurityCode.Type=GSCT_Puk;
1414 else if (!strcmp(type,"PIN2"))
1415 SecurityCode.Type=GSCT_Pin2;
1416 else if (!strcmp(type,"PUK2"))
1417 SecurityCode.Type=GSCT_Puk2;
1418 // FIXME: Entering of SecurityCode does not work :-(
1419 // else if (!strcmp(type,"SecurityCode"))
1420 // SecurityCode.Type=GSCT_SecurityCode;
1425 printf("Enter your code: ");
1426 gets(SecurityCode.Code);
1428 strcpy(SecurityCode.Code,getpass(_("Enter your code: ")));
1431 test = GSM->EnterSecurityCode(SecurityCode);
1432 if (test == GE_INVALIDSECURITYCODE)
1433 fprintf(stdout, _("Error: invalid code.\n"));
1434 else if (test == GE_NONE)
1435 fprintf(stdout, _("Code ok.\n"));
1436 else if (test == GE_NOTIMPLEMENTED)
1437 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1439 fprintf(stdout, _("Other error.\n"));
1446 int getsecuritycodestatus(void)
1450 if (GSM->GetSecurityCodeStatus(&Status) == GE_NONE) {
1452 fprintf(stdout, _("Security code status: "));
1455 case GSCT_SecurityCode:
1456 fprintf(stdout, _("waiting for Security Code.\n"));
1459 fprintf(stdout, _("waiting for PIN.\n"));
1462 fprintf(stdout, _("waiting for PIN2.\n"));
1465 fprintf(stdout, _("waiting for PUK.\n"));
1468 fprintf(stdout, _("waiting for PUK2.\n"));
1471 fprintf(stdout, _("nothing to enter.\n"));
1474 fprintf(stdout, _("Unknown!\n"));
1487 /* Voice dialing mode. */
1488 int dialvoice(char *Number)
1490 GSM->DialVoice(Number);
1497 /* The following function allows to send logos using SMS */
1498 int sendlogo(int argc, char *argv[])
1503 char Data[sizeof(bitmap.bitmap) +64/*headers safety*/];
1507 struct option options[] = {
1512 /* Default settings for SMS message:
1513 - no delivery report
1519 - set UserDataHeaderIndicator
1524 SMS.Compression = false;
1525 SMS.EightBit = true;
1526 SMS.MessageCenter.No = 1;
1527 SMS.Validity = 4320; /* 4320 minutes == 72 hours */
1531 while ((i = getopt_long(argc, argv, "", options, NULL)) != -1) {
1532 if (smsc_options_parse(i,&SMS))
1536 usage(); /* Would be better to have an sendsms_usage() here. */
1541 if (argc!=3 && argc!=4)
1545 /* The first argument is the type of the logo. */
1546 if (!strcmp(argv[0], "op")) {
1547 SMS_SetupUDH(&SMS,GSM_OpLogo); /* error ignored */
1548 fprintf(stdout, _("Sending operator logo.\n"));
1549 } else if (!strcmp(argv[0], "caller")) { /* error ignored */
1550 SMS_SetupUDH(&SMS,GSM_CallerIDLogo);
1551 fprintf(stdout, _("Sending caller line identification logo.\n"));
1553 fprintf(stderr, _("You should specify what kind of logo to send!\n"));
1557 /* The second argument is the destination, ie the phone number of recipient. */
1558 strcpy(SMS.Destination,argv[1]);
1560 /* The third argument is the bitmap file. */
1561 GSM_ReadBitmapFile(argv[2], &bitmap);
1563 /* If we are sending op logo we can rewrite network code. */
1564 if (!strcmp(argv[0], "op")) {
1566 * The fourth argument, if present, is the Network code of the operator.
1567 * Network code is in this format: "xxx yy".
1570 strcpy(bitmap.netcode, argv[3]);
1572 fprintf(stdout, _("Operator code: %s\n"), argv[3]);
1576 /* Set the network code */
1577 Data[current++] = ((bitmap.netcode[1] & 0x0f) << 4) | (bitmap.netcode[0] & 0xf);
1578 Data[current++] = 0xf0 | (bitmap.netcode[2] & 0x0f);
1579 Data[current++] = ((bitmap.netcode[5] & 0x0f) << 4) | (bitmap.netcode[4] & 0xf);
1582 /* Set the logo size */
1583 Data[current++] = 0x00; /* RFU by Nokia */
1584 Data[current++] = bitmap.width;
1585 Data[current++] = bitmap.height;
1587 Data[current++] = 0x01; /* depth=number of grayscales */
1589 memcpy(Data+current,bitmap.bitmap,bitmap.size);
1590 current+=bitmap.size;
1592 /* Send the message. */
1593 sendsms_deconcatenated(&SMS,Data,current,true/*useudh*/);
1599 /* Getting logos. */
1600 GSM_Error SaveBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1607 /* Ask before overwriting */
1608 while (stat(FileName, &buf) == 0) {
1611 fprintf(stderr, _("Saving logo. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "), FileName);
1612 GetLine(stdin, ans, 4);
1613 if (!strcmp(ans, "O") || !strcmp(ans, "o")) confirm = 1;
1614 if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm = 2;
1615 if (!strcmp(ans, "S") || !strcmp(ans, "s")) return GE_USERCANCELED;
1617 if (confirm == 1) break;
1619 fprintf(stderr, _("Enter name of new file: "));
1620 GetLine(stdin, FileName, 50);
1621 if (!FileName || (*FileName == 0)) return GE_USERCANCELED;
1625 error = GSM_SaveBitmapFile(FileName, bitmap);
1628 case GE_CANTOPENFILE:
1629 fprintf(stderr, _("Failed to write file \"%s\"\n"), FileName);
1638 int getlogo(int argc, char *argv[])
1642 GSM_Statemachine *sm = &State;
1644 bitmap.type=GSM_None;
1646 if (!strcmp(argv[0], "op"))
1647 bitmap.type = GSM_OperatorLogo;
1649 if (!strcmp(argv[0], "caller")) {
1650 /* There is caller group number missing in argument list. */
1652 bitmap.number=argv[2][0]-'0';
1653 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1657 bitmap.type = GSM_CallerLogo;
1660 if (!strcmp(argv[0],"startup"))
1661 bitmap.type = GSM_StartupLogo;
1662 else if (!strcmp(argv[0], "dealer"))
1663 bitmap.type = GSM_DealerNoteText;
1664 else if (!strcmp(argv[0], "text"))
1665 bitmap.type=GSM_WelcomeNoteText;
1667 if (bitmap.type != GSM_None) {
1669 fprintf(stdout, _("Getting Logo\n"));
1671 data.Bitmap=&bitmap;
1672 error=SM_Functions(GOP_GetBitmap, &data, sm);
1676 if (bitmap.type == GSM_DealerNoteText) fprintf(stdout, _("Dealer welcome note "));
1677 if (bitmap.type == GSM_WelcomeNoteText) fprintf(stdout, _("Welcome note "));
1678 if (bitmap.type == GSM_DealerNoteText || bitmap.type==GSM_WelcomeNoteText) {
1679 if (bitmap.text[0]) {
1680 fprintf(stdout, _("currently set to \"%s\"\n"), bitmap.text);
1682 fprintf(stdout, _("currently empty\n"));
1686 switch (bitmap.type) {
1687 case GSM_OperatorLogo:
1688 fprintf(stdout,"Operator logo for %s (%s) network got succesfully\n",bitmap.netcode,GSM_GetNetworkName(bitmap.netcode));
1690 strncpy(bitmap.netcode,argv[2], 7);
1691 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1692 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1697 case GSM_StartupLogo:
1698 fprintf(stdout, "Startup logo got successfully\n");
1700 strncpy(bitmap.netcode,argv[2], 7);
1701 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1702 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1707 case GSM_CallerLogo:
1708 fprintf(stdout,"Caller logo got successfully\n");
1710 strncpy(bitmap.netcode,argv[3],7);
1711 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1712 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1718 fprintf(stdout,"Unknown bitmap type.\n");
1722 if (SaveBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) return (-1);
1725 fprintf(stdout,"Your phone doesn't have logo uploaded !\n");
1730 case GE_NOTIMPLEMENTED:
1731 fprintf(stderr, _("Function not implemented !\n"));
1733 case GE_NOTSUPPORTED:
1734 fprintf(stderr, _("This kind of logo is not supported !\n"));
1737 fprintf(stderr, _("Error getting logo !\n"));
1741 fprintf(stderr, _("What kind of logo do you want to get ?\n"));
1749 /* Sending logos. */
1750 GSM_Error ReadBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1754 error = GSM_ReadBitmapFile(FileName, bitmap);
1757 case GE_CANTOPENFILE:
1758 fprintf(stderr, _("Failed to read file \"%s\"\n"), FileName);
1760 case GE_WRONGNUMBEROFCOLORS:
1761 fprintf(stderr, _("Wrong number of colors in \"%s\" logofile (accepted only 2-colors files) !\n"), FileName);
1763 case GE_WRONGCOLORS:
1764 fprintf(stderr, _("Wrong colors in \"%s\" logofile !\n"), FileName);
1766 case GE_INVALIDFILEFORMAT:
1767 fprintf(stderr, _("Invalid format of \"%s\" logofile !\n"), FileName);
1769 case GE_SUBFORMATNOTSUPPORTED:
1770 fprintf(stderr, _("Sorry, gnokii doesn't support used subformat in file \"%s\" !\n"), FileName);
1772 case GE_FILETOOSHORT:
1773 fprintf(stderr, _("\"%s\" logofile is too short !\n"), FileName);
1775 case GE_INVALIDIMAGESIZE:
1776 fprintf(stderr, _("Bitmap size doesn't supported by fileformat or different from 72x14, 84x48 and 72x28 !\n"));
1786 int setlogo(int argc, char *argv[])
1788 GSM_Bitmap bitmap,oldbit;
1789 GSM_NetworkInfo NetworkInfo;
1795 if (!strcmp(argv[0],"text") || !strcmp(argv[0],"dealer")) {
1796 if (!strcmp(argv[0], "text")) bitmap.type = GSM_WelcomeNoteText;
1797 else bitmap.type = GSM_DealerNoteText;
1798 bitmap.text[0] = 0x00;
1799 if (argc > 1) strncpy(bitmap.text, argv[1], 255);
1801 if (!strcmp(argv[0], "op") || !strcmp(argv[0], "startup") || !strcmp(argv[0], "caller")) {
1803 if (ReadBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) {
1808 if (!strcmp(argv[0], "op")) {
1809 if (bitmap.type != GSM_OperatorLogo || argc < 3) {
1810 if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode, NetworkInfo.NetworkCode, 7);
1812 GSM_ResizeBitmap(&bitmap, GSM_OperatorLogo, GSM_Info);
1814 strncpy(bitmap.netcode, argv[2], 7);
1815 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1816 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1821 if (!strcmp(argv[0], "startup")) {
1822 GSM_ResizeBitmap(&bitmap, GSM_StartupLogo, GSM_Info);
1824 if (!strcmp(argv[0],"caller")) {
1825 GSM_ResizeBitmap(&bitmap, GSM_CallerLogo, GSM_Info);
1827 bitmap.number = argv[2][0] - '0';
1828 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1832 oldbit.type = GSM_CallerLogo;
1833 oldbit.number = bitmap.number;
1834 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1835 /* We have to get the old name and ringtone!! */
1836 bitmap.ringtone = oldbit.ringtone;
1837 strncpy(bitmap.text, oldbit.text, 255);
1839 if (argc > 3) strncpy(bitmap.text, argv[3], 255);
1841 fprintf(stdout, _("Setting Logo.\n"));
1843 /* FIX ME: is it possible to permanently remove op logo ? */
1844 if (!strcmp(argv[0], "op"))
1846 bitmap.type = GSM_OperatorLogo;
1847 strncpy(bitmap.netcode, "000 00", 7);
1850 bitmap.size = bitmap.width * bitmap.height / 8;
1851 GSM_ClearBitmap(&bitmap);
1853 /* FIX ME: how to remove startup and group logos ? */
1854 fprintf(stdout, _("Removing Logo.\n"));
1857 fprintf(stderr, _("What kind of logo do you want to set ?\n"));
1863 error=GSM->SetBitmap(&bitmap);
1867 oldbit.type = bitmap.type;
1868 oldbit.number = bitmap.number;
1869 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1870 if (bitmap.type == GSM_WelcomeNoteText ||
1871 bitmap.type == GSM_DealerNoteText) {
1872 if (strcmp(bitmap.text, oldbit.text)) {
1873 fprintf(stderr, _("Error setting"));
1874 if (bitmap.type == GSM_DealerNoteText) fprintf(stderr, _(" dealer"));
1875 fprintf(stderr, _(" welcome note - "));
1877 /* I know, it looks horrible, but... */
1878 /* I set it to the short string - if it won't be set */
1879 /* it means, PIN is required. If it will be correct, previous */
1880 /* (user) text was too long */
1882 /* Without it, I could have such thing: */
1883 /* user set text to very short string (for example, "Marcin") */
1884 /* then enable phone without PIN and try to set it to the very long (too long for phone) */
1885 /* string (which start with "Marcin"). If we compare them as only length different, we could think, */
1886 /* that phone accepts strings 6 chars length only (length of "Marcin") */
1887 /* When we make it correct, we don't have this mistake */
1889 strcpy(oldbit.text, "!\0");
1890 GSM->SetBitmap(&oldbit);
1891 GSM->GetBitmap(&oldbit);
1892 if (oldbit.text[0]!='!') {
1893 fprintf(stderr, _("SIM card and PIN is required\n"));
1895 GSM->SetBitmap(&bitmap);
1896 GSM->GetBitmap(&oldbit);
1897 fprintf(stderr, _("too long, truncated to \"%s\" (length %i)\n"),oldbit.text,strlen(oldbit.text));
1902 if (bitmap.type == GSM_StartupLogo) {
1903 for (i = 0; i < oldbit.size; i++) {
1904 if (oldbit.bitmap[i] != bitmap.bitmap[i]) {
1905 fprintf(stderr, _("Error setting startup logo - SIM card and PIN is required\n"));
1913 if (ok) fprintf(stdout, _("Done.\n"));
1915 case GE_NOTIMPLEMENTED:
1916 fprintf(stderr, _("Function not implemented.\n"));
1918 case GE_NOTSUPPORTED:
1919 fprintf(stderr, _("This kind of logo is not supported.\n"));
1922 fprintf(stderr, _("Error !\n"));
1932 int viewlogo(char *filename)
1936 error = GSM_ShowBitmapFile(filename);
1940 /* Calendar notes receiving. */
1941 int getcalendarnote(int argc, char *argv[])
1943 GSM_CalendarNote CalendarNote;
1945 GSM_Error error = GE_NONE;
1946 int i, first_location, last_location;
1949 struct option options[] = {
1950 { "vCard", optional_argument, NULL, '1'},
1957 first_location = last_location = atoi(argv[0]);
1958 if ((argc > 1) && (argv[1][0] != '-')) {
1959 last_location = atoi(argv[1]);
1962 while ((i = getopt_long(argc, argv, "v", options, NULL)) != -1) {
1968 usage(); /* Would be better to have an calendar_usage() here. */
1974 for (i = first_location; i <= last_location; i++) {
1975 CalendarNote.Location = i;
1976 if (GSM && GSM->GetCalendarNote && GSM->Terminate) {
1977 error = GSM->GetCalendarNote(&CalendarNote);
1980 GSM_DataClear(&data);
1981 data.CalendarNote = &CalendarNote;
1983 error = SM_Functions(GOP_GetCalendarNote, &data, &State);
1988 fprintf(stdout, "BEGIN:VCALENDAR\n");
1989 fprintf(stdout, "VERSION:1.0\n");
1990 fprintf(stdout, "BEGIN:VEVENT\n");
1991 fprintf(stdout, "CATEGORIES:");
1992 switch (CalendarNote.Type) {
1994 fprintf(stdout, "MISCELLANEOUS\n");
1997 fprintf(stdout, "PHONE CALL\n");
2000 fprintf(stdout, "MEETING\n");
2003 fprintf(stdout, "SPECIAL OCCASION\n");
2006 fprintf(stdout, "UNKNOWN\n");
2009 fprintf(stdout, "SUMMARY:%s\n",CalendarNote.Text);
2010 fprintf(stdout, "DTSTART:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Time.Year,
2011 CalendarNote.Time.Month, CalendarNote.Time.Day, CalendarNote.Time.Hour,
2012 CalendarNote.Time.Minute, CalendarNote.Time.Second);
2013 if (CalendarNote.Alarm.Year!=0) {
2014 fprintf(stdout, "DALARM:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Alarm.Year,
2015 CalendarNote.Alarm.Month, CalendarNote.Alarm.Day, CalendarNote.Alarm.Hour,
2016 CalendarNote.Alarm.Minute, CalendarNote.Alarm.Second);
2018 fprintf(stdout, "END:VEVENT\n");
2019 fprintf(stdout, "END:VCALENDAR\n");
2021 } else { /* not vCal */
2022 fprintf(stdout, _(" Type of the note: "));
2024 switch (CalendarNote.Type) {
2026 fprintf(stdout, _("Reminder\n"));
2029 fprintf(stdout, _("Call\n"));
2032 fprintf(stdout, _("Meeting\n"));
2035 fprintf(stdout, _("Birthday\n"));
2038 fprintf(stdout, _("Unknown\n"));
2042 fprintf(stdout, _(" Date: %d-%02d-%02d\n"), CalendarNote.Time.Year,
2043 CalendarNote.Time.Month,
2044 CalendarNote.Time.Day);
2046 fprintf(stdout, _(" Time: %02d:%02d:%02d\n"), CalendarNote.Time.Hour,
2047 CalendarNote.Time.Minute,
2048 CalendarNote.Time.Second);
2050 if (CalendarNote.Alarm.AlarmEnabled == 1) {
2051 fprintf(stdout, _(" Alarm date: %d-%02d-%02d\n"), CalendarNote.Alarm.Year,
2052 CalendarNote.Alarm.Month,
2053 CalendarNote.Alarm.Day);
2055 fprintf(stdout, _(" Alarm time: %02d:%02d:%02d\n"), CalendarNote.Alarm.Hour,
2056 CalendarNote.Alarm.Minute,
2057 CalendarNote.Alarm.Second);
2060 fprintf(stdout, _(" Text: %s\n"), CalendarNote.Text);
2062 if (CalendarNote.Type == GCN_CALL)
2063 fprintf(stdout, _(" Phone: %s\n"), CalendarNote.Phone);
2066 case GE_NOTIMPLEMENTED:
2067 fprintf(stderr, _("Function not implemented.\n"));
2070 fprintf(stderr, _("The calendar note can not be read\n"));
2079 /* Writing calendar notes. */
2080 int writecalendarnote(char *argv[])
2082 GSM_CalendarNote CalendarNote;
2084 if (GSM_ReadVCalendarFile(argv[0], &CalendarNote, atoi(argv[1]))) {
2085 fprintf(stdout, _("Failed to load vCalendar file.\n"));
2089 /* Error 22=Calendar full ;-) */
2090 if ((GSM->WriteCalendarNote(&CalendarNote)) == GE_NONE)
2091 fprintf(stdout, _("Succesfully written!\n"));
2093 fprintf(stdout, _("Failed to write calendar note!\n"));
2100 /* Calendar note deleting. */
2101 int deletecalendarnote(int argc, char *argv[])
2103 GSM_CalendarNote CalendarNote;
2104 int i, first_location, last_location;
2106 first_location = last_location = atoi(argv[0]);
2107 if (argc > 1) last_location = atoi(argv[1]);
2109 for (i = first_location; i <= last_location; i++) {
2111 CalendarNote.Location = i;
2113 if (GSM->DeleteCalendarNote(&CalendarNote) == GE_NONE) {
2114 fprintf(stdout, _(" Calendar note deleted.\n"));
2116 fprintf(stderr, _("The calendar note can not be deleted\n"));
2126 /* Setting the date and time. */
2127 int setdatetime(int argc, char *argv[])
2134 now = localtime(&nowh);
2136 Date.Year = now->tm_year;
2137 Date.Month = now->tm_mon+1;
2138 Date.Day = now->tm_mday;
2139 Date.Hour = now->tm_hour;
2140 Date.Minute = now->tm_min;
2141 Date.Second = now->tm_sec;
2143 if (argc > 0) Date.Year = atoi (argv[0]);
2144 if (argc > 1) Date.Month = atoi (argv[1]);
2145 if (argc > 2) Date.Day = atoi (argv[2]);
2146 if (argc > 3) Date.Hour = atoi (argv[3]);
2147 if (argc > 4) Date.Minute = atoi (argv[4]);
2149 if (Date.Year < 1900) {
2151 /* Well, this thing is copyrighted in U.S. This technique is known as
2152 Windowing and you can read something about it in LinuxWeekly News:
2153 http://lwn.net/1999/features/Windowing.phtml. This thing is beeing
2154 written in Czech republic and Poland where algorithms are not allowed
2158 Date.Year = Date.Year + 1900;
2160 Date.Year = Date.Year + 2000;
2163 /* FIXME: Error checking should be here. */
2164 GSM->SetDateTime(&Date);
2171 /* In this mode we receive the date and time from mobile phone. */
2172 int getdatetime(void) {
2174 GSM_DateTime date_time;
2177 if (GSM && GSM->GetDateTime && GSM->Terminate) {
2178 error = GSM->GetDateTime(&date_time);
2181 GSM_DataClear(&data);
2182 data.DateTime = &date_time;
2184 error = SM_Functions(GOP_GetDateTime, &data, &State);
2189 fprintf(stdout, _("Date: %4d/%02d/%02d\n"), date_time.Year, date_time.Month, date_time.Day);
2190 fprintf(stdout, _("Time: %02d:%02d:%02d\n"), date_time.Hour, date_time.Minute, date_time.Second);
2192 case GE_NOTIMPLEMENTED:
2193 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2196 fprintf(stdout, _("Internal error\n"));
2203 /* Setting the alarm. */
2204 int setalarm(char *argv[])
2208 Date.Hour = atoi(argv[0]);
2209 Date.Minute = atoi(argv[1]);
2211 GSM->SetAlarm(1, &Date);
2218 /* Getting the alarm. */
2223 GSM_DateTime date_time;
2225 if (GSM && GSM->GetAlarm && GSM->Terminate) {
2226 error = GSM->GetAlarm(0, &date_time);
2229 GSM_DataClear(&data);
2230 data.DateTime = &date_time;
2232 error = SM_Functions(GOP_GetAlarm, &data, &State);
2237 fprintf(stdout, _("Alarm: %s\n"), (date_time.AlarmEnabled==0)?"off":"on");
2238 fprintf(stdout, _("Time: %02d:%02d\n"), date_time.Hour, date_time.Minute);
2240 case GE_NOTIMPLEMENTED:
2241 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2244 fprintf(stdout, _("Internal error\n"));
2251 /* In monitor mode we don't do much, we just initialise the fbus code.
2252 Note that the fbus code no longer has an internal monitor mode switch,
2253 instead compile with DEBUG enabled to get all the gumpf. */
2254 int monitormode(void)
2256 float rflevel = -1, batterylevel = -1;
2257 // GSM_PowerSource powersource = -1;
2258 GSM_RFUnits rf_units = GRF_Arbitrary;
2259 GSM_BatteryUnits batt_units = GBU_Arbitrary;
2260 GSM_Statemachine *sm = &State;
2263 // GSM_NetworkInfo NetworkInfo;
2264 // GSM_CBMessage CBMessage;
2266 GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0};
2267 GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0};
2268 GSM_MemoryStatus DC_MemoryStatus = {GMT_DC, 0, 0};
2269 GSM_MemoryStatus EN_MemoryStatus = {GMT_EN, 0, 0};
2270 GSM_MemoryStatus FD_MemoryStatus = {GMT_FD, 0, 0};
2271 GSM_MemoryStatus LD_MemoryStatus = {GMT_LD, 0, 0};
2272 GSM_MemoryStatus MC_MemoryStatus = {GMT_MC, 0, 0};
2273 GSM_MemoryStatus ON_MemoryStatus = {GMT_ON, 0, 0};
2274 GSM_MemoryStatus RC_MemoryStatus = {GMT_RC, 0, 0};
2276 // GSM_SMSStatus SMSStatus = {0, 0};
2280 GSM_DataClear(&data);
2282 /* We do not want to monitor serial line forever - press Ctrl+C to stop the
2284 signal(SIGINT, interrupted);
2286 fprintf (stderr, _("Entering monitor mode...\n"));
2289 //GSM->EnableCellBroadcast();
2291 /* Loop here indefinitely - allows you to see messages from GSM code in
2292 response to unknown messages etc. The loops ends after pressing the
2294 data.RFUnits=&rf_units;
2295 data.RFLevel=&rflevel;
2296 data.BatteryUnits=&batt_units;
2297 data.BatteryLevel=&batterylevel;
2299 while (!bshutdown) {
2300 if (SM_Functions(GOP_GetRFLevel,&data,sm) == GE_NONE)
2301 fprintf(stdout, _("RFLevel: %d\n"), (int)rflevel);
2303 if (SM_Functions(GOP_GetBatteryLevel,&data,sm) == GE_NONE)
2304 fprintf(stdout, _("Battery: %d\n"), (int)batterylevel);
2306 // if (GSM->GetPowerSource(&powersource) == GE_NONE)
2307 // fprintf(stdout, _("Power Source: %s\n"), (powersource==GPS_ACDC)?_("AC/DC"):_("battery"));
2309 data.MemoryStatus=&SIMMemoryStatus;
2310 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2311 fprintf(stdout, _("SIM: Used %d, Free %d\n"), SIMMemoryStatus.Used, SIMMemoryStatus.Free);
2313 data.MemoryStatus=&PhoneMemoryStatus;
2314 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2315 fprintf(stdout, _("Phone: Used %d, Free %d\n"), PhoneMemoryStatus.Used, PhoneMemoryStatus.Free);
2317 data.MemoryStatus=&DC_MemoryStatus;
2318 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2319 fprintf(stdout, _("DC: Used %d, Free %d\n"), DC_MemoryStatus.Used, DC_MemoryStatus.Free);
2321 data.MemoryStatus=&EN_MemoryStatus;
2322 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2323 fprintf(stdout, _("EN: Used %d, Free %d\n"), EN_MemoryStatus.Used, EN_MemoryStatus.Free);
2325 data.MemoryStatus=&FD_MemoryStatus;
2326 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2327 fprintf(stdout, _("FD: Used %d, Free %d\n"), FD_MemoryStatus.Used, FD_MemoryStatus.Free);
2329 data.MemoryStatus=&LD_MemoryStatus;
2330 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2331 fprintf(stdout, _("LD: Used %d, Free %d\n"), LD_MemoryStatus.Used, LD_MemoryStatus.Free);
2333 data.MemoryStatus=&MC_MemoryStatus;
2334 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2335 fprintf(stdout, _("MC: Used %d, Free %d\n"), MC_MemoryStatus.Used, MC_MemoryStatus.Free);
2337 data.MemoryStatus=&ON_MemoryStatus;
2338 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2339 fprintf(stdout, _("ON: Used %d, Free %d\n"), ON_MemoryStatus.Used, ON_MemoryStatus.Free);
2341 data.MemoryStatus=&RC_MemoryStatus;
2342 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2343 fprintf(stdout, _("RC: Used %d, Free %d\n"), RC_MemoryStatus.Used, RC_MemoryStatus.Free);
2345 // if (GSM->GetSMSStatus(&SMSStatus) == GE_NONE)
2346 // fprintf(stdout, _("SMS Messages: UnRead %d, Number %d\n"), SMSStatus.UnRead, SMSStatus.Number);
2348 // if (GSM->GetIncomingCallNr(Number) == GE_NONE)
2349 // fprintf(stdout, _("Incoming call: %s\n"), Number);
2351 // if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE)
2352 // fprintf(stdout, _("Network: %s (%s), LAC: %s, CellID: %s\n"), GSM_GetNetworkName (NetworkInfo.NetworkCode), GSM_GetCountryName(NetworkInfo.NetworkCode), NetworkInfo.LAC, NetworkInfo.CellID);
2354 // if (GSM->ReadCellBroadcast(&CBMessage) == GE_NONE)
2355 // fprintf(stdout, _("Cell broadcast received on channel %d: %s\n"), CBMessage.Channel, CBMessage.Message);
2360 fprintf (stderr, _("Leaving monitor mode...\n"));
2370 static GSM_Error PrettyOutputFn(char *Display, char *Indicators)
2373 printf(ESC "[10;0H Display is:\n%s\n", Display);
2375 printf(ESC "[9;0H Indicators: %s \n", Indicators);
2376 printf(ESC "[1;1H");
2381 // Uncomment it if used
2382 static GSM_Error OutputFn(char *Display, char *Indicators)
2385 printf("New display is:\n%s\n", Display);
2387 printf("Indicators: %s\n", Indicators);
2392 void console_raw(void)
2397 tcgetattr(fileno(stdin), &it);
2398 it.c_lflag &= ~(ICANON);
2399 //it.c_iflag &= ~(INPCK|ISTRIP|IXON);
2403 tcsetattr(fileno(stdin), TCSANOW, &it);
2407 int displayoutput(void)
2410 GSM_Statemachine *sm = &State;
2413 data.OutputFn = PrettyOutputFn;
2415 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2417 fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
2419 if (error == GE_NONE) {
2421 /* We do not want to see texts forever - press Ctrl+C to stop. */
2422 signal(SIGINT, interrupted);
2424 fprintf (stderr, _("Entered display monitoring mode...\n"));
2425 fprintf (stderr, ESC "c" );
2427 /* Loop here indefinitely - allows you to read texts from phone's
2428 display. The loops ends after pressing the Ctrl+C. */
2429 while (!bshutdown) {
2431 memset(&buf[0], 0, 102);
2432 while (read(0, buf, 100) > 0) {
2433 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
2434 if (GSM->HandleString(buf) != GE_NONE)
2435 fprintf(stdout, _("Key press simulation failed.\n"));
2436 memset(buf, 0, 102);
2440 fprintf (stderr, "Shutting down\n");
2442 fprintf (stderr, _("Leaving display monitor mode...\n"));
2443 data.OutputFn = NULL;
2445 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2446 if (error != GE_NONE)
2447 fprintf (stderr, _("Error!\n"));
2449 fprintf (stderr, _("Error!\n"));
2455 /* Reads profile from phone and displays its' settings */
2456 int getprofile(int argc, char *argv[])
2460 GSM_Profile profile;
2463 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2467 error = GSM->GetProfile(&profile);
2469 if (error == GE_NONE) {
2471 while (GSM->GetModel(model) != GE_NONE)
2474 max_profiles = 7; /* This is correct for 6110 (at least my). How do we get
2475 the number of profiles? */
2478 /*FIX ME: It should be set to 3 for N5130 and 3210 too*/
2479 if (!strcmp(model, "NSE-1"))
2483 profile.Number = atoi(argv[0]) - 1;
2484 start = profile.Number;
2487 if (profile.Number < 0) {
2488 fprintf(stderr, _("Profile number must be value from 1 to %d!\n"), max_profiles);
2493 if (profile.Number >= max_profiles) {
2494 fprintf(stderr, _("This phone supports only %d profiles!\n"), max_profiles);
2500 stop = max_profiles;
2507 if (profile.Number != 0)
2508 GSM->GetProfile(&profile);
2510 fprintf(stdout, "%d. \"%s\"\n", profile.Number + 1, profile.Name);
2511 if (profile.DefaultName == -1) fprintf(stdout, _(" (name defined)\n"));
2513 fprintf(stdout, _("Incoming call alert: %s\n"), GetProfileCallAlertString(profile.CallAlert));
2515 /* For different phones different ringtones names */
2517 if (!strcmp(model, "NSE-3"))
2518 fprintf(stdout, _("Ringing tone: %s (%d)\n"), RingingTones[profile.Ringtone], profile.Ringtone);
2520 fprintf(stdout, _("Ringtone number: %d\n"), profile.Ringtone);
2522 fprintf(stdout, _("Ringing volume: %s\n"), GetProfileVolumeString(profile.Volume));
2524 fprintf(stdout, _("Message alert tone: %s\n"), GetProfileMessageToneString(profile.MessageTone));
2526 fprintf(stdout, _("Keypad tones: %s\n"), GetProfileKeypadToneString(profile.KeypadTone));
2528 fprintf(stdout, _("Warning and game tones: %s\n"), GetProfileWarningToneString(profile.WarningTone));
2530 /* FIXME: Light settings is only used for Car */
2531 if (profile.Number == (max_profiles - 2)) fprintf(stdout, _("Lights: %s\n"), profile.Lights ? _("On") : _("Automatic"));
2533 fprintf(stdout, _("Vibration: %s\n"), GetProfileVibrationString(profile.Vibration));
2535 /* FIXME: it will be nice to add here reading caller group name. */
2536 if (max_profiles != 3) fprintf(stdout, _("Caller groups: 0x%02x\n"), profile.CallerGroups);
2538 /* FIXME: Automatic answer is only used for Car and Headset. */
2539 if (profile.Number >= (max_profiles - 2)) fprintf(stdout, _("Automatic answer: %s\n"), profile.AutomaticAnswer ? _("On") : _("Off"));
2541 fprintf(stdout, "\n");
2546 if (error == GE_NOTIMPLEMENTED) {
2547 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2551 fprintf(stderr, _("Unspecified error\n"));
2561 /* Get requested range of memory storage entries and output to stdout in
2562 easy-to-parse format */
2563 int getmemory(int argc, char *argv[])
2565 GSM_PhonebookEntry entry;
2568 char *memory_type_string;
2571 GSM_Statemachine *sm = &State;
2573 /* Handle command line args that set type, start and end locations. */
2574 memory_type_string = argv[0];
2575 entry.MemoryType = StrToMemoryType(memory_type_string);
2576 if (entry.MemoryType == GMT_XX) {
2577 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
2581 start_entry = atoi (argv[1]);
2582 if (argc > 2) end_entry = atoi (argv[2]);
2583 else end_entry = start_entry;
2585 /* Now retrieve the requested entries. */
2586 for (count = start_entry; count <= end_entry; count ++) {
2588 entry.Location = count;
2590 data.PhonebookEntry=&entry;
2591 error=SM_Functions(GOP_ReadPhonebook,&data,sm);
2593 if (error == GE_NONE) {
2594 fprintf(stdout, "%s;%s;%s;%d;%d\n", entry.Name, entry.Number, memory_type_string, entry.Location, entry.Group);
2595 if (entry.MemoryType == GMT_MC || entry.MemoryType == GMT_DC || entry.MemoryType == GMT_RC)
2596 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);
2599 if (error == GE_NOTIMPLEMENTED) {
2600 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2603 else if (error == GE_INVALIDMEMORYTYPE) {
2604 fprintf(stderr, _("Memory type %s not supported!\n"), memory_type_string);
2608 fprintf(stdout, _("%s|%d|Bad location or other error!(%d)\n"), memory_type_string, count, error);
2614 /* Read data from stdin, parse and write to phone. The parsing is relatively
2615 crude and doesn't allow for much variation from the stipulated format. */
2616 /* FIXME: I guess there's *very* similar code in xgnokii */
2617 int writephonebook(int argc, char *args[])
2619 GSM_PhonebookEntry entry;
2621 char *memory_type_string;
2625 char *Line, OLine[100], BackLine[100];
2628 /* Check argument */
2629 if (argc && (strcmp("-i", args[0])))
2634 /* Go through data from stdin. */
2635 while (GetLine(stdin, Line, 99)) {
2636 strcpy(BackLine, Line);
2639 ptr = strtok(Line, ";");
2640 if (ptr) strcpy(entry.Name, ptr);
2641 else entry.Name[0] = 0;
2643 ptr = strtok(NULL, ";");
2644 if (ptr) strcpy(entry.Number, ptr);
2645 else entry.Number[0] = 0;
2647 ptr = strtok(NULL, ";");
2650 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2655 if (!strncmp(ptr,"ME", 2)) {
2656 memory_type_string = "int";
2657 entry.MemoryType = GMT_ME;
2659 if (!strncmp(ptr,"SM", 2)) {
2660 memory_type_string = "sim";
2661 entry.MemoryType = GMT_SM;
2663 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2668 ptr = strtok(NULL, ";");
2669 if (ptr) entry.Location = atoi(ptr);
2670 else entry.Location = 0;
2672 ptr = strtok(NULL, ";");
2673 if (ptr) entry.Group = atoi(ptr);
2674 else entry.Group = 0;
2677 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2681 for (subentry = 0; ; subentry++) {
2682 ptr = strtok(NULL, ";");
2684 if (ptr && *ptr != 0)
2685 entry.SubEntries[subentry].EntryType = atoi(ptr);
2689 ptr = strtok(NULL, ";");
2691 entry.SubEntries[subentry].NumberType=atoi(ptr);
2693 /* Phone Numbers need to have a number type. */
2694 if (!ptr && entry.SubEntries[subentry].EntryType == GSM_Number) {
2695 fprintf(stderr, _("Missing phone number type on line %d"
2696 " entry %d [%s]\n"), line_count, subentry, BackLine);
2701 ptr = strtok(NULL, ";");
2703 entry.SubEntries[subentry].BlockNumber=atoi(ptr);
2705 ptr = strtok(NULL, ";");
2707 /* 0x13 Date Type; it is only for Dailed Numbers, etc.
2708 we don't store to this memories so it's an error to use it. */
2709 if (!ptr || entry.SubEntries[subentry].EntryType == GSM_Date) {
2710 fprintf(stdout, _("There is no phone number on line %d entry %d [%s]\n"),
2711 line_count, subentry, BackLine);
2715 strcpy(entry.SubEntries[subentry].data.Number, ptr);
2718 entry.SubEntriesCount = subentry;
2720 /* This is to send other exports (like from 6110) to 7110 */
2721 if (!entry.SubEntriesCount) {
2722 entry.SubEntriesCount = 1;
2723 entry.SubEntries[subentry].EntryType = GSM_Number;
2724 entry.SubEntries[subentry].NumberType = GSM_General;
2725 entry.SubEntries[subentry].BlockNumber = 2;
2726 strcpy(entry.SubEntries[subentry].data.Number, entry.Number);
2732 GSM_PhonebookEntry aux;
2734 aux.Location = entry.Location;
2735 error = GSM->GetMemoryLocation(&aux);
2737 if (error == GE_NONE) {
2742 fprintf(stdout, _("Location busy. "));
2743 while (confirm < 0) {
2744 fprintf(stdout, _("Overwrite? (yes/no) "));
2745 GetLine(stdin, ans, 7);
2746 if (!strcmp(ans, _("yes"))) confirm = 1;
2747 else if (!strcmp(ans, _("no"))) confirm = 0;
2749 if (!confirm) continue;
2752 fprintf(stderr, _("Unknown error (%d)\n"), error);
2758 /* Do write and report success/failure. */
2759 error = GSM->WritePhonebookLocation(&entry);
2761 if (error == GE_NONE)
2762 fprintf (stdout, _("Write Succeeded: memory type: %s, loc: %d, name: %s, number: %s\n"), memory_type_string, entry.Location, entry.Name, entry.Number);
2764 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);
2772 /* Getting speed dials. */
2773 int getspeeddial(char *Number)
2775 GSM_SpeedDial SpeedDial;
2779 SpeedDial.Number = atoi(Number);
2781 if (GSM && GSM->GetSpeedDial && GSM->Terminate) {
2782 error = GSM->GetSpeedDial(&SpeedDial);
2785 GSM_DataClear(&data);
2786 data.SpeedDial = &SpeedDial;
2788 error = SM_Functions(GOP_GetSpeedDial, &data, &State);
2793 fprintf(stdout, _("SpeedDial nr. %d: %d:%d\n"), SpeedDial.Number, SpeedDial.MemoryType, SpeedDial.Location);
2795 case GE_NOTIMPLEMENTED:
2796 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2799 fprintf(stdout, _("Internal error\n"));
2806 /* Setting speed dials. */
2807 int setspeeddial(char *argv[])
2809 GSM_SpeedDial entry;
2811 char *memory_type_string;
2813 /* Handle command line args that set type, start and end locations. */
2815 if (strcmp(argv[1], "ME") == 0) {
2816 entry.MemoryType = 0x02;
2817 memory_type_string = "ME";
2818 } else if (strcmp(argv[1], "SM") == 0) {
2819 entry.MemoryType = 0x03;
2820 memory_type_string = "SM";
2822 fprintf(stderr, _("Unknown memory type %s!\n"), argv[1]);
2826 entry.Number = atoi(argv[0]);
2827 entry.Location = atoi(argv[2]);
2829 if (GSM->SetSpeedDial(&entry) == GE_NONE) {
2830 fprintf(stdout, _("Succesfully written!\n"));
2837 /* Getting the status of the display. */
2838 int getdisplaystatus(void)
2842 GSM->GetDisplayStatus(&Status);
2844 fprintf(stdout, _("Call in progress: %s\n"), Status & (1<<DS_Call_In_Progress)?_("on"):_("off"));
2845 fprintf(stdout, _("Unknown: %s\n"), Status & (1<<DS_Unknown)?_("on"):_("off"));
2846 fprintf(stdout, _("Unread SMS: %s\n"), Status & (1<<DS_Unread_SMS)?_("on"):_("off"));
2847 fprintf(stdout, _("Voice call: %s\n"), Status & (1<<DS_Voice_Call)?_("on"):_("off"));
2848 fprintf(stdout, _("Fax call active: %s\n"), Status & (1<<DS_Fax_Call)?_("on"):_("off"));
2849 fprintf(stdout, _("Data call active: %s\n"), Status & (1<<DS_Data_Call)?_("on"):_("off"));
2850 fprintf(stdout, _("Keyboard lock: %s\n"), Status & (1<<DS_Keyboard_Lock)?_("on"):_("off"));
2851 fprintf(stdout, _("SMS storage full: %s\n"), Status & (1<<DS_SMS_Storage_Full)?_("on"):_("off"));
2857 int netmonitor(char *Mode)
2859 unsigned char mode = atoi(Mode);
2862 if (!strcmp(Mode, "reset"))
2864 else if (!strcmp(Mode, "off"))
2866 else if (!strcmp(Mode, "field"))
2868 else if (!strcmp(Mode, "devel"))
2870 else if (!strcmp(Mode, "next"))
2873 memset(&Screen, 0, 50);
2874 GSM->NetMonitor(mode, Screen);
2877 fprintf(stdout, "%s\n", Screen);
2885 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2886 char imei[64], model[64], rev[64], manufacturer[64];
2887 GSM_Statemachine *sm = &State;
2889 data.Manufacturer=manufacturer;
2894 /* Retrying is bad idea: what if function is simply not implemented?
2895 Anyway let's wait 2 seconds for the right packet from the phone. */
2898 strcpy(imei, "(unknown)");
2899 strcpy(manufacturer, "(unknown)");
2900 strcpy(model, "(unknown)");
2901 strcpy(rev, "(unknown)");
2903 SM_Functions(GOP_Identify, &data, sm);
2905 fprintf(stdout, _("IMEI: %s\n"), imei);
2906 fprintf(stdout, _("Manufacturer: %s\n"), manufacturer);
2907 fprintf(stdout, _("Model: %s\n"), model);
2908 fprintf(stdout, _("Revision: %s\n"), rev);
2915 int senddtmf(char *String)
2917 GSM->SendDTMF(String);
2922 /* Resets the phone */
2923 int reset( char *type)
2925 unsigned char _type = 0x03;
2928 if(!strcmp(type, "soft"))
2931 if(!strcmp(type, "hard"))
2934 fprintf(stderr, _("What kind of reset do you want??\n"));
2945 /* pmon allows fbus code to run in a passive state - it doesn't worry about
2946 whether comms are established with the phone. A debugging/development
2952 GSM_ConnectionType connection=GCT_Serial;
2953 GSM_Statemachine sm;
2955 /* Initialise the code for the GSM interface. */
2956 error = GSM_Initialise(model, Port, Initlength, connection, NULL, &sm);
2958 if (error != GE_NONE) {
2959 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
2970 int sendringtone(int argc, char *argv[])
2973 GSM_Ringtone ringtone;
2975 int size = GSM_MAX_RINGTONE_PACKAGE_LENGTH;
2976 char Package[GSM_MAX_RINGTONE_PACKAGE_LENGTH];
2978 struct option options[] = {
2983 /* Default settings for SMS message:
2984 - no delivery report
2990 - set UserDataHeaderIndicator
2995 SMS.Compression = false;
2996 SMS.EightBit = true;
2997 SMS.MessageCenter.No = 1;
2998 SMS.Validity = 4320; /* 4320 minutes == 72 hours */
3000 SMS_SetupUDH(&SMS,GSM_RingtoneUDH); /* error ignored */
3007 while ((i = getopt_long(argc, argv, "", options, NULL)) != -1) {
3008 if (smsc_options_parse(i,&SMS))
3012 usage(); /* Would be better to have an sendsms_usage() here. */
3021 if (GSM_ReadRingtoneFile(argv[1], &ringtone)) {
3022 fprintf(stdout, _("Failed to load ringtone.\n"));
3025 if (strlen(argv[0])+1 > sizeof(SMS.Destination)) {
3026 fprintf(stdout, _("Destination number \"%s\" length too long!\n"), argv[0]);
3029 strcpy(SMS.Destination, argv[0]);
3030 GSM_PackRingtone(&ringtone, Package, &size);
3032 sendsms_deconcatenated(&SMS,Package,size,true/*useudh*/);
3039 int setringtone(int argc, char *argv[])
3041 GSM_Ringtone ringtone;
3044 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
3045 fprintf(stdout, _("Failed to load ringtone.\n"));
3049 error = GSM->SetRingtone(&ringtone);
3051 if (error == GE_NONE)
3052 fprintf(stdout, _("Send succeeded!\n"));
3054 fprintf(stdout, _("Send failed\n"));
3060 int presskeysequence(void)
3066 memset(&buf[0], 0, 102);
3067 while (read(0, buf, 100) > 0) {
3068 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
3069 if (GSM->HandleString(buf) != GE_NONE)
3070 fprintf(stdout, _("Key press simulation failed.\n"));
3071 memset(buf, 0, 102);
3078 /* This is a "convenience" function to allow quick test of new API stuff which
3079 doesn't warrant a "proper" command line function. */
3081 int foogle(char *argv[])
3083 /* Initialise the code for the GSM interface. */
3085 // Fill in what you would like to test here...