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 static int writephonebook(int argc, char *args[]);
289 /* Main function - handles command line arguments, passes them to separate
290 functions accordingly. */
291 int main(int argc, char *argv[])
297 /* Every option should be in this array. */
298 static struct option long_options[] =
300 /* FIXME: these comments are nice, but they would be more usefull as docs for the user */
302 { "help", no_argument, NULL, OPT_HELP },
304 /* Display version and build information. */
305 { "version", no_argument, NULL, OPT_VERSION },
308 { "monitor", no_argument, NULL, OPT_MONITOR },
312 /* Enter Security Code mode */
313 { "entersecuritycode", required_argument, NULL, OPT_ENTERSECURITYCODE },
315 // Get Security Code status
316 { "getsecuritycodestatus", no_argument, NULL, OPT_GETSECURITYCODESTATUS },
321 { "setdatetime", optional_argument, NULL, OPT_SETDATETIME },
323 // Get date and time mode
324 { "getdatetime", no_argument, NULL, OPT_GETDATETIME },
327 { "setalarm", required_argument, NULL, OPT_SETALARM },
330 { "getalarm", no_argument, NULL, OPT_GETALARM },
333 { "dialvoice", required_argument, NULL, OPT_DIALVOICE },
335 // Get calendar note mode
336 { "getcalendarnote", required_argument, NULL, OPT_GETCALENDARNOTE },
338 // Write calendar note mode
339 { "writecalendarnote", required_argument, NULL, OPT_WRITECALENDARNOTE },
341 // Delete calendar note mode
342 { "deletecalendarnote", required_argument, NULL, OPT_DELCALENDARNOTE },
344 // Get display status mode
345 { "getdisplaystatus", no_argument, NULL, OPT_GETDISPLAYSTATUS },
348 { "getmemory", required_argument, NULL, OPT_GETMEMORY },
350 // Write phonebook (memory) mode
351 { "writephonebook", optional_argument, NULL, OPT_WRITEPHONEBOOK },
353 // Get speed dial mode
354 { "getspeeddial", required_argument, NULL, OPT_GETSPEEDDIAL },
356 // Set speed dial mode
357 { "setspeeddial", required_argument, NULL, OPT_SETSPEEDDIAL },
359 // Get SMS message mode
360 { "getsms", required_argument, NULL, OPT_GETSMS },
362 // Delete SMS message mode
363 { "deletesms", required_argument, NULL, OPT_DELETESMS },
365 // Send SMS message mode
366 { "sendsms", required_argument, NULL, OPT_SENDSMS },
368 // Ssve SMS message mode
369 { "savesms", optional_argument, NULL, OPT_SAVESMS },
371 // Send logo as SMS message mode
372 { "sendlogo", required_argument, NULL, OPT_SENDLOGO },
374 // Send ringtone as SMS message
375 { "sendringtone", required_argument, NULL, OPT_SENDRINGTONE },
378 { "setringtone", required_argument, NULL, OPT_SETRINGTONE },
380 // Get SMS center number mode
381 { "getsmsc", required_argument, NULL, OPT_GETSMSC },
383 // For development purposes: run in passive monitoring mode
384 { "pmon", no_argument, NULL, OPT_PMON },
387 { "netmonitor", required_argument, NULL, OPT_NETMONITOR },
390 { "identify", no_argument, NULL, OPT_IDENTIFY },
392 // Send DTMF sequence
393 { "senddtmf", required_argument, NULL, OPT_SENDDTMF },
396 { "reset", optional_argument, NULL, OPT_RESET },
399 { "setlogo", optional_argument, NULL, OPT_SETLOGO },
402 { "getlogo", required_argument, NULL, OPT_GETLOGO },
405 { "viewlogo", required_argument, NULL, OPT_VIEWLOGO },
408 { "getprofile", optional_argument, NULL, OPT_GETPROFILE },
410 // Show texts from phone's display
411 { "displayoutput", no_argument, NULL, OPT_DISPLAYOUTPUT },
413 // Simulate pressing the keys
414 { "keysequence", no_argument, NULL, OPT_KEYPRESS },
417 { "divert", required_argument, NULL, OPT_DIVERT },
419 // For development purposes: insert you function calls here
420 { "foogle", no_argument, NULL, OPT_FOOGLE },
425 /* Every command which requires arguments should have an appropriate entry
427 struct gnokii_arg_len gals[] =
431 { OPT_ENTERSECURITYCODE, 1, 1, 0 },
434 { OPT_SETDATETIME, 0, 5, 0 },
435 { OPT_SETALARM, 2, 2, 0 },
436 { OPT_DIALVOICE, 1, 1, 0 },
437 { OPT_GETCALENDARNOTE, 1, 3, 0 },
438 { OPT_WRITECALENDARNOTE, 2, 2, 0 },
439 { OPT_DELCALENDARNOTE, 1, 2, 0 },
440 { OPT_GETMEMORY, 2, 3, 0 },
441 { OPT_GETSPEEDDIAL, 1, 1, 0 },
442 { OPT_SETSPEEDDIAL, 3, 3, 0 },
443 { OPT_GETSMS, 2, 5, 0 },
444 { OPT_DELETESMS, 2, 3, 0 },
445 { OPT_SENDSMS, 1, 10, 0 },
446 { OPT_SAVESMS, 0, 6, 0 },
447 { OPT_SENDLOGO, 3, 4, GAL_XOR },
448 { OPT_SENDRINGTONE, 2, 2, 0 },
449 { OPT_GETSMSC, 1, 1, 0 },
450 { OPT_GETWELCOMENOTE, 1, 1, 0 },
451 { OPT_SETWELCOMENOTE, 1, 1, 0 },
452 { OPT_NETMONITOR, 1, 1, 0 },
453 { OPT_SENDDTMF, 1, 1, 0 },
454 { OPT_SETLOGO, 1, 4, 0 },
455 { OPT_GETLOGO, 1, 4, 0 },
456 { OPT_VIEWLOGO, 1, 1, 0 },
457 { OPT_SETRINGTONE, 1, 1, 0 },
458 { OPT_RESET, 0, 1, 0 },
459 { OPT_GETPROFILE, 0, 1, 0 },
460 { OPT_WRITEPHONEBOOK, 0, 1, 0 },
461 { OPT_DIVERT, 6, 10, 0 },
468 /* For GNU gettext */
470 textdomain("gnokii");
471 setlocale(LC_ALL, "");
474 /* Read config file */
475 if (readconfig(&model, &Port, &Initlength, &Connection, &BinDir) < 0) {
479 /* Introduce yourself */
482 /* Handle command line arguments. */
483 c = getopt_long(argc, argv, "", long_options, NULL);
484 if (c == -1) /* No argument given - we should display usage. */
488 /* First, error conditions */
491 fprintf(stderr, _("Use '%s --help' for usage informations.\n"), argv[0]);
493 /* Then, options with no arguments */
501 /* We have to build an array of the arguments which will be passed to the
502 functions. Please note that every text after the --command will be
503 passed as arguments. A syntax like gnokii --cmd1 args --cmd2 args will
504 not work as expected; instead args --cmd2 args is passed as a
506 if ((nargv = malloc(sizeof(char *) * argc)) != NULL) {
507 for (i = 2; i < argc; i++)
508 nargv[i-2] = argv[i];
510 if (checkargs(c, gals, nargc)) {
511 free(nargv); /* Wrong number of arguments - we should display usage. */
516 /* have to ignore SIGALARM */
520 /* Initialise the code for the GSM interface. */
528 case OPT_ENTERSECURITYCODE:
529 rc = entersecuritycode(optarg);
531 case OPT_GETSECURITYCODESTATUS:
532 rc = getsecuritycodestatus();
535 case OPT_GETDATETIME:
541 case OPT_GETDISPLAYSTATUS:
542 rc = getdisplaystatus();
547 case OPT_WRITEPHONEBOOK:
548 rc = writephonebook(nargc, nargv);
550 /* Now, options with arguments */
551 case OPT_SETDATETIME:
552 rc = setdatetime(nargc, nargv);
555 rc = setalarm(nargv);
558 rc = dialvoice(optarg);
560 case OPT_GETCALENDARNOTE:
561 rc = getcalendarnote(nargc, nargv);
563 case OPT_DELCALENDARNOTE:
564 rc = deletecalendarnote(nargc, nargv);
566 case OPT_WRITECALENDARNOTE:
567 rc = writecalendarnote(nargv);
570 rc = getmemory(nargc, nargv);
572 case OPT_GETSPEEDDIAL:
573 rc = getspeeddial(optarg);
575 case OPT_SETSPEEDDIAL:
576 rc = setspeeddial(nargv);
579 rc = getsms(argc, argv);
582 rc = deletesms(nargc, nargv);
585 rc = sendsms(nargc, nargv);
588 rc = savesms(argc, argv);
591 rc = sendlogo(nargc, nargv);
594 rc = getsmsc(optarg);
597 rc = netmonitor(optarg);
603 rc = setlogo(nargc, nargv);
606 rc = getlogo(nargc, nargv);
609 rc = viewlogo(optarg);
611 case OPT_SETRINGTONE:
612 rc = setringtone(nargc, nargv);
614 case OPT_SENDRINGTONE:
615 rc = sendringtone(nargc, nargv);
618 rc = getprofile(nargc, nargv);
620 case OPT_DISPLAYOUTPUT:
621 rc = displayoutput();
624 rc = presskeysequence();
627 rc = senddtmf(optarg);
633 rc = divert(argc, argv);
641 fprintf(stderr, _("Unknown option: %d\n"), c);
648 fprintf(stderr, _("Wrong number of arguments\n"));
652 /* Send SMS messages. */
653 int sendsms(int argc, char *argv[])
657 // char UDH[GSM_MAX_USER_DATA_HEADER_LENGTH];
658 /* The maximum length of an uncompressed concatenated short message is
659 255 * 153 = 39015 default alphabet characters */
660 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
661 int input_len, chars_read;
662 int i; /*, offset, nr_msg, aux;*/
664 struct option options[] = {
665 { "smsc", required_argument, NULL, '1'},
666 { "smscno", required_argument, NULL, '2'},
667 { "long", required_argument, NULL, '3'},
671 input_len = GSM_MAX_SMS_LENGTH;
679 - message validity for 3 days
680 - unset user data header indicator
683 memset(&SMS, 0, sizeof(GSM_SMSMessage));
685 SMS.Type = SMS_Submit;
686 SMS.DCS.Type = SMS_GeneralDataCoding;
687 SMS.DCS.u.General.Compressed = false;
688 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
689 SMS.DCS.u.General.Class = 0;
690 SMS.MessageCenter.No = 1;
691 SMS.Validity.VPF = SMS_RelativeFormat;
692 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
696 strcpy(SMS.RemoteNumber.number, argv[0]);
697 if (SMS.RemoteNumber.number[0] == '+') SMS.RemoteNumber.type = SMS_International;
698 else SMS.RemoteNumber.type = SMS_Unknown;
703 while ((i = getopt_long(argc, argv, "r8cC:v:", options, NULL)) != -1) {
704 switch (i) { // -8 is for 8-bit data, -c for compression. both are not yet implemented.
705 case '1': /* SMSC number */
706 SMS.MessageCenter.No = 0;
707 strcpy(SMS.MessageCenter.Number, optarg);
708 if (SMS.MessageCenter.Number[0] == '+') SMS.MessageCenter.Type = SMS_International;
709 else SMS.MessageCenter.Type = SMS_Unknown;
711 case '2': /* SMSC number index in phone memory */
712 SMS.MessageCenter.No = atoi(optarg);
714 if (SMS.MessageCenter.No < 1 || SMS.MessageCenter.No > 5)
716 data.MessageCenter = &SMS.MessageCenter;
717 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
719 case '3': /* we send long message */
720 input_len = atoi(optarg);
721 if (input_len > 255 * GSM_MAX_SMS_LENGTH) {
722 fprintf(stderr, _("Input too long!\n"));
726 case 'r': /* request for delivery report */
729 case 'C': /* class Message */
732 SMS.DCS.u.General.Class = 1;
735 SMS.DCS.u.General.Class = 2;
738 SMS.DCS.u.General.Class = 3;
741 SMS.DCS.u.General.Class = 4;
748 SMS.Validity.u.Relative = atoi(optarg);
751 usage(); /* Would be better to have an sendsms_usage() here. */
755 /* Get message text from stdin. */
756 chars_read = fread(message_buffer, 1, input_len, stdin);
758 if (chars_read == 0) {
759 fprintf(stderr, _("Couldn't read from stdin!\n"));
761 } else if (chars_read > input_len) {
762 fprintf(stderr, _("Input too long!\n"));
766 /* Null terminate. */
767 message_buffer[chars_read] = 0x00;
768 strncpy(SMS.MessageText, message_buffer, chars_read);
769 data.SMSMessage = &SMS;
771 /* Send the message. */
772 error = SM_Functions(GOP_SendSMS, &data, &State);
774 if (error == GE_SMSSENDOK) {
775 fprintf(stdout, _("Send succeeded!\n"));
777 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
780 if (GSM && GSM->Terminate) GSM->Terminate();
785 int savesms(int argc, char *argv[])
789 /* The maximum length of an uncompressed concatenated short message is
790 255 * 153 = 39015 default alphabet characters */
791 char message_buffer[255 * GSM_MAX_SMS_LENGTH];
792 int input_len, chars_read;
798 SMS.Type = SMS_Deliver;
799 SMS.DCS.Type = SMS_GeneralDataCoding;
800 SMS.DCS.u.General.Compressed = false;
801 SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
802 SMS.DCS.u.General.Class = 0;
803 SMS.MessageCenter.No = 1;
804 SMS.Validity.VPF = SMS_RelativeFormat;
805 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
807 SMS.Status = SMS_Unsent;
810 input_len = GSM_MAX_SMS_LENGTH;
813 while ((i = getopt(argc, argv, "ml:in:s:c:")) != -1) {
815 case 'm': /* mark the message as sent */
816 SMS.Status = SMS_Sent;
818 case 'l': /* Specify the location */
819 SMS.Number = atoi(optarg);
821 case 'i': /* Ask before overwriting */
824 case 'n': /* Specify the from number */
826 case 's': /* Specify the smsc number */
828 case 'c': /* Specify the smsc location */
839 aux.Number = SMS.Number;
840 data.SMSMessage = &aux;
841 error = SM_Functions(GOP_GetSMS, &data, &State);
844 fprintf(stderr, _("Message at specified location exists. "));
845 while (confirm < 0) {
846 fprintf(stderr, _("Overwrite? (yes/no) "));
847 GetLine(stdin, ans, 7);
848 if (!strcmp(ans, _("yes"))) confirm = 1;
849 else if (!strcmp(ans, _("no"))) confirm = 0;
852 if (GSM && GSM->Terminate) GSM->Terminate();
856 case GE_INVALIDSMSLOCATION:
857 fprintf(stderr, _("Invalid location\n"));
858 if (GSM && GSM->Terminate) GSM->Terminate();
861 dprintf("Location %d empty. Saving\n", SMS.Number);
865 chars_read = fread(message_buffer, 1, input_len, stdin);
867 if (chars_read == 0) {
869 fprintf(stderr, _("Couldn't read from stdin!\n"));
872 } else if (chars_read > input_len) {
874 fprintf(stderr, _("Input too long!\n"));
879 strncpy (SMS.MessageText, message_buffer, chars_read);
880 SMS.MessageText[chars_read] = 0;
882 error = GSM->SaveSMSMessage(&SMS);
884 if (error == GE_NONE) {
885 fprintf(stdout, _("Saved!\n"));
887 fprintf(stdout, _("Saving failed (error=%d)\n"), error);
890 if (GSM && GSM->Terminate) GSM->Terminate();
895 /* Get SMSC number */
896 int getsmsc(char *MessageCenterNumber)
898 SMS_MessageCenter MessageCenter;
902 memset(&MessageCenter, 0, sizeof(MessageCenter));
903 MessageCenter.No = atoi(MessageCenterNumber);
905 if (GSM && GSM->GetSMSCenter && GSM->Terminate) {
906 error = GSM->GetSMSCenter(&MessageCenter);
909 GSM_DataClear(&data);
910 data.MessageCenter = &MessageCenter;
911 error = SM_Functions(GOP_GetSMSCenter, &data, &State);
916 fprintf(stdout, _("%d. SMS center (%s) number is %s\n"), MessageCenter.No, MessageCenter.Name, MessageCenter.Number);
917 fprintf(stdout, _("Default recipient number is %s\n"), MessageCenter.Recipient);
918 fprintf(stdout, _("Messages sent as "));
920 switch (MessageCenter.Format) {
922 fprintf(stdout, _("Text"));
925 fprintf(stdout, _("VoiceMail"));
928 fprintf(stdout, _("Fax"));
932 fprintf(stdout, _("Email"));
935 fprintf(stdout, _("ERMES"));
938 fprintf(stdout, _("X.400"));
941 fprintf(stdout, _("Unknown"));
946 fprintf(stdout, _("Message validity is "));
948 switch (MessageCenter.Validity) {
950 fprintf(stdout, _("1 hour"));
953 fprintf(stdout, _("6 hours"));
956 fprintf(stdout, _("24 hours"));
959 fprintf(stdout, _("72 hours"));
962 fprintf(stdout, _("1 week"));
965 fprintf(stdout, _("Maximum time"));
968 fprintf(stdout, _("Unknown"));
972 fprintf(stdout, "\n");
975 case GE_NOTIMPLEMENTED:
976 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
979 fprintf(stdout, _("SMS center can not be found :-(\n"));
986 /* Get SMS messages. */
987 int getsms(int argc, char *argv[])
991 SMS_FolderList folderlist;
992 GSM_SMSMessage message;
993 char *memory_type_string;
994 int start_message, end_message, count, mode = 1;
1001 /* Handle command line args that set type, start and end locations. */
1002 memory_type_string = argv[2];
1003 message.MemoryType = StrToMemoryType(memory_type_string);
1004 if (message.MemoryType == GMT_XX) {
1005 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[2]);
1009 memset(&filename, 0, 64);
1011 start_message = end_message = atoi(argv[3]);
1015 /* [end] can be only argv[4] */
1016 if (argv[4][0] != '-') {
1017 end_message = atoi(argv[4]);
1020 /* parse all options (beginning with '-' */
1021 while ((i = getopt(argc, argv, "f:F:d")) != -1) {
1030 fprintf(stderr, _("Saving into %s\n"), optarg);
1031 strncpy(filename, optarg, 64);
1032 if (strlen(optarg) > 63) {
1033 fprintf(stderr, _("Filename too long - will be truncated to 63 characters.\n"));
1036 filename[strlen(optarg)] = 0;
1045 data.SMSFolderList = &folderlist;
1046 folder.FolderID = 0;
1047 data.SMSFolder = &folder;
1048 /* Now retrieve the requested entries. */
1049 for (count = start_message; count <= end_message; count ++) {
1052 message.Number = count;
1053 data.SMSMessage = &message;
1054 dprintf("MemoryType (gnokii.c) : %i\n", data.SMSMessage->MemoryType);
1055 error = SM_Functions(GOP_GetSMS, &data, &State);
1059 switch (message.Type) {
1061 fprintf(stdout, _("%d. MO Message "), message.Number);
1063 fprintf(stdout, _("(sent)\n"));
1064 fprintf(stdout, _("%d. MO Message "), message.Number);
1066 fprintf(stdout, _("(not sent)\n"));
1067 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1069 case SMS_Delivery_Report:
1070 fprintf(stdout, _("%d. Delivery Report "), message.Number);
1072 fprintf(stdout, _("(read)\n"));
1074 fprintf(stdout, _("(not read)\n"));
1075 fprintf(stdout, _("Sending date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1076 message.Time.Day, message.Time.Month, message.Time.Year, \
1077 message.Time.Hour, message.Time.Minute, message.Time.Second);
1078 if (message.Time.Timezone) {
1079 if (message.Time.Timezone > 0)
1080 fprintf(stdout,_("+%02d00"), message.Time.Timezone);
1082 fprintf(stdout,_("%02d00"), message.Time.Timezone);
1084 fprintf(stdout, "\n");
1085 fprintf(stdout, _("Response date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1086 message.SMSCTime.Day, message.SMSCTime.Month, message.SMSCTime.Year, \
1087 message.SMSCTime.Hour, message.SMSCTime.Minute, message.SMSCTime.Second);
1088 if (message.SMSCTime.Timezone) {
1089 if (message.SMSCTime.Timezone > 0)
1090 fprintf(stdout,_("+%02d00"),message.SMSCTime.Timezone);
1092 fprintf(stdout,_("%02d00"),message.SMSCTime.Timezone);
1094 fprintf(stdout, "\n");
1095 fprintf(stdout, _("Receiver: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1096 fprintf(stdout, _("Text: %s\n\n"), message.MessageText);
1099 fprintf(stdout, _("%d. Inbox Message "), message.Number);
1101 fprintf(stdout, _("(read)\n"));
1103 fprintf(stdout, _("(not read)\n"));
1104 fprintf(stdout, _("Date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
1105 message.Time.Day, message.Time.Month, message.Time.Year, \
1106 message.Time.Hour, message.Time.Minute, message.Time.Second);
1107 if (message.Time.Timezone) {
1108 if (message.Time.Timezone > 0)
1109 fprintf(stdout,_("+%02d00"),message.Time.Timezone);
1111 fprintf(stdout,_("%02d00"),message.Time.Timezone);
1113 fprintf(stdout, "\n");
1114 fprintf(stdout, _("Sender: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
1115 switch (message.UDH[0].Type) {
1117 fprintf(stdout, _("GSM operator logo for %s (%s) network.\n"), bitmap.netcode, GSM_GetNetworkName(bitmap.netcode));
1118 if (!strcmp(message.RemoteNumber.number, "+998000005") && !strcmp(message.MessageCenter.Number, "+886935074443")) fprintf(stdout, _("Saved by Logo Express\n"));
1119 if (!strcmp(message.RemoteNumber.number, "+998000002") || !strcmp(message.RemoteNumber.number, "+998000003")) fprintf(stdout, _("Saved by Operator Logo Uploader by Thomas Kessler\n"));
1121 case SMS_CallerIDLogo:
1122 fprintf(stdout, ("Logo:\n"));
1123 /* put bitmap into bitmap structure */
1124 GSM_ReadSMSBitmap(message.UDH[0].Type, message.MessageText+2+offset, message.MessageText, &bitmap);
1125 GSM_PrintBitmap(&bitmap);
1128 if ((stat(filename, &buf) == 0)) {
1129 fprintf(stdout, _("File %s exists.\n"), filename);
1130 fprintf(stdout, _("Overwrite? (yes/no) "));
1131 GetLine(stdin, ans, 4);
1132 if (!strcmp(ans, _("yes"))) {
1133 error = GSM_SaveBitmapFile(filename, &bitmap);
1135 } else error = GSM_SaveBitmapFile(filename, &bitmap);
1136 if (error != GE_NONE) fprintf(stderr, _("Couldn't save logofile %s!\n"), filename);
1140 fprintf(stdout, _("Ringtone\n"));
1142 case SMS_ConcatenatedMessages:
1143 fprintf(stdout, _("Linked (%d/%d):\n"),
1144 message.UDH[0].u.ConcatenatedShortMessage.CurrentNumber,
1145 message.UDH[0].u.ConcatenatedShortMessage.MaximumNumber);
1147 fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText);
1148 if ((mode != -1) && *filename) {
1150 sprintf(buf, "%s%d", filename, count);
1151 mode = GSM_SaveTextFile(buf, message.MessageText, mode);
1154 case SMS_BusinessCard:
1155 fprintf(stdout, _("Business Card:\n%s"), message.MessageText);
1158 fprintf(stderr, _("Unknown\n"));
1164 data.SMSMessage = &message;
1165 if (GE_NONE != SM_Functions(GOP_DeleteSMS, &data, &State))
1166 fprintf(stdout, _("(delete failed)\n"));
1168 fprintf(stdout, _("(message deleted)\n"));
1171 case GE_NOTIMPLEMENTED:
1172 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1173 if (GSM && GSM->Terminate) GSM->Terminate();
1175 case GE_INVALIDSMSLOCATION:
1176 fprintf(stderr, _("Invalid location: %s %d\n"), memory_type_string, count);
1178 case GE_EMPTYSMSLOCATION:
1179 fprintf(stderr, _("SMS location %s %d empty.\n"), memory_type_string, count);
1182 fprintf(stdout, _("GetSMS %s %d failed!(%s)\n\n"), memory_type_string, count, print_error(error));
1187 if (GSM && GSM->Terminate) GSM->Terminate();
1192 /* Delete SMS messages. */
1193 int deletesms(int argc, char *argv[])
1195 GSM_SMSMessage message;
1196 char *memory_type_string;
1197 int start_message, end_message, count;
1200 /* Handle command line args that set type, start and end locations. */
1201 memory_type_string = argv[0];
1202 message.MemoryType = StrToMemoryType(memory_type_string);
1203 if (message.MemoryType == GMT_XX) {
1204 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
1208 start_message = end_message = atoi (argv[1]);
1209 if (argc > 2) end_message = atoi (argv[2]);
1211 /* Now delete the requested entries. */
1212 for (count = start_message; count <= end_message; count ++) {
1214 message.Number = count;
1215 data.SMSMessage = &message;
1216 error = SM_Functions(GOP_DeleteSMS, &data, &State);
1218 if (error == GE_NONE)
1219 fprintf(stdout, _("Deleted SMS %s %d\n"), memory_type_string, count);
1221 if (error == GE_NOTIMPLEMENTED) {
1222 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1223 if (GSM && GSM->Terminate) GSM->Terminate();
1226 fprintf(stdout, _("DeleteSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
1230 if (GSM && GSM->Terminate) GSM->Terminate();
1235 static volatile bool bshutdown = false;
1237 /* SIGINT signal handler. */
1238 static void interrupted(int sig)
1240 signal(sig, SIG_IGN);
1246 /* In this mode we get the code from the keyboard and send it to the mobile
1248 int entersecuritycode(char *type)
1251 GSM_SecurityCode SecurityCode;
1253 if (!strcmp(type, "PIN"))
1254 SecurityCode.Type = GSCT_Pin;
1255 else if (!strcmp(type, "PUK"))
1256 SecurityCode.Type = GSCT_Puk;
1257 else if (!strcmp(type, "PIN2"))
1258 SecurityCode.Type = GSCT_Pin2;
1259 else if (!strcmp(type, "PUK2"))
1260 SecurityCode.Type = GSCT_Puk2;
1261 /* FIXME: Entering of SecurityCode does not work :-(
1262 else if (!strcmp(type, "SecurityCode"))
1263 SecurityCode.Type = GSCT_SecurityCode;
1269 printf("Enter your code: ");
1270 gets(SecurityCode.Code);
1272 strcpy(SecurityCode.Code, getpass(_("Enter your code: ")));
1275 if (GSM && GSM->EnterSecurityCode) test = GSM->EnterSecurityCode(SecurityCode);
1276 if (test == GE_INVALIDSECURITYCODE)
1277 fprintf(stdout, _("Error: invalid code.\n"));
1278 else if (test == GE_NONE)
1279 fprintf(stdout, _("Code ok.\n"));
1280 else if (test == GE_NOTIMPLEMENTED)
1281 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
1283 fprintf(stdout, _("Other error.\n"));
1285 if (GSM && GSM->Terminate) GSM->Terminate();
1290 int getsecuritycodestatus(void)
1294 if (GSM && GSM->GetSecurityCodeStatus && GSM->GetSecurityCodeStatus(&Status) == GE_NONE) {
1296 fprintf(stdout, _("Security code status: "));
1299 case GSCT_SecurityCode:
1300 fprintf(stdout, _("waiting for Security Code.\n"));
1303 fprintf(stdout, _("waiting for PIN.\n"));
1306 fprintf(stdout, _("waiting for PIN2.\n"));
1309 fprintf(stdout, _("waiting for PUK.\n"));
1312 fprintf(stdout, _("waiting for PUK2.\n"));
1315 fprintf(stdout, _("nothing to enter.\n"));
1318 fprintf(stdout, _("Unknown!\n"));
1323 if (GSM && GSM->Terminate) GSM->Terminate();
1331 /* Voice dialing mode. */
1332 int dialvoice(char *Number)
1334 if (GSM && GSM->DialVoice) GSM->DialVoice(Number);
1336 if (GSM && GSM->Terminate) GSM->Terminate();
1341 /* The following function allows to send logos using SMS */
1342 int sendlogo(int argc, char *argv[])
1348 char UserDataHeader[7] = { 0x06, /* UDH Length */
1349 0x05, /* IEI: application port addressing scheme, 16 bit address */
1350 0x04, /* IEI length */
1351 0x15, /* destination address: high byte */
1352 0x00, /* destination address: low byte */
1353 0x00, /* originator address */
1356 char Data[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1360 /* Default settings for SMS message:
1361 - no delivery report
1367 - set UserDataHeaderIndicator
1369 SMS.Type = SMS_Submit;
1370 SMS.DCS.Type = SMS_GeneralDataCoding;
1371 SMS.DCS.u.General.Compressed = false;
1372 SMS.DCS.u.General.Alphabet = SMS_8bit;
1373 SMS.DCS.u.General.Class = 2;
1374 SMS.MessageCenter.No = 1;
1375 SMS.Validity.VPF = SMS_RelativeFormat;
1376 SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
1378 /* The first argument is the type of the logo. */
1379 if (!strcmp(argv[0], "op")) {
1380 SMS.UDH[0].Type = SMS_OpLogo;
1381 UserDataHeader[4] = 0x82; /* NBS port 0x1582 */
1382 fprintf(stdout, _("Sending operator logo.\n"));
1383 } else if (!strcmp(argv[0], "caller")) {
1384 SMS.UDH[0].Type = SMS_CallerIDLogo;
1385 UserDataHeader[4] = 0x83; /* NBS port 0x1583 */
1386 fprintf(stdout, _("Sending caller line identification logo.\n"));
1388 fprintf(stderr, _("You should specify what kind of logo to send!\n"));
1392 /* The second argument is the destination, ie the phone number of recipient. */
1393 SMS.MemoryType = atoi(argv[1]);
1395 /* The third argument is the bitmap file. */
1396 GSM_ReadBitmapFile(argv[2], &bitmap);
1398 /* If we are sending op logo we can rewrite network code. */
1399 if (!strcmp(argv[0], "op")) {
1401 * The fourth argument, if present, is the Network code of the operator.
1402 * Network code is in this format: "xxx yy".
1405 strcpy(bitmap.netcode, argv[3]);
1407 fprintf(stdout, _("Operator code: %s\n"), argv[3]);
1411 /* Set the network code */
1412 Data[current++] = ((bitmap.netcode[1] & 0x0f) << 4) | (bitmap.netcode[0] & 0xf);
1413 Data[current++] = 0xf0 | (bitmap.netcode[2] & 0x0f);
1414 Data[current++] = ((bitmap.netcode[5] & 0x0f) << 4) | (bitmap.netcode[4] & 0xf);
1417 /* Set the logo size */
1419 Data[current++] = bitmap.width;
1420 Data[current++] = bitmap.height;
1422 Data[current++] = 0x01;
1424 memcpy(SMS.MessageText, UserDataHeader, 7);
1425 memcpy(SMS.MessageText, Data, current);
1426 memcpy(SMS.MessageText+current, bitmap.bitmap, bitmap.size);
1428 /* Send the message. */
1429 error = GSM->SendSMSMessage(&SMS,current+bitmap.size);
1431 if (error == GE_SMSSENDOK)
1432 fprintf(stdout, _("Send succeeded!\n"));
1434 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
1440 /* Getting logos. */
1441 GSM_Error SaveBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1448 /* Ask before overwriting */
1449 while (stat(FileName, &buf) == 0) {
1452 fprintf(stderr, _("Saving logo. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "), FileName);
1453 GetLine(stdin, ans, 4);
1454 if (!strcmp(ans, _("O")) || !strcmp(ans, _("o"))) confirm = 1;
1455 if (!strcmp(ans, _("N")) || !strcmp(ans, _("n"))) confirm = 2;
1456 if (!strcmp(ans, _("S")) || !strcmp(ans, _("s"))) return GE_USERCANCELED;
1458 if (confirm == 1) break;
1460 fprintf(stderr, _("Enter name of new file: "));
1461 GetLine(stdin, FileName, 50);
1462 if (!FileName || (*FileName == 0)) return GE_USERCANCELED;
1466 error = GSM_SaveBitmapFile(FileName, bitmap);
1469 case GE_CANTOPENFILE:
1470 fprintf(stderr, _("Failed to write file \"%s\"\n"), FileName);
1479 int getlogo(int argc, char *argv[])
1483 GSM_Statemachine *sm = &State;
1485 bitmap.type=GSM_None;
1487 if (!strcmp(argv[0], "op"))
1488 bitmap.type = GSM_OperatorLogo;
1490 if (!strcmp(argv[0], "caller")) {
1491 /* There is caller group number missing in argument list. */
1493 bitmap.number=argv[2][0]-'0';
1494 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1498 bitmap.type = GSM_CallerLogo;
1501 if (!strcmp(argv[0],"startup"))
1502 bitmap.type = GSM_StartupLogo;
1503 else if (!strcmp(argv[0], "dealer"))
1504 bitmap.type = GSM_DealerNoteText;
1505 else if (!strcmp(argv[0], "text"))
1506 bitmap.type=GSM_WelcomeNoteText;
1508 if (bitmap.type != GSM_None) {
1510 fprintf(stdout, _("Getting Logo\n"));
1512 data.Bitmap=&bitmap;
1513 error=SM_Functions(GOP_GetBitmap, &data, sm);
1517 if (bitmap.type == GSM_DealerNoteText) fprintf(stdout, _("Dealer welcome note "));
1518 if (bitmap.type == GSM_WelcomeNoteText) fprintf(stdout, _("Welcome note "));
1519 if (bitmap.type == GSM_DealerNoteText || bitmap.type==GSM_WelcomeNoteText) {
1520 if (bitmap.text[0]) {
1521 fprintf(stdout, _("currently set to \"%s\"\n"), bitmap.text);
1523 fprintf(stdout, _("currently empty\n"));
1527 switch (bitmap.type) {
1528 case GSM_OperatorLogo:
1529 fprintf(stdout,"Operator logo for %s (%s) network got succesfully\n",bitmap.netcode,GSM_GetNetworkName(bitmap.netcode));
1531 strncpy(bitmap.netcode,argv[2], 7);
1532 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1533 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1538 case GSM_StartupLogo:
1539 fprintf(stdout, "Startup logo got successfully\n");
1541 strncpy(bitmap.netcode,argv[2], 7);
1542 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1543 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1548 case GSM_CallerLogo:
1549 fprintf(stdout,"Caller logo got successfully\n");
1551 strncpy(bitmap.netcode,argv[3],7);
1552 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1553 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1559 fprintf(stdout,"Unknown bitmap type.\n");
1563 if (SaveBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) return (-1);
1566 fprintf(stdout,"Your phone doesn't have logo uploaded !\n");
1571 case GE_NOTIMPLEMENTED:
1572 fprintf(stderr, _("Function not implemented !\n"));
1574 case GE_NOTSUPPORTED:
1575 fprintf(stderr, _("This kind of logo is not supported !\n"));
1578 fprintf(stderr, _("Error getting logo !\n"));
1582 fprintf(stderr, _("What kind of logo do you want to get ?\n"));
1590 /* Sending logos. */
1591 GSM_Error ReadBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
1595 error = GSM_ReadBitmapFile(FileName, bitmap);
1598 case GE_CANTOPENFILE:
1599 fprintf(stderr, _("Failed to read file \"%s\"\n"), FileName);
1601 case GE_WRONGNUMBEROFCOLORS:
1602 fprintf(stderr, _("Wrong number of colors in \"%s\" logofile (accepted only 2-colors files) !\n"), FileName);
1604 case GE_WRONGCOLORS:
1605 fprintf(stderr, _("Wrong colors in \"%s\" logofile !\n"), FileName);
1607 case GE_INVALIDFILEFORMAT:
1608 fprintf(stderr, _("Invalid format of \"%s\" logofile !\n"), FileName);
1610 case GE_SUBFORMATNOTSUPPORTED:
1611 fprintf(stderr, _("Sorry, gnokii doesn't support used subformat in file \"%s\" !\n"), FileName);
1613 case GE_FILETOOSHORT:
1614 fprintf(stderr, _("\"%s\" logofile is too short !\n"), FileName);
1616 case GE_INVALIDIMAGESIZE:
1617 fprintf(stderr, _("Bitmap size doesn't supported by fileformat or different from 72x14, 84x48 and 72x28 !\n"));
1627 int setlogo(int argc, char *argv[])
1629 GSM_Bitmap bitmap,oldbit;
1630 GSM_NetworkInfo NetworkInfo;
1636 if (!strcmp(argv[0],"text") || !strcmp(argv[0],"dealer")) {
1637 if (!strcmp(argv[0], "text")) bitmap.type = GSM_WelcomeNoteText;
1638 else bitmap.type = GSM_DealerNoteText;
1639 bitmap.text[0] = 0x00;
1640 if (argc > 1) strncpy(bitmap.text, argv[1], 255);
1642 if (!strcmp(argv[0], "op") || !strcmp(argv[0], "startup") || !strcmp(argv[0], "caller")) {
1644 if (ReadBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) {
1645 if (GSM && GSM->Terminate) GSM->Terminate();
1649 if (!strcmp(argv[0], "op")) {
1650 if (bitmap.type != GSM_OperatorLogo || argc < 3) {
1651 if (GSM && GSM->GetNetworkInfo && GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode, NetworkInfo.NetworkCode, 7);
1653 GSM_ResizeBitmap(&bitmap, GSM_OperatorLogo, GSM_Info);
1655 strncpy(bitmap.netcode, argv[2], 7);
1656 if (!strcmp(GSM_GetNetworkName(bitmap.netcode), "unknown")) {
1657 fprintf(stderr, "Sorry, gnokii doesn't know %s network !\n", bitmap.netcode);
1662 if (!strcmp(argv[0], "startup")) {
1663 GSM_ResizeBitmap(&bitmap, GSM_StartupLogo, GSM_Info);
1665 if (!strcmp(argv[0],"caller")) {
1666 GSM_ResizeBitmap(&bitmap, GSM_CallerLogo, GSM_Info);
1668 bitmap.number = argv[2][0] - '0';
1669 if ((bitmap.number < 0) || (bitmap.number > 9)) bitmap.number = 0;
1673 oldbit.type = GSM_CallerLogo;
1674 oldbit.number = bitmap.number;
1675 if (GSM && GSM->GetBitmap && GSM->GetBitmap(&oldbit) == GE_NONE) {
1676 /* We have to get the old name and ringtone!! */
1677 bitmap.ringtone = oldbit.ringtone;
1678 strncpy(bitmap.text, oldbit.text, 255);
1680 if (argc > 3) strncpy(bitmap.text, argv[3], 255);
1682 fprintf(stdout, _("Setting Logo.\n"));
1684 /* FIX ME: is it possible to permanently remove op logo ? */
1685 if (!strcmp(argv[0], "op"))
1687 bitmap.type = GSM_OperatorLogo;
1688 strncpy(bitmap.netcode, "000 00", 7);
1691 bitmap.size = bitmap.width * bitmap.height / 8;
1692 GSM_ClearBitmap(&bitmap);
1694 /* FIX ME: how to remove startup and group logos ? */
1695 fprintf(stdout, _("Removing Logo.\n"));
1698 fprintf(stderr, _("What kind of logo do you want to set ?\n"));
1699 if (GSM && GSM->Terminate) GSM->Terminate();
1704 if (GSM && GSM->SetBitmap) error = GSM->SetBitmap(&bitmap);
1708 oldbit.type = bitmap.type;
1709 oldbit.number = bitmap.number;
1710 if (GSM && GSM->GetBitmap && GSM->GetBitmap(&oldbit) == GE_NONE) {
1711 if (bitmap.type == GSM_WelcomeNoteText ||
1712 bitmap.type == GSM_DealerNoteText) {
1713 if (strcmp(bitmap.text, oldbit.text)) {
1714 fprintf(stderr, _("Error setting"));
1715 if (bitmap.type == GSM_DealerNoteText) fprintf(stderr, _(" dealer"));
1716 fprintf(stderr, _(" welcome note - "));
1718 /* I know, it looks horrible, but... */
1719 /* I set it to the short string - if it won't be set */
1720 /* it means, PIN is required. If it will be correct, previous */
1721 /* (user) text was too long */
1723 /* Without it, I could have such thing: */
1724 /* user set text to very short string (for example, "Marcin") */
1725 /* then enable phone without PIN and try to set it to the very long (too long for phone) */
1726 /* string (which start with "Marcin"). If we compare them as only length different, we could think, */
1727 /* that phone accepts strings 6 chars length only (length of "Marcin") */
1728 /* When we make it correct, we don't have this mistake */
1730 strcpy(oldbit.text, "!\0");
1731 if (GSM && GSM->SetBitmap) GSM->SetBitmap(&oldbit);
1732 if (GSM && GSM->GetBitmap) GSM->GetBitmap(&oldbit);
1733 if (oldbit.text[0]!='!') {
1734 fprintf(stderr, _("SIM card and PIN is required\n"));
1736 if (GSM && GSM->SetBitmap) GSM->SetBitmap(&bitmap);
1737 if (GSM && GSM->GetBitmap) GSM->GetBitmap(&oldbit);
1738 fprintf(stderr, _("too long, truncated to \"%s\" (length %i)\n"),oldbit.text,strlen(oldbit.text));
1743 if (bitmap.type == GSM_StartupLogo) {
1744 for (i = 0; i < oldbit.size; i++) {
1745 if (oldbit.bitmap[i] != bitmap.bitmap[i]) {
1746 fprintf(stderr, _("Error setting startup logo - SIM card and PIN is required\n"));
1754 if (ok) fprintf(stdout, _("Done.\n"));
1756 case GE_NOTIMPLEMENTED:
1757 fprintf(stderr, _("Function not implemented.\n"));
1759 case GE_NOTSUPPORTED:
1760 fprintf(stderr, _("This kind of logo is not supported.\n"));
1763 fprintf(stderr, _("Error !\n"));
1767 if (GSM && GSM->Terminate) GSM->Terminate();
1773 int viewlogo(char *filename)
1777 error = GSM_ShowBitmapFile(filename);
1781 /* Calendar notes receiving. */
1782 int getcalendarnote(int argc, char *argv[])
1784 GSM_CalendarNote CalendarNote;
1786 GSM_Error error = GE_NONE;
1787 int i, first_location, last_location;
1790 struct option options[] = {
1791 { "vCard", optional_argument, NULL, '1'},
1798 first_location = last_location = atoi(argv[0]);
1799 if ((argc > 1) && (argv[1][0] != '-')) {
1800 last_location = atoi(argv[1]);
1803 while ((i = getopt_long(argc, argv, "v", options, NULL)) != -1) {
1809 usage(); /* Would be better to have an calendar_usage() here. */
1815 for (i = first_location; i <= last_location; i++) {
1816 CalendarNote.Location = i;
1817 if (GSM && GSM->GetCalendarNote && GSM->Terminate) {
1818 error = GSM->GetCalendarNote(&CalendarNote);
1821 GSM_DataClear(&data);
1822 data.CalendarNote = &CalendarNote;
1824 error = SM_Functions(GOP_GetCalendarNote, &data, &State);
1829 fprintf(stdout, "BEGIN:VCALENDAR\n");
1830 fprintf(stdout, "VERSION:1.0\n");
1831 fprintf(stdout, "BEGIN:VEVENT\n");
1832 fprintf(stdout, "CATEGORIES:");
1833 switch (CalendarNote.Type) {
1835 fprintf(stdout, "MISCELLANEOUS\n");
1838 fprintf(stdout, "PHONE CALL\n");
1841 fprintf(stdout, "MEETING\n");
1844 fprintf(stdout, "SPECIAL OCCASION\n");
1847 fprintf(stdout, "UNKNOWN\n");
1850 fprintf(stdout, "SUMMARY:%s\n",CalendarNote.Text);
1851 fprintf(stdout, "DTSTART:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Time.Year,
1852 CalendarNote.Time.Month, CalendarNote.Time.Day, CalendarNote.Time.Hour,
1853 CalendarNote.Time.Minute, CalendarNote.Time.Second);
1854 if (CalendarNote.Alarm.Year!=0) {
1855 fprintf(stdout, "DALARM:%04d%02d%02dT%02d%02d%02d\n", CalendarNote.Alarm.Year,
1856 CalendarNote.Alarm.Month, CalendarNote.Alarm.Day, CalendarNote.Alarm.Hour,
1857 CalendarNote.Alarm.Minute, CalendarNote.Alarm.Second);
1859 fprintf(stdout, "END:VEVENT\n");
1860 fprintf(stdout, "END:VCALENDAR\n");
1862 } else { /* not vCal */
1863 fprintf(stdout, _(" Type of the note: "));
1865 switch (CalendarNote.Type) {
1867 fprintf(stdout, _("Reminder\n"));
1870 fprintf(stdout, _("Call\n"));
1873 fprintf(stdout, _("Meeting\n"));
1876 fprintf(stdout, _("Birthday\n"));
1879 fprintf(stdout, _("Unknown\n"));
1883 fprintf(stdout, _(" Date: %d-%02d-%02d\n"), CalendarNote.Time.Year,
1884 CalendarNote.Time.Month,
1885 CalendarNote.Time.Day);
1887 fprintf(stdout, _(" Time: %02d:%02d:%02d\n"), CalendarNote.Time.Hour,
1888 CalendarNote.Time.Minute,
1889 CalendarNote.Time.Second);
1891 if (CalendarNote.Alarm.AlarmEnabled == 1) {
1892 fprintf(stdout, _(" Alarm date: %d-%02d-%02d\n"), CalendarNote.Alarm.Year,
1893 CalendarNote.Alarm.Month,
1894 CalendarNote.Alarm.Day);
1896 fprintf(stdout, _(" Alarm time: %02d:%02d:%02d\n"), CalendarNote.Alarm.Hour,
1897 CalendarNote.Alarm.Minute,
1898 CalendarNote.Alarm.Second);
1901 fprintf(stdout, _(" Text: %s\n"), CalendarNote.Text);
1903 if (CalendarNote.Type == GCN_CALL)
1904 fprintf(stdout, _(" Phone: %s\n"), CalendarNote.Phone);
1907 case GE_NOTIMPLEMENTED:
1908 fprintf(stderr, _("Function not implemented.\n"));
1911 fprintf(stderr, _("The calendar note can not be read\n"));
1916 if (GSM && GSM->Terminate) GSM->Terminate();
1920 /* Writing calendar notes. */
1921 int writecalendarnote(char *argv[])
1923 GSM_CalendarNote CalendarNote;
1925 if (GSM_ReadVCalendarFile(argv[0], &CalendarNote, atoi(argv[1]))) {
1926 fprintf(stdout, _("Failed to load vCalendar file.\n"));
1930 /* Error 22=Calendar full ;-) */
1931 if (GSM && GSM->WriteCalendarNote && GSM->WriteCalendarNote(&CalendarNote) == GE_NONE)
1932 fprintf(stdout, _("Succesfully written!\n"));
1934 fprintf(stdout, _("Failed to write calendar note!\n"));
1936 if (GSM && GSM->Terminate) GSM->Terminate();
1941 /* Calendar note deleting. */
1942 int deletecalendarnote(int argc, char *argv[])
1944 GSM_CalendarNote CalendarNote;
1945 int i, first_location, last_location;
1947 first_location = last_location = atoi(argv[0]);
1948 if (argc > 1) last_location = atoi(argv[1]);
1950 for (i = first_location; i <= last_location; i++) {
1952 CalendarNote.Location = i;
1954 if (GSM && GSM->DeleteCalendarNote && GSM->DeleteCalendarNote(&CalendarNote) == GE_NONE) {
1955 fprintf(stdout, _(" Calendar note deleted.\n"));
1957 fprintf(stderr, _("The calendar note can not be deleted\n"));
1962 if (GSM && GSM->Terminate) GSM->Terminate();
1967 /* Setting the date and time. */
1968 int setdatetime(int argc, char *argv[])
1975 now = localtime(&nowh);
1977 Date.Year = now->tm_year;
1978 Date.Month = now->tm_mon+1;
1979 Date.Day = now->tm_mday;
1980 Date.Hour = now->tm_hour;
1981 Date.Minute = now->tm_min;
1982 Date.Second = now->tm_sec;
1984 if (argc > 0) Date.Year = atoi (argv[0]);
1985 if (argc > 1) Date.Month = atoi (argv[1]);
1986 if (argc > 2) Date.Day = atoi (argv[2]);
1987 if (argc > 3) Date.Hour = atoi (argv[3]);
1988 if (argc > 4) Date.Minute = atoi (argv[4]);
1990 if (Date.Year < 1900) {
1992 /* Well, this thing is copyrighted in U.S. This technique is known as
1993 Windowing and you can read something about it in LinuxWeekly News:
1994 http://lwn.net/1999/features/Windowing.phtml. This thing is beeing
1995 written in Czech republic and Poland where algorithms are not allowed
1999 Date.Year = Date.Year + 1900;
2001 Date.Year = Date.Year + 2000;
2004 /* FIXME: Error checking should be here. */
2005 if (GSM && GSM->SetDateTime) GSM->SetDateTime(&Date);
2007 if (GSM && GSM->Terminate) GSM->Terminate();
2012 /* In this mode we receive the date and time from mobile phone. */
2013 int getdatetime(void)
2016 GSM_DateTime date_time;
2019 if (GSM && GSM->GetDateTime && GSM->Terminate) {
2020 error = GSM->GetDateTime(&date_time);
2023 GSM_DataClear(&data);
2024 data.DateTime = &date_time;
2026 error = SM_Functions(GOP_GetDateTime, &data, &State);
2031 fprintf(stdout, _("Date: %4d/%02d/%02d\n"), date_time.Year, date_time.Month, date_time.Day);
2032 fprintf(stdout, _("Time: %02d:%02d:%02d\n"), date_time.Hour, date_time.Minute, date_time.Second);
2034 case GE_NOTIMPLEMENTED:
2035 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2038 fprintf(stdout, _("Internal error\n"));
2045 /* Setting the alarm. */
2046 int setalarm(char *argv[])
2050 Date.Hour = atoi(argv[0]);
2051 Date.Minute = atoi(argv[1]);
2053 if (GSM && GSM->SetAlarm) GSM->SetAlarm(1, &Date);
2055 if (GSM && GSM->Terminate) GSM->Terminate();
2060 /* Getting the alarm. */
2065 GSM_DateTime date_time;
2067 if (GSM && GSM->GetAlarm && GSM->Terminate) {
2068 error = GSM->GetAlarm(0, &date_time);
2071 GSM_DataClear(&data);
2072 data.DateTime = &date_time;
2074 error = SM_Functions(GOP_GetAlarm, &data, &State);
2079 fprintf(stdout, _("Alarm: %s\n"), (date_time.AlarmEnabled==0)?"off":"on");
2080 fprintf(stdout, _("Time: %02d:%02d\n"), date_time.Hour, date_time.Minute);
2082 case GE_NOTIMPLEMENTED:
2083 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2086 fprintf(stdout, _("Internal error\n"));
2093 /* In monitor mode we don't do much, we just initialise the fbus code.
2094 Note that the fbus code no longer has an internal monitor mode switch,
2095 instead compile with DEBUG enabled to get all the gumpf. */
2096 int monitormode(void)
2098 float rflevel = -1, batterylevel = -1;
2099 // GSM_PowerSource powersource = -1;
2100 GSM_RFUnits rf_units = GRF_Arbitrary;
2101 GSM_BatteryUnits batt_units = GBU_Arbitrary;
2102 GSM_Statemachine *sm = &State;
2105 // GSM_NetworkInfo NetworkInfo;
2106 // GSM_CBMessage CBMessage;
2108 GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0};
2109 GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0};
2110 GSM_MemoryStatus DC_MemoryStatus = {GMT_DC, 0, 0};
2111 GSM_MemoryStatus EN_MemoryStatus = {GMT_EN, 0, 0};
2112 GSM_MemoryStatus FD_MemoryStatus = {GMT_FD, 0, 0};
2113 GSM_MemoryStatus LD_MemoryStatus = {GMT_LD, 0, 0};
2114 GSM_MemoryStatus MC_MemoryStatus = {GMT_MC, 0, 0};
2115 GSM_MemoryStatus ON_MemoryStatus = {GMT_ON, 0, 0};
2116 GSM_MemoryStatus RC_MemoryStatus = {GMT_RC, 0, 0};
2118 // GSM_SMSStatus SMSStatus = {0, 0};
2122 GSM_DataClear(&data);
2124 /* We do not want to monitor serial line forever - press Ctrl+C to stop the
2126 signal(SIGINT, interrupted);
2128 fprintf (stderr, _("Entering monitor mode...\n"));
2131 //GSM->EnableCellBroadcast();
2133 /* Loop here indefinitely - allows you to see messages from GSM code in
2134 response to unknown messages etc. The loops ends after pressing the
2136 data.RFUnits = &rf_units;
2137 data.RFLevel = &rflevel;
2138 data.BatteryUnits = &batt_units;
2139 data.BatteryLevel = &batterylevel;
2141 while (!bshutdown) {
2142 if (SM_Functions(GOP_GetRFLevel, &data, sm) == GE_NONE)
2143 fprintf(stdout, _("RFLevel: %d\n"), (int)rflevel);
2145 if (SM_Functions(GOP_GetBatteryLevel, &data, sm) == GE_NONE)
2146 fprintf(stdout, _("Battery: %d\n"), (int)batterylevel);
2148 // if (GSM->GetPowerSource(&powersource) == GE_NONE)
2149 // fprintf(stdout, _("Power Source: %s\n"), (powersource==GPS_ACDC)?_("AC/DC"):_("battery"));
2151 data.MemoryStatus = &SIMMemoryStatus;
2152 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2153 fprintf(stdout, _("SIM: Used %d, Free %d\n"), SIMMemoryStatus.Used, SIMMemoryStatus.Free);
2155 data.MemoryStatus = &PhoneMemoryStatus;
2156 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2157 fprintf(stdout, _("Phone: Used %d, Free %d\n"), PhoneMemoryStatus.Used, PhoneMemoryStatus.Free);
2159 data.MemoryStatus = &DC_MemoryStatus;
2160 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2161 fprintf(stdout, _("DC: Used %d, Free %d\n"), DC_MemoryStatus.Used, DC_MemoryStatus.Free);
2163 data.MemoryStatus = &EN_MemoryStatus;
2164 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2165 fprintf(stdout, _("EN: Used %d, Free %d\n"), EN_MemoryStatus.Used, EN_MemoryStatus.Free);
2167 data.MemoryStatus = &FD_MemoryStatus;
2168 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2169 fprintf(stdout, _("FD: Used %d, Free %d\n"), FD_MemoryStatus.Used, FD_MemoryStatus.Free);
2171 data.MemoryStatus = &LD_MemoryStatus;
2172 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2173 fprintf(stdout, _("LD: Used %d, Free %d\n"), LD_MemoryStatus.Used, LD_MemoryStatus.Free);
2175 data.MemoryStatus = &MC_MemoryStatus;
2176 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2177 fprintf(stdout, _("MC: Used %d, Free %d\n"), MC_MemoryStatus.Used, MC_MemoryStatus.Free);
2179 data.MemoryStatus = &ON_MemoryStatus;
2180 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2181 fprintf(stdout, _("ON: Used %d, Free %d\n"), ON_MemoryStatus.Used, ON_MemoryStatus.Free);
2183 data.MemoryStatus = &RC_MemoryStatus;
2184 if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
2185 fprintf(stdout, _("RC: Used %d, Free %d\n"), RC_MemoryStatus.Used, RC_MemoryStatus.Free);
2187 // if (GSM->GetSMSStatus(&SMSStatus) == GE_NONE)
2188 // fprintf(stdout, _("SMS Messages: UnRead %d, Number %d\n"), SMSStatus.UnRead, SMSStatus.Number);
2190 // if (GSM->GetIncomingCallNr(Number) == GE_NONE)
2191 // fprintf(stdout, _("Incoming call: %s\n"), Number);
2193 // if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE)
2194 // fprintf(stdout, _("Network: %s (%s), LAC: %s, CellID: %s\n"), GSM_GetNetworkName (NetworkInfo.NetworkCode), GSM_GetCountryName(NetworkInfo.NetworkCode), NetworkInfo.LAC, NetworkInfo.CellID);
2196 // if (GSM->ReadCellBroadcast(&CBMessage) == GE_NONE)
2197 // fprintf(stdout, _("Cell broadcast received on channel %d: %s\n"), CBMessage.Channel, CBMessage.Message);
2202 fprintf(stderr, _("Leaving monitor mode...\n"));
2210 static GSM_Error PrettyOutputFn(char *Display, char *Indicators)
2213 printf(ESC "[10;0H Display is:\n%s\n", Display);
2215 printf(ESC "[9;0H Indicators: %s \n", Indicators);
2216 printf(ESC "[1;1H");
2221 /* Uncomment it if used */
2222 static GSM_Error OutputFn(char *Display, char *Indicators)
2225 printf("New display is:\n%s\n", Display);
2227 printf("Indicators: %s\n", Indicators);
2232 void console_raw(void)
2237 tcgetattr(fileno(stdin), &it);
2238 it.c_lflag &= ~(ICANON);
2239 //it.c_iflag &= ~(INPCK|ISTRIP|IXON);
2243 tcsetattr(fileno(stdin), TCSANOW, &it);
2247 int displayoutput(void)
2250 GSM_Statemachine *sm = &State;
2253 data.OutputFn = PrettyOutputFn;
2255 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2257 fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
2259 if (error == GE_NONE) {
2261 /* We do not want to see texts forever - press Ctrl+C to stop. */
2262 signal(SIGINT, interrupted);
2264 fprintf (stderr, _("Entered display monitoring mode...\n"));
2265 fprintf (stderr, ESC "c" );
2267 /* Loop here indefinitely - allows you to read texts from phone's
2268 display. The loops ends after pressing the Ctrl+C. */
2269 while (!bshutdown) {
2271 memset(&buf[0], 0, 102);
2272 while (read(0, buf, 100) > 0) {
2273 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
2274 if (GSM && GSM->HandleString && GSM->HandleString(buf) != GE_NONE)
2275 fprintf(stdout, _("Key press simulation failed.\n"));
2276 memset(buf, 0, 102);
2280 fprintf (stderr, "Shutting down\n");
2282 fprintf (stderr, _("Leaving display monitor mode...\n"));
2283 data.OutputFn = NULL;
2285 error = SM_Functions(GOP_DisplayOutput, &data, sm);
2286 if (error != GE_NONE)
2287 fprintf (stderr, _("Error!\n"));
2289 fprintf (stderr, _("Error!\n"));
2291 if (GSM && GSM->Terminate) GSM->Terminate();
2295 /* Reads profile from phone and displays its' settings */
2296 int getprofile(int argc, char *argv[])
2300 GSM_Profile profile;
2303 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2307 if (GSM && GSM->GetProfile) error = GSM->GetProfile(&profile);
2309 if (error == GE_NONE) {
2311 while (GSM && GSM->GetModel && GSM->GetModel(model) != GE_NONE)
2314 max_profiles = 7; /* This is correct for 6110 (at least my). How do we get
2315 the number of profiles? */
2318 /* FIXME: It should be set to 3 for N5130 and 3210 too */
2319 if (!strcmp(model, "NSE-1"))
2323 profile.Number = atoi(argv[0]) - 1;
2324 start = profile.Number;
2327 if (profile.Number < 0) {
2328 fprintf(stderr, _("Profile number must be value from 1 to %d!\n"), max_profiles);
2329 if (GSM && GSM->Terminate) GSM->Terminate();
2333 if (profile.Number >= max_profiles) {
2334 fprintf(stderr, _("This phone supports only %d profiles!\n"), max_profiles);
2335 if (GSM && GSM->Terminate) GSM->Terminate();
2340 stop = max_profiles;
2347 if (profile.Number != 0)
2348 if (GSM && GSM->GetProfile) GSM->GetProfile(&profile);
2350 fprintf(stdout, "%d. \"%s\"\n", profile.Number + 1, profile.Name);
2351 if (profile.DefaultName == -1) fprintf(stdout, _(" (name defined)\n"));
2353 fprintf(stdout, _("Incoming call alert: %s\n"), GetProfileCallAlertString(profile.CallAlert));
2355 /* For different phones different ringtones names */
2357 if (!strcmp(model, "NSE-3"))
2358 fprintf(stdout, _("Ringing tone: %s (%d)\n"), RingingTones[profile.Ringtone], profile.Ringtone);
2360 fprintf(stdout, _("Ringtone number: %d\n"), profile.Ringtone);
2362 fprintf(stdout, _("Ringing volume: %s\n"), GetProfileVolumeString(profile.Volume));
2364 fprintf(stdout, _("Message alert tone: %s\n"), GetProfileMessageToneString(profile.MessageTone));
2366 fprintf(stdout, _("Keypad tones: %s\n"), GetProfileKeypadToneString(profile.KeypadTone));
2368 fprintf(stdout, _("Warning and game tones: %s\n"), GetProfileWarningToneString(profile.WarningTone));
2370 /* FIXME: Light settings is only used for Car */
2371 if (profile.Number == (max_profiles - 2)) fprintf(stdout, _("Lights: %s\n"), profile.Lights ? _("On") : _("Automatic"));
2373 fprintf(stdout, _("Vibration: %s\n"), GetProfileVibrationString(profile.Vibration));
2375 /* FIXME: it will be nice to add here reading caller group name. */
2376 if (max_profiles != 3) fprintf(stdout, _("Caller groups: 0x%02x\n"), profile.CallerGroups);
2378 /* FIXME: Automatic answer is only used for Car and Headset. */
2379 if (profile.Number >= (max_profiles - 2)) fprintf(stdout, _("Automatic answer: %s\n"), profile.AutomaticAnswer ? _("On") : _("Off"));
2381 fprintf(stdout, "\n");
2386 if (error == GE_NOTIMPLEMENTED) {
2387 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2388 if (GSM && GSM->Terminate) GSM->Terminate();
2391 fprintf(stderr, _("Unspecified error\n"));
2392 if (GSM && GSM->Terminate) GSM->Terminate();
2397 if (GSM && GSM->Terminate) GSM->Terminate();
2401 /* Get requested range of memory storage entries and output to stdout in
2402 easy-to-parse format */
2403 int getmemory(int argc, char *argv[])
2405 GSM_PhonebookEntry entry;
2408 char *memory_type_string;
2411 GSM_Statemachine *sm = &State;
2413 /* Handle command line args that set type, start and end locations. */
2414 memory_type_string = argv[0];
2415 entry.MemoryType = StrToMemoryType(memory_type_string);
2416 if (entry.MemoryType == GMT_XX) {
2417 fprintf(stderr, _("Unknown memory type %s (use ME, SM, ...)!\n"), argv[0]);
2421 start_entry = atoi (argv[1]);
2422 if (argc > 2) end_entry = atoi (argv[2]);
2423 else end_entry = start_entry;
2425 /* Now retrieve the requested entries. */
2426 for (count = start_entry; count <= end_entry; count ++) {
2428 entry.Location = count;
2430 data.PhonebookEntry = &entry;
2431 error = SM_Functions(GOP_ReadPhonebook, &data, sm);
2433 if (error == GE_NONE) {
2434 fprintf(stdout, "%s;%s;%s;%d;%d\n", entry.Name, entry.Number, memory_type_string, entry.Location, entry.Group);
2435 if (entry.MemoryType == GMT_MC || entry.MemoryType == GMT_DC || entry.MemoryType == GMT_RC)
2436 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);
2439 if (error == GE_NOTIMPLEMENTED) {
2440 fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2443 else if (error == GE_INVALIDMEMORYTYPE) {
2444 fprintf(stderr, _("Memory type %s not supported!\n"), memory_type_string);
2448 fprintf(stdout, _("%s|%d|Bad location or other error!(%d)\n"), memory_type_string, count, error);
2454 /* Read data from stdin, parse and write to phone. The parsing is relatively
2455 crude and doesn't allow for much variation from the stipulated format. */
2456 /* FIXME: I guess there's *very* similar code in xgnokii */
2457 static int writephonebook(int argc, char *args[])
2459 GSM_PhonebookEntry entry;
2461 char *memory_type_string;
2465 char *Line, OLine[100], BackLine[100];
2468 /* Check argument */
2469 if (argc && (strcmp("-i", args[0])))
2474 /* Go through data from stdin. */
2475 while (GetLine(stdin, Line, 99)) {
2476 strcpy(BackLine, Line);
2479 ptr = strtok(Line, ";");
2480 if (ptr) strcpy(entry.Name, ptr);
2481 else entry.Name[0] = 0;
2483 ptr = strtok(NULL, ";");
2484 if (ptr) strcpy(entry.Number, ptr);
2485 else entry.Number[0] = 0;
2487 ptr = strtok(NULL, ";");
2490 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2495 if (!strncmp(ptr,"ME", 2)) {
2496 memory_type_string = "int";
2497 entry.MemoryType = GMT_ME;
2499 if (!strncmp(ptr,"SM", 2)) {
2500 memory_type_string = "sim";
2501 entry.MemoryType = GMT_SM;
2503 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2508 ptr = strtok(NULL, ";");
2509 if (ptr) entry.Location = atoi(ptr);
2510 else entry.Location = 0;
2512 ptr = strtok(NULL, ";");
2513 if (ptr) entry.Group = atoi(ptr);
2514 else entry.Group = 0;
2517 fprintf(stderr, _("Format problem on line %d [%s]\n"), line_count, BackLine);
2521 for (subentry = 0; ; subentry++) {
2522 ptr = strtok(NULL, ";");
2524 if (ptr && *ptr != 0)
2525 entry.SubEntries[subentry].EntryType = atoi(ptr);
2529 ptr = strtok(NULL, ";");
2531 entry.SubEntries[subentry].NumberType=atoi(ptr);
2533 /* Phone Numbers need to have a number type. */
2534 if (!ptr && entry.SubEntries[subentry].EntryType == GSM_Number) {
2535 fprintf(stderr, _("Missing phone number type on line %d"
2536 " entry %d [%s]\n"), line_count, subentry, BackLine);
2541 ptr = strtok(NULL, ";");
2543 entry.SubEntries[subentry].BlockNumber=atoi(ptr);
2545 ptr = strtok(NULL, ";");
2547 /* 0x13 Date Type; it is only for Dailed Numbers, etc.
2548 we don't store to this memories so it's an error to use it. */
2549 if (!ptr || entry.SubEntries[subentry].EntryType == GSM_Date) {
2550 fprintf(stdout, _("There is no phone number on line %d entry %d [%s]\n"),
2551 line_count, subentry, BackLine);
2555 strcpy(entry.SubEntries[subentry].data.Number, ptr);
2558 entry.SubEntriesCount = subentry;
2560 /* This is to send other exports (like from 6110) to 7110 */
2561 if (!entry.SubEntriesCount) {
2562 entry.SubEntriesCount = 1;
2563 entry.SubEntries[subentry].EntryType = GSM_Number;
2564 entry.SubEntries[subentry].NumberType = GSM_General;
2565 entry.SubEntries[subentry].BlockNumber = 2;
2566 strcpy(entry.SubEntries[subentry].data.Number, entry.Number);
2572 GSM_PhonebookEntry aux;
2574 aux.Location = entry.Location;
2575 if (GSM && GSM->GetMemoryLocation) error = GSM->GetMemoryLocation(&aux);
2577 if (error == GE_NONE) {
2582 fprintf(stdout, _("Location busy. "));
2583 while (confirm < 0) {
2584 fprintf(stdout, _("Overwrite? (yes/no) "));
2585 GetLine(stdin, ans, 7);
2586 if (!strcmp(ans, _("yes"))) confirm = 1;
2587 else if (!strcmp(ans, _("no"))) confirm = 0;
2589 if (!confirm) continue;
2592 fprintf(stderr, _("Unknown error (%d)\n"), error);
2593 if (GSM && GSM->Terminate) GSM->Terminate();
2598 /* Do write and report success/failure. */
2599 if (GSM && GSM->WritePhonebookLocation) error = GSM->WritePhonebookLocation(&entry);
2601 if (error == GE_NONE)
2602 fprintf (stdout, _("Write Succeeded: memory type: %s, loc: %d, name: %s, number: %s\n"), memory_type_string, entry.Location, entry.Name, entry.Number);
2604 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);
2608 if (GSM && GSM->Terminate) GSM->Terminate();
2612 /* Getting speed dials. */
2613 int getspeeddial(char *Number)
2615 GSM_SpeedDial SpeedDial;
2619 SpeedDial.Number = atoi(Number);
2621 if (GSM && GSM->GetSpeedDial && GSM->Terminate) {
2622 error = GSM->GetSpeedDial(&SpeedDial);
2625 GSM_DataClear(&data);
2626 data.SpeedDial = &SpeedDial;
2628 error = SM_Functions(GOP_GetSpeedDial, &data, &State);
2633 fprintf(stdout, _("SpeedDial nr. %d: %d:%d\n"), SpeedDial.Number, SpeedDial.MemoryType, SpeedDial.Location);
2635 case GE_NOTIMPLEMENTED:
2636 fprintf(stdout, _("Function not implemented in %s !\n"), model);
2639 fprintf(stdout, _("Internal error\n"));
2646 /* Setting speed dials. */
2647 int setspeeddial(char *argv[])
2649 GSM_SpeedDial entry;
2651 char *memory_type_string;
2653 /* Handle command line args that set type, start and end locations. */
2655 if (strcmp(argv[1], "ME") == 0) {
2656 entry.MemoryType = 0x02;
2657 memory_type_string = "ME";
2658 } else if (strcmp(argv[1], "SM") == 0) {
2659 entry.MemoryType = 0x03;
2660 memory_type_string = "SM";
2662 fprintf(stderr, _("Unknown memory type %s!\n"), argv[1]);
2666 entry.Number = atoi(argv[0]);
2667 entry.Location = atoi(argv[2]);
2669 if (GSM && GSM->SetSpeedDial && GSM->SetSpeedDial(&entry) == GE_NONE) {
2670 fprintf(stdout, _("Succesfully written!\n"));
2673 if (GSM && GSM->Terminate) GSM->Terminate();
2677 /* Getting the status of the display. */
2678 int getdisplaystatus(void)
2682 if (GSM && GSM->GetDisplayStatus) GSM->GetDisplayStatus(&Status);
2684 fprintf(stdout, _("Call in progress: %s\n"), Status & (1<<DS_Call_In_Progress)?_("on"):_("off"));
2685 fprintf(stdout, _("Unknown: %s\n"), Status & (1<<DS_Unknown)?_("on"):_("off"));
2686 fprintf(stdout, _("Unread SMS: %s\n"), Status & (1<<DS_Unread_SMS)?_("on"):_("off"));
2687 fprintf(stdout, _("Voice call: %s\n"), Status & (1<<DS_Voice_Call)?_("on"):_("off"));
2688 fprintf(stdout, _("Fax call active: %s\n"), Status & (1<<DS_Fax_Call)?_("on"):_("off"));
2689 fprintf(stdout, _("Data call active: %s\n"), Status & (1<<DS_Data_Call)?_("on"):_("off"));
2690 fprintf(stdout, _("Keyboard lock: %s\n"), Status & (1<<DS_Keyboard_Lock)?_("on"):_("off"));
2691 fprintf(stdout, _("SMS storage full: %s\n"), Status & (1<<DS_SMS_Storage_Full)?_("on"):_("off"));
2693 if (GSM && GSM->Terminate) GSM->Terminate();
2697 int netmonitor(char *Mode)
2699 unsigned char mode = atoi(Mode);
2702 if (!strcmp(Mode, "reset"))
2704 else if (!strcmp(Mode, "off"))
2706 else if (!strcmp(Mode, "field"))
2708 else if (!strcmp(Mode, "devel"))
2710 else if (!strcmp(Mode, "next"))
2713 memset(&Screen, 0, 50);
2714 if (GSM && GSM->NetMonitor) GSM->NetMonitor(mode, Screen);
2717 fprintf(stdout, "%s\n", Screen);
2719 if (GSM && GSM->Terminate) GSM->Terminate();
2725 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
2726 char imei[64], model[64], rev[64], manufacturer[64];
2727 GSM_Statemachine *sm = &State;
2729 data.Manufacturer = manufacturer;
2731 data.Revision = rev;
2734 /* Retrying is bad idea: what if function is simply not implemented?
2735 Anyway let's wait 2 seconds for the right packet from the phone. */
2738 strcpy(imei, "(unknown)");
2739 strcpy(manufacturer, "(unknown)");
2740 strcpy(model, "(unknown)");
2741 strcpy(rev, "(unknown)");
2743 SM_Functions(GOP_Identify, &data, sm);
2745 fprintf(stdout, _("IMEI: %s\n"), imei);
2746 fprintf(stdout, _("Manufacturer: %s\n"), manufacturer);
2747 fprintf(stdout, _("Model: %s\n"), model);
2748 fprintf(stdout, _("Revision: %s\n"), rev);
2753 int senddtmf(char *String)
2755 if (GSM && GSM->SendDTMF) GSM->SendDTMF(String);
2756 if (GSM && GSM->Terminate) GSM->Terminate();
2760 /* Resets the phone */
2761 int reset( char *type)
2763 unsigned char _type = 0x03;
2766 if(!strcmp(type, "soft"))
2769 if(!strcmp(type, "hard"))
2772 fprintf(stderr, _("What kind of reset do you want??\n"));
2777 if (GSM && GSM->Reset) GSM->Reset(_type);
2778 if (GSM && GSM->Terminate) GSM->Terminate();
2783 /* pmon allows fbus code to run in a passive state - it doesn't worry about
2784 whether comms are established with the phone. A debugging/development
2789 GSM_ConnectionType connection=GCT_Serial;
2790 GSM_Statemachine sm;
2792 /* Initialise the code for the GSM interface. */
2793 error = GSM_Initialise(model, Port, Initlength, connection, NULL, &sm);
2795 if (error != GE_NONE) {
2796 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
2807 int sendringtone(int argc, char *argv[])
2809 GSM_Ringtone ringtone;
2812 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2813 fprintf(stdout, _("Failed to load ringtone.\n"));
2817 if (GSM && GSM->SendRingtone) error = GSM->SendRingtone(&ringtone,argv[1]);
2819 if (error == GE_NONE)
2820 fprintf(stdout, _("Send succeeded!\n"));
2822 fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
2824 if (GSM && GSM->Terminate) GSM->Terminate();
2829 int setringtone(int argc, char *argv[])
2831 GSM_Ringtone ringtone;
2834 if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
2835 fprintf(stdout, _("Failed to load ringtone.\n"));
2839 if (GSM && GSM->SetRingtone) error = GSM->SetRingtone(&ringtone);
2841 if (error == GE_NONE)
2842 fprintf(stdout, _("Send succeeded!\n"));
2844 fprintf(stdout, _("Send failed\n"));
2846 if (GSM && GSM->Terminate) GSM->Terminate();
2850 int presskeysequence(void)
2856 memset(&buf[0], 0, 102);
2857 while (read(0, buf, 100) > 0) {
2858 fprintf(stderr, "handling keys (%d).\n", strlen(buf));
2859 if (GSM && GSM->HandleString && GSM->HandleString(buf) != GE_NONE)
2860 fprintf(stdout, _("Key press simulation failed.\n"));
2861 memset(buf, 0, 102);
2864 if (GSM && GSM->Terminate) GSM->Terminate();
2868 /* Options for --divert:
2869 --op, -o [register|enable|query|disable|erasure] REQ
2870 --type, -t [all|busy|noans|outofreach|notavail] REQ
2871 --call, -c [all|voice|fax|data] REQ
2872 --timeout, m time_in_seconds OPT
2873 --number, -n number OPT
2875 int divert(int argc, char **argv)
2879 GSM_Statemachine *sm = &State;
2882 struct option options[] = {
2883 { "op", required_argument, NULL, 'o'},
2884 { "type", required_argument, NULL, 't'},
2885 { "call", required_argument, NULL, 'c'},
2886 { "number", required_argument, NULL, 'n'},
2887 { "timeout", required_argument, NULL, 'm'},
2897 memset(&cd, 0, sizeof(GSM_CallDivert));
2899 while ((opt = getopt_long(argc, argv, "o:t:n:c:m:", options, NULL)) != -1) {
2902 if (!strcmp("register", optarg)) {
2903 cd.Operation = GSM_CDV_Register;
2904 } else if (!strcmp("enable", optarg)) {
2905 cd.Operation = GSM_CDV_Enable;
2906 } else if (!strcmp("disable", optarg)) {
2907 cd.Operation = GSM_CDV_Disable;
2908 } else if (!strcmp("erasure", optarg)) {
2909 cd.Operation = GSM_CDV_Erasure;
2910 } else if (!strcmp("query", optarg)) {
2911 cd.Operation = GSM_CDV_Query;
2918 if (!strcmp("all", optarg)) {
2919 cd.DType = GSM_CDV_AllTypes;
2920 } else if (!strcmp("busy", optarg)) {
2921 cd.DType = GSM_CDV_Busy;
2922 } else if (!strcmp("noans", optarg)) {
2923 cd.DType = GSM_CDV_NoAnswer;
2924 } else if (!strcmp("outofreach", optarg)) {
2925 cd.DType = GSM_CDV_OutOfReach;
2926 } else if (!strcmp("notavail", optarg)) {
2927 cd.DType = GSM_CDV_NotAvailable;
2934 if (!strcmp("all", optarg)) {
2935 cd.CType = GSM_CDV_AllCalls;
2936 } else if (!strcmp("voice", optarg)) {
2937 cd.CType = GSM_CDV_VoiceCalls;
2938 } else if (!strcmp("fax", optarg)) {
2939 cd.CType = GSM_CDV_FaxCalls;
2940 } else if (!strcmp("data", optarg)) {
2941 cd.CType = GSM_CDV_DataCalls;
2948 cd.Timeout = atoi(optarg);
2951 strcpy(cd.Number.number, optarg);
2952 if (cd.Number.number[0] == '+') cd.Number.type = SMS_International;
2953 else cd.Number.type = SMS_Unknown;
2960 data.CallDivert = &cd;
2961 error = SM_Functions(GOP_CallDivert, &data, sm);
2963 if (error == GE_NONE) {
2964 fprintf(stderr, "Divert succeeded.\n");
2966 fprintf(stderr, "%s\n", print_error(error));
2971 /* This is a "convenience" function to allow quick test of new API stuff which
2972 doesn't warrant a "proper" command line function. */
2974 int foogle(char *argv[])
2976 /* Fill in what you would like to test here... */