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 :-)
30 # include <strings.h> /* for memset */
33 #include <sys/types.h>
39 #define sleep(x) Sleep((x) * 1000)
40 #define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
42 #include "win32/getopt.h"
57 #include "gsm-common.h"
59 #include "gsm-networks.h"
60 #include "cfgreader.h"
62 #include "gsm-filetypes.h"
63 #include "gsm-bitmaps.h"
64 #include "gsm-ringtones.h"
65 #include "gsm-statemachine.h"
67 char *model; /* Model from .gnokiirc file. */
68 char *Port; /* Serial port from .gnokiirc file */
69 char *Initlength; /* Init length from .gnokiirc file */
70 char *Connection; /* Connection type from .gnokiirc file */
71 char *BinDir; /* Binaries directory from .gnokiirc file - not used here yet */
74 char *GetProfileCallAlertString(int code)
77 case PROFILE_CALLALERT_RINGING: return "Ringing";
78 case PROFILE_CALLALERT_ASCENDING: return "Ascending";
79 case PROFILE_CALLALERT_RINGONCE: return "Ring once";
80 case PROFILE_CALLALERT_BEEPONCE: return "Beep once";
81 case PROFILE_CALLALERT_CALLERGROUPS: return "Caller groups";
82 case PROFILE_CALLALERT_OFF: return "Off";
83 default: return "Unknown";
87 char *GetProfileVolumeString(int code)
90 case PROFILE_VOLUME_LEVEL1: return "Level 1";
91 case PROFILE_VOLUME_LEVEL2: return "Level 2";
92 case PROFILE_VOLUME_LEVEL3: return "Level 3";
93 case PROFILE_VOLUME_LEVEL4: return "Level 4";
94 case PROFILE_VOLUME_LEVEL5: return "Level 5";
95 default: return "Unknown";
99 char *GetProfileKeypadToneString(int code)
102 case PROFILE_KEYPAD_OFF: return "Off";
103 case PROFILE_KEYPAD_LEVEL1: return "Level 1";
104 case PROFILE_KEYPAD_LEVEL2: return "Level 2";
105 case PROFILE_KEYPAD_LEVEL3: return "Level 3";
106 default: return "Unknown";
110 char *GetProfileMessageToneString(int code)
113 case PROFILE_MESSAGE_NOTONE: return "No tone";
114 case PROFILE_MESSAGE_STANDARD: return "Standard";
115 case PROFILE_MESSAGE_SPECIAL: return "Special";
116 case PROFILE_MESSAGE_BEEPONCE: return "Beep once";
117 case PROFILE_MESSAGE_ASCENDING: return "Ascending";
118 default: return "Unknown";
122 char *GetProfileWarningToneString(int code)
125 case PROFILE_WARNING_OFF: return "Off";
126 case PROFILE_WARNING_ON: return "On";
127 default: return "Unknown";
131 char *GetProfileVibrationString(int code)
134 case PROFILE_VIBRATION_OFF: return "Off";
135 case PROFILE_VIBRATION_ON: return "On";
136 default: return "Unknown";
140 void short_version(void)
142 fprintf(stderr, _("GNOKII Version %s\n"), VERSION);
145 /* This function shows the copyright and some informations usefull for
149 fprintf(stderr, _("Copyright (C) Hugh Blemings <hugh@blemings.org>, 1999, 2000\n"
150 "Copyright (C) Pavel Janík ml. <Pavel.Janik@suse.cz>, 1999, 2000\n"
151 "Copyright (C) Pavel Machek <pavel@ucw.cz>, 2001\n"
152 "Copyright (C) Pawe³ Kot <pkot@linuxnews.pl>, 2001\n"
153 "gnokii is free software, covered by the GNU General Public License, and you are\n"
154 "welcome to change it and/or distribute copies of it under certain conditions.\n"
155 "There is absolutely no warranty for gnokii. See GPL for details.\n"
156 "Built %s %s for %s on %s \n"), __TIME__, __DATE__, model, Port);
159 /* The function usage is only informative - it prints this program's usage and
160 command-line options. */
163 fprintf(stderr, _(" usage: gnokii [--help|--monitor|--version]\n"
164 " gnokii --getmemory memory_type start [end]\n"
165 " gnokii --writephonebook [-i]\n"
166 " gnokii --getspeeddial number\n"
167 " gnokii --setspeeddial number memory_type location\n"
168 " gnokii --getsms memory_type start [end] [-f file] [-F file] [-d]\n"
169 " gnokii --deletesms memory_type start [end]\n"
170 " gnokii --sendsms destination [--smsc message_center_number |\n"
171 " --smscno message_center_index] [-r] [-C n] [-v n]\n"
173 " gnokii --savesms [-m] [-l n] [-i]\n"
174 " gnokii --getsmsc message_center_number\n"
175 " gnokii --setdatetime [YYYY [MM [DD [HH [MM]]]]]\n"
176 " gnokii --getdatetime\n"
177 " gnokii --setalarm HH MM\n"
178 " gnokii --getalarm\n"
179 " gnokii --dialvoice number\n"
180 " gnokii --getcalendarnote start [end] [-v]\n"
181 " gnokii --writecalendarnote vcardfile number\n"
182 " gnokii --deletecalendarnote start [end]\n"
183 " gnokii --getdisplaystatus\n"
184 " gnokii --netmonitor {reset|off|field|devel|next|nr}\n"
185 " gnokii --identify\n"
186 " gnokii --senddtmf string\n"
187 " gnokii --sendlogo {caller|op} destination logofile [network code]\n"
188 " gnokii --sendringtone destination rtttlfile\n"
189 " gnokii --setlogo op [logofile] [network code]\n"
190 " gnokii --setlogo startup [logofile]\n"
191 " gnokii --setlogo caller [logofile] [caller group number] [group name]\n"
192 " gnokii --setlogo {dealer|text} [text]\n"
193 " gnokii --getlogo op [logofile] [network code]\n"
194 " gnokii --getlogo startup [logofile] [network code]\n"
195 " gnokii --getlogo caller [logofile][caller group number][network code]\n"
196 " gnokii --getlogo {dealer|text}\n"
197 " gnokii --viewlogo logofile\n"
198 " gnokii --setringtone rtttlfile\n"
199 " gnokii --reset [soft|hard]\n"
200 " gnokii --getprofile [number]\n"
201 " gnokii --displayoutput\n"
202 " gnokii --keysequence\n"
206 " gnokii --entersecuritycode PIN|PIN2|PUK|PUK2\n"
207 " gnokii --getsecuritycodestatus\n"
213 /* fbusinit is the generic function which waits for the FBUS link. The limit
214 is 10 seconds. After 10 seconds we quit. */
216 static GSM_Statemachine State;
217 static GSM_Data data;
219 void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame))
223 GSM_ConnectionType connection = GCT_Serial;
225 GSM_DataClear(&data);
227 if (!strcasecmp(Connection, "dau9p")) connection = GCT_DAU9P; /* Use only with 6210/7110 for faster connection with such cable */
228 if (!strcasecmp(Connection, "infrared")) connection = GCT_Infrared;
229 if (!strcasecmp(Connection, "irda")) connection = GCT_Irda;
231 /* Initialise the code for the GSM interface. */
233 error = GSM_Initialise(model, Port, Initlength, connection, rlp_handler, &State);
235 if (error != GE_NONE) {
236 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
240 /* First (and important!) wait for GSM link to be active. We allow 10
243 while (count++ < 200 && *GSM_LinkOK == false)
246 if (*GSM_LinkOK == false) {
247 fprintf (stderr, _("Hmmm... GSM_LinkOK never went true. Quitting.\n"));
252 /* This function checks that the argument count for a given options is withing
254 int checkargs(int opt, struct gnokii_arg_len gals[], int argc)
258 /* Walk through the whole array with options requiring arguments. */
259 for (i = 0; !(gals[i].gal_min == 0 && gals[i].gal_max == 0); i++) {
261 /* Current option. */
262 if (gals[i].gal_opt == opt) {
264 /* Argument count checking. */
265 if (gals[i].gal_flags == GAL_XOR) {
266 if (gals[i].gal_min == argc || gals[i].gal_max == argc)
269 if (gals[i].gal_min <= argc && gals[i].gal_max >= argc)
277 /* We do not have options without arguments in the array, so check them. */
278 if (argc == 0) return 0;
282 /* Main function - handles command line arguments, passes them to separate
283 functions accordingly. */
284 int main(int argc, char *argv[])
290 /* Every option should be in this array. */
291 static struct option long_options[] =
293 /* FIXME: these comments are nice, but they would be more usefull as docs for the user */
295 { "help", no_argument, NULL, OPT_HELP },
297 /* Display version and build information. */
298 { "version", no_argument, NULL, OPT_VERSION },
301 { "monitor", no_argument, NULL, OPT_MONITOR },
305 /* Enter Security Code mode */
306 { "entersecuritycode", required_argument, NULL, OPT_ENTERSECURITYCODE },
308 // Get Security Code status
309 { "getsecuritycodestatus", no_argument, NULL, OPT_GETSECURITYCODESTATUS },
314 { "setdatetime", optional_argument, NULL, OPT_SETDATETIME },
316 // Get date and time mode
317 { "getdatetime", no_argument, NULL, OPT_GETDATETIME },
320 { "setalarm", required_argument, NULL, OPT_SETALARM },
323 { "getalarm", no_argument, NULL, OPT_GETALARM },
326 { "dialvoice", required_argument, NULL, OPT_DIALVOICE },
328 // Get calendar note mode
329 { "getcalendarnote", required_argument, NULL, OPT_GETCALENDARNOTE },
331 // Write calendar note mode
332 { "writecalendarnote", required_argument, NULL, OPT_WRITECALENDARNOTE },
334 // Delete calendar note mode
335 { "deletecalendarnote", required_argument, NULL, OPT_DELCALENDARNOTE },
337 // Get display status mode
338 { "getdisplaystatus", no_argument, NULL, OPT_GETDISPLAYSTATUS },
341 { "getmemory", required_argument, NULL, OPT_GETMEMORY },
343 // Write phonebook (memory) mode
344 { "writephonebook", optional_argument, NULL, OPT_WRITEPHONEBOOK },
346 // Get speed dial mode
347 { "getspeeddial", required_argument, NULL, OPT_GETSPEEDDIAL },
349 // Set speed dial mode
350 { "setspeeddial", required_argument, NULL, OPT_SETSPEEDDIAL },
352 // Get SMS message mode
353 { "getsms", required_argument, NULL, OPT_GETSMS },
355 // Delete SMS message mode
356 { "deletesms", required_argument, NULL, OPT_DELETESMS },
358 // Send SMS message mode
359 { "sendsms", required_argument, NULL, OPT_SENDSMS },
361 // Ssve SMS message mode
362 { "savesms", optional_argument, NULL, OPT_SAVESMS },
364 // Send logo as SMS message mode
365 { "sendlogo", required_argument, NULL, OPT_SENDLOGO },
367 // Send ringtone as SMS message
368 { "sendringtone", required_argument, NULL, OPT_SENDRINGTONE },
371 { "setringtone", required_argument, NULL, OPT_SETRINGTONE },
373 // Get SMS center number mode
374 { "getsmsc", required_argument, NULL, OPT_GETSMSC },
376 // For development purposes: run in passive monitoring mode
377 { "pmon", no_argument, NULL, OPT_PMON },
380 { "netmonitor", required_argument, NULL, OPT_NETMONITOR },
383 { "identify", no_argument, NULL, OPT_IDENTIFY },
385 // Send DTMF sequence
386 { "senddtmf", required_argument, NULL, OPT_SENDDTMF },
389 { "reset", optional_argument, NULL, OPT_RESET },
392 { "setlogo", optional_argument, NULL, OPT_SETLOGO },
395 { "getlogo", required_argument, NULL, OPT_GETLOGO },
398 { "viewlogo", required_argument, NULL, OPT_VIEWLOGO },
401 { "getprofile", optional_argument, NULL, OPT_GETPROFILE },
403 // Show texts from phone's display
404 { "displayoutput", no_argument, NULL, OPT_DISPLAYOUTPUT },
406 // Simulate pressing the keys
407 { "keysequence", no_argument, NULL, OPT_KEYPRESS },
409 // For development purposes: insert you function calls here
410 { "foogle", no_argument, NULL, OPT_FOOGLE },
415 /* Every command which requires arguments should have an appropriate entry
417 struct gnokii_arg_len gals[] =
421 { OPT_ENTERSECURITYCODE, 1, 1, 0 },
424 { OPT_SETDATETIME, 0, 5, 0 },
425 { OPT_SETALARM, 2, 2, 0 },
426 { OPT_DIALVOICE, 1, 1, 0 },
427 { OPT_GETCALENDARNOTE, 1, 3, 0 },
428 { OPT_WRITECALENDARNOTE, 2, 2, 0 },
429 { OPT_DELCALENDARNOTE, 1, 2, 0 },
430 { OPT_GETMEMORY, 2, 3, 0 },
431 { OPT_GETSPEEDDIAL, 1, 1, 0 },
432 { OPT_SETSPEEDDIAL, 3, 3, 0 },
433 { OPT_GETSMS, 2, 5, 0 },
434 { OPT_DELETESMS, 2, 3, 0 },
435 { OPT_SENDSMS, 1, 10, 0 },
436 { OPT_SAVESMS, 0, 6, 0 },
437 { OPT_SENDLOGO, 3, 4, GAL_XOR },
438 { OPT_SENDRINGTONE, 2, 2, 0 },
439 { OPT_GETSMSC, 1, 1, 0 },
440 { OPT_GETWELCOMENOTE, 1, 1, 0 },
441 { OPT_SETWELCOMENOTE, 1, 1, 0 },
442 { OPT_NETMONITOR, 1, 1, 0 },
443 { OPT_SENDDTMF, 1, 1, 0 },
444 { OPT_SETLOGO, 1, 4, 0 },
445 { OPT_GETLOGO, 1, 4, 0 },
446 { OPT_VIEWLOGO, 1, 1, 0 },
447 { OPT_SETRINGTONE, 1, 1, 0 },
448 { OPT_RESET, 0, 1, 0 },
449 { OPT_GETPROFILE, 0, 1, 0 },
450 { OPT_WRITEPHONEBOOK, 0, 1, 0 },
457 /* For GNU gettext */
459 textdomain("gnokii");
460 setlocale(LC_ALL, "");
463 /* Read config file */
464 if (readconfig(&model, &Port, &Initlength, &Connection, &BinDir) < 0) {
468 /* Introduce yourself */
471 /* Handle command line arguments. */
472 c = getopt_long(argc, argv, "", long_options, NULL);
473 if (c == -1) /* No argument given - we should display usage. */
477 // First, error conditions
480 fprintf(stderr, _("Use '%s --help' for usage informations.\n"), argv[0]);
482 // Then, options with no arguments
490 /* We have to build an array of the arguments which will be passed to the
491 functions. Please note that every text after the --command will be
492 passed as arguments. A syntax like gnokii --cmd1 args --cmd2 args will
493 not work as expected; instead args --cmd2 args is passed as a
495 if ((nargv = malloc(sizeof(char *) * argc)) != NULL) {
496 for (i = 2; i < argc; i++)
497 nargv[i-2] = argv[i];
499 if (checkargs(c, gals, nargc)) {
500 free(nargv); /* Wrong number of arguments - we should display usage. */
505 /* have to ignore SIGALARM */
509 /* Initialise the code for the GSM interface. */
517 case OPT_ENTERSECURITYCODE:
518 rc = entersecuritycode(optarg);
520 case OPT_GETSECURITYCODESTATUS:
521 rc = getsecuritycodestatus();
524 case OPT_GETDATETIME:
530 case OPT_GETDISPLAYSTATUS:
531 rc = getdisplaystatus();
536 case OPT_WRITEPHONEBOOK:
537 rc = writephonebook(nargc, nargv);
539 // Now, options with arguments
540 case OPT_SETDATETIME:
541 rc = setdatetime(nargc, nargv);
544 rc = setalarm(nargv);
547 rc = dialvoice(optarg);
549 case OPT_GETCALENDARNOTE:
550 rc = getcalendarnote(nargc, nargv);
552 case OPT_DELCALENDARNOTE:
553 rc = deletecalendarnote(nargc, nargv);
555 case OPT_WRITECALENDARNOTE:
556 rc = writecalendarnote(nargv);
559 rc = getmemory(nargc, nargv);
561 case OPT_GETSPEEDDIAL:
562 rc = getspeeddial(optarg);
564 case OPT_SETSPEEDDIAL:
565 rc = setspeeddial(nargv);
568 rc = getsms(argc, argv);
571 rc = deletesms(nargc, nargv);
574 rc = sendsms(nargc, nargv);
577 rc = savesms(argc, argv);
580 rc = sendlogo(nargc, nargv);
583 rc = getsmsc(optarg);
586 rc = netmonitor(optarg);
592 rc = setlogo(nargc, nargv);
595 rc = getlogo(nargc, nargv);
598 rc = viewlogo(optarg);
600 case OPT_SETRINGTONE:
601 rc = setringtone(nargc, nargv);
603 case OPT_SENDRINGTONE:
604 rc = sendringtone(nargc, nargv);
607 rc = getprofile(nargc, nargv);
609 case OPT_DISPLAYOUTPUT:
610 rc = displayoutput();
613 rc = presskeysequence();
621 rc = senddtmf(optarg);
627 fprintf(stderr, _("Unknown option: %d\n"), c);
634 fprintf(stderr, _("Wrong number of arguments\n"));
638 /* Send SMS messages. */
639 int sendsms(int argc, char *argv[])
643 // char UDH[GSM_MAX_USER_DATA_HEADER_LENGTH];
644 /* The maximum length of an uncompressed concatenated short message is
645 255 * 153 = 39015 default alphabet characters */
646 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
647 int input_len, chars_read;
648 int i; /*, offset, nr_msg, aux;*/
650 struct option options[] = {
651 { "smsc", required_argument, NULL, '1'},
652 { "smscno", required_argument, NULL, '2'},
653 { "long", required_argument, NULL, '3'},
657 input_len = GSM_MAX_SMS_LENGTH;
665 - message validity for 3 days
666 - unset user data header indicator
669 memset(&SMS, 0, sizeof(GSM_SMSMessage));
671 SMS.Type = SMS_Submit;
672 SMS.DCS.Type = SMS_GeneralDataCoding;
673 SMS.DCS.u.General.Compressed = false;
674 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
675 SMS.DCS.u.General.Class = 0;
676 SMS.MessageCenter.No = 1;
677 SMS.Validity.VPF = SMS_RelativeFormat;
678 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
682 strcpy(SMS.RemoteNumber.number, argv[0]);
683 if (SMS.RemoteNumber.number[0] == '+') SMS.RemoteNumber.type = SMS_International;
684 else SMS.RemoteNumber.type = SMS_Unknown;
689 while ((i = getopt_long(argc, argv, "r8cC:v:", options, NULL)) != -1) {
690 switch (i) { // -8 is for 8-bit data, -c for compression. both are not yet implemented.
691 case '1': /* SMSC number */
692 SMS.MessageCenter.No = 0;
693 strcpy(SMS.MessageCenter.Number, optarg);
694 if (SMS.MessageCenter.Number[0] == '+') SMS.MessageCenter.Type = SMS_International;
695 else SMS.MessageCenter.Type = SMS_Unknown;
697 case '2': /* SMSC number index in phone memory */
698 SMS.MessageCenter.No = atoi(optarg);
700 if (SMS.MessageCenter.No < 1 || SMS.MessageCenter.No > 5)
702 data.MessageCenter = &SMS.MessageCenter;
703 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
705 case '3': /* we send long message */
706 input_len = atoi(optarg);
707 if (input_len > 255 * GSM_MAX_SMS_LENGTH) {
708 fprintf(stderr, _("Input too long!\n"));
712 case 'r': /* request for delivery report */
715 case 'C': /* class Message */
718 SMS.DCS.u.General.Class = 1;
721 SMS.DCS.u.General.Class = 2;
724 SMS.DCS.u.General.Class = 3;
727 SMS.DCS.u.General.Class = 4;
734 SMS.Validity.u.Relative = atoi(optarg);
737 usage(); /* Would be better to have an sendsms_usage() here. */
741 /* Get message text from stdin. */
742 chars_read = fread(message_buffer, 1, input_len, stdin);
744 if (chars_read == 0) {
745 fprintf(stderr, _("Couldn't read from stdin!\n"));
747 } else if (chars_read > input_len) {
748 fprintf(stderr, _("Input too long!\n"));
752 /* Null terminate. */
753 message_buffer[chars_read] = 0x00;
754 strncpy(SMS.MessageText, message_buffer, chars_read);
755 data.SMSMessage = &SMS;
757 /* Send the message. */
758 error = SM_Functions(GOP_SendSMS, &data, &State);
760 if (error == GE_SMSSENDOK) {
761 fprintf(stdout, _("Send succeeded!\n"));
763 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
766 if (GSM && GSM->Terminate) GSM->Terminate();
771 int savesms(int argc, char *argv[])
775 /* The maximum length of an uncompressed concatenated short message is
776 255 * 153 = 39015 default alphabet characters */
777 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
778 int input_len, chars_read;
784 SMS.Type = SMS_Deliver;
785 SMS.DCS.Type = SMS_GeneralDataCoding;
786 SMS.DCS.u.General.Compressed = false;
787 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
788 SMS.DCS.u.General.Class = 0;
789 SMS.MessageCenter.No = 1;
790 SMS.Validity.VPF = SMS_RelativeFormat;
791 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
793 SMS.Status = SMS_Unsent;
796 input_len = GSM_MAX_SMS_LENGTH;
799 while ((i = getopt(argc, argv, "ml:in:s:c:")) != -1) {
801 case 'm': /* mark the message as sent */
802 SMS.Status = SMS_Sent;
804 case 'l': /* Specify the location */
805 SMS.Number = atoi(optarg);
807 case 'i': /* Ask before overwriting */
810 case 'n': /* Specify the from number */
812 case 's': /* Specify the smsc number */
814 case 'c': /* Specify the smsc location */
825 aux.Number = SMS.Number;
826 data.SMSMessage = &aux;
827 error = SM_Functions(GOP_GetSMS, &data, &State);
830 fprintf(stderr, _("Message at specified location exists. "));
831 while (confirm < 0) {
832 fprintf(stderr, _("Overwrite? (yes/no) "));
833 GetLine(stdin, ans, 7);
834 if (!strcmp(ans, _("yes"))) confirm = 1;
835 else if (!strcmp(ans, _("no"))) confirm = 0;
837 if (!confirm) { GSM->Terminate(); return 0; }
839 case GE_INVALIDSMSLOCATION:
840 fprintf(stderr, _("Invalid location\n"));
844 /* FIXME: Remove this fprintf when the function is thoroughly tested */
846 fprintf(stderr, _("Location %d empty. Saving\n"), SMS.Number);
851 chars_read = fread(message_buffer, 1, input_len, stdin);
853 if (chars_read == 0) {
855 fprintf(stderr, _("Couldn't read from stdin!\n"));
858 } else if (chars_read > input_len) {
860 fprintf(stderr, _("Input too long!\n"));
865 strncpy (SMS.MessageText, message_buffer, chars_read);
866 SMS.MessageText[chars_read] = 0;
868 error = GSM->SaveSMSMessage(&SMS);
870 if (error == GE_NONE) {
871 fprintf(stdout, _("Saved!\n"));
873 fprintf(stdout, _("Saving failed (error=%d)\n"), error);
881 /* Get SMSC number */
882 int getsmsc(char *MessageCenterNumber)
884 SMS_MessageCenter MessageCenter;
888 memset(&MessageCenter, 0, sizeof(MessageCenter));
889 MessageCenter.No=atoi(MessageCenterNumber);
891 if (GSM && GSM->GetSMSCenter && GSM->Terminate) {
892 error = GSM->GetSMSCenter(&MessageCenter);
895 GSM_DataClear(&data);
896 data.MessageCenter = &MessageCenter;
897 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
902 fprintf(stdout, _("%d. SMS center (%s) number is %s\n"), MessageCenter.No, MessageCenter.Name, MessageCenter.Number);
903 fprintf(stdout, _("Default recipient number is %s\n"), MessageCenter.Recipient);
904 fprintf(stdout, _("Messages sent as "));
906 switch (MessageCenter.Format) {
908 fprintf(stdout, _("Text"));
911 fprintf(stdout, _("VoiceMail"));
914 fprintf(stdout, _("Fax"));
918 fprintf(stdout, _("Email"));
921 fprintf(stdout, _("ERMES"));
924 fprintf(stdout, _("X.400"));
927 fprintf(stdout, _("Unknown"));
932 fprintf(stdout, _("Message validity is "));
934 switch (MessageCenter.Validity) {
936 fprintf(stdout, _("1 hour"));
939 fprintf(stdout, _("6 hours"));
942 fprintf(stdout, _("24 hours"));
945 fprintf(stdout, _("72 hours"));
948 fprintf(stdout, _("1 week"));
951 fprintf(stdout, _("Maximum time"));
954 fprintf(stdout, _("Unknown"));
958 fprintf(stdout, "\n");
961 case GE_NOTIMPLEMENTED:
962 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
965 fprintf(stdout, _("SMS center can not be found :-(\n"));
972 /* Get SMS messages. */
973 int getsms(int argc, char *argv[])
977 SMS_FolderList folderlist;
978 GSM_SMSMessage message;
979 char *memory_type_string;
980 int start_message, end_message, count, mode = 1;
987 /* Handle command line args that set type, start and end locations. */
988 memory_type_string = argv[2];
989 message.MemoryType = StrToMemoryType(memory_type_string);
990 if (message.MemoryType == GMT_XX) {
991 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[2]);
995 memset(&filename, 0, 64);
997 start_message = end_message = atoi(argv[3]);
1001 /* [end] can be only argv[4] */
1002 if (argv[4][0] != '-') {
1003 end_message = atoi(argv[4]);
1006 /* parse all options (beginning with '-' */
1007 while ((i = getopt(argc, argv, "f:F:d")) != -1) {
1016 fprintf(stderr, _("Saving into %s\n"), optarg);
1017 strncpy(filename, optarg, 64);
1018 if (strlen(optarg) > 63) {
1019 fprintf(stderr, _("Filename too long - will be truncated to 63 characters.\n"));
1022 filename[strlen(optarg)] = 0;
1031 data.SMSFolderList = &folderlist;
1032 folder.FolderID = 0;
1033 data.SMSFolder = &folder;
1034 /* Now retrieve the requested entries. */
1035 for (count = start_message; count <= end_message; count ++) {
1038 message.Number = count;
1039 data.SMSMessage = &message;
1040 dprintf("MemoryType (gnokii.c) : %i\n", data.SMSMessage->MemoryType);
1041 error = SM_Functions(GOP_GetSMS, &data, &State);
1045 switch (message.Type) {
1047 fprintf(stdout, _("%d. MO Message "), message.Number);
1049 fprintf(stdout, _("(sent)\n"));
1050 fprintf(stdout, _("%d. MO Message "), message.Number);
1052 fprintf(stdout, _("(not sent)\n"));
1053 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1055 case SMS_Delivery_Report:
1056 fprintf(stdout, _("%d. Delivery Report "), message.Number);
1058 fprintf(stdout, _("(read)\n"));
1060 fprintf(stdout, _("(not read)\n"));
1061 fprintf(stdout, _("Sending date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1062 message.Time.Day, message.Time.Month, message.Time.Year, \
1063 message.Time.Hour, message.Time.Minute, message.Time.Second);
1064 if (message.Time.Timezone) {
1065 if (message.Time.Timezone > 0)
1066 fprintf(stdout,_("+%02d00"), message.Time.Timezone);
1068 fprintf(stdout,_("%02d00"), message.Time.Timezone);
1070 fprintf(stdout, "\n");
1071 fprintf(stdout, _("Response date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1072 message.SMSCTime.Day, message.SMSCTime.Month, message.SMSCTime.Year, \
1073 message.SMSCTime.Hour, message.SMSCTime.Minute, message.SMSCTime.Second);
1074 if (message.SMSCTime.Timezone) {
1075 if (message.SMSCTime.Timezone > 0)
1076 fprintf(stdout,_("+%02d00"),message.SMSCTime.Timezone);
1078 fprintf(stdout,_("%02d00"),message.SMSCTime.Timezone);
1080 fprintf(stdout, "\n");
1081 fprintf(stdout, _("Receiver: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1082 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1085 fprintf(stdout, _("%d. Inbox Message "), message.Number);
1087 fprintf(stdout, _("(read)\n"));
1089 fprintf(stdout, _("(not read)\n"));
1090 fprintf(stdout, _("Date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1091 message.Time.Day, message.Time.Month, message.Time.Year, \
1092 message.Time.Hour, message.Time.Minute, message.Time.Second);
1093 if (message.Time.Timezone) {
1094 if (message.Time.Timezone > 0)
1095 fprintf(stdout,_("+%02d00"),message.Time.Timezone);
1097 fprintf(stdout,_("%02d00"),message.Time.Timezone);
1099 fprintf(stdout, "\n");
1100 fprintf(stdout, _("Sender: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1101 switch (message.UDH[0].Type) {
1103 fprintf(stdout, _("GSM operator logo for %s (%s) network.\n"), bitmap.netcode, GSM_GetNetworkName(bitmap.netcode));
1104 if (!strcmp(message.RemoteNumber.number, "+998000005") && !strcmp(message.MessageCenter.Number, "+886935074443")) fprintf(stdout, _("Saved by Logo Express\n"));
1105 if (!strcmp(message.RemoteNumber.number, "+998000002") || !strcmp(message.RemoteNumber.number, "+998000003")) fprintf(stdout, _("Saved by Operator Logo Uploader by Thomas Kessler\n"));
1107 case SMS_CallerIDLogo:
1108 fprintf(stdout, ("Logo:\n"));
1109 /* put bitmap into bitmap structure */
1110 GSM_ReadSMSBitmap(message.UDH[0].Type, message.MessageText+2+offset, message.MessageText, &bitmap);
1111 GSM_PrintBitmap(&bitmap);
1114 if ((stat(filename, &buf) == 0)) {
1115 fprintf(stdout, _("File %s exists.\n"), filename);
1116 fprintf(stdout, _("Overwrite? (yes/no) "));
1117 GetLine(stdin, ans, 4);
1118 if (!strcmp(ans, _("yes"))) {
1119 error = GSM_SaveBitmapFile(filename, &bitmap);
1121 } else error = GSM_SaveBitmapFile(filename, &bitmap);
1122 if (error != GE_NONE) fprintf(stderr, _("Couldn't save logofile %s!\n"), filename);
1126 fprintf(stdout, _("Ringtone\n"));
1128 case SMS_ConcatenatedMessages:
1129 fprintf(stdout, _("Linked (%d/%d):\n"),
1130 message.UDH[0].u.ConcatenatedShortMessage.CurrentNumber,
1131 message.UDH[0].u.ConcatenatedShortMessage.MaximumNumber);
1133 fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText);
1134 if ((mode != -1) && *filename) {
1136 sprintf(buf, "%s%d", filename, count);
1137 mode = GSM_SaveTextFile(buf, message.MessageText, mode);
1140 case SMS_BusinessCard:
1141 fprintf(stdout, _("Business Card:\n%s"), message.MessageText);
1144 fprintf(stderr, _("Unknown\n"));
1150 data.SMSMessage = &message;
1151 if (GE_NONE != SM_Functions(GOP_DeleteSMS, &data, &State))
1152 fprintf(stdout, _("(delete failed)\n"));
1154 fprintf(stdout, _("(message deleted)\n"));
1157 case GE_NOTIMPLEMENTED:
1158 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1159 if (GSM && GSM->Terminate) GSM->Terminate();
1161 case GE_INVALIDSMSLOCATION:
1162 fprintf(stderr, _("Invalid location: %s %d\n"), memory_type_string, count);
1164 case GE_EMPTYSMSLOCATION:
1165 fprintf(stderr, _("SMS location %s %d empty.\n"), memory_type_string, count);
1168 fprintf(stdout, _("GetSMS %s %d failed!(%s)\n\n"), memory_type_string, count, print_error(error));
1173 if (GSM && GSM->Terminate) GSM->Terminate();
1178 /* Delete SMS messages. */
1179 int deletesms(int argc, char *argv[])
1181 GSM_SMSMessage message;
1182 char *memory_type_string;
1183 int start_message, end_message, count;
1186 /* Handle command line args that set type, start and end locations. */
1187 memory_type_string = argv[0];
1188 message.MemoryType = StrToMemoryType(memory_type_string);
1189 if (message.MemoryType == GMT_XX) {
1190 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
1194 start_message = end_message = atoi (argv[1]);
1195 if (argc > 2) end_message = atoi (argv[2]);
1197 /* Now delete the requested entries. */
1198 for (count = start_message; count <= end_message; count ++) {
1200 message.Number = count;
1201 data.SMSMessage = &message;
1202 error = SM_Functions(GOP_DeleteSMS, &data, &State);
1204 if (error == GE_NONE)
1205 fprintf(stdout, _("Deleted SMS %s %d\n"), memory_type_string, count);
1207 if (error == GE_NOTIMPLEMENTED) {
1208 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1212 fprintf(stdout, _("DeleteSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
1221 static volatile bool bshutdown = false;
1223 /* SIGINT signal handler. */
1224 static void interrupted(int sig)
1226 signal(sig, SIG_IGN);
1232 /* In this mode we get the code from the keyboard and send it to the mobile
1234 int entersecuritycode(char *type)
1237 GSM_SecurityCode SecurityCode;
1239 if (!strcmp(type,"PIN"))
1240 SecurityCode.Type=GSCT_Pin;
1241 else if (!strcmp(type,"PUK"))
1242 SecurityCode.Type=GSCT_Puk;
1243 else if (!strcmp(type,"PIN2"))
1244 SecurityCode.Type=GSCT_Pin2;
1245 else if (!strcmp(type,"PUK2"))
1246 SecurityCode.Type=GSCT_Puk2;
1247 // FIXME: Entering of SecurityCode does not work :-(
1248 // else if (!strcmp(type,"SecurityCode"))
1249 // SecurityCode.Type=GSCT_SecurityCode;
1254 printf("Enter your code: ");
1255 gets(SecurityCode.Code);
1257 strcpy(SecurityCode.Code,getpass(_("Enter your code: ")));
1260 test = GSM->EnterSecurityCode(SecurityCode);
1261 if (test == GE_INVALIDSECURITYCODE)
1262 fprintf(stdout, _("Error: invalid code.\n"));
1263 else if (test == GE_NONE)
1264 fprintf(stdout, _("Code ok.\n"));
1265 else if (test == GE_NOTIMPLEMENTED)
1266 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1268 fprintf(stdout, _("Other error.\n"));
1275 int getsecuritycodestatus(void)
1279 if (GSM->GetSecurityCodeStatus(&Status) == GE_NONE) {
1281 fprintf(stdout, _("Security code status: "));
1284 case GSCT_SecurityCode:
1285 fprintf(stdout, _("waiting for Security Code.\n"));
1288 fprintf(stdout, _("waiting for PIN.\n"));
1291 fprintf(stdout, _("waiting for PIN2.\n"));
1294 fprintf(stdout, _("waiting for PUK.\n"));
1297 fprintf(stdout, _("waiting for PUK2.\n"));
1300 fprintf(stdout, _("nothing to enter.\n"));
1303 fprintf(stdout, _("Unknown!\n"));
1316 /* Voice dialing mode. */
1317 int dialvoice(char *Number)
1319 GSM->DialVoice(Number);
1326 /* The following function allows to send logos using SMS */
1327 int sendlogo(int argc, char *argv[])
1333 char UserDataHeader[7] = { 0x06, /* UDH Length */
1334 0x05, /* IEI: application port addressing scheme, 16 bit address */
1335 0x04, /* IEI length */
1336 0x15, /* destination address: high byte */
1337 0x00, /* destination address: low byte */
1338 0x00, /* originator address */
1341 char Data[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1345 /* Default settings for SMS message:
1346 - no delivery report
1352 - set UserDataHeaderIndicator
1354 SMS.Type = SMS_Submit;
1355 SMS.DCS.Type = SMS_GeneralDataCoding;
1356 SMS.DCS.u.General.Compressed = false;
1357 SMS.DCS.u.General.Alphabet = SMS_8bit;
1358 SMS.DCS.u.General.Class = 2;
1359 SMS.MessageCenter.No = 1;
1360 SMS.Validity.VPF = SMS_RelativeFormat;
1361 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
1363 /* The first argument is the type of the logo. */
1364 if (!strcmp(argv[0], "op")) {
1365 SMS.UDH[0].Type = SMS_OpLogo;
1366 UserDataHeader[4] = 0x82; /* NBS port 0x1582 */
1367 fprintf(stdout, _("Sending operator logo.\n"));
1368 } else if (!strcmp(argv[0], "caller")) {
1369 SMS.UDH[0].Type = SMS_CallerIDLogo;
1370 UserDataHeader[4] = 0x83; /* NBS port 0x1583 */
1371 fprintf(stdout, _("Sending caller line identification logo.\n"));
1373 fprintf(stderr, _("You should specify what kind of logo to send!\n"));
1377 /* The second argument is the destination, ie the phone number of recipient. */
1378 SMS.MemoryType = atoi(argv[1]);
1380 /* The third argument is the bitmap file. */
1381 GSM_ReadBitmapFile(argv[2], &bitmap);
1383 /* If we are sending op logo we can rewrite network code. */
1384 if (!strcmp(argv[0], "op")) {
1386 * The fourth argument, if present, is the Network code of the operator.
1387 * Network code is in this format: "xxx yy".
1390 strcpy(bitmap.netcode, argv[3]);
1392 fprintf(stdout, _("Operator code: %s\n"), argv[3]);
1396 /* Set the network code */
1397 Data[current++] = ((bitmap.netcode[1] & 0x0f) << 4) | (bitmap.netcode[0] & 0xf);
1398 Data[current++] = 0xf0 | (bitmap.netcode[2] & 0x0f);
1399 Data[current++] = ((bitmap.netcode[5] & 0x0f) << 4) | (bitmap.netcode[4] & 0xf);
1402 /* Set the logo size */
1404 Data[current++] = bitmap.width;
1405 Data[current++] = bitmap.height;
1407 Data[current++] = 0x01;
1409 memcpy(SMS.MessageText, UserDataHeader, 7);
1410 memcpy(SMS.MessageText, Data, current);
1411 memcpy(SMS.MessageText+current, bitmap.bitmap, bitmap.size);
1413 /* Send the message. */
1414 error = GSM->SendSMSMessage(&SMS,current+bitmap.size);
1416 if (error == GE_SMSSENDOK)
1417 fprintf(stdout, _("Send succeeded!\n"));
1419 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
1425 /* Getting logos. */
1426 GSM_Error SaveBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1433 /* Ask before overwriting */
1434 while (stat(FileName, &buf) == 0) {
1437 fprintf(stderr, _("Saving logo. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "), FileName);
1438 GetLine(stdin, ans, 4);
1439 if (!strcmp(ans, "O") || !strcmp(ans, "o")) confirm = 1;
1440 if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm = 2;
1441 if (!strcmp(ans, "S") || !strcmp(ans, "s")) return GE_USERCANCELED;
1443 if (confirm == 1) break;
1445 fprintf(stderr, _("Enter name of new file: "));
1446 GetLine(stdin, FileName, 50);
1447 if (!FileName || (*FileName == 0)) return GE_USERCANCELED;
1451 error = GSM_SaveBitmapFile(FileName, bitmap);
1454 case GE_CANTOPENFILE:
1455 fprintf(stderr, _("Failed to write file \"%s\"\n"), FileName);
1464 int getlogo(int argc, char *argv[])
1468 GSM_Statemachine *sm = &State;
1470 bitmap.type=GSM_None;
1472 if (!strcmp(argv[0], "op"))
1473 bitmap.type = GSM_OperatorLogo;
1475 if (!strcmp(argv[0], "caller")) {
1476 /* There is caller group number missing in argument list. */
1478 bitmap.number=argv[2][0]-'0';
1479 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1483 bitmap.type = GSM_CallerLogo;
1486 if (!strcmp(argv[0],"startup"))
1487 bitmap.type = GSM_StartupLogo;
1488 else if (!strcmp(argv[0], "dealer"))
1489 bitmap.type = GSM_DealerNoteText;
1490 else if (!strcmp(argv[0], "text"))
1491 bitmap.type=GSM_WelcomeNoteText;
1493 if (bitmap.type != GSM_None) {
1495 fprintf(stdout, _("Getting Logo\n"));
1497 data.Bitmap=&bitmap;
1498 error=SM_Functions(GOP_GetBitmap, &data, sm);
1502 if (bitmap.type == GSM_DealerNoteText) fprintf(stdout, _("Dealer welcome note "));
1503 if (bitmap.type == GSM_WelcomeNoteText) fprintf(stdout, _("Welcome note "));
1504 if (bitmap.type == GSM_DealerNoteText || bitmap.type==GSM_WelcomeNoteText) {
1505 if (bitmap.text[0]) {
1506 fprintf(stdout, _("currently set to \"%s\"\n"), bitmap.text);
1508 fprintf(stdout, _("currently empty\n"));
1512 switch (bitmap.type) {
1513 case GSM_OperatorLogo:
1514 fprintf(stdout,"Operator logo for %s (%s) network got succesfully\n",bitmap.netcode,GSM_GetNetworkName(bitmap.netcode));
1516 strncpy(bitmap.netcode,argv[2], 7);
1517 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1518 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1523 case GSM_StartupLogo:
1524 fprintf(stdout, "Startup logo got successfully\n");
1526 strncpy(bitmap.netcode,argv[2], 7);
1527 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1528 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1533 case GSM_CallerLogo:
1534 fprintf(stdout,"Caller logo got successfully\n");
1536 strncpy(bitmap.netcode,argv[3],7);
1537 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1538 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1544 fprintf(stdout,"Unknown bitmap type.\n");
1548 if (SaveBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) return (-1);
1551 fprintf(stdout,"Your phone doesn't have logo uploaded !\n");
1556 case GE_NOTIMPLEMENTED:
1557 fprintf(stderr, _("Function not implemented !\n"));
1559 case GE_NOTSUPPORTED:
1560 fprintf(stderr, _("This kind of logo is not supported !\n"));
1563 fprintf(stderr, _("Error getting logo !\n"));
1567 fprintf(stderr, _("What kind of logo do you want to get ?\n"));
1575 /* Sending logos. */
1576 GSM_Error ReadBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1580 error = GSM_ReadBitmapFile(FileName, bitmap);
1583 case GE_CANTOPENFILE:
1584 fprintf(stderr, _("Failed to read file \"%s\"\n"), FileName);
1586 case GE_WRONGNUMBEROFCOLORS:
1587 fprintf(stderr, _("Wrong number of colors in \"%s\" logofile (accepted only 2-colors files) !\n"), FileName);
1589 case GE_WRONGCOLORS:
1590 fprintf(stderr, _("Wrong colors in \"%s\" logofile !\n"), FileName);
1592 case GE_INVALIDFILEFORMAT:
1593 fprintf(stderr, _("Invalid format of \"%s\" logofile !\n"), FileName);
1595 case GE_SUBFORMATNOTSUPPORTED:
1596 fprintf(stderr, _("Sorry, gnokii doesn't support used subformat in file \"%s\" !\n"), FileName);
1598 case GE_FILETOOSHORT:
1599 fprintf(stderr, _("\"%s\" logofile is too short !\n"), FileName);
1601 case GE_INVALIDIMAGESIZE:
1602 fprintf(stderr, _("Bitmap size doesn't supported by fileformat or different from 72x14, 84x48 and 72x28 !\n"));
1612 int setlogo(int argc, char *argv[])
1614 GSM_Bitmap bitmap,oldbit;
1615 GSM_NetworkInfo NetworkInfo;
1621 if (!strcmp(argv[0],"text") || !strcmp(argv[0],"dealer")) {
1622 if (!strcmp(argv[0], "text")) bitmap.type = GSM_WelcomeNoteText;
1623 else bitmap.type = GSM_DealerNoteText;
1624 bitmap.text[0] = 0x00;
1625 if (argc > 1) strncpy(bitmap.text, argv[1], 255);
1627 if (!strcmp(argv[0], "op") || !strcmp(argv[0], "startup") || !strcmp(argv[0], "caller")) {
1629 if (ReadBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) {
1634 if (!strcmp(argv[0], "op")) {
1635 if (bitmap.type != GSM_OperatorLogo || argc < 3) {
1636 if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode, NetworkInfo.NetworkCode, 7);
1638 GSM_ResizeBitmap(&bitmap, GSM_OperatorLogo, GSM_Info);
1640 strncpy(bitmap.netcode, argv[2], 7);
1641 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1642 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1647 if (!strcmp(argv[0], "startup")) {
1648 GSM_ResizeBitmap(&bitmap, GSM_StartupLogo, GSM_Info);
1650 if (!strcmp(argv[0],"caller")) {
1651 GSM_ResizeBitmap(&bitmap, GSM_CallerLogo, GSM_Info);
1653 bitmap.number = argv[2][0] - '0';
1654 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1658 oldbit.type = GSM_CallerLogo;
1659 oldbit.number = bitmap.number;
1660 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1661 /* We have to get the old name and ringtone!! */
1662 bitmap.ringtone = oldbit.ringtone;
1663 strncpy(bitmap.text, oldbit.text, 255);
1665 if (argc > 3) strncpy(bitmap.text, argv[3], 255);
1667 fprintf(stdout, _("Setting Logo.\n"));
1669 /* FIX ME: is it possible to permanently remove op logo ? */
1670 if (!strcmp(argv[0], "op"))
1672 bitmap.type = GSM_OperatorLogo;
1673 strncpy(bitmap.netcode, "000 00", 7);
1676 bitmap.size = bitmap.width * bitmap.height / 8;
1677 GSM_ClearBitmap(&bitmap);
1679 /* FIX ME: how to remove startup and group logos ? */
1680 fprintf(stdout, _("Removing Logo.\n"));
1683 fprintf(stderr, _("What kind of logo do you want to set ?\n"));
1689 error=GSM->SetBitmap(&bitmap);
1693 oldbit.type = bitmap.type;
1694 oldbit.number = bitmap.number;
1695 if (GSM->GetBitmap(&oldbit) == GE_NONE) {
1696 if (bitmap.type == GSM_WelcomeNoteText ||
1697 bitmap.type == GSM_DealerNoteText) {
1698 if (strcmp(bitmap.text, oldbit.text)) {
1699 fprintf(stderr, _("Error setting"));
1700 if (bitmap.type == GSM_DealerNoteText) fprintf(stderr, _(" dealer"));
1701 fprintf(stderr, _(" welcome note - "));
1703 /* I know, it looks horrible, but... */
1704 /* I set it to the short string - if it won't be set */
1705 /* it means, PIN is required. If it will be correct, previous */
1706 /* (user) text was too long */
1708 /* Without it, I could have such thing: */
1709 /* user set text to very short string (for example, "Marcin") */
1710 /* then enable phone without PIN and try to set it to the very long (too long for phone) */
1711 /* string (which start with "Marcin"). If we compare them as only length different, we could think, */
1712 /* that phone accepts strings 6 chars length only (length of "Marcin") */
1713 /* When we make it correct, we don't have this mistake */
1715 strcpy(oldbit.text, "!\0");
1716 GSM->SetBitmap(&oldbit);
1717 GSM->GetBitmap(&oldbit);
1718 if (oldbit.text[0]!='!') {
1719 fprintf(stderr, _("SIM card and PIN is required\n"));
1721 GSM->SetBitmap(&bitmap);
1722 GSM->GetBitmap(&oldbit);
1723 fprintf(stderr, _("too long, truncated to \"%s\" (length %i)\n"),oldbit.text,strlen(oldbit.text));
1728 if (bitmap.type == GSM_StartupLogo) {
1729 for (i = 0; i < oldbit.size; i++) {
1730 if (oldbit.bitmap[i] != bitmap.bitmap[i]) {
1731 fprintf(stderr, _("Error setting startup logo - SIM card and PIN is required\n"));
1739 if (ok) fprintf(stdout, _("Done.\n"));
1741 case GE_NOTIMPLEMENTED:
1742 fprintf(stderr, _("Function not implemented.\n"));
1744 case GE_NOTSUPPORTED:
1745 fprintf(stderr, _("This kind of logo is not supported.\n"));
1748 fprintf(stderr, _("Error !\n"));
1758 int viewlogo(char *filename)
1762 error = GSM_ShowBitmapFile(filename);
1766 /* Calendar notes receiving. */
1767 int getcalendarnote(int argc, char *argv[])
1769 GSM_CalendarNote CalendarNote;
1771 GSM_Error error = GE_NONE;
1772 int i, first_location, last_location;
1775 struct option options[] = {
1776 { "vCard", optional_argument, NULL, '1'},
1783 first_location = last_location = atoi(argv[0]);
1784 if ((argc > 1) && (argv[1][0] != '-')) {
1785 last_location = atoi(argv[1]);
1788 while ((i = getopt_long(argc, argv, "v", options, NULL)) != -1) {
1794 usage(); /* Would be better to have an calendar_usage() here. */
1800 for (i = first_location; i <= last_location; i++) {
1801 CalendarNote.Location = i;
1802 if (GSM && GSM->GetCalendarNote && GSM->Terminate) {
1803 error = GSM->GetCalendarNote(&CalendarNote);
1806 GSM_DataClear(&data);
1807 data.CalendarNote = &CalendarNote;
1809 error = SM_Functions(GOP_GetCalendarNote, &data, &State);
1814 fprintf(stdout, "BEGIN:VCALENDAR\n");
1815 fprintf(stdout, "VERSION:1.0\n");
1816 fprintf(stdout, "BEGIN:VEVENT\n");
1817 fprintf(stdout, "CATEGORIES:");
1818 switch (CalendarNote.Type) {
1820 fprintf(stdout, "MISCELLANEOUS\n");
1823 fprintf(stdout, "PHONE CALL\n");
1826 fprintf(stdout, "MEETING\n");
1829 fprintf(stdout, "SPECIAL OCCASION\n");
1832 fprintf(stdout, "UNKNOWN\n");
1835 fprintf(stdout, "SUMMARY:%s\n",CalendarNote.Text);
1836 fprintf(stdout, "DTSTART:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Time.Year,
1837 CalendarNote.Time.Month, CalendarNote.Time.Day, CalendarNote.Time.Hour,
1838 CalendarNote.Time.Minute, CalendarNote.Time.Second);
1839 if (CalendarNote.Alarm.Year!=0) {
1840 fprintf(stdout, "DALARM:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Alarm.Year,
1841 CalendarNote.Alarm.Month, CalendarNote.Alarm.Day, CalendarNote.Alarm.Hour,
1842 CalendarNote.Alarm.Minute, CalendarNote.Alarm.Second);
1844 fprintf(stdout, "END:VEVENT\n");
1845 fprintf(stdout, "END:VCALENDAR\n");
1847 } else { /* not vCal */
1848 fprintf(stdout, _(" Type of the note: "));
1850 switch (CalendarNote.Type) {
1852 fprintf(stdout, _("Reminder\n"));
1855 fprintf(stdout, _("Call\n"));
1858 fprintf(stdout, _("Meeting\n"));
1861 fprintf(stdout, _("Birthday\n"));
1864 fprintf(stdout, _("Unknown\n"));
1868 fprintf(stdout, _(" Date: %d-%02d-%02d\n"), CalendarNote.Time.Year,
1869 CalendarNote.Time.Month,
1870 CalendarNote.Time.Day);
1872 fprintf(stdout, _(" Time: %02d:%02d:%02d\n"), CalendarNote.Time.Hour,
1873 CalendarNote.Time.Minute,
1874 CalendarNote.Time.Second);
1876 if (CalendarNote.Alarm.AlarmEnabled == 1) {
1877 fprintf(stdout, _(" Alarm date: %d-%02d-%02d\n"), CalendarNote.Alarm.Year,
1878 CalendarNote.Alarm.Month,
1879 CalendarNote.Alarm.Day);
1881 fprintf(stdout, _(" Alarm time: %02d:%02d:%02d\n"), CalendarNote.Alarm.Hour,
1882 CalendarNote.Alarm.Minute,
1883 CalendarNote.Alarm.Second);
1886 fprintf(stdout, _(" Text: %s\n"), CalendarNote.Text);
1888 if (CalendarNote.Type == GCN_CALL)
1889 fprintf(stdout, _(" Phone: %s\n"), CalendarNote.Phone);
1892 case GE_NOTIMPLEMENTED:
1893 fprintf(stderr, _("Function not implemented.\n"));
1896 fprintf(stderr, _("The calendar note can not be read\n"));
1905 /* Writing calendar notes. */
1906 int writecalendarnote(char *argv[])
1908 GSM_CalendarNote CalendarNote;
1910 if (GSM_ReadVCalendarFile(argv[0], &CalendarNote, atoi(argv[1]))) {
1911 fprintf(stdout, _("Failed to load vCalendar file.\n"));
1915 /* Error 22=Calendar full ;-) */
1916 if ((GSM->WriteCalendarNote(&CalendarNote)) == GE_NONE)
1917 fprintf(stdout, _("Succesfully written!\n"));
1919 fprintf(stdout, _("Failed to write calendar note!\n"));
1926 /* Calendar note deleting. */
1927 int deletecalendarnote(int argc, char *argv[])
1929 GSM_CalendarNote CalendarNote;
1930 int i, first_location, last_location;
1932 first_location = last_location = atoi(argv[0]);
1933 if (argc > 1) last_location = atoi(argv[1]);
1935 for (i = first_location; i <= last_location; i++) {
1937 CalendarNote.Location = i;
1939 if (GSM->DeleteCalendarNote(&CalendarNote) == GE_NONE) {
1940 fprintf(stdout, _(" Calendar note deleted.\n"));
1942 fprintf(stderr, _("The calendar note can not be deleted\n"));
1952 /* Setting the date and time. */
1953 int setdatetime(int argc, char *argv[])
1960 now = localtime(&nowh);
1962 Date.Year = now->tm_year;
1963 Date.Month = now->tm_mon+1;
1964 Date.Day = now->tm_mday;
1965 Date.Hour = now->tm_hour;
1966 Date.Minute = now->tm_min;
1967 Date.Second = now->tm_sec;
1969 if (argc > 0) Date.Year = atoi (argv[0]);
1970 if (argc > 1) Date.Month = atoi (argv[1]);
1971 if (argc > 2) Date.Day = atoi (argv[2]);
1972 if (argc > 3) Date.Hour = atoi (argv[3]);
1973 if (argc > 4) Date.Minute = atoi (argv[4]);
1975 if (Date.Year < 1900) {
1977 /* Well, this thing is copyrighted in U.S. This technique is known as
1978 Windowing and you can read something about it in LinuxWeekly News:
1979 http://lwn.net/1999/features/Windowing.phtml. This thing is beeing
1980 written in Czech republic and Poland where algorithms are not allowed
1984 Date.Year = Date.Year + 1900;
1986 Date.Year = Date.Year + 2000;
1989 /* FIXME: Error checking should be here. */
1990 GSM->SetDateTime(&Date);
1997 /* In this mode we receive the date and time from mobile phone. */
1998 int getdatetime(void) {
2000 GSM_DateTime date_time;
2003 if (GSM && GSM->GetDateTime && GSM->Terminate) {
2004 error = GSM->GetDateTime(&date_time);
2007 GSM_DataClear(&data);
2008 data.DateTime = &date_time;
2010 error = SM_Functions(GOP_GetDateTime, &data, &State);
2015 fprintf(stdout, _("Date: %4d/%02d/%02d\n"), date_time.Year, date_time.Month, date_time.Day);
2016 fprintf(stdout, _("Time: %02d:%02d:%02d\n"), date_time.Hour, date_time.Minute, date_time.Second);
2018 case GE_NOTIMPLEMENTED:
2019 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2022 fprintf(stdout, _("Internal error\n"));
2029 /* Setting the alarm. */
2030 int setalarm(char *argv[])
2034 Date.Hour = atoi(argv[0]);
2035 Date.Minute = atoi(argv[1]);
2037 GSM->SetAlarm(1, &Date);
2044 /* Getting the alarm. */
2049 GSM_DateTime date_time;
2051 if (GSM && GSM->GetAlarm && GSM->Terminate) {
2052 error = GSM->GetAlarm(0, &date_time);
2055 GSM_DataClear(&data);
2056 data.DateTime = &date_time;
2058 error = SM_Functions(GOP_GetAlarm, &data, &State);
2063 fprintf(stdout, _("Alarm: %s\n"), (date_time.AlarmEnabled==0)?"off":"on");
2064 fprintf(stdout, _("Time: %02d:%02d\n"), date_time.Hour, date_time.Minute);
2066 case GE_NOTIMPLEMENTED:
2067 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2070 fprintf(stdout, _("Internal error\n"));
2077 /* In monitor mode we don't do much, we just initialise the fbus code.
2078 Note that the fbus code no longer has an internal monitor mode switch,
2079 instead compile with DEBUG enabled to get all the gumpf. */
2080 int monitormode(void)
2082 float rflevel = -1, batterylevel = -1;
2083 // GSM_PowerSource powersource = -1;
2084 GSM_RFUnits rf_units = GRF_Arbitrary;
2085 GSM_BatteryUnits batt_units = GBU_Arbitrary;
2086 GSM_Statemachine *sm = &State;
2089 // GSM_NetworkInfo NetworkInfo;
2090 // GSM_CBMessage CBMessage;
2092 GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0};
2093 GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0};
2094 GSM_MemoryStatus DC_MemoryStatus = {GMT_DC, 0, 0};
2095 GSM_MemoryStatus EN_MemoryStatus = {GMT_EN, 0, 0};
2096 GSM_MemoryStatus FD_MemoryStatus = {GMT_FD, 0, 0};
2097 GSM_MemoryStatus LD_MemoryStatus = {GMT_LD, 0, 0};
2098 GSM_MemoryStatus MC_MemoryStatus = {GMT_MC, 0, 0};
2099 GSM_MemoryStatus ON_MemoryStatus = {GMT_ON, 0, 0};
2100 GSM_MemoryStatus RC_MemoryStatus = {GMT_RC, 0, 0};
2102 // GSM_SMSStatus SMSStatus = {0, 0};
2106 GSM_DataClear(&data);
2108 /* We do not want to monitor serial line forever - press Ctrl+C to stop the
2110 signal(SIGINT, interrupted);
2112 fprintf (stderr, _("Entering monitor mode...\n"));
2115 //GSM->EnableCellBroadcast();
2117 /* Loop here indefinitely - allows you to see messages from GSM code in
2118 response to unknown messages etc. The loops ends after pressing the
2120 data.RFUnits=&rf_units;
2121 data.RFLevel=&rflevel;
2122 data.BatteryUnits=&batt_units;
2123 data.BatteryLevel=&batterylevel;
2125 while (!bshutdown) {
2126 if (SM_Functions(GOP_GetRFLevel,&data,sm) == GE_NONE)
2127 fprintf(stdout, _("RFLevel: %d\n"), (int)rflevel);
2129 if (SM_Functions(GOP_GetBatteryLevel,&data,sm) == GE_NONE)
2130 fprintf(stdout, _("Battery: %d\n"), (int)batterylevel);
2132 // if (GSM->GetPowerSource(&powersource) == GE_NONE)
2133 // fprintf(stdout, _("Power Source: %s\n"), (powersource==GPS_ACDC)?_("AC/DC"):_("battery"));
2135 data.MemoryStatus=&SIMMemoryStatus;
2136 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2137 fprintf(stdout, _("SIM: Used %d, Free %d\n"), SIMMemoryStatus.Used, SIMMemoryStatus.Free);
2139 data.MemoryStatus=&PhoneMemoryStatus;
2140 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2141 fprintf(stdout, _("Phone: Used %d, Free %d\n"), PhoneMemoryStatus.Used, PhoneMemoryStatus.Free);
2143 data.MemoryStatus=&DC_MemoryStatus;
2144 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2145 fprintf(stdout, _("DC: Used %d, Free %d\n"), DC_MemoryStatus.Used, DC_MemoryStatus.Free);
2147 data.MemoryStatus=&EN_MemoryStatus;
2148 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2149 fprintf(stdout, _("EN: Used %d, Free %d\n"), EN_MemoryStatus.Used, EN_MemoryStatus.Free);
2151 data.MemoryStatus=&FD_MemoryStatus;
2152 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2153 fprintf(stdout, _("FD: Used %d, Free %d\n"), FD_MemoryStatus.Used, FD_MemoryStatus.Free);
2155 data.MemoryStatus=&LD_MemoryStatus;
2156 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2157 fprintf(stdout, _("LD: Used %d, Free %d\n"), LD_MemoryStatus.Used, LD_MemoryStatus.Free);
2159 data.MemoryStatus=&MC_MemoryStatus;
2160 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2161 fprintf(stdout, _("MC: Used %d, Free %d\n"), MC_MemoryStatus.Used, MC_MemoryStatus.Free);
2163 data.MemoryStatus=&ON_MemoryStatus;
2164 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2165 fprintf(stdout, _("ON: Used %d, Free %d\n"), ON_MemoryStatus.Used, ON_MemoryStatus.Free);
2167 data.MemoryStatus=&RC_MemoryStatus;
2168 if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
2169 fprintf(stdout, _("RC: Used %d, Free %d\n"), RC_MemoryStatus.Used, RC_MemoryStatus.Free);
2171 // if (GSM->GetSMSStatus(&SMSStatus) == GE_NONE)
2172 // fprintf(stdout, _("SMS Messages: UnRead %d, Number %d\n"), SMSStatus.UnRead, SMSStatus.Number);
2174 // if (GSM->GetIncomingCallNr(Number) == GE_NONE)
2175 // fprintf(stdout, _("Incoming call: %s\n"), Number);
2177 // if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE)
2178 // fprintf(stdout, _("Network: %s (%s), LAC: %s, CellID: %s\n"), GSM_GetNetworkName (NetworkInfo.NetworkCode), GSM_GetCountryName(NetworkInfo.NetworkCode), NetworkInfo.LAC, NetworkInfo.CellID);
2180 // if (GSM->ReadCellBroadcast(&CBMessage) == GE_NONE)
2181 // fprintf(stdout, _("Cell broadcast received on channel %d: %s\n"), CBMessage.Channel, CBMessage.Message);
2186 fprintf (stderr, _("Leaving monitor mode...\n"));
2196 static GSM_Error PrettyOutputFn(char *Display, char *Indicators)
2199 printf(ESC "[10;0H Display is:\n%s\n", Display);
2201 printf(ESC "[9;0H Indicators: %s \n", Indicators);
2202 printf(ESC "[1;1H");
2207 // Uncomment it if used
2208 static GSM_Error OutputFn(char *Display, char *Indicators)
2211 printf("New display is:\n%s\n", Display);
2213 printf("Indicators: %s\n", Indicators);
2218 void console_raw(void)
2223 tcgetattr(fileno(stdin), &it);
2224 it.c_lflag &= ~(ICANON);
2225 //it.c_iflag &= ~(INPCK|ISTRIP|IXON);
2229 tcsetattr(fileno(stdin), TCSANOW, &it);
2233 int displayoutput(void)
2236 GSM_Statemachine *sm = &State;
2239 data.OutputFn = PrettyOutputFn;
2241 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2243 fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
2245 if (error == GE_NONE) {
2247 /* We do not want to see texts forever - press Ctrl+C to stop. */
2248 signal(SIGINT, interrupted);
2250 fprintf (stderr, _("Entered display monitoring mode...\n"));
2251 fprintf (stderr, ESC "c" );
2253 /* Loop here indefinitely - allows you to read texts from phone's
2254 display. The loops ends after pressing the Ctrl+C. */
2255 while (!bshutdown) {
2257 memset(&buf[0], 0, 102);
2258 while (read(0, buf, 100) > 0) {
2259 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
2260 if (GSM->HandleString(buf) != GE_NONE)
2261 fprintf(stdout, _("Key press simulation failed.\n"));
2262 memset(buf, 0, 102);
2266 fprintf (stderr, "Shutting down\n");
2268 fprintf (stderr, _("Leaving display monitor mode...\n"));
2269 data.OutputFn = NULL;
2271 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2272 if (error != GE_NONE)
2273 fprintf (stderr, _("Error!\n"));
2275 fprintf (stderr, _("Error!\n"));
2281 /* Reads profile from phone and displays its' settings */
2282 int getprofile(int argc, char *argv[])
2286 GSM_Profile profile;
2289 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2293 error = GSM->GetProfile(&profile);
2295 if (error == GE_NONE) {
2297 while (GSM->GetModel(model) != GE_NONE)
2300 max_profiles = 7; /* This is correct for 6110 (at least my). How do we get
2301 the number of profiles? */
2304 /*FIX ME: It should be set to 3 for N5130 and 3210 too*/
2305 if (!strcmp(model, "NSE-1"))
2309 profile.Number = atoi(argv[0]) - 1;
2310 start = profile.Number;
2313 if (profile.Number < 0) {
2314 fprintf(stderr, _("Profile number must be value from 1 to %d!\n"), max_profiles);
2319 if (profile.Number >= max_profiles) {
2320 fprintf(stderr, _("This phone supports only %d profiles!\n"), max_profiles);
2326 stop = max_profiles;
2333 if (profile.Number != 0)
2334 GSM->GetProfile(&profile);
2336 fprintf(stdout, "%d. \"%s\"\n", profile.Number + 1, profile.Name);
2337 if (profile.DefaultName == -1) fprintf(stdout, _(" (name defined)\n"));
2339 fprintf(stdout, _("Incoming call alert: %s\n"), GetProfileCallAlertString(profile.CallAlert));
2341 /* For different phones different ringtones names */
2343 if (!strcmp(model, "NSE-3"))
2344 fprintf(stdout, _("Ringing tone: %s (%d)\n"), RingingTones[profile.Ringtone], profile.Ringtone);
2346 fprintf(stdout, _("Ringtone number: %d\n"), profile.Ringtone);
2348 fprintf(stdout, _("Ringing volume: %s\n"), GetProfileVolumeString(profile.Volume));
2350 fprintf(stdout, _("Message alert tone: %s\n"), GetProfileMessageToneString(profile.MessageTone));
2352 fprintf(stdout, _("Keypad tones: %s\n"), GetProfileKeypadToneString(profile.KeypadTone));
2354 fprintf(stdout, _("Warning and game tones: %s\n"), GetProfileWarningToneString(profile.WarningTone));
2356 /* FIXME: Light settings is only used for Car */
2357 if (profile.Number == (max_profiles - 2)) fprintf(stdout, _("Lights: %s\n"), profile.Lights ? _("On") : _("Automatic"));
2359 fprintf(stdout, _("Vibration: %s\n"), GetProfileVibrationString(profile.Vibration));
2361 /* FIXME: it will be nice to add here reading caller group name. */
2362 if (max_profiles != 3) fprintf(stdout, _("Caller groups: 0x%02x\n"), profile.CallerGroups);
2364 /* FIXME: Automatic answer is only used for Car and Headset. */
2365 if (profile.Number >= (max_profiles - 2)) fprintf(stdout, _("Automatic answer: %s\n"), profile.AutomaticAnswer ? _("On") : _("Off"));
2367 fprintf(stdout, "\n");
2372 if (error == GE_NOTIMPLEMENTED) {
2373 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2377 fprintf(stderr, _("Unspecified error\n"));
2387 /* Get requested range of memory storage entries and output to stdout in
2388 easy-to-parse format */
2389 int getmemory(int argc, char *argv[])
2391 GSM_PhonebookEntry entry;
2394 char *memory_type_string;
2397 GSM_Statemachine *sm = &State;
2399 /* Handle command line args that set type, start and end locations. */
2400 memory_type_string = argv[0];
2401 entry.MemoryType = StrToMemoryType(memory_type_string);
2402 if (entry.MemoryType == GMT_XX) {
2403 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
2407 start_entry = atoi (argv[1]);
2408 if (argc > 2) end_entry = atoi (argv[2]);
2409 else end_entry = start_entry;
2411 /* Now retrieve the requested entries. */
2412 for (count = start_entry; count <= end_entry; count ++) {
2414 entry.Location = count;
2416 data.PhonebookEntry=&entry;
2417 error=SM_Functions(GOP_ReadPhonebook,&data,sm);
2419 if (error == GE_NONE) {
2420 fprintf(stdout, "%s;%s;%s;%d;%d\n", entry.Name, entry.Number, memory_type_string, entry.Location, entry.Group);
2421 if (entry.MemoryType == GMT_MC || entry.MemoryType == GMT_DC || entry.MemoryType == GMT_RC)
2422 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);
2425 if (error == GE_NOTIMPLEMENTED) {
2426 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2429 else if (error == GE_INVALIDMEMORYTYPE) {
2430 fprintf(stderr, _("Memory type %s not supported!\n"), memory_type_string);
2434 fprintf(stdout, _("%s|%d|Bad location or other error!(%d)\n"), memory_type_string, count, error);
2440 /* Read data from stdin, parse and write to phone. The parsing is relatively
2441 crude and doesn't allow for much variation from the stipulated format. */
2442 /* FIXME: I guess there's *very* similar code in xgnokii */
2443 int writephonebook(int argc, char *args[])
2445 GSM_PhonebookEntry entry;
2447 char *memory_type_string;
2451 char *Line, OLine[100], BackLine[100];
2454 /* Check argument */
2455 if (argc && (strcmp("-i", args[0])))
2460 /* Go through data from stdin. */
2461 while (GetLine(stdin, Line, 99)) {
2462 strcpy(BackLine, Line);
2465 ptr = strtok(Line, ";");
2466 if (ptr) strcpy(entry.Name, ptr);
2467 else entry.Name[0] = 0;
2469 ptr = strtok(NULL, ";");
2470 if (ptr) strcpy(entry.Number, ptr);
2471 else entry.Number[0] = 0;
2473 ptr = strtok(NULL, ";");
2476 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2481 if (!strncmp(ptr,"ME", 2)) {
2482 memory_type_string = "int";
2483 entry.MemoryType = GMT_ME;
2485 if (!strncmp(ptr,"SM", 2)) {
2486 memory_type_string = "sim";
2487 entry.MemoryType = GMT_SM;
2489 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2494 ptr = strtok(NULL, ";");
2495 if (ptr) entry.Location = atoi(ptr);
2496 else entry.Location = 0;
2498 ptr = strtok(NULL, ";");
2499 if (ptr) entry.Group = atoi(ptr);
2500 else entry.Group = 0;
2503 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2507 for (subentry = 0; ; subentry++) {
2508 ptr = strtok(NULL, ";");
2510 if (ptr && *ptr != 0)
2511 entry.SubEntries[subentry].EntryType = atoi(ptr);
2515 ptr = strtok(NULL, ";");
2517 entry.SubEntries[subentry].NumberType=atoi(ptr);
2519 /* Phone Numbers need to have a number type. */
2520 if (!ptr && entry.SubEntries[subentry].EntryType == GSM_Number) {
2521 fprintf(stderr, _("Missing phone number type on line %d"
2522 " entry %d [%s]\n"), line_count, subentry, BackLine);
2527 ptr = strtok(NULL, ";");
2529 entry.SubEntries[subentry].BlockNumber=atoi(ptr);
2531 ptr = strtok(NULL, ";");
2533 /* 0x13 Date Type; it is only for Dailed Numbers, etc.
2534 we don't store to this memories so it's an error to use it. */
2535 if (!ptr || entry.SubEntries[subentry].EntryType == GSM_Date) {
2536 fprintf(stdout, _("There is no phone number on line %d entry %d [%s]\n"),
2537 line_count, subentry, BackLine);
2541 strcpy(entry.SubEntries[subentry].data.Number, ptr);
2544 entry.SubEntriesCount = subentry;
2546 /* This is to send other exports (like from 6110) to 7110 */
2547 if (!entry.SubEntriesCount) {
2548 entry.SubEntriesCount = 1;
2549 entry.SubEntries[subentry].EntryType = GSM_Number;
2550 entry.SubEntries[subentry].NumberType = GSM_General;
2551 entry.SubEntries[subentry].BlockNumber = 2;
2552 strcpy(entry.SubEntries[subentry].data.Number, entry.Number);
2558 GSM_PhonebookEntry aux;
2560 aux.Location = entry.Location;
2561 error = GSM->GetMemoryLocation(&aux);
2563 if (error == GE_NONE) {
2568 fprintf(stdout, _("Location busy. "));
2569 while (confirm < 0) {
2570 fprintf(stdout, _("Overwrite? (yes/no) "));
2571 GetLine(stdin, ans, 7);
2572 if (!strcmp(ans, _("yes"))) confirm = 1;
2573 else if (!strcmp(ans, _("no"))) confirm = 0;
2575 if (!confirm) continue;
2578 fprintf(stderr, _("Unknown error (%d)\n"), error);
2584 /* Do write and report success/failure. */
2585 error = GSM->WritePhonebookLocation(&entry);
2587 if (error == GE_NONE)
2588 fprintf (stdout, _("Write Succeeded: memory type: %s, loc: %d, name: %s, number: %s\n"), memory_type_string, entry.Location, entry.Name, entry.Number);
2590 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);
2598 /* Getting speed dials. */
2599 int getspeeddial(char *Number)
2601 GSM_SpeedDial SpeedDial;
2605 SpeedDial.Number = atoi(Number);
2607 if (GSM && GSM->GetSpeedDial && GSM->Terminate) {
2608 error = GSM->GetSpeedDial(&SpeedDial);
2611 GSM_DataClear(&data);
2612 data.SpeedDial = &SpeedDial;
2614 error = SM_Functions(GOP_GetSpeedDial, &data, &State);
2619 fprintf(stdout, _("SpeedDial nr. %d: %d:%d\n"), SpeedDial.Number, SpeedDial.MemoryType, SpeedDial.Location);
2621 case GE_NOTIMPLEMENTED:
2622 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2625 fprintf(stdout, _("Internal error\n"));
2632 /* Setting speed dials. */
2633 int setspeeddial(char *argv[])
2635 GSM_SpeedDial entry;
2637 char *memory_type_string;
2639 /* Handle command line args that set type, start and end locations. */
2641 if (strcmp(argv[1], "ME") == 0) {
2642 entry.MemoryType = 0x02;
2643 memory_type_string = "ME";
2644 } else if (strcmp(argv[1], "SM") == 0) {
2645 entry.MemoryType = 0x03;
2646 memory_type_string = "SM";
2648 fprintf(stderr, _("Unknown memory type %s!\n"), argv[1]);
2652 entry.Number = atoi(argv[0]);
2653 entry.Location = atoi(argv[2]);
2655 if (GSM->SetSpeedDial(&entry) == GE_NONE) {
2656 fprintf(stdout, _("Succesfully written!\n"));
2663 /* Getting the status of the display. */
2664 int getdisplaystatus(void)
2668 GSM->GetDisplayStatus(&Status);
2670 fprintf(stdout, _("Call in progress: %s\n"), Status & (1<<DS_Call_In_Progress)?_("on"):_("off"));
2671 fprintf(stdout, _("Unknown: %s\n"), Status & (1<<DS_Unknown)?_("on"):_("off"));
2672 fprintf(stdout, _("Unread SMS: %s\n"), Status & (1<<DS_Unread_SMS)?_("on"):_("off"));
2673 fprintf(stdout, _("Voice call: %s\n"), Status & (1<<DS_Voice_Call)?_("on"):_("off"));
2674 fprintf(stdout, _("Fax call active: %s\n"), Status & (1<<DS_Fax_Call)?_("on"):_("off"));
2675 fprintf(stdout, _("Data call active: %s\n"), Status & (1<<DS_Data_Call)?_("on"):_("off"));
2676 fprintf(stdout, _("Keyboard lock: %s\n"), Status & (1<<DS_Keyboard_Lock)?_("on"):_("off"));
2677 fprintf(stdout, _("SMS storage full: %s\n"), Status & (1<<DS_SMS_Storage_Full)?_("on"):_("off"));
2683 int netmonitor(char *Mode)
2685 unsigned char mode = atoi(Mode);
2688 if (!strcmp(Mode, "reset"))
2690 else if (!strcmp(Mode, "off"))
2692 else if (!strcmp(Mode, "field"))
2694 else if (!strcmp(Mode, "devel"))
2696 else if (!strcmp(Mode, "next"))
2699 memset(&Screen, 0, 50);
2700 GSM->NetMonitor(mode, Screen);
2703 fprintf(stdout, "%s\n", Screen);
2711 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2712 char imei[64], model[64], rev[64], manufacturer[64];
2713 GSM_Statemachine *sm = &State;
2715 data.Manufacturer=manufacturer;
2720 /* Retrying is bad idea: what if function is simply not implemented?
2721 Anyway let's wait 2 seconds for the right packet from the phone. */
2724 strcpy(imei, "(unknown)");
2725 strcpy(manufacturer, "(unknown)");
2726 strcpy(model, "(unknown)");
2727 strcpy(rev, "(unknown)");
2729 SM_Functions(GOP_Identify, &data, sm);
2731 fprintf(stdout, _("IMEI: %s\n"), imei);
2732 fprintf(stdout, _("Manufacturer: %s\n"), manufacturer);
2733 fprintf(stdout, _("Model: %s\n"), model);
2734 fprintf(stdout, _("Revision: %s\n"), rev);
2741 int senddtmf(char *String)
2743 GSM->SendDTMF(String);
2748 /* Resets the phone */
2749 int reset( char *type)
2751 unsigned char _type = 0x03;
2754 if(!strcmp(type, "soft"))
2757 if(!strcmp(type, "hard"))
2760 fprintf(stderr, _("What kind of reset do you want??\n"));
2771 /* pmon allows fbus code to run in a passive state - it doesn't worry about
2772 whether comms are established with the phone. A debugging/development
2778 GSM_ConnectionType connection=GCT_Serial;
2779 GSM_Statemachine sm;
2781 /* Initialise the code for the GSM interface. */
2782 error = GSM_Initialise(model, Port, Initlength, connection, NULL, &sm);
2784 if (error != GE_NONE) {
2785 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
2796 int sendringtone(int argc, char *argv[])
2798 GSM_Ringtone ringtone;
2801 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2802 fprintf(stdout, _("Failed to load ringtone.\n"));
2806 error = GSM->SendRingtone(&ringtone,argv[1]);
2808 if (error == GE_NONE)
2809 fprintf(stdout, _("Send succeeded!\n"));
2811 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
2819 int setringtone(int argc, char *argv[])
2821 GSM_Ringtone ringtone;
2824 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2825 fprintf(stdout, _("Failed to load ringtone.\n"));
2829 error = GSM->SetRingtone(&ringtone);
2831 if (error == GE_NONE)
2832 fprintf(stdout, _("Send succeeded!\n"));
2834 fprintf(stdout, _("Send failed\n"));
2841 int presskeysequence(void)
2847 memset(&buf[0], 0, 102);
2848 while (read(0, buf, 100) > 0) {
2849 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
2850 if (GSM->HandleString(buf) != GE_NONE)
2851 fprintf(stdout, _("Key press simulation failed.\n"));
2852 memset(buf, 0, 102);
2859 /* This is a "convenience" function to allow quick test of new API stuff which
2860 doesn't warrant a "proper" command line function. */
2862 int foogle(char *argv[])
2864 /* Initialise the code for the GSM interface. */
2866 // Fill in what you would like to test here...