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"
203 " gnokii --divert {--op|-o} {register|enable|query|disable|erasure}\n"
204 " {--type|-t} {all|busy|noans|outofreach|notavail}\n"
205 " {--call|-c} {all|voice|fax|data}\n"
206 " [{--timeout|-m} time_in_seconds]\n"
207 " [{--number|-n} number]\n"
211 " gnokii --entersecuritycode PIN|PIN2|PUK|PUK2\n"
212 " gnokii --getsecuritycodestatus\n"
218 /* fbusinit is the generic function which waits for the FBUS link. The limit
219 is 10 seconds. After 10 seconds we quit. */
221 static GSM_Statemachine State;
222 static GSM_Data data;
224 void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame))
228 GSM_ConnectionType connection = GCT_Serial;
230 GSM_DataClear(&data);
232 if (!strcasecmp(Connection, "dau9p")) connection = GCT_DAU9P; /* Use only with 6210/7110 for faster connection with such cable */
233 if (!strcasecmp(Connection, "infrared")) connection = GCT_Infrared;
234 if (!strcasecmp(Connection, "irda")) connection = GCT_Irda;
236 /* Initialise the code for the GSM interface. */
238 error = GSM_Initialise(model, Port, Initlength, connection, rlp_handler, &State);
240 if (error != GE_NONE) {
241 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
245 /* First (and important!) wait for GSM link to be active. We allow 10
248 while (count++ < 200 && *GSM_LinkOK == false)
251 if (*GSM_LinkOK == false) {
252 fprintf (stderr, _("Hmmm... GSM_LinkOK never went true. Quitting.\n"));
257 /* This function checks that the argument count for a given options is withing
259 int checkargs(int opt, struct gnokii_arg_len gals[], int argc)
263 /* Walk through the whole array with options requiring arguments. */
264 for (i = 0; !(gals[i].gal_min == 0 && gals[i].gal_max == 0); i++) {
266 /* Current option. */
267 if (gals[i].gal_opt == opt) {
269 /* Argument count checking. */
270 if (gals[i].gal_flags == GAL_XOR) {
271 if (gals[i].gal_min == argc || gals[i].gal_max == argc)
274 if (gals[i].gal_min <= argc && gals[i].gal_max >= argc)
282 /* We do not have options without arguments in the array, so check them. */
283 if (argc == 0) return 0;
287 /* Main function - handles command line arguments, passes them to separate
288 functions accordingly. */
289 int main(int argc, char *argv[])
295 /* Every option should be in this array. */
296 static struct option long_options[] =
298 /* FIXME: these comments are nice, but they would be more usefull as docs for the user */
300 { "help", no_argument, NULL, OPT_HELP },
302 /* Display version and build information. */
303 { "version", no_argument, NULL, OPT_VERSION },
306 { "monitor", no_argument, NULL, OPT_MONITOR },
310 /* Enter Security Code mode */
311 { "entersecuritycode", required_argument, NULL, OPT_ENTERSECURITYCODE },
313 // Get Security Code status
314 { "getsecuritycodestatus", no_argument, NULL, OPT_GETSECURITYCODESTATUS },
319 { "setdatetime", optional_argument, NULL, OPT_SETDATETIME },
321 // Get date and time mode
322 { "getdatetime", no_argument, NULL, OPT_GETDATETIME },
325 { "setalarm", required_argument, NULL, OPT_SETALARM },
328 { "getalarm", no_argument, NULL, OPT_GETALARM },
331 { "dialvoice", required_argument, NULL, OPT_DIALVOICE },
333 // Get calendar note mode
334 { "getcalendarnote", required_argument, NULL, OPT_GETCALENDARNOTE },
336 // Write calendar note mode
337 { "writecalendarnote", required_argument, NULL, OPT_WRITECALENDARNOTE },
339 // Delete calendar note mode
340 { "deletecalendarnote", required_argument, NULL, OPT_DELCALENDARNOTE },
342 // Get display status mode
343 { "getdisplaystatus", no_argument, NULL, OPT_GETDISPLAYSTATUS },
346 { "getmemory", required_argument, NULL, OPT_GETMEMORY },
348 // Write phonebook (memory) mode
349 { "writephonebook", optional_argument, NULL, OPT_WRITEPHONEBOOK },
351 // Get speed dial mode
352 { "getspeeddial", required_argument, NULL, OPT_GETSPEEDDIAL },
354 // Set speed dial mode
355 { "setspeeddial", required_argument, NULL, OPT_SETSPEEDDIAL },
357 // Get SMS message mode
358 { "getsms", required_argument, NULL, OPT_GETSMS },
360 // Delete SMS message mode
361 { "deletesms", required_argument, NULL, OPT_DELETESMS },
363 // Send SMS message mode
364 { "sendsms", required_argument, NULL, OPT_SENDSMS },
366 // Ssve SMS message mode
367 { "savesms", optional_argument, NULL, OPT_SAVESMS },
369 // Send logo as SMS message mode
370 { "sendlogo", required_argument, NULL, OPT_SENDLOGO },
372 // Send ringtone as SMS message
373 { "sendringtone", required_argument, NULL, OPT_SENDRINGTONE },
376 { "setringtone", required_argument, NULL, OPT_SETRINGTONE },
378 // Get SMS center number mode
379 { "getsmsc", required_argument, NULL, OPT_GETSMSC },
381 // For development purposes: run in passive monitoring mode
382 { "pmon", no_argument, NULL, OPT_PMON },
385 { "netmonitor", required_argument, NULL, OPT_NETMONITOR },
388 { "identify", no_argument, NULL, OPT_IDENTIFY },
390 // Send DTMF sequence
391 { "senddtmf", required_argument, NULL, OPT_SENDDTMF },
394 { "reset", optional_argument, NULL, OPT_RESET },
397 { "setlogo", optional_argument, NULL, OPT_SETLOGO },
400 { "getlogo", required_argument, NULL, OPT_GETLOGO },
403 { "viewlogo", required_argument, NULL, OPT_VIEWLOGO },
406 { "getprofile", optional_argument, NULL, OPT_GETPROFILE },
408 // Show texts from phone's display
409 { "displayoutput", no_argument, NULL, OPT_DISPLAYOUTPUT },
411 // Simulate pressing the keys
412 { "keysequence", no_argument, NULL, OPT_KEYPRESS },
415 { "divert", required_argument, NULL, OPT_DIVERT },
417 // For development purposes: insert you function calls here
418 { "foogle", no_argument, NULL, OPT_FOOGLE },
423 /* Every command which requires arguments should have an appropriate entry
425 struct gnokii_arg_len gals[] =
429 { OPT_ENTERSECURITYCODE, 1, 1, 0 },
432 { OPT_SETDATETIME, 0, 5, 0 },
433 { OPT_SETALARM, 2, 2, 0 },
434 { OPT_DIALVOICE, 1, 1, 0 },
435 { OPT_GETCALENDARNOTE, 1, 3, 0 },
436 { OPT_WRITECALENDARNOTE, 2, 2, 0 },
437 { OPT_DELCALENDARNOTE, 1, 2, 0 },
438 { OPT_GETMEMORY, 2, 3, 0 },
439 { OPT_GETSPEEDDIAL, 1, 1, 0 },
440 { OPT_SETSPEEDDIAL, 3, 3, 0 },
441 { OPT_GETSMS, 2, 5, 0 },
442 { OPT_DELETESMS, 2, 3, 0 },
443 { OPT_SENDSMS, 1, 10, 0 },
444 { OPT_SAVESMS, 0, 6, 0 },
445 { OPT_SENDLOGO, 3, 4, GAL_XOR },
446 { OPT_SENDRINGTONE, 2, 2, 0 },
447 { OPT_GETSMSC, 1, 1, 0 },
448 { OPT_GETWELCOMENOTE, 1, 1, 0 },
449 { OPT_SETWELCOMENOTE, 1, 1, 0 },
450 { OPT_NETMONITOR, 1, 1, 0 },
451 { OPT_SENDDTMF, 1, 1, 0 },
452 { OPT_SETLOGO, 1, 4, 0 },
453 { OPT_GETLOGO, 1, 4, 0 },
454 { OPT_VIEWLOGO, 1, 1, 0 },
455 { OPT_SETRINGTONE, 1, 1, 0 },
456 { OPT_RESET, 0, 1, 0 },
457 { OPT_GETPROFILE, 0, 1, 0 },
458 { OPT_WRITEPHONEBOOK, 0, 1, 0 },
459 { OPT_DIVERT, 6, 10, 0 },
466 /* For GNU gettext */
468 textdomain("gnokii");
469 setlocale(LC_ALL, "");
472 /* Read config file */
473 if (readconfig(&model, &Port, &Initlength, &Connection, &BinDir) < 0) {
477 /* Introduce yourself */
480 /* Handle command line arguments. */
481 c = getopt_long(argc, argv, "", long_options, NULL);
482 if (c == -1) /* No argument given - we should display usage. */
486 /* First, error conditions */
489 fprintf(stderr, _("Use '%s --help' for usage informations.\n"), argv[0]);
491 /* Then, options with no arguments */
499 /* We have to build an array of the arguments which will be passed to the
500 functions. Please note that every text after the --command will be
501 passed as arguments. A syntax like gnokii --cmd1 args --cmd2 args will
502 not work as expected; instead args --cmd2 args is passed as a
504 if ((nargv = malloc(sizeof(char *) * argc)) != NULL) {
505 for (i = 2; i < argc; i++)
506 nargv[i-2] = argv[i];
508 if (checkargs(c, gals, nargc)) {
509 free(nargv); /* Wrong number of arguments - we should display usage. */
514 /* have to ignore SIGALARM */
518 /* Initialise the code for the GSM interface. */
526 case OPT_ENTERSECURITYCODE:
527 rc = entersecuritycode(optarg);
529 case OPT_GETSECURITYCODESTATUS:
530 rc = getsecuritycodestatus();
533 case OPT_GETDATETIME:
539 case OPT_GETDISPLAYSTATUS:
540 rc = getdisplaystatus();
545 case OPT_WRITEPHONEBOOK:
546 rc = writephonebook(nargc, nargv);
548 /* Now, options with arguments */
549 case OPT_SETDATETIME:
550 rc = setdatetime(nargc, nargv);
553 rc = setalarm(nargv);
556 rc = dialvoice(optarg);
558 case OPT_GETCALENDARNOTE:
559 rc = getcalendarnote(nargc, nargv);
561 case OPT_DELCALENDARNOTE:
562 rc = deletecalendarnote(nargc, nargv);
564 case OPT_WRITECALENDARNOTE:
565 rc = writecalendarnote(nargv);
568 rc = getmemory(nargc, nargv);
570 case OPT_GETSPEEDDIAL:
571 rc = getspeeddial(optarg);
573 case OPT_SETSPEEDDIAL:
574 rc = setspeeddial(nargv);
577 rc = getsms(argc, argv);
580 rc = deletesms(nargc, nargv);
583 rc = sendsms(nargc, nargv);
586 rc = savesms(argc, argv);
589 rc = sendlogo(nargc, nargv);
592 rc = getsmsc(optarg);
595 rc = netmonitor(optarg);
601 rc = setlogo(nargc, nargv);
604 rc = getlogo(nargc, nargv);
607 rc = viewlogo(optarg);
609 case OPT_SETRINGTONE:
610 rc = setringtone(nargc, nargv);
612 case OPT_SENDRINGTONE:
613 rc = sendringtone(nargc, nargv);
616 rc = getprofile(nargc, nargv);
618 case OPT_DISPLAYOUTPUT:
619 rc = displayoutput();
622 rc = presskeysequence();
625 rc = senddtmf(optarg);
631 rc = divert(argc, argv);
639 fprintf(stderr, _("Unknown option: %d\n"), c);
646 fprintf(stderr, _("Wrong number of arguments\n"));
650 /* Send SMS messages. */
651 int sendsms(int argc, char *argv[])
655 // char UDH[GSM_MAX_USER_DATA_HEADER_LENGTH];
656 /* The maximum length of an uncompressed concatenated short message is
657 255 * 153 = 39015 default alphabet characters */
658 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
659 int input_len, chars_read;
660 int i; /*, offset, nr_msg, aux;*/
662 struct option options[] = {
663 { "smsc", required_argument, NULL, '1'},
664 { "smscno", required_argument, NULL, '2'},
665 { "long", required_argument, NULL, '3'},
669 input_len = GSM_MAX_SMS_LENGTH;
677 - message validity for 3 days
678 - unset user data header indicator
681 memset(&SMS, 0, sizeof(GSM_SMSMessage));
683 SMS.Type = SMS_Submit;
684 SMS.DCS.Type = SMS_GeneralDataCoding;
685 SMS.DCS.u.General.Compressed = false;
686 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
687 SMS.DCS.u.General.Class = 0;
688 SMS.MessageCenter.No = 1;
689 SMS.Validity.VPF = SMS_RelativeFormat;
690 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
694 strcpy(SMS.RemoteNumber.number, argv[0]);
695 if (SMS.RemoteNumber.number[0] == '+') SMS.RemoteNumber.type = SMS_International;
696 else SMS.RemoteNumber.type = SMS_Unknown;
701 while ((i = getopt_long(argc, argv, "r8cC:v:", options, NULL)) != -1) {
702 switch (i) { // -8 is for 8-bit data, -c for compression. both are not yet implemented.
703 case '1': /* SMSC number */
704 SMS.MessageCenter.No = 0;
705 strcpy(SMS.MessageCenter.Number, optarg);
706 if (SMS.MessageCenter.Number[0] == '+') SMS.MessageCenter.Type = SMS_International;
707 else SMS.MessageCenter.Type = SMS_Unknown;
709 case '2': /* SMSC number index in phone memory */
710 SMS.MessageCenter.No = atoi(optarg);
712 if (SMS.MessageCenter.No < 1 || SMS.MessageCenter.No > 5)
714 data.MessageCenter = &SMS.MessageCenter;
715 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
717 case '3': /* we send long message */
718 input_len = atoi(optarg);
719 if (input_len > 255 * GSM_MAX_SMS_LENGTH) {
720 fprintf(stderr, _("Input too long!\n"));
724 case 'r': /* request for delivery report */
727 case 'C': /* class Message */
730 SMS.DCS.u.General.Class = 1;
733 SMS.DCS.u.General.Class = 2;
736 SMS.DCS.u.General.Class = 3;
739 SMS.DCS.u.General.Class = 4;
746 SMS.Validity.u.Relative = atoi(optarg);
749 usage(); /* Would be better to have an sendsms_usage() here. */
753 /* Get message text from stdin. */
754 chars_read = fread(message_buffer, 1, input_len, stdin);
756 if (chars_read == 0) {
757 fprintf(stderr, _("Couldn't read from stdin!\n"));
759 } else if (chars_read > input_len) {
760 fprintf(stderr, _("Input too long!\n"));
764 /* Null terminate. */
765 message_buffer[chars_read] = 0x00;
766 strncpy(SMS.MessageText, message_buffer, chars_read);
767 data.SMSMessage = &SMS;
769 /* Send the message. */
770 error = SM_Functions(GOP_SendSMS, &data, &State);
772 if (error == GE_SMSSENDOK) {
773 fprintf(stdout, _("Send succeeded!\n"));
775 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
778 if (GSM && GSM->Terminate) GSM->Terminate();
783 int savesms(int argc, char *argv[])
787 /* The maximum length of an uncompressed concatenated short message is
788 255 * 153 = 39015 default alphabet characters */
789 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
790 int input_len, chars_read;
796 SMS.Type = SMS_Deliver;
797 SMS.DCS.Type = SMS_GeneralDataCoding;
798 SMS.DCS.u.General.Compressed = false;
799 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
800 SMS.DCS.u.General.Class = 0;
801 SMS.MessageCenter.No = 1;
802 SMS.Validity.VPF = SMS_RelativeFormat;
803 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
805 SMS.Status = SMS_Unsent;
808 input_len = GSM_MAX_SMS_LENGTH;
811 while ((i = getopt(argc, argv, "ml:in:s:c:")) != -1) {
813 case 'm': /* mark the message as sent */
814 SMS.Status = SMS_Sent;
816 case 'l': /* Specify the location */
817 SMS.Number = atoi(optarg);
819 case 'i': /* Ask before overwriting */
822 case 'n': /* Specify the from number */
824 case 's': /* Specify the smsc number */
826 case 'c': /* Specify the smsc location */
837 aux.Number = SMS.Number;
838 data.SMSMessage = &aux;
839 error = SM_Functions(GOP_GetSMS, &data, &State);
842 fprintf(stderr, _("Message at specified location exists. "));
843 while (confirm < 0) {
844 fprintf(stderr, _("Overwrite? (yes/no) "));
845 GetLine(stdin, ans, 7);
846 if (!strcmp(ans, _("yes"))) confirm = 1;
847 else if (!strcmp(ans, _("no"))) confirm = 0;
850 if (GSM && GSM->Terminate) GSM->Terminate();
854 case GE_INVALIDSMSLOCATION:
855 fprintf(stderr, _("Invalid location\n"));
856 if (GSM && GSM->Terminate) GSM->Terminate();
859 dprintf("Location %d empty. Saving\n", SMS.Number);
863 chars_read = fread(message_buffer, 1, input_len, stdin);
865 if (chars_read == 0) {
867 fprintf(stderr, _("Couldn't read from stdin!\n"));
870 } else if (chars_read > input_len) {
872 fprintf(stderr, _("Input too long!\n"));
877 strncpy (SMS.MessageText, message_buffer, chars_read);
878 SMS.MessageText[chars_read] = 0;
880 error = GSM->SaveSMSMessage(&SMS);
882 if (error == GE_NONE) {
883 fprintf(stdout, _("Saved!\n"));
885 fprintf(stdout, _("Saving failed (error=%d)\n"), error);
888 if (GSM && GSM->Terminate) GSM->Terminate();
893 /* Get SMSC number */
894 int getsmsc(char *MessageCenterNumber)
896 SMS_MessageCenter MessageCenter;
900 memset(&MessageCenter, 0, sizeof(MessageCenter));
901 MessageCenter.No = atoi(MessageCenterNumber);
903 if (GSM && GSM->GetSMSCenter && GSM->Terminate) {
904 error = GSM->GetSMSCenter(&MessageCenter);
907 GSM_DataClear(&data);
908 data.MessageCenter = &MessageCenter;
909 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
914 fprintf(stdout, _("%d. SMS center (%s) number is %s\n"), MessageCenter.No, MessageCenter.Name, MessageCenter.Number);
915 fprintf(stdout, _("Default recipient number is %s\n"), MessageCenter.Recipient);
916 fprintf(stdout, _("Messages sent as "));
918 switch (MessageCenter.Format) {
920 fprintf(stdout, _("Text"));
923 fprintf(stdout, _("VoiceMail"));
926 fprintf(stdout, _("Fax"));
930 fprintf(stdout, _("Email"));
933 fprintf(stdout, _("ERMES"));
936 fprintf(stdout, _("X.400"));
939 fprintf(stdout, _("Unknown"));
944 fprintf(stdout, _("Message validity is "));
946 switch (MessageCenter.Validity) {
948 fprintf(stdout, _("1 hour"));
951 fprintf(stdout, _("6 hours"));
954 fprintf(stdout, _("24 hours"));
957 fprintf(stdout, _("72 hours"));
960 fprintf(stdout, _("1 week"));
963 fprintf(stdout, _("Maximum time"));
966 fprintf(stdout, _("Unknown"));
970 fprintf(stdout, "\n");
973 case GE_NOTIMPLEMENTED:
974 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
977 fprintf(stdout, _("SMS center can not be found :-(\n"));
984 /* Get SMS messages. */
985 int getsms(int argc, char *argv[])
989 SMS_FolderList folderlist;
990 GSM_SMSMessage message;
991 char *memory_type_string;
992 int start_message, end_message, count, mode = 1;
999 /* Handle command line args that set type, start and end locations. */
1000 memory_type_string = argv[2];
1001 message.MemoryType = StrToMemoryType(memory_type_string);
1002 if (message.MemoryType == GMT_XX) {
1003 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[2]);
1007 memset(&filename, 0, 64);
1009 start_message = end_message = atoi(argv[3]);
1013 /* [end] can be only argv[4] */
1014 if (argv[4][0] != '-') {
1015 end_message = atoi(argv[4]);
1018 /* parse all options (beginning with '-' */
1019 while ((i = getopt(argc, argv, "f:F:d")) != -1) {
1028 fprintf(stderr, _("Saving into %s\n"), optarg);
1029 strncpy(filename, optarg, 64);
1030 if (strlen(optarg) > 63) {
1031 fprintf(stderr, _("Filename too long - will be truncated to 63 characters.\n"));
1034 filename[strlen(optarg)] = 0;
1043 data.SMSFolderList = &folderlist;
1044 folder.FolderID = 0;
1045 data.SMSFolder = &folder;
1046 /* Now retrieve the requested entries. */
1047 for (count = start_message; count <= end_message; count ++) {
1050 message.Number = count;
1051 data.SMSMessage = &message;
1052 dprintf("MemoryType (gnokii.c) : %i\n", data.SMSMessage->MemoryType);
1053 error = SM_Functions(GOP_GetSMS, &data, &State);
1057 switch (message.Type) {
1059 fprintf(stdout, _("%d. MO Message "), message.Number);
1061 fprintf(stdout, _("(sent)\n"));
1062 fprintf(stdout, _("%d. MO Message "), message.Number);
1064 fprintf(stdout, _("(not sent)\n"));
1065 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1067 case SMS_Delivery_Report:
1068 fprintf(stdout, _("%d. Delivery Report "), message.Number);
1070 fprintf(stdout, _("(read)\n"));
1072 fprintf(stdout, _("(not read)\n"));
1073 fprintf(stdout, _("Sending date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1074 message.Time.Day, message.Time.Month, message.Time.Year, \
1075 message.Time.Hour, message.Time.Minute, message.Time.Second);
1076 if (message.Time.Timezone) {
1077 if (message.Time.Timezone > 0)
1078 fprintf(stdout,_("+%02d00"), message.Time.Timezone);
1080 fprintf(stdout,_("%02d00"), message.Time.Timezone);
1082 fprintf(stdout, "\n");
1083 fprintf(stdout, _("Response date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1084 message.SMSCTime.Day, message.SMSCTime.Month, message.SMSCTime.Year, \
1085 message.SMSCTime.Hour, message.SMSCTime.Minute, message.SMSCTime.Second);
1086 if (message.SMSCTime.Timezone) {
1087 if (message.SMSCTime.Timezone > 0)
1088 fprintf(stdout,_("+%02d00"),message.SMSCTime.Timezone);
1090 fprintf(stdout,_("%02d00"),message.SMSCTime.Timezone);
1092 fprintf(stdout, "\n");
1093 fprintf(stdout, _("Receiver: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1094 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1097 fprintf(stdout, _("%d. Inbox Message "), message.Number);
1099 fprintf(stdout, _("(read)\n"));
1101 fprintf(stdout, _("(not read)\n"));
1102 fprintf(stdout, _("Date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1103 message.Time.Day, message.Time.Month, message.Time.Year, \
1104 message.Time.Hour, message.Time.Minute, message.Time.Second);
1105 if (message.Time.Timezone) {
1106 if (message.Time.Timezone > 0)
1107 fprintf(stdout,_("+%02d00"),message.Time.Timezone);
1109 fprintf(stdout,_("%02d00"),message.Time.Timezone);
1111 fprintf(stdout, "\n");
1112 fprintf(stdout, _("Sender: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1113 switch (message.UDH[0].Type) {
1115 fprintf(stdout, _("GSM operator logo for %s (%s) network.\n"), bitmap.netcode, GSM_GetNetworkName(bitmap.netcode));
1116 if (!strcmp(message.RemoteNumber.number, "+998000005") && !strcmp(message.MessageCenter.Number, "+886935074443")) fprintf(stdout, _("Saved by Logo Express\n"));
1117 if (!strcmp(message.RemoteNumber.number, "+998000002") || !strcmp(message.RemoteNumber.number, "+998000003")) fprintf(stdout, _("Saved by Operator Logo Uploader by Thomas Kessler\n"));
1119 case SMS_CallerIDLogo:
1120 fprintf(stdout, ("Logo:\n"));
1121 /* put bitmap into bitmap structure */
1122 GSM_ReadSMSBitmap(message.UDH[0].Type, message.MessageText+2+offset, message.MessageText, &bitmap);
1123 GSM_PrintBitmap(&bitmap);
1126 if ((stat(filename, &buf) == 0)) {
1127 fprintf(stdout, _("File %s exists.\n"), filename);
1128 fprintf(stdout, _("Overwrite? (yes/no) "));
1129 GetLine(stdin, ans, 4);
1130 if (!strcmp(ans, _("yes"))) {
1131 error = GSM_SaveBitmapFile(filename, &bitmap);
1133 } else error = GSM_SaveBitmapFile(filename, &bitmap);
1134 if (error != GE_NONE) fprintf(stderr, _("Couldn't save logofile %s!\n"), filename);
1138 fprintf(stdout, _("Ringtone\n"));
1140 case SMS_ConcatenatedMessages:
1141 fprintf(stdout, _("Linked (%d/%d):\n"),
1142 message.UDH[0].u.ConcatenatedShortMessage.CurrentNumber,
1143 message.UDH[0].u.ConcatenatedShortMessage.MaximumNumber);
1145 fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText);
1146 if ((mode != -1) && *filename) {
1148 sprintf(buf, "%s%d", filename, count);
1149 mode = GSM_SaveTextFile(buf, message.MessageText, mode);
1152 case SMS_BusinessCard:
1153 fprintf(stdout, _("Business Card:\n%s"), message.MessageText);
1156 fprintf(stderr, _("Unknown\n"));
1162 data.SMSMessage = &message;
1163 if (GE_NONE != SM_Functions(GOP_DeleteSMS, &data, &State))
1164 fprintf(stdout, _("(delete failed)\n"));
1166 fprintf(stdout, _("(message deleted)\n"));
1169 case GE_NOTIMPLEMENTED:
1170 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1171 if (GSM && GSM->Terminate) GSM->Terminate();
1173 case GE_INVALIDSMSLOCATION:
1174 fprintf(stderr, _("Invalid location: %s %d\n"), memory_type_string, count);
1176 case GE_EMPTYSMSLOCATION:
1177 fprintf(stderr, _("SMS location %s %d empty.\n"), memory_type_string, count);
1180 fprintf(stdout, _("GetSMS %s %d failed!(%s)\n\n"), memory_type_string, count, print_error(error));
1185 if (GSM && GSM->Terminate) GSM->Terminate();
1190 /* Delete SMS messages. */
1191 int deletesms(int argc, char *argv[])
1193 GSM_SMSMessage message;
1194 char *memory_type_string;
1195 int start_message, end_message, count;
1198 /* Handle command line args that set type, start and end locations. */
1199 memory_type_string = argv[0];
1200 message.MemoryType = StrToMemoryType(memory_type_string);
1201 if (message.MemoryType == GMT_XX) {
1202 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
1206 start_message = end_message = atoi (argv[1]);
1207 if (argc > 2) end_message = atoi (argv[2]);
1209 /* Now delete the requested entries. */
1210 for (count = start_message; count <= end_message; count ++) {
1212 message.Number = count;
1213 data.SMSMessage = &message;
1214 error = SM_Functions(GOP_DeleteSMS, &data, &State);
1216 if (error == GE_NONE)
1217 fprintf(stdout, _("Deleted SMS %s %d\n"), memory_type_string, count);
1219 if (error == GE_NOTIMPLEMENTED) {
1220 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1221 if (GSM && GSM->Terminate) GSM->Terminate();
1224 fprintf(stdout, _("DeleteSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
1228 if (GSM && GSM->Terminate) GSM->Terminate();
1233 static volatile bool bshutdown = false;
1235 /* SIGINT signal handler. */
1236 static void interrupted(int sig)
1238 signal(sig, SIG_IGN);
1244 /* In this mode we get the code from the keyboard and send it to the mobile
1246 int entersecuritycode(char *type)
1249 GSM_SecurityCode SecurityCode;
1251 if (!strcmp(type, "PIN"))
1252 SecurityCode.Type = GSCT_Pin;
1253 else if (!strcmp(type, "PUK"))
1254 SecurityCode.Type = GSCT_Puk;
1255 else if (!strcmp(type, "PIN2"))
1256 SecurityCode.Type = GSCT_Pin2;
1257 else if (!strcmp(type, "PUK2"))
1258 SecurityCode.Type = GSCT_Puk2;
1259 /* FIXME: Entering of SecurityCode does not work :-(
1260 else if (!strcmp(type, "SecurityCode"))
1261 SecurityCode.Type = GSCT_SecurityCode;
1267 printf("Enter your code: ");
1268 gets(SecurityCode.Code);
1270 strcpy(SecurityCode.Code, getpass(_("Enter your code: ")));
1273 if (GSM && GSM->EnterSecurityCode) test = GSM->EnterSecurityCode(SecurityCode);
1274 if (test == GE_INVALIDSECURITYCODE)
1275 fprintf(stdout, _("Error: invalid code.\n"));
1276 else if (test == GE_NONE)
1277 fprintf(stdout, _("Code ok.\n"));
1278 else if (test == GE_NOTIMPLEMENTED)
1279 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1281 fprintf(stdout, _("Other error.\n"));
1283 if (GSM && GSM->Terminate) GSM->Terminate();
1288 int getsecuritycodestatus(void)
1292 if (GSM && GSM->GetSecurityCodeStatus && GSM->GetSecurityCodeStatus(&Status) == GE_NONE) {
1294 fprintf(stdout, _("Security code status: "));
1297 case GSCT_SecurityCode:
1298 fprintf(stdout, _("waiting for Security Code.\n"));
1301 fprintf(stdout, _("waiting for PIN.\n"));
1304 fprintf(stdout, _("waiting for PIN2.\n"));
1307 fprintf(stdout, _("waiting for PUK.\n"));
1310 fprintf(stdout, _("waiting for PUK2.\n"));
1313 fprintf(stdout, _("nothing to enter.\n"));
1316 fprintf(stdout, _("Unknown!\n"));
1321 if (GSM && GSM->Terminate) GSM->Terminate();
1329 /* Voice dialing mode. */
1330 int dialvoice(char *Number)
1332 if (GSM && GSM->DialVoice) GSM->DialVoice(Number);
1334 if (GSM && GSM->Terminate) GSM->Terminate();
1339 /* The following function allows to send logos using SMS */
1340 int sendlogo(int argc, char *argv[])
1346 char UserDataHeader[7] = { 0x06, /* UDH Length */
1347 0x05, /* IEI: application port addressing scheme, 16 bit address */
1348 0x04, /* IEI length */
1349 0x15, /* destination address: high byte */
1350 0x00, /* destination address: low byte */
1351 0x00, /* originator address */
1354 char Data[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1358 /* Default settings for SMS message:
1359 - no delivery report
1365 - set UserDataHeaderIndicator
1367 SMS.Type = SMS_Submit;
1368 SMS.DCS.Type = SMS_GeneralDataCoding;
1369 SMS.DCS.u.General.Compressed = false;
1370 SMS.DCS.u.General.Alphabet = SMS_8bit;
1371 SMS.DCS.u.General.Class = 2;
1372 SMS.MessageCenter.No = 1;
1373 SMS.Validity.VPF = SMS_RelativeFormat;
1374 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
1376 /* The first argument is the type of the logo. */
1377 if (!strcmp(argv[0], "op")) {
1378 SMS.UDH[0].Type = SMS_OpLogo;
1379 UserDataHeader[4] = 0x82; /* NBS port 0x1582 */
1380 fprintf(stdout, _("Sending operator logo.\n"));
1381 } else if (!strcmp(argv[0], "caller")) {
1382 SMS.UDH[0].Type = SMS_CallerIDLogo;
1383 UserDataHeader[4] = 0x83; /* NBS port 0x1583 */
1384 fprintf(stdout, _("Sending caller line identification logo.\n"));
1386 fprintf(stderr, _("You should specify what kind of logo to send!\n"));
1390 /* The second argument is the destination, ie the phone number of recipient. */
1391 SMS.MemoryType = atoi(argv[1]);
1393 /* The third argument is the bitmap file. */
1394 GSM_ReadBitmapFile(argv[2], &bitmap);
1396 /* If we are sending op logo we can rewrite network code. */
1397 if (!strcmp(argv[0], "op")) {
1399 * The fourth argument, if present, is the Network code of the operator.
1400 * Network code is in this format: "xxx yy".
1403 strcpy(bitmap.netcode, argv[3]);
1405 fprintf(stdout, _("Operator code: %s\n"), argv[3]);
1409 /* Set the network code */
1410 Data[current++] = ((bitmap.netcode[1] & 0x0f) << 4) | (bitmap.netcode[0] & 0xf);
1411 Data[current++] = 0xf0 | (bitmap.netcode[2] & 0x0f);
1412 Data[current++] = ((bitmap.netcode[5] & 0x0f) << 4) | (bitmap.netcode[4] & 0xf);
1415 /* Set the logo size */
1417 Data[current++] = bitmap.width;
1418 Data[current++] = bitmap.height;
1420 Data[current++] = 0x01;
1422 memcpy(SMS.MessageText, UserDataHeader, 7);
1423 memcpy(SMS.MessageText, Data, current);
1424 memcpy(SMS.MessageText+current, bitmap.bitmap, bitmap.size);
1426 /* Send the message. */
1427 error = GSM->SendSMSMessage(&SMS,current+bitmap.size);
1429 if (error == GE_SMSSENDOK)
1430 fprintf(stdout, _("Send succeeded!\n"));
1432 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
1438 /* Getting logos. */
1439 GSM_Error SaveBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1446 /* Ask before overwriting */
1447 while (stat(FileName, &buf) == 0) {
1450 fprintf(stderr, _("Saving logo. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "), FileName);
1451 GetLine(stdin, ans, 4);
1452 if (!strcmp(ans, _("O")) || !strcmp(ans, _("o"))) confirm = 1;
1453 if (!strcmp(ans, _("N")) || !strcmp(ans, _("n"))) confirm = 2;
1454 if (!strcmp(ans, _("S")) || !strcmp(ans, _("s"))) return GE_USERCANCELED;
1456 if (confirm == 1) break;
1458 fprintf(stderr, _("Enter name of new file: "));
1459 GetLine(stdin, FileName, 50);
1460 if (!FileName || (*FileName == 0)) return GE_USERCANCELED;
1464 error = GSM_SaveBitmapFile(FileName, bitmap);
1467 case GE_CANTOPENFILE:
1468 fprintf(stderr, _("Failed to write file \"%s\"\n"), FileName);
1477 int getlogo(int argc, char *argv[])
1481 GSM_Statemachine *sm = &State;
1483 bitmap.type=GSM_None;
1485 if (!strcmp(argv[0], "op"))
1486 bitmap.type = GSM_OperatorLogo;
1488 if (!strcmp(argv[0], "caller")) {
1489 /* There is caller group number missing in argument list. */
1491 bitmap.number=argv[2][0]-'0';
1492 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1496 bitmap.type = GSM_CallerLogo;
1499 if (!strcmp(argv[0],"startup"))
1500 bitmap.type = GSM_StartupLogo;
1501 else if (!strcmp(argv[0], "dealer"))
1502 bitmap.type = GSM_DealerNoteText;
1503 else if (!strcmp(argv[0], "text"))
1504 bitmap.type=GSM_WelcomeNoteText;
1506 if (bitmap.type != GSM_None) {
1508 fprintf(stdout, _("Getting Logo\n"));
1510 data.Bitmap=&bitmap;
1511 error=SM_Functions(GOP_GetBitmap, &data, sm);
1515 if (bitmap.type == GSM_DealerNoteText) fprintf(stdout, _("Dealer welcome note "));
1516 if (bitmap.type == GSM_WelcomeNoteText) fprintf(stdout, _("Welcome note "));
1517 if (bitmap.type == GSM_DealerNoteText || bitmap.type==GSM_WelcomeNoteText) {
1518 if (bitmap.text[0]) {
1519 fprintf(stdout, _("currently set to \"%s\"\n"), bitmap.text);
1521 fprintf(stdout, _("currently empty\n"));
1525 switch (bitmap.type) {
1526 case GSM_OperatorLogo:
1527 fprintf(stdout,"Operator logo for %s (%s) network got succesfully\n",bitmap.netcode,GSM_GetNetworkName(bitmap.netcode));
1529 strncpy(bitmap.netcode,argv[2], 7);
1530 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1531 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1536 case GSM_StartupLogo:
1537 fprintf(stdout, "Startup logo got successfully\n");
1539 strncpy(bitmap.netcode,argv[2], 7);
1540 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1541 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1546 case GSM_CallerLogo:
1547 fprintf(stdout,"Caller logo got successfully\n");
1549 strncpy(bitmap.netcode,argv[3],7);
1550 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1551 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1557 fprintf(stdout,"Unknown bitmap type.\n");
1561 if (SaveBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) return (-1);
1564 fprintf(stdout,"Your phone doesn't have logo uploaded !\n");
1569 case GE_NOTIMPLEMENTED:
1570 fprintf(stderr, _("Function not implemented !\n"));
1572 case GE_NOTSUPPORTED:
1573 fprintf(stderr, _("This kind of logo is not supported !\n"));
1576 fprintf(stderr, _("Error getting logo !\n"));
1580 fprintf(stderr, _("What kind of logo do you want to get ?\n"));
1588 /* Sending logos. */
1589 GSM_Error ReadBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1593 error = GSM_ReadBitmapFile(FileName, bitmap);
1596 case GE_CANTOPENFILE:
1597 fprintf(stderr, _("Failed to read file \"%s\"\n"), FileName);
1599 case GE_WRONGNUMBEROFCOLORS:
1600 fprintf(stderr, _("Wrong number of colors in \"%s\" logofile (accepted only 2-colors files) !\n"), FileName);
1602 case GE_WRONGCOLORS:
1603 fprintf(stderr, _("Wrong colors in \"%s\" logofile !\n"), FileName);
1605 case GE_INVALIDFILEFORMAT:
1606 fprintf(stderr, _("Invalid format of \"%s\" logofile !\n"), FileName);
1608 case GE_SUBFORMATNOTSUPPORTED:
1609 fprintf(stderr, _("Sorry, gnokii doesn't support used subformat in file \"%s\" !\n"), FileName);
1611 case GE_FILETOOSHORT:
1612 fprintf(stderr, _("\"%s\" logofile is too short !\n"), FileName);
1614 case GE_INVALIDIMAGESIZE:
1615 fprintf(stderr, _("Bitmap size doesn't supported by fileformat or different from 72x14, 84x48 and 72x28 !\n"));
1625 int setlogo(int argc, char *argv[])
1627 GSM_Bitmap bitmap,oldbit;
1628 GSM_NetworkInfo NetworkInfo;
1634 if (!strcmp(argv[0],"text") || !strcmp(argv[0],"dealer")) {
1635 if (!strcmp(argv[0], "text")) bitmap.type = GSM_WelcomeNoteText;
1636 else bitmap.type = GSM_DealerNoteText;
1637 bitmap.text[0] = 0x00;
1638 if (argc > 1) strncpy(bitmap.text, argv[1], 255);
1640 if (!strcmp(argv[0], "op") || !strcmp(argv[0], "startup") || !strcmp(argv[0], "caller")) {
1642 if (ReadBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) {
1643 if (GSM && GSM->Terminate) GSM->Terminate();
1647 if (!strcmp(argv[0], "op")) {
1648 if (bitmap.type != GSM_OperatorLogo || argc < 3) {
1649 if (GSM && GSM->GetNetworkInfo && GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode, NetworkInfo.NetworkCode, 7);
1651 GSM_ResizeBitmap(&bitmap, GSM_OperatorLogo, GSM_Info);
1653 strncpy(bitmap.netcode, argv[2], 7);
1654 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1655 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1660 if (!strcmp(argv[0], "startup")) {
1661 GSM_ResizeBitmap(&bitmap, GSM_StartupLogo, GSM_Info);
1663 if (!strcmp(argv[0],"caller")) {
1664 GSM_ResizeBitmap(&bitmap, GSM_CallerLogo, GSM_Info);
1666 bitmap.number = argv[2][0] - '0';
1667 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1671 oldbit.type = GSM_CallerLogo;
1672 oldbit.number = bitmap.number;
1673 if (GSM && GSM->GetBitmap && GSM->GetBitmap(&oldbit) == GE_NONE) {
1674 /* We have to get the old name and ringtone!! */
1675 bitmap.ringtone = oldbit.ringtone;
1676 strncpy(bitmap.text, oldbit.text, 255);
1678 if (argc > 3) strncpy(bitmap.text, argv[3], 255);
1680 fprintf(stdout, _("Setting Logo.\n"));
1682 /* FIX ME: is it possible to permanently remove op logo ? */
1683 if (!strcmp(argv[0], "op"))
1685 bitmap.type = GSM_OperatorLogo;
1686 strncpy(bitmap.netcode, "000 00", 7);
1689 bitmap.size = bitmap.width * bitmap.height / 8;
1690 GSM_ClearBitmap(&bitmap);
1692 /* FIX ME: how to remove startup and group logos ? */
1693 fprintf(stdout, _("Removing Logo.\n"));
1696 fprintf(stderr, _("What kind of logo do you want to set ?\n"));
1697 if (GSM && GSM->Terminate) GSM->Terminate();
1702 if (GSM && GSM->SetBitmap) error = GSM->SetBitmap(&bitmap);
1706 oldbit.type = bitmap.type;
1707 oldbit.number = bitmap.number;
1708 if (GSM && GSM->GetBitmap && GSM->GetBitmap(&oldbit) == GE_NONE) {
1709 if (bitmap.type == GSM_WelcomeNoteText ||
1710 bitmap.type == GSM_DealerNoteText) {
1711 if (strcmp(bitmap.text, oldbit.text)) {
1712 fprintf(stderr, _("Error setting"));
1713 if (bitmap.type == GSM_DealerNoteText) fprintf(stderr, _(" dealer"));
1714 fprintf(stderr, _(" welcome note - "));
1716 /* I know, it looks horrible, but... */
1717 /* I set it to the short string - if it won't be set */
1718 /* it means, PIN is required. If it will be correct, previous */
1719 /* (user) text was too long */
1721 /* Without it, I could have such thing: */
1722 /* user set text to very short string (for example, "Marcin") */
1723 /* then enable phone without PIN and try to set it to the very long (too long for phone) */
1724 /* string (which start with "Marcin"). If we compare them as only length different, we could think, */
1725 /* that phone accepts strings 6 chars length only (length of "Marcin") */
1726 /* When we make it correct, we don't have this mistake */
1728 strcpy(oldbit.text, "!\0");
1729 if (GSM && GSM->SetBitmap) GSM->SetBitmap(&oldbit);
1730 if (GSM && GSM->GetBitmap) GSM->GetBitmap(&oldbit);
1731 if (oldbit.text[0]!='!') {
1732 fprintf(stderr, _("SIM card and PIN is required\n"));
1734 if (GSM && GSM->SetBitmap) GSM->SetBitmap(&bitmap);
1735 if (GSM && GSM->GetBitmap) GSM->GetBitmap(&oldbit);
1736 fprintf(stderr, _("too long, truncated to \"%s\" (length %i)\n"),oldbit.text,strlen(oldbit.text));
1741 if (bitmap.type == GSM_StartupLogo) {
1742 for (i = 0; i < oldbit.size; i++) {
1743 if (oldbit.bitmap[i] != bitmap.bitmap[i]) {
1744 fprintf(stderr, _("Error setting startup logo - SIM card and PIN is required\n"));
1752 if (ok) fprintf(stdout, _("Done.\n"));
1754 case GE_NOTIMPLEMENTED:
1755 fprintf(stderr, _("Function not implemented.\n"));
1757 case GE_NOTSUPPORTED:
1758 fprintf(stderr, _("This kind of logo is not supported.\n"));
1761 fprintf(stderr, _("Error !\n"));
1765 if (GSM && GSM->Terminate) GSM->Terminate();
1771 int viewlogo(char *filename)
1775 error = GSM_ShowBitmapFile(filename);
1779 /* Calendar notes receiving. */
1780 int getcalendarnote(int argc, char *argv[])
1782 GSM_CalendarNote CalendarNote;
1784 GSM_Error error = GE_NONE;
1785 int i, first_location, last_location;
1788 struct option options[] = {
1789 { "vCard", optional_argument, NULL, '1'},
1796 first_location = last_location = atoi(argv[0]);
1797 if ((argc > 1) && (argv[1][0] != '-')) {
1798 last_location = atoi(argv[1]);
1801 while ((i = getopt_long(argc, argv, "v", options, NULL)) != -1) {
1807 usage(); /* Would be better to have an calendar_usage() here. */
1813 for (i = first_location; i <= last_location; i++) {
1814 CalendarNote.Location = i;
1815 if (GSM && GSM->GetCalendarNote && GSM->Terminate) {
1816 error = GSM->GetCalendarNote(&CalendarNote);
1819 GSM_DataClear(&data);
1820 data.CalendarNote = &CalendarNote;
1822 error = SM_Functions(GOP_GetCalendarNote, &data, &State);
1827 fprintf(stdout, "BEGIN:VCALENDAR\n");
1828 fprintf(stdout, "VERSION:1.0\n");
1829 fprintf(stdout, "BEGIN:VEVENT\n");
1830 fprintf(stdout, "CATEGORIES:");
1831 switch (CalendarNote.Type) {
1833 fprintf(stdout, "MISCELLANEOUS\n");
1836 fprintf(stdout, "PHONE CALL\n");
1839 fprintf(stdout, "MEETING\n");
1842 fprintf(stdout, "SPECIAL OCCASION\n");
1845 fprintf(stdout, "UNKNOWN\n");
1848 fprintf(stdout, "SUMMARY:%s\n",CalendarNote.Text);
1849 fprintf(stdout, "DTSTART:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Time.Year,
1850 CalendarNote.Time.Month, CalendarNote.Time.Day, CalendarNote.Time.Hour,
1851 CalendarNote.Time.Minute, CalendarNote.Time.Second);
1852 if (CalendarNote.Alarm.Year!=0) {
1853 fprintf(stdout, "DALARM:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Alarm.Year,
1854 CalendarNote.Alarm.Month, CalendarNote.Alarm.Day, CalendarNote.Alarm.Hour,
1855 CalendarNote.Alarm.Minute, CalendarNote.Alarm.Second);
1857 fprintf(stdout, "END:VEVENT\n");
1858 fprintf(stdout, "END:VCALENDAR\n");
1860 } else { /* not vCal */
1861 fprintf(stdout, _(" Type of the note: "));
1863 switch (CalendarNote.Type) {
1865 fprintf(stdout, _("Reminder\n"));
1868 fprintf(stdout, _("Call\n"));
1871 fprintf(stdout, _("Meeting\n"));
1874 fprintf(stdout, _("Birthday\n"));
1877 fprintf(stdout, _("Unknown\n"));
1881 fprintf(stdout, _(" Date: %d-%02d-%02d\n"), CalendarNote.Time.Year,
1882 CalendarNote.Time.Month,
1883 CalendarNote.Time.Day);
1885 fprintf(stdout, _(" Time: %02d:%02d:%02d\n"), CalendarNote.Time.Hour,
1886 CalendarNote.Time.Minute,
1887 CalendarNote.Time.Second);
1889 if (CalendarNote.Alarm.AlarmEnabled == 1) {
1890 fprintf(stdout, _(" Alarm date: %d-%02d-%02d\n"), CalendarNote.Alarm.Year,
1891 CalendarNote.Alarm.Month,
1892 CalendarNote.Alarm.Day);
1894 fprintf(stdout, _(" Alarm time: %02d:%02d:%02d\n"), CalendarNote.Alarm.Hour,
1895 CalendarNote.Alarm.Minute,
1896 CalendarNote.Alarm.Second);
1899 fprintf(stdout, _(" Text: %s\n"), CalendarNote.Text);
1901 if (CalendarNote.Type == GCN_CALL)
1902 fprintf(stdout, _(" Phone: %s\n"), CalendarNote.Phone);
1905 case GE_NOTIMPLEMENTED:
1906 fprintf(stderr, _("Function not implemented.\n"));
1909 fprintf(stderr, _("The calendar note can not be read\n"));
1914 if (GSM && GSM->Terminate) GSM->Terminate();
1918 /* Writing calendar notes. */
1919 int writecalendarnote(char *argv[])
1921 GSM_CalendarNote CalendarNote;
1923 if (GSM_ReadVCalendarFile(argv[0], &CalendarNote, atoi(argv[1]))) {
1924 fprintf(stdout, _("Failed to load vCalendar file.\n"));
1928 /* Error 22=Calendar full ;-) */
1929 if (GSM && GSM->WriteCalendarNote && GSM->WriteCalendarNote(&CalendarNote) == GE_NONE)
1930 fprintf(stdout, _("Succesfully written!\n"));
1932 fprintf(stdout, _("Failed to write calendar note!\n"));
1934 if (GSM && GSM->Terminate) GSM->Terminate();
1939 /* Calendar note deleting. */
1940 int deletecalendarnote(int argc, char *argv[])
1942 GSM_CalendarNote CalendarNote;
1943 int i, first_location, last_location;
1945 first_location = last_location = atoi(argv[0]);
1946 if (argc > 1) last_location = atoi(argv[1]);
1948 for (i = first_location; i <= last_location; i++) {
1950 CalendarNote.Location = i;
1952 if (GSM && GSM->DeleteCalendarNote && GSM->DeleteCalendarNote(&CalendarNote) == GE_NONE) {
1953 fprintf(stdout, _(" Calendar note deleted.\n"));
1955 fprintf(stderr, _("The calendar note can not be deleted\n"));
1960 if (GSM && GSM->Terminate) GSM->Terminate();
1965 /* Setting the date and time. */
1966 int setdatetime(int argc, char *argv[])
1973 now = localtime(&nowh);
1975 Date.Year = now->tm_year;
1976 Date.Month = now->tm_mon+1;
1977 Date.Day = now->tm_mday;
1978 Date.Hour = now->tm_hour;
1979 Date.Minute = now->tm_min;
1980 Date.Second = now->tm_sec;
1982 if (argc > 0) Date.Year = atoi (argv[0]);
1983 if (argc > 1) Date.Month = atoi (argv[1]);
1984 if (argc > 2) Date.Day = atoi (argv[2]);
1985 if (argc > 3) Date.Hour = atoi (argv[3]);
1986 if (argc > 4) Date.Minute = atoi (argv[4]);
1988 if (Date.Year < 1900) {
1990 /* Well, this thing is copyrighted in U.S. This technique is known as
1991 Windowing and you can read something about it in LinuxWeekly News:
1992 http://lwn.net/1999/features/Windowing.phtml. This thing is beeing
1993 written in Czech republic and Poland where algorithms are not allowed
1997 Date.Year = Date.Year + 1900;
1999 Date.Year = Date.Year + 2000;
2002 /* FIXME: Error checking should be here. */
2003 if (GSM && GSM->SetDateTime) GSM->SetDateTime(&Date);
2005 if (GSM && GSM->Terminate) GSM->Terminate();
2010 /* In this mode we receive the date and time from mobile phone. */
2011 int getdatetime(void)
2014 GSM_DateTime date_time;
2017 if (GSM && GSM->GetDateTime && GSM->Terminate) {
2018 error = GSM->GetDateTime(&date_time);
2021 GSM_DataClear(&data);
2022 data.DateTime = &date_time;
2024 error = SM_Functions(GOP_GetDateTime, &data, &State);
2029 fprintf(stdout, _("Date: %4d/%02d/%02d\n"), date_time.Year, date_time.Month, date_time.Day);
2030 fprintf(stdout, _("Time: %02d:%02d:%02d\n"), date_time.Hour, date_time.Minute, date_time.Second);
2032 case GE_NOTIMPLEMENTED:
2033 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2036 fprintf(stdout, _("Internal error\n"));
2043 /* Setting the alarm. */
2044 int setalarm(char *argv[])
2048 Date.Hour = atoi(argv[0]);
2049 Date.Minute = atoi(argv[1]);
2051 if (GSM && GSM->SetAlarm) GSM->SetAlarm(1, &Date);
2053 if (GSM && GSM->Terminate) GSM->Terminate();
2058 /* Getting the alarm. */
2063 GSM_DateTime date_time;
2065 if (GSM && GSM->GetAlarm && GSM->Terminate) {
2066 error = GSM->GetAlarm(0, &date_time);
2069 GSM_DataClear(&data);
2070 data.DateTime = &date_time;
2072 error = SM_Functions(GOP_GetAlarm, &data, &State);
2077 fprintf(stdout, _("Alarm: %s\n"), (date_time.AlarmEnabled==0)?"off":"on");
2078 fprintf(stdout, _("Time: %02d:%02d\n"), date_time.Hour, date_time.Minute);
2080 case GE_NOTIMPLEMENTED:
2081 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2084 fprintf(stdout, _("Internal error\n"));
2091 /* In monitor mode we don't do much, we just initialise the fbus code.
2092 Note that the fbus code no longer has an internal monitor mode switch,
2093 instead compile with DEBUG enabled to get all the gumpf. */
2094 int monitormode(void)
2096 float rflevel = -1, batterylevel = -1;
2097 // GSM_PowerSource powersource = -1;
2098 GSM_RFUnits rf_units = GRF_Arbitrary;
2099 GSM_BatteryUnits batt_units = GBU_Arbitrary;
2100 GSM_Statemachine *sm = &State;
2103 // GSM_NetworkInfo NetworkInfo;
2104 // GSM_CBMessage CBMessage;
2106 GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0};
2107 GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0};
2108 GSM_MemoryStatus DC_MemoryStatus = {GMT_DC, 0, 0};
2109 GSM_MemoryStatus EN_MemoryStatus = {GMT_EN, 0, 0};
2110 GSM_MemoryStatus FD_MemoryStatus = {GMT_FD, 0, 0};
2111 GSM_MemoryStatus LD_MemoryStatus = {GMT_LD, 0, 0};
2112 GSM_MemoryStatus MC_MemoryStatus = {GMT_MC, 0, 0};
2113 GSM_MemoryStatus ON_MemoryStatus = {GMT_ON, 0, 0};
2114 GSM_MemoryStatus RC_MemoryStatus = {GMT_RC, 0, 0};
2116 // GSM_SMSStatus SMSStatus = {0, 0};
2120 GSM_DataClear(&data);
2122 /* We do not want to monitor serial line forever - press Ctrl+C to stop the
2124 signal(SIGINT, interrupted);
2126 fprintf (stderr, _("Entering monitor mode...\n"));
2129 //GSM->EnableCellBroadcast();
2131 /* Loop here indefinitely - allows you to see messages from GSM code in
2132 response to unknown messages etc. The loops ends after pressing the
2134 data.RFUnits = &rf_units;
2135 data.RFLevel = &rflevel;
2136 data.BatteryUnits = &batt_units;
2137 data.BatteryLevel = &batterylevel;
2139 while (!bshutdown) {
2140 if (SM_Functions(GOP_GetRFLevel, &data, sm) == GE_NONE)
2141 fprintf(stdout, _("RFLevel: %d\n"), (int)rflevel);
2143 if (SM_Functions(GOP_GetBatteryLevel, &data, sm) == GE_NONE)
2144 fprintf(stdout, _("Battery: %d\n"), (int)batterylevel);
2146 // if (GSM->GetPowerSource(&powersource) == GE_NONE)
2147 // fprintf(stdout, _("Power Source: %s\n"), (powersource==GPS_ACDC)?_("AC/DC"):_("battery"));
2149 data.MemoryStatus = &SIMMemoryStatus;
2150 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2151 fprintf(stdout, _("SIM: Used %d, Free %d\n"), SIMMemoryStatus.Used, SIMMemoryStatus.Free);
2153 data.MemoryStatus = &PhoneMemoryStatus;
2154 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2155 fprintf(stdout, _("Phone: Used %d, Free %d\n"), PhoneMemoryStatus.Used, PhoneMemoryStatus.Free);
2157 data.MemoryStatus = &DC_MemoryStatus;
2158 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2159 fprintf(stdout, _("DC: Used %d, Free %d\n"), DC_MemoryStatus.Used, DC_MemoryStatus.Free);
2161 data.MemoryStatus = &EN_MemoryStatus;
2162 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2163 fprintf(stdout, _("EN: Used %d, Free %d\n"), EN_MemoryStatus.Used, EN_MemoryStatus.Free);
2165 data.MemoryStatus = &FD_MemoryStatus;
2166 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2167 fprintf(stdout, _("FD: Used %d, Free %d\n"), FD_MemoryStatus.Used, FD_MemoryStatus.Free);
2169 data.MemoryStatus = &LD_MemoryStatus;
2170 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2171 fprintf(stdout, _("LD: Used %d, Free %d\n"), LD_MemoryStatus.Used, LD_MemoryStatus.Free);
2173 data.MemoryStatus = &MC_MemoryStatus;
2174 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2175 fprintf(stdout, _("MC: Used %d, Free %d\n"), MC_MemoryStatus.Used, MC_MemoryStatus.Free);
2177 data.MemoryStatus = &ON_MemoryStatus;
2178 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2179 fprintf(stdout, _("ON: Used %d, Free %d\n"), ON_MemoryStatus.Used, ON_MemoryStatus.Free);
2181 data.MemoryStatus = &RC_MemoryStatus;
2182 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2183 fprintf(stdout, _("RC: Used %d, Free %d\n"), RC_MemoryStatus.Used, RC_MemoryStatus.Free);
2185 // if (GSM->GetSMSStatus(&SMSStatus) == GE_NONE)
2186 // fprintf(stdout, _("SMS Messages: UnRead %d, Number %d\n"), SMSStatus.UnRead, SMSStatus.Number);
2188 // if (GSM->GetIncomingCallNr(Number) == GE_NONE)
2189 // fprintf(stdout, _("Incoming call: %s\n"), Number);
2191 // if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE)
2192 // fprintf(stdout, _("Network: %s (%s), LAC: %s, CellID: %s\n"), GSM_GetNetworkName (NetworkInfo.NetworkCode), GSM_GetCountryName(NetworkInfo.NetworkCode), NetworkInfo.LAC, NetworkInfo.CellID);
2194 // if (GSM->ReadCellBroadcast(&CBMessage) == GE_NONE)
2195 // fprintf(stdout, _("Cell broadcast received on channel %d: %s\n"), CBMessage.Channel, CBMessage.Message);
2200 fprintf(stderr, _("Leaving monitor mode...\n"));
2208 static GSM_Error PrettyOutputFn(char *Display, char *Indicators)
2211 printf(ESC "[10;0H Display is:\n%s\n", Display);
2213 printf(ESC "[9;0H Indicators: %s \n", Indicators);
2214 printf(ESC "[1;1H");
2219 /* Uncomment it if used */
2220 static GSM_Error OutputFn(char *Display, char *Indicators)
2223 printf("New display is:\n%s\n", Display);
2225 printf("Indicators: %s\n", Indicators);
2230 void console_raw(void)
2235 tcgetattr(fileno(stdin), &it);
2236 it.c_lflag &= ~(ICANON);
2237 //it.c_iflag &= ~(INPCK|ISTRIP|IXON);
2241 tcsetattr(fileno(stdin), TCSANOW, &it);
2245 int displayoutput(void)
2248 GSM_Statemachine *sm = &State;
2251 data.OutputFn = PrettyOutputFn;
2253 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2255 fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
2257 if (error == GE_NONE) {
2259 /* We do not want to see texts forever - press Ctrl+C to stop. */
2260 signal(SIGINT, interrupted);
2262 fprintf (stderr, _("Entered display monitoring mode...\n"));
2263 fprintf (stderr, ESC "c" );
2265 /* Loop here indefinitely - allows you to read texts from phone's
2266 display. The loops ends after pressing the Ctrl+C. */
2267 while (!bshutdown) {
2269 memset(&buf[0], 0, 102);
2270 while (read(0, buf, 100) > 0) {
2271 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
2272 if (GSM && GSM->HandleString && GSM->HandleString(buf) != GE_NONE)
2273 fprintf(stdout, _("Key press simulation failed.\n"));
2274 memset(buf, 0, 102);
2278 fprintf (stderr, "Shutting down\n");
2280 fprintf (stderr, _("Leaving display monitor mode...\n"));
2281 data.OutputFn = NULL;
2283 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2284 if (error != GE_NONE)
2285 fprintf (stderr, _("Error!\n"));
2287 fprintf (stderr, _("Error!\n"));
2289 if (GSM && GSM->Terminate) GSM->Terminate();
2293 /* Reads profile from phone and displays its' settings */
2294 int getprofile(int argc, char *argv[])
2298 GSM_Profile profile;
2301 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2305 if (GSM && GSM->GetProfile) error = GSM->GetProfile(&profile);
2307 if (error == GE_NONE) {
2309 while (GSM && GSM->GetModel && GSM->GetModel(model) != GE_NONE)
2312 max_profiles = 7; /* This is correct for 6110 (at least my). How do we get
2313 the number of profiles? */
2316 /* FIXME: It should be set to 3 for N5130 and 3210 too */
2317 if (!strcmp(model, "NSE-1"))
2321 profile.Number = atoi(argv[0]) - 1;
2322 start = profile.Number;
2325 if (profile.Number < 0) {
2326 fprintf(stderr, _("Profile number must be value from 1 to %d!\n"), max_profiles);
2327 if (GSM && GSM->Terminate) GSM->Terminate();
2331 if (profile.Number >= max_profiles) {
2332 fprintf(stderr, _("This phone supports only %d profiles!\n"), max_profiles);
2333 if (GSM && GSM->Terminate) GSM->Terminate();
2338 stop = max_profiles;
2345 if (profile.Number != 0)
2346 if (GSM && GSM->GetProfile) GSM->GetProfile(&profile);
2348 fprintf(stdout, "%d. \"%s\"\n", profile.Number + 1, profile.Name);
2349 if (profile.DefaultName == -1) fprintf(stdout, _(" (name defined)\n"));
2351 fprintf(stdout, _("Incoming call alert: %s\n"), GetProfileCallAlertString(profile.CallAlert));
2353 /* For different phones different ringtones names */
2355 if (!strcmp(model, "NSE-3"))
2356 fprintf(stdout, _("Ringing tone: %s (%d)\n"), RingingTones[profile.Ringtone], profile.Ringtone);
2358 fprintf(stdout, _("Ringtone number: %d\n"), profile.Ringtone);
2360 fprintf(stdout, _("Ringing volume: %s\n"), GetProfileVolumeString(profile.Volume));
2362 fprintf(stdout, _("Message alert tone: %s\n"), GetProfileMessageToneString(profile.MessageTone));
2364 fprintf(stdout, _("Keypad tones: %s\n"), GetProfileKeypadToneString(profile.KeypadTone));
2366 fprintf(stdout, _("Warning and game tones: %s\n"), GetProfileWarningToneString(profile.WarningTone));
2368 /* FIXME: Light settings is only used for Car */
2369 if (profile.Number == (max_profiles - 2)) fprintf(stdout, _("Lights: %s\n"), profile.Lights ? _("On") : _("Automatic"));
2371 fprintf(stdout, _("Vibration: %s\n"), GetProfileVibrationString(profile.Vibration));
2373 /* FIXME: it will be nice to add here reading caller group name. */
2374 if (max_profiles != 3) fprintf(stdout, _("Caller groups: 0x%02x\n"), profile.CallerGroups);
2376 /* FIXME: Automatic answer is only used for Car and Headset. */
2377 if (profile.Number >= (max_profiles - 2)) fprintf(stdout, _("Automatic answer: %s\n"), profile.AutomaticAnswer ? _("On") : _("Off"));
2379 fprintf(stdout, "\n");
2384 if (error == GE_NOTIMPLEMENTED) {
2385 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2386 if (GSM && GSM->Terminate) GSM->Terminate();
2389 fprintf(stderr, _("Unspecified error\n"));
2390 if (GSM && GSM->Terminate) GSM->Terminate();
2395 if (GSM && GSM->Terminate) GSM->Terminate();
2399 /* Get requested range of memory storage entries and output to stdout in
2400 easy-to-parse format */
2401 int getmemory(int argc, char *argv[])
2403 GSM_PhonebookEntry entry;
2406 char *memory_type_string;
2409 GSM_Statemachine *sm = &State;
2411 /* Handle command line args that set type, start and end locations. */
2412 memory_type_string = argv[0];
2413 entry.MemoryType = StrToMemoryType(memory_type_string);
2414 if (entry.MemoryType == GMT_XX) {
2415 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
2419 start_entry = atoi (argv[1]);
2420 if (argc > 2) end_entry = atoi (argv[2]);
2421 else end_entry = start_entry;
2423 /* Now retrieve the requested entries. */
2424 for (count = start_entry; count <= end_entry; count ++) {
2426 entry.Location = count;
2428 data.PhonebookEntry = &entry;
2429 error = SM_Functions(GOP_ReadPhonebook, &data, sm);
2431 if (error == GE_NONE) {
2432 fprintf(stdout, "%s;%s;%s;%d;%d\n", entry.Name, entry.Number, memory_type_string, entry.Location, entry.Group);
2433 if (entry.MemoryType == GMT_MC || entry.MemoryType == GMT_DC || entry.MemoryType == GMT_RC)
2434 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);
2437 if (error == GE_NOTIMPLEMENTED) {
2438 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2441 else if (error == GE_INVALIDMEMORYTYPE) {
2442 fprintf(stderr, _("Memory type %s not supported!\n"), memory_type_string);
2446 fprintf(stdout, _("%s|%d|Bad location or other error!(%d)\n"), memory_type_string, count, error);
2452 /* Read data from stdin, parse and write to phone. The parsing is relatively
2453 crude and doesn't allow for much variation from the stipulated format. */
2454 /* FIXME: I guess there's *very* similar code in xgnokii */
2455 int writephonebook(int argc, char *args[])
2457 GSM_PhonebookEntry entry;
2459 char *memory_type_string;
2463 char *Line, OLine[100], BackLine[100];
2466 /* Check argument */
2467 if (argc && (strcmp("-i", args[0])))
2472 /* Go through data from stdin. */
2473 while (GetLine(stdin, Line, 99)) {
2474 strcpy(BackLine, Line);
2477 ptr = strtok(Line, ";");
2478 if (ptr) strcpy(entry.Name, ptr);
2479 else entry.Name[0] = 0;
2481 ptr = strtok(NULL, ";");
2482 if (ptr) strcpy(entry.Number, ptr);
2483 else entry.Number[0] = 0;
2485 ptr = strtok(NULL, ";");
2488 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2493 if (!strncmp(ptr,"ME", 2)) {
2494 memory_type_string = "int";
2495 entry.MemoryType = GMT_ME;
2497 if (!strncmp(ptr,"SM", 2)) {
2498 memory_type_string = "sim";
2499 entry.MemoryType = GMT_SM;
2501 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2506 ptr = strtok(NULL, ";");
2507 if (ptr) entry.Location = atoi(ptr);
2508 else entry.Location = 0;
2510 ptr = strtok(NULL, ";");
2511 if (ptr) entry.Group = atoi(ptr);
2512 else entry.Group = 0;
2515 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2519 for (subentry = 0; ; subentry++) {
2520 ptr = strtok(NULL, ";");
2522 if (ptr && *ptr != 0)
2523 entry.SubEntries[subentry].EntryType = atoi(ptr);
2527 ptr = strtok(NULL, ";");
2529 entry.SubEntries[subentry].NumberType=atoi(ptr);
2531 /* Phone Numbers need to have a number type. */
2532 if (!ptr && entry.SubEntries[subentry].EntryType == GSM_Number) {
2533 fprintf(stderr, _("Missing phone number type on line %d"
2534 " entry %d [%s]\n"), line_count, subentry, BackLine);
2539 ptr = strtok(NULL, ";");
2541 entry.SubEntries[subentry].BlockNumber=atoi(ptr);
2543 ptr = strtok(NULL, ";");
2545 /* 0x13 Date Type; it is only for Dailed Numbers, etc.
2546 we don't store to this memories so it's an error to use it. */
2547 if (!ptr || entry.SubEntries[subentry].EntryType == GSM_Date) {
2548 fprintf(stdout, _("There is no phone number on line %d entry %d [%s]\n"),
2549 line_count, subentry, BackLine);
2553 strcpy(entry.SubEntries[subentry].data.Number, ptr);
2556 entry.SubEntriesCount = subentry;
2558 /* This is to send other exports (like from 6110) to 7110 */
2559 if (!entry.SubEntriesCount) {
2560 entry.SubEntriesCount = 1;
2561 entry.SubEntries[subentry].EntryType = GSM_Number;
2562 entry.SubEntries[subentry].NumberType = GSM_General;
2563 entry.SubEntries[subentry].BlockNumber = 2;
2564 strcpy(entry.SubEntries[subentry].data.Number, entry.Number);
2570 GSM_PhonebookEntry aux;
2572 aux.Location = entry.Location;
2573 if (GSM && GSM->GetMemoryLocation) error = GSM->GetMemoryLocation(&aux);
2575 if (error == GE_NONE) {
2580 fprintf(stdout, _("Location busy. "));
2581 while (confirm < 0) {
2582 fprintf(stdout, _("Overwrite? (yes/no) "));
2583 GetLine(stdin, ans, 7);
2584 if (!strcmp(ans, _("yes"))) confirm = 1;
2585 else if (!strcmp(ans, _("no"))) confirm = 0;
2587 if (!confirm) continue;
2590 fprintf(stderr, _("Unknown error (%d)\n"), error);
2591 if (GSM && GSM->Terminate) GSM->Terminate();
2596 /* Do write and report success/failure. */
2597 if (GSM && GSM->WritePhonebookLocation) error = GSM->WritePhonebookLocation(&entry);
2599 if (error == GE_NONE)
2600 fprintf (stdout, _("Write Succeeded: memory type: %s, loc: %d, name: %s, number: %s\n"), memory_type_string, entry.Location, entry.Name, entry.Number);
2602 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);
2606 if (GSM && GSM->Terminate) GSM->Terminate();
2610 /* Getting speed dials. */
2611 int getspeeddial(char *Number)
2613 GSM_SpeedDial SpeedDial;
2617 SpeedDial.Number = atoi(Number);
2619 if (GSM && GSM->GetSpeedDial && GSM->Terminate) {
2620 error = GSM->GetSpeedDial(&SpeedDial);
2623 GSM_DataClear(&data);
2624 data.SpeedDial = &SpeedDial;
2626 error = SM_Functions(GOP_GetSpeedDial, &data, &State);
2631 fprintf(stdout, _("SpeedDial nr. %d: %d:%d\n"), SpeedDial.Number, SpeedDial.MemoryType, SpeedDial.Location);
2633 case GE_NOTIMPLEMENTED:
2634 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2637 fprintf(stdout, _("Internal error\n"));
2644 /* Setting speed dials. */
2645 int setspeeddial(char *argv[])
2647 GSM_SpeedDial entry;
2649 char *memory_type_string;
2651 /* Handle command line args that set type, start and end locations. */
2653 if (strcmp(argv[1], "ME") == 0) {
2654 entry.MemoryType = 0x02;
2655 memory_type_string = "ME";
2656 } else if (strcmp(argv[1], "SM") == 0) {
2657 entry.MemoryType = 0x03;
2658 memory_type_string = "SM";
2660 fprintf(stderr, _("Unknown memory type %s!\n"), argv[1]);
2664 entry.Number = atoi(argv[0]);
2665 entry.Location = atoi(argv[2]);
2667 if (GSM && GSM->SetSpeedDial && GSM->SetSpeedDial(&entry) == GE_NONE) {
2668 fprintf(stdout, _("Succesfully written!\n"));
2671 if (GSM && GSM->Terminate) GSM->Terminate();
2675 /* Getting the status of the display. */
2676 int getdisplaystatus(void)
2680 if (GSM && GSM->GetDisplayStatus) GSM->GetDisplayStatus(&Status);
2682 fprintf(stdout, _("Call in progress: %s\n"), Status & (1<<DS_Call_In_Progress)?_("on"):_("off"));
2683 fprintf(stdout, _("Unknown: %s\n"), Status & (1<<DS_Unknown)?_("on"):_("off"));
2684 fprintf(stdout, _("Unread SMS: %s\n"), Status & (1<<DS_Unread_SMS)?_("on"):_("off"));
2685 fprintf(stdout, _("Voice call: %s\n"), Status & (1<<DS_Voice_Call)?_("on"):_("off"));
2686 fprintf(stdout, _("Fax call active: %s\n"), Status & (1<<DS_Fax_Call)?_("on"):_("off"));
2687 fprintf(stdout, _("Data call active: %s\n"), Status & (1<<DS_Data_Call)?_("on"):_("off"));
2688 fprintf(stdout, _("Keyboard lock: %s\n"), Status & (1<<DS_Keyboard_Lock)?_("on"):_("off"));
2689 fprintf(stdout, _("SMS storage full: %s\n"), Status & (1<<DS_SMS_Storage_Full)?_("on"):_("off"));
2691 if (GSM && GSM->Terminate) GSM->Terminate();
2695 int netmonitor(char *Mode)
2697 unsigned char mode = atoi(Mode);
2700 if (!strcmp(Mode, "reset"))
2702 else if (!strcmp(Mode, "off"))
2704 else if (!strcmp(Mode, "field"))
2706 else if (!strcmp(Mode, "devel"))
2708 else if (!strcmp(Mode, "next"))
2711 memset(&Screen, 0, 50);
2712 if (GSM && GSM->NetMonitor) GSM->NetMonitor(mode, Screen);
2715 fprintf(stdout, "%s\n", Screen);
2717 if (GSM && GSM->Terminate) GSM->Terminate();
2723 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2724 char imei[64], model[64], rev[64], manufacturer[64];
2725 GSM_Statemachine *sm = &State;
2727 data.Manufacturer = manufacturer;
2729 data.Revision = rev;
2732 /* Retrying is bad idea: what if function is simply not implemented?
2733 Anyway let's wait 2 seconds for the right packet from the phone. */
2736 strcpy(imei, "(unknown)");
2737 strcpy(manufacturer, "(unknown)");
2738 strcpy(model, "(unknown)");
2739 strcpy(rev, "(unknown)");
2741 SM_Functions(GOP_Identify, &data, sm);
2743 fprintf(stdout, _("IMEI: %s\n"), imei);
2744 fprintf(stdout, _("Manufacturer: %s\n"), manufacturer);
2745 fprintf(stdout, _("Model: %s\n"), model);
2746 fprintf(stdout, _("Revision: %s\n"), rev);
2751 int senddtmf(char *String)
2753 if (GSM && GSM->SendDTMF) GSM->SendDTMF(String);
2754 if (GSM && GSM->Terminate) GSM->Terminate();
2758 /* Resets the phone */
2759 int reset( char *type)
2761 unsigned char _type = 0x03;
2764 if(!strcmp(type, "soft"))
2767 if(!strcmp(type, "hard"))
2770 fprintf(stderr, _("What kind of reset do you want??\n"));
2775 if (GSM && GSM->Reset) GSM->Reset(_type);
2776 if (GSM && GSM->Terminate) GSM->Terminate();
2781 /* pmon allows fbus code to run in a passive state - it doesn't worry about
2782 whether comms are established with the phone. A debugging/development
2787 GSM_ConnectionType connection=GCT_Serial;
2788 GSM_Statemachine sm;
2790 /* Initialise the code for the GSM interface. */
2791 error = GSM_Initialise(model, Port, Initlength, connection, NULL, &sm);
2793 if (error != GE_NONE) {
2794 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
2805 int sendringtone(int argc, char *argv[])
2807 GSM_Ringtone ringtone;
2810 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2811 fprintf(stdout, _("Failed to load ringtone.\n"));
2815 if (GSM && GSM->SendRingtone) error = GSM->SendRingtone(&ringtone,argv[1]);
2817 if (error == GE_NONE)
2818 fprintf(stdout, _("Send succeeded!\n"));
2820 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
2822 if (GSM && GSM->Terminate) GSM->Terminate();
2827 int setringtone(int argc, char *argv[])
2829 GSM_Ringtone ringtone;
2832 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2833 fprintf(stdout, _("Failed to load ringtone.\n"));
2837 if (GSM && GSM->SetRingtone) error = GSM->SetRingtone(&ringtone);
2839 if (error == GE_NONE)
2840 fprintf(stdout, _("Send succeeded!\n"));
2842 fprintf(stdout, _("Send failed\n"));
2844 if (GSM && GSM->Terminate) GSM->Terminate();
2848 int presskeysequence(void)
2854 memset(&buf[0], 0, 102);
2855 while (read(0, buf, 100) > 0) {
2856 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
2857 if (GSM && GSM->HandleString && GSM->HandleString(buf) != GE_NONE)
2858 fprintf(stdout, _("Key press simulation failed.\n"));
2859 memset(buf, 0, 102);
2862 if (GSM && GSM->Terminate) GSM->Terminate();
2866 /* Options for --divert:
2867 --op, -o [register|enable|query|disable|erasure] REQ
2868 --type, -t [all|busy|noans|outofreach|notavail] REQ
2869 --call, -c [all|voice|fax|data] REQ
2870 --timeout, m time_in_seconds OPT
2871 --number, -n number OPT
2873 int divert(int argc, char **argv)
2877 GSM_Statemachine *sm = &State;
2880 struct option options[] = {
2881 { "op", required_argument, NULL, 'o'},
2882 { "type", required_argument, NULL, 't'},
2883 { "call", required_argument, NULL, 'c'},
2884 { "number", required_argument, NULL, 'n'},
2885 { "timeout", required_argument, NULL, 'm'},
2895 memset(&cd, 0, sizeof(GSM_CallDivert));
2897 while ((opt = getopt_long(argc, argv, "o:t:n:c:m:", options, NULL)) != -1) {
2900 if (!strcmp("register", optarg)) {
2901 cd.Operation = GSM_CDV_Register;
2902 } else if (!strcmp("enable", optarg)) {
2903 cd.Operation = GSM_CDV_Enable;
2904 } else if (!strcmp("disable", optarg)) {
2905 cd.Operation = GSM_CDV_Disable;
2906 } else if (!strcmp("erasure", optarg)) {
2907 cd.Operation = GSM_CDV_Erasure;
2908 } else if (!strcmp("query", optarg)) {
2909 cd.Operation = GSM_CDV_Query;
2916 if (!strcmp("all", optarg)) {
2917 cd.DType = GSM_CDV_AllTypes;
2918 } else if (!strcmp("busy", optarg)) {
2919 cd.DType = GSM_CDV_Busy;
2920 } else if (!strcmp("noans", optarg)) {
2921 cd.DType = GSM_CDV_NoAnswer;
2922 } else if (!strcmp("outofreach", optarg)) {
2923 cd.DType = GSM_CDV_OutOfReach;
2924 } else if (!strcmp("notavail", optarg)) {
2925 cd.DType = GSM_CDV_NotAvailable;
2932 if (!strcmp("all", optarg)) {
2933 cd.CType = GSM_CDV_AllCalls;
2934 } else if (!strcmp("voice", optarg)) {
2935 cd.CType = GSM_CDV_VoiceCalls;
2936 } else if (!strcmp("fax", optarg)) {
2937 cd.CType = GSM_CDV_FaxCalls;
2938 } else if (!strcmp("data", optarg)) {
2939 cd.CType = GSM_CDV_DataCalls;
2946 cd.Timeout = atoi(optarg);
2949 strcpy(cd.Number.number, optarg);
2950 if (cd.Number.number[0] == '+') cd.Number.type = SMS_International;
2951 else cd.Number.type = SMS_Unknown;
2958 data.CallDivert = &cd;
2959 error = SM_Functions(GOP_CallDivert, &data, sm);
2961 if (error == GE_NONE) {
2962 fprintf(stderr, "Divert succeeded.\n");
2964 fprintf(stderr, "%s\n", print_error(error));
2969 /* This is a "convenience" function to allow quick test of new API stuff which
2970 doesn't warrant a "proper" command line function. */
2972 int foogle(char *argv[])
2974 /* Fill in what you would like to test here... */