From: jankratochvil <> Date: Thu, 28 Feb 2002 02:40:36 +0000 (+0000) Subject: This commit was manufactured by cvs2svn to create branch 'decode'. X-Git-Tag: bp_decode~5 X-Git-Url: http://git.jankratochvil.net/?p=gnokii.git;a=commitdiff_plain;h=1bbe44edac4bf7f36360bf713eeb6df2ad68b9c3 This commit was manufactured by cvs2svn to create branch 'decode'. Cherrypick from uc 2002-02-18 02:07:04 UTC jankratochvil 'This commit was manufactured by cvs2svn to create branch 'uc'.': common/devices/unixserial.c common/files/cfgreader.c include/config.h.in.in include/protocol/fbus.h Cherrypick from ats 2002-02-28 02:40:34 UTC short '\r\n -> \n': common/misc.c gnokii/gnokii.c Cherrypick from mygnokii 2002-02-28 02:40:35 UTC short '\r\n -> \n': common/newmodules/n6110.c common/protocol/fbus.c --- diff --git a/common/devices/unixserial.c b/common/devices/unixserial.c new file mode 100644 index 0000000..bc7e37e --- /dev/null +++ b/common/devices/unixserial.c @@ -0,0 +1,266 @@ +/* + + $Id$ + + G N O K I I + + A Linux/Unix toolset and driver for Nokia mobile phones. + + Released under the terms of the GNU GPL, see file COPYING for more details. + +*/ + +#include "misc.h" + +/* Do not compile this file under Win32 systems. */ + +#ifndef WIN32 + +#include +#include +#include +#include + +#if __unices__ +# include +#endif + +#include +#include "devices/unixserial.h" + +#ifdef HAVE_SYS_IOCTL_COMPAT_H + #include +#endif + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +/* If the target operating system does not have cfsetspeed, we can emulate + it. */ + +#ifndef HAVE_CFSETSPEED + #if defined(HAVE_CFSETISPEED) && defined(HAVE_CFSETOSPEED) + #define cfsetspeed(t, speed) \ + (cfsetispeed(t, speed) || cfsetospeed(t, speed)) + #else + static int cfsetspeed(struct termios *t, int speed) { + #ifdef HAVE_TERMIOS_CSPEED + t->c_ispeed = speed; + t->c_ospeed = speed; + #else + t->c_cflag |= speed; + #endif + return 0; + } + #endif +#endif + +#ifndef O_NONBLOCK + #define O_NONBLOCK 0 +#endif + +/* Structure to backup the setting of the terminal. */ + +struct termios serial_termios; + +/* Open the serial port and store the settings. */ + +int serial_open(__const char *__file, int __oflag) { + + int __fd; + int retcode; + + __fd = open(__file, __oflag); + if (__fd == -1) { + perror("Gnokii serial_open: open"); + return (-1); + } + + retcode=tcgetattr(__fd, &serial_termios); + if(retcode==-1) { + perror("Gnokii serial_open:tcgetattr"); + /* Don't call serial_close since serial_termios is not valid */ + close(__fd); + return(-1); + } + + return __fd; +} + +/* Close the serial port and restore old settings. */ + +int serial_close(int __fd) { + + if (__fd >= 0) + tcsetattr(__fd, TCSANOW, &serial_termios); + + return (close(__fd)); +} + +/* Open a device with standard options. */ + +int serial_opendevice(__const char *__file, int __with_odd_parity, int __with_async, int __with_hw_handshake) { + + int fd; + int retcode; + struct termios tp; + + /* Open device */ + + fd = serial_open(__file, O_RDWR | O_NOCTTY | O_NONBLOCK); + + if (fd < 0) + return fd; + + /* Allow process/thread to receive SIGIO */ + +#if !(__unices__) + retcode = fcntl(fd, F_SETOWN, getpid()); + if (retcode == -1){ + perror("Gnokii serial_opendevice: fnctl(F_SETOWN)"); + serial_close(fd); + return(-1); + } +#endif + + /* Make filedescriptor asynchronous. */ + + if (__with_async) { + retcode=fcntl(fd, F_SETFL, FASYNC); + if (retcode == -1){ + perror("Gnokii serial_opendevice: fnctl(F_SETFL)"); + serial_close(fd); + return(-1); + } + } + + /* Initialise the port settings */ + + memcpy(&tp, &serial_termios, sizeof(struct termios)); + + /* Set port settings for canonical input processing */ + + tp.c_cflag = B0 | CS8 | CLOCAL | CREAD; + if (__with_odd_parity) { + tp.c_cflag |= (PARENB | PARODD); + tp.c_iflag = 0; + } + else + tp.c_iflag = IGNPAR; + if (__with_hw_handshake) + tp.c_cflag |= CRTSCTS; + else + tp.c_cflag &= ~CRTSCTS; + + tp.c_oflag = 0; + tp.c_lflag = 0; + tp.c_cc[VMIN] = 1; + tp.c_cc[VTIME] = 0; + + retcode=tcflush(fd, TCIFLUSH); + if (retcode == -1) { + perror("Gnokii serial_opendevice: tcflush"); + serial_close(fd); + return(-1); + } + + retcode=tcsetattr(fd, TCSANOW, &tp); + if (retcode == -1){ + perror("Gnokii serial_opendevice: tcsetattr"); + serial_close(fd); + return(-1); + } + + return fd; +} + +/* Set the DTR and RTS bit of the serial device. */ + +void serial_setdtrrts(int __fd, int __dtr, int __rts) { + + unsigned int flags; + + flags = TIOCM_DTR; + + if (__dtr) ioctl(__fd, TIOCMBIS, &flags); + else ioctl(__fd, TIOCMBIC, &flags); + + flags = TIOCM_RTS; + + if (__rts) ioctl(__fd, TIOCMBIS, &flags); + else ioctl(__fd, TIOCMBIC, &flags); +} + + +int serial_select(int fd, struct timeval *timeout) { + + fd_set readfds; + + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + + return (select(fd + 1, &readfds, NULL, NULL, timeout)); + +} + + +/* Change the speed of the serial device. */ + +void serial_changespeed(int __fd, int __speed) { + +#ifndef SGTTY + struct termios t; +#else + struct sgttyb t; +#endif + + int speed=B9600; + + switch (__speed) { + case 9600: speed = B9600; break; + case 19200: speed = B19200; break; + case 38400: speed = B38400; break; + case 57600: speed = B57600; break; + case 115200: speed = B115200; break; + } + +#ifndef SGTTY + tcgetattr(__fd, &t); + + // This is not needed! We set up the speed via cfsetspeed + // t.c_cflag &= ~CBAUD; + // t.c_cflag |= speed; +#ifdef DEBUG + if (cfsetspeed(&t, speed) == -1) + fprintf(stdout,_("Serial port speed setting failed\n")); +#else + cfsetspeed(&t, speed); +#endif + + tcsetattr(__fd, TCSADRAIN, &t); +#else + ioctl(__fd, TIOCGETP, &t); + + t.sg_ispeed = speed; + t.sg_ospeed = speed; + + ioctl(__fd, TIOCSETN, &t); +#endif +} + +/* Read from serial device. */ + +size_t serial_read(int __fd, __ptr_t __buf, size_t __nbytes) { + + return (read(__fd, __buf, __nbytes)); +} + +/* Write to serial device. */ + +size_t serial_write(int __fd, __const __ptr_t __buf, size_t __n) { + + return (write(__fd, __buf, __n)); +} + +#endif /* WIN32 */ diff --git a/common/files/cfgreader.c b/common/files/cfgreader.c new file mode 100644 index 0000000..9908cc1 --- /dev/null +++ b/common/files/cfgreader.c @@ -0,0 +1,339 @@ +/* + + $Id$ + + G N O K I I + + A Linux/Unix toolset and driver for Nokia mobile phones. + + Released under the terms of the GNU GPL, see file COPYING for more details. + + Config file (/etc/gnokiirc and ~/.gnokiirc) reader. + + Modified from code by Tim Potter. + +*/ + +#include "misc.h" + +#include +#include +#include +#if __unices__ +# include +#endif +#include +#include + +#include "files/cfgreader.h" + +/* Read configuration information from a ".INI" style file */ +struct CFG_Header *CFG_ReadFile(char *filename) +{ + FILE *handle; + char *line; + char *buf; + struct CFG_Header *cfg_info = NULL, *cfg_head = NULL; + + /* Error check */ + if (filename == NULL) { + return NULL; + } + + /* Initialisation */ + if ((buf = (char *)malloc(255)) == NULL) { + return NULL; + } + + /* Open file */ + if ((handle = fopen(filename, "r")) == NULL) { +#ifdef DEBUG + fprintf( stderr, "CFG_ReadFile - open %s: %s\n", filename, strerror(errno)); +#endif /* DEBUG */ + return NULL; + } +#ifdef DEBUG + else + fprintf( stderr, "Opened configuration file %s\n", filename ); +#endif /* DEBUG */ + + /* Iterate over lines in the file */ + while (fgets(buf, 255, handle) != NULL) { + + line = buf; + + /* Strip leading, trailing whitespace */ + while(isspace((int) *line)) + line++; + + while((strlen(line) > 0) && isspace((int) line[strlen(line) - 1])) + line[strlen(line) - 1] = '\0'; + + /* Ignore blank lines and comments */ + if ((*line == '\n') || (*line == '\0') || (*line == '#')) + continue; + + /* Look for "headings" enclosed in square brackets */ + if ((line[0] == '[') && (line[strlen(line) - 1] == ']')) { + struct CFG_Header *heading; + + /* Allocate new heading entry */ + if ((heading = (struct CFG_Header *)malloc(sizeof(*heading))) == NULL) { + return NULL; + } + + /* Fill in fields */ + memset(heading, '\0', sizeof(*heading)); + + line++; + line[strlen(line) - 1] = '\0'; + + /* FIXME: strdup is not ANSI C compliant. */ + heading->section = strdup(line); + + /* Add to tail of list */ + heading->prev = cfg_info; + + if (cfg_info != NULL) { + cfg_info->next = heading; + } else { + /* Store copy of head of list for return value */ + cfg_head = heading; + } + + cfg_info = heading; + +#ifdef DEBUG + fprintf(stderr, "Added new section %s\n", heading->section); +#endif + /* Go on to next line */ + + continue; + } + + /* Process key/value line */ + + if ((strchr(line, '=') != NULL) && cfg_info != NULL) { + struct CFG_Entry *entry; + char *value; + + /* Allocate new entry */ + if ((entry = (struct CFG_Entry *)malloc(sizeof(*entry))) == NULL) { + return NULL; + } + + /* Fill in fields */ + memset(entry, '\0', sizeof(*entry)); + + value = strchr(line, '='); + *value = '\0'; /* Split string */ + value++; + + while(isspace((int) *value)) { /* Remove leading white */ + value++; + } + + entry->value = strdup(value); + + while((strlen(line) > 0) && isspace((int) line[strlen(line) - 1])) { + line[strlen(line) - 1] = '\0'; /* Remove trailing white */ + } + + /* FIXME: strdup is not ANSI C compliant. */ + entry->key = strdup(line); + + /* Add to head of list */ + + entry->next = cfg_info->entries; + + if (cfg_info->entries != NULL) { + cfg_info->entries->prev = entry; + } + + cfg_info->entries = entry; + +#ifdef DEBUG + fprintf(stderr, "Adding key/value %s/%s\n", entry->key, entry->value); +#endif + /* Go on to next line */ + continue; + } + + /* Line not part of any heading */ + fprintf(stderr, "Orphaned line: %s\n", line); + } + + /* Return pointer to configuration information */ + return cfg_head; +} + +/* Write configuration information to a config file */ + +int CFG_WriteFile(struct CFG_Header *cfg, char *filename) +{ + /* Not implemented - tricky to do and preserve comments */ + + return 0; +} + +/* + * Find the value of a key in a config file. Return value associated + * with key or NULL if no such key exists. + */ + +char *CFG_Get(struct CFG_Header *cfg, char *section, char *key) +{ + struct CFG_Header *h; + struct CFG_Entry *e; + + if ((cfg == NULL) || (section == NULL) || (key == NULL)) { + return NULL; + } + + /* Search for section name */ + for (h = cfg; h != NULL; h = h->next) { + if (strcmp(section, h->section) == 0) { + /* Search for key within section */ + for (e = h->entries; e != NULL; e = e->next) { + if (strcmp(key, e->key) == 0) { + /* Found! */ + return e->value; + } + } + } + } + /* Key not found in section */ + return NULL; +} + +/* Set the value of a key in a config file. Return the new value if + the section/key can be found, else return NULL. */ + +char *CFG_Set(struct CFG_Header *cfg, char *section, char *key, + char *value) +{ + struct CFG_Header *h; + struct CFG_Entry *e; + + if ((cfg == NULL) || (section == NULL) || (key == NULL) || + (value == NULL)) { + return NULL; + } + + /* Search for section name */ + for (h = cfg; h != NULL; h = h->next) { + if (strcmp(section, h->section) == 0) { + /* Search for key within section */ + for (e = h->entries; e != NULL; e = e->next) { + if ((e->key != NULL) && strcmp(key, e->key) == 0) { + /* Found - set value */ + free(e->key); + /* FIXME: strdup is not ANSI C compliant. */ + e->key = strdup(value); + return e->value; + } + } + } + } + /* Key not found in section */ + return NULL; +} + +struct CFG_Header *CFG_FindGnokiirc() +{ + struct CFG_Header *cfg_info; + char *homedir; + char rcfile[200]; + +#ifdef WIN32 + homedir = getenv("HOMEDRIVE"); + strncpy(rcfile, homedir ? homedir : "", 200); + homedir = getenv("HOMEPATH"); + strncat(rcfile, homedir ? homedir : "", 200); + strncat(rcfile, "\gnokiirc", 200); +#else + homedir = getenv("HOME"); + if (homedir) strncpy(rcfile, homedir, 200); + strncat(rcfile, "/.gnokiirc", 200); +#endif + + /* Try opening .gnokirc from users home directory first */ + if ((cfg_info = CFG_ReadFile(rcfile)) == NULL) { +#ifndef WIN32 + + /* It failed so try for /etc/gnokiirc */ + if ((cfg_info = CFG_ReadFile("/etc/gnokiirc")) == NULL) { + /* That failed too so exit */ +#ifdef DEBUG + fprintf(stderr, _("Couldn't open %s or /etc/gnokiirc. Using defaults...\n"), rcfile); +#endif /* DEBUG */ + return NULL; + } + +#else /* WIN32 */ + + /* It failed so try for gnokiirc */ + if ((cfg_info = CFG_ReadFile("gnokiirc")) == NULL) { + /* That failed too so exit */ +#ifdef DEBUG + fprintf(stderr, _("Couldn't open %s or gnokiirc. Using defaults...\n"), rcfile); +#endif /* DEBUG */ + return NULL; + } + +#endif /* WIN32 */ + } + + return cfg_info; +} + +int CFG_ReadConfig(char **model, char **port, char **initlength, + char **connection, char **bindir, char **synchronizetime, + bool isgnokiid) +{ + struct CFG_Header *cfg_info; +#ifdef WIN32 + char *DefaultPort = "com2:"; +#else + char *DefaultPort = "/dev/ttyS1"; +#endif + char *DefaultModel = "auto"; + char *DefaultConnection = "fbus"; + char *DefaultBindir = "/usr/local/sbin/"; + char *DefaultSynchronizeTime = "yes"; + char *DefaultInitLength = "30"; + + char *section = "global"; + + (char *)*model = DefaultModel; + (char *)*port = DefaultPort; + (char *)*connection = DefaultConnection; + (char *)*bindir = DefaultBindir; + (char *)*synchronizetime = DefaultSynchronizeTime; + (char *)*initlength = DefaultInitLength; + + cfg_info=CFG_FindGnokiirc(); + if (cfg_info==NULL) return 0; + + if (isgnokiid) (char *)section = "gnokiid"; + + (char *)*model = CFG_Get(cfg_info, section, "model"); + if (!*model) (char *)*model = DefaultModel; + + (char *)*port = CFG_Get(cfg_info, section, "port"); + if (!*port) (char *)*port = DefaultPort; + + (char *)*connection = CFG_Get(cfg_info, section, "connection"); + if (!*connection) (char *)*connection = DefaultConnection; + + (char *)*bindir = CFG_Get(cfg_info, section, "bindir"); + if (!*bindir) (char *)*bindir = DefaultBindir; + + (char *)*synchronizetime = CFG_Get(cfg_info, section, "synchronizetime"); + if (!*synchronizetime) (char *)*synchronizetime = DefaultSynchronizeTime; + + (char *)*initlength = CFG_Get(cfg_info, section, "initlength"); + if (!*initlength) (char *)*initlength = "default"; + + return 0; +} diff --git a/common/misc.c b/common/misc.c new file mode 100644 index 0000000..b17a93e --- /dev/null +++ b/common/misc.c @@ -0,0 +1,240 @@ +/* + + G N O K I I + + A Linux/Unix toolset and driver for Nokia mobile phones. + + Released under the terms of the GNU GPL, see file COPYING for more details. + +*/ + +#include +#include +#include + +#ifndef WIN32 + #include + #include + #include + #include + #include + #include + #include +#endif + +#include "misc.h" +#include "gsm-common.h" + +#ifndef HAVE_TIMEOPS + +/* FIXME: I have timersub defined in sys/time.h :-( PJ + FIXME: Jano wants this function too... PJ + +int timersub(struct timeval *a, struct timeval *b, struct timeval *result) { + do { + (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; + (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; + if ((result)->tv_usec < 0) { + --(result)->tv_sec; + (result)->tv_usec += 1000000; + } + } while (0); +} +*/ + +#endif + +int GetLine(FILE *File, char *Line, int count) { + + char *ptr; + + if (fgets(Line, count, File)) { + ptr=Line+strlen(Line)-1; + + while ( (*ptr == '\n' || *ptr == '\r') && ptr>=Line) *ptr--='\0'; + + return strlen(Line); + } else return -1; +} + +/* + * like atoi, but of a non-null-terminated string of a specified portion + */ +int mem_to_int(const char str[], int len) +{ + char aux[81]; + + strncpy(aux, str, len); + aux[len]=0; + return( atoi(aux) ); +} + +/* + * make hexdump of Message + */ +#ifdef DEBUG +void hexdump(u16 MessageLength, u8 *MessageBuffer) +{ + + int count; + int n=0; + char string1[80]=""; + char string2[80]=""; + char hex1[10]; + char hex2[10]; + + for (count = 0; count < MessageLength; count ++) + { + n++; + + switch (MessageBuffer[count]) { + case 0x09: + sprintf(hex1,"%02x ",MessageBuffer[count]); + strcpy(hex2,"."); + break; + default: + if (isprint(MessageBuffer[count])) + sprintf(hex1,"%02x%c ",MessageBuffer[count],MessageBuffer[count]); + else + sprintf(hex1,"%02x ",MessageBuffer[count]); + + if (isprint(MessageBuffer[count])) sprintf(hex2,"%c",MessageBuffer[count]); + else strcpy(hex2,"."); + break; + } + + if ( n!=15 && count != MessageLength-1 ) hex1[3]='|'; + + strcat(string1,hex1); + strcat(string2,hex2); + + if ( n==15 || count == MessageLength-1 ) + { + fprintf(stdout,"%-60s%03x %s\n",string1,count+1,string2); + strcpy(string1,""); + strcpy(string2,""); + n=0; + } + }//for count + + if (n!=0) fprintf (stdout,_("\n")); + + fflush(stdout); +} + +void txhexdump(u16 MessageLength, u8 *MessageBuffer) +{ + int count; + int n=0; + + for (count = 0; count < MessageLength; count ++) + { + n++; + fprintf(stdout,_("%02x"),MessageBuffer[count]); + switch (MessageBuffer[count]) { + case 0x09: + fprintf(stdout,_(" |")); + break; + default: + if (isprint(MessageBuffer[count])) fprintf(stdout, _("%c|"),MessageBuffer[count]); + else fprintf(stdout,_(" |")); + break; + } + + if (n==18) + { + fprintf (stdout,_("\n")); + n=0; + } + }//for count + + if (n!=0) fprintf (stdout,_("\n")); + + fflush(stdout); +} +#endif + +#ifndef WIN32 + +#define max_buf_len 128 +#define lock_path "/var/lock/LCK.." + +/* Lock the device. Return allocated string with a lock name */ +char *lock_device(const char* port) +{ + char *lock_file = NULL; + char buffer[max_buf_len]; + char *aux = rindex(port, '/'); + int fd, len = strlen(aux) + strlen(lock_path); + + memset(buffer, 0, sizeof(buffer)); + lock_file = calloc(len + 1, 1); + if (!lock_file) { + fprintf(stderr, _("Cannot lock device\n")); + return NULL; + } + /* I think we don't need to use strncpy, as we should have enough + * buffer due to strlen results + */ + strcpy(lock_file, lock_path); + strcat(lock_file, aux); + + /* Check for the stale lockfile. + * The code taken from minicom by Miquel van Smoorenburg */ + if ((fd = open(lock_file, O_RDONLY)) >= 0) { + char buf[max_buf_len]; + int pid, n = 0; + + n = read(fd, buf, sizeof(buf) - 1); + close(fd); + if (n > 0) { + pid = -1; + if (n == 4) + /* Kermit-style lockfile. */ + pid = *(int *)buf; + else { + /* Ascii lockfile. */ + buf[n] = 0; + sscanf(buf, "%d", &pid); + } + if (pid > 0 && kill((pid_t)pid, 0) < 0 && errno == ESRCH) { + fprintf(stderr, _("Lockfile is stale. Overriding it..\n")); + sleep(1); + unlink(lock_file); + } else + n = 0; + } + if (n == 0) { + free(lock_file); + fprintf(stderr, _("Device is already locked.\n")); + return NULL; + } + } + + /* Try to create a new file, with 0644 mode */ + fd = open(lock_file, O_CREAT | O_EXCL, 0644); + if (fd == -1) { + free(lock_file); + fprintf(stderr, _("Cannot lock device\n")); + return NULL; + } + sprintf(buffer, "%10ld gnokii\n", (long)getpid()); + write(fd, buffer, strlen(buffer)); + close(fd); + return lock_file; +} + +/* Removes lock and frees memory */ +bool unlock_device(char *lock_file) +{ + int err; + + if (!lock_file) { + fprintf(stderr, _("Cannot unlock device\n")); + return false; + } + err = unlink(lock_file); + free(lock_file); + return (err + 1); +} +#endif /* WIN32 */ diff --git a/common/newmodules/n6110.c b/common/newmodules/n6110.c new file mode 100644 index 0000000..324b401 --- /dev/null +++ b/common/newmodules/n6110.c @@ -0,0 +1,5645 @@ +/* + + G N O K I I + + A Linux/Unix toolset and driver for Nokia mobile phones. + + Released under the terms of the GNU GPL, see file COPYING for more details. + + This file provides an API for accessing functions on the 6110 and similar + phones. + +*/ + +/* "Turn on" prototypes in n-6110.h */ + +#define __n_6110_c + +/* System header files */ +#include +#include +#include + +#ifdef WIN32 + #include "misc_win32.h" +#endif + +/* Various header file */ +#ifndef VC6 + #include "config.h" +#endif + +#include "gsm-api.h" +#include "gsm-coding.h" +#include "newmodules/n6110.h" +#include "newmodules/n7110.h" +#include "protocol/fbus.h" +#include "devices/device.h" +/* Global variables used by code in gsm-api.c to expose the functions + supported by this model of phone. */ + + + + + + + +/* Here we initialise model specific functions. */ +GSM_Functions N6110_Functions = { + N6110_Initialise, + N6110_DispatchMessage, + NULL_Terminate, + NULL_KeepAlive, + N6110_GetMemoryLocation, + N6110_WritePhonebookLocation, + N6110_GetSpeedDial, + N6110_SetSpeedDial, + N6110_GetMemoryStatus, + N6110_GetSMSStatus, + N6110_GetSMSCenter, + N6110_SetSMSCenter, + N6110_GetSMSMessage, + N6110_DeleteSMSMessage, + N6110_SendSMSMessage, + N6110_SaveSMSMessage, + N6110_GetRFLevel, + N6110_GetBatteryLevel, + N6110_GetPowerSource, + N6110_GetDisplayStatus, + N6110_EnterSecurityCode, + N6110_GetSecurityCodeStatus, + N6110_GetSecurityCode, + N6110_GetIMEI, + N6110_GetRevision, + N6110_GetModel, + N6110_GetDateTime, + N6110_SetDateTime, + N6110_GetAlarm, + N6110_SetAlarm, + N6110_DialVoice, + N6110_DialData, + N6110_GetIncomingCallNr, + N6110_GetNetworkInfo, + N6110_GetCalendarNote, + N6110_WriteCalendarNote, + N6110_DeleteCalendarNote, + N6110_NetMonitor, + N6110_SendDTMF, + N6110_GetBitmap, + N6110_SetBitmap, + N6110_SetRingTone, + N6110_SetBinRingTone, + N6110_GetBinRingTone, + N6110_Reset, + N6110_GetProfile, + N6110_SetProfile, + N6110_SendRLPFrame, + N6110_CancelCall, + N6110_PressKey, + N6110_EnableDisplayOutput, + N6110_DisableDisplayOutput, + N6110_EnableCellBroadcast, + N6110_DisableCellBroadcast, + N6110_ReadCellBroadcast, + N6110_PlayTone, + N6110_GetProductProfileSetting, + N6110_SetProductProfileSetting, + N6110_GetOperatorName, + N6110_SetOperatorName, + N6110_GetVoiceMailbox, N6110_Tests, + N6110_SimlockInfo, + UNIMPLEMENTED, //GetCalendarNotesInfo + N6110_GetSMSFolders, + N6110_ResetPhoneSettings, + N7110_GetWAPBookmark, + N7110_SetWAPBookmark, + N7110_GetWAPSettings, + N6110_CallDivert, + N6110_AnswerCall, + N6110_GetManufacturer +}; + +/* Mobile phone information */ + +GSM_Information N6110_Information = { + "3210|3310|3330|5110|5130|5190|6110|6130|6150|6190|8210|8850", + /* Supported models in FBUS */ + "3210|3310|3330|5110|5130|5190|6110|6130|6150|6190|8210|8850", + /* Supported models in MBUS */ + "6110|6130|6150|8210|8850", + /* Supported models in FBUS over infrared */ + "", + /* Supported models in FBUS over DLR3 */ + "", + /* AT commands */ + "8210|8850", + /* infrared sockets */ + "6110|6130|6150|8210|8850", + /* Supported models in FBUS over infrared with Tekram device */ + 4, /* Max RF Level */ + 0, /* Min RF Level */ + GRF_Arbitrary, /* RF level units */ + 4, /* Max Battery Level */ + 0, /* Min Battery Level */ + GBU_Arbitrary, /* Battery level units */ + GDT_DateTime, /* Have date/time support */ + GDT_TimeOnly, /* Alarm supports time only */ + 1 /* Only one alarm available */ +}; + +const char *N6110_MemoryType_String [] = { + "", /* 0x00 */ + "MT", /* 0x01 */ + "ME", /* 0x02 */ + "SM", /* 0x03 */ + "FD", /* 0x04 */ + "ON", /* 0x05 */ + "EN", /* 0x06 */ + "DC", /* 0x07 */ + "RC", /* 0x08 */ + "MC", /* 0x09 */ +}; + +/* Magic bytes from the phone. */ +unsigned char MagicBytes[4] = { 0x00, 0x00, 0x00, 0x00 }; + +/* For DisplayOutput */ +char PhoneScreen[5+1][27+1]; +int OldX=1000,OldY=0,NewX=0,NewY=0; + +void N6110_ReplyEnableExtendedCommands(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#ifdef DEBUG + fprintf(stdout, _("Message: Answer for EnableExtendedSecurityCommands frame, meaning not known :-(\n")); +#endif /* DEBUG */ + + CurrentEnableExtendedCommandsError=GE_NONE; +} + +/* If you set make some things (for example, + change Security Code from phone's menu, disable and enable + phone), it won't answer for 0x40 frame - you won't be able + to play tones, get netmonitor, etc. + + This function do thing called "Enabling extended security commands" - + it enables 0x40 frame functions. + + This frame can also some other things - see below */ +GSM_Error N6110_EnableExtendedCommands (unsigned char status) +{ + unsigned char req[4] = { 0x00, + 0x01,0x64, /* Enable extended commands request */ + 0x01 }; /* 0x01 - on, 0x00 - off, + 0x03 & 0x04 - soft & hard reset, + 0x06 - CONTACT SERVICE */ + + /* 0x06 MAKES CONTACT SERVICE! BE CAREFULL! */ + /* When use 0x03 and had during session changed time & date + some phones (like 6150 or 6210) can ask for time & date after reset + or disable clock on the screen */ + if (status!=0x06) req[3] = status; + + return NULL_SendMessageSequence + (50, &CurrentEnableExtendedCommandsError, 4, 0x40, req); +} + +void N6110_ReplyIMEI(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#if defined WIN32 || !defined HAVE_SNPRINTF + sprintf(Current_IMEI, "%s", MessageBuffer+4); +#else + snprintf(Current_IMEI, GSM_MAX_IMEI_LENGTH, "%s", MessageBuffer+4); +#endif + +#ifdef DEBUG + fprintf(stdout, _("Message: IMEI %s received\n"),Current_IMEI); +#endif + + CurrentGetIMEIError=GE_NONE; +} + +GSM_Error N6110_SendIMEIFrame() +{ + unsigned char req[4] = {0x00, 0x01, 0x66, 0x00}; + + GSM_Error error; + + error=N6110_EnableExtendedCommands(0x01); + if (error!=GE_NONE) return error; + + return NULL_SendMessageSequence (20, &CurrentGetIMEIError, 4, 0x40, req); +} + +void N6110_ReplyHW(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + int i, j; + + if (MessageBuffer[3]==0x05) { + +#ifdef DEBUG + fprintf(stdout,_("Message: Hardware version received: ")); +#endif + + j=strlen(Current_Revision); + Current_Revision[j++]=','; + Current_Revision[j++]=' '; + Current_Revision[j++]='H'; + Current_Revision[j++]='W'; + + for (i=5;i<9;i++) { +#ifdef DEBUG + fprintf(stdout,_("%c"), MessageBuffer[i]); +#endif + Current_Revision[j++]=MessageBuffer[i]; + } + +#ifdef DEBUG + fprintf(stdout,_("\n")); +#endif + + CurrentGetHWError=GE_NONE; + } +} + +GSM_Error N6110_SendHWFrame() +{ + unsigned char req[4] = {0x00, 0x01, 0xc8, 0x05}; + + GSM_Error error; + + error=N6110_EnableExtendedCommands(0x01); + if (error!=GE_NONE) return error; + + return NULL_SendMessageSequence (20, &CurrentGetHWError, 4, 0x40, req); +} + +void N6110_ReplyID(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + int i, j; + +#ifdef DEBUG + fprintf(stdout, _("Message: Mobile phone model identification received:\n")); + fprintf(stdout, _(" Firmware: ")); +#endif + + strcpy(Current_Revision,"SW"); + + i=6;j=2; + while (MessageBuffer[i]!=0x0a) { + Current_Revision[j]=MessageBuffer[i]; +#ifdef DEBUG + fprintf(stdout, _("%c"),MessageBuffer[i]); +#endif + if (j==GSM_MAX_REVISION_LENGTH-1) { +#ifdef DEBUG + fprintf(stderr,_("ERROR: increase GSM_MAX_REVISION_LENGTH!\n")); +#endif + break; + } + j++; + i++; + } + Current_Revision[j+1]=0; + +#ifdef DEBUG + fprintf(stdout, _("\n Firmware date: ")); +#endif + + i++; + while (MessageBuffer[i]!=0x0a) { +#ifdef DEBUG + fprintf(stdout, _("%c"),MessageBuffer[i]); +#endif + i++; + } + +#ifdef DEBUG + fprintf(stdout, _("\n Model: ")); +#endif /* DEBUG */ + + i++;j=0; + while (MessageBuffer[i]!=0x0a) { + Current_Model[j]=MessageBuffer[i]; +#ifdef DEBUG + fprintf(stdout, _("%c"),MessageBuffer[i]); +#endif + if (j==GSM_MAX_MODEL_LENGTH-1) { +#ifdef DEBUG + fprintf(stderr,_("ERROR: increase GSM_MAX_MODEL_LENGTH!\n")); +#endif + break; + } + j++; + i++; + } + Current_Model[j+1]=0; + +#ifdef DEBUG + fprintf(stdout, _("\n")); +#endif /* DEBUG */ + + CurrentMagicError=GE_NONE; +} + +GSM_Error N6110_SendIDFrame() +{ + unsigned char req[5] = {N6110_FRAME_HEADER, 0x03, 0x00}; + + return NULL_SendMessageSequence (50, &CurrentMagicError, 5, 0xd1, req); +} + +/* This function send the status request to the phone. */ +/* Seems to be ignored in N3210 */ +GSM_Error N6110_SendStatusRequest(void) +{ + unsigned char req[] = {N6110_FRAME_HEADER, 0x01}; + + Protocol->SendMessage(4, 0x04, req); + + return (GE_NONE); +} + +void N6110_ReplyGetAuthentication(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#if defined WIN32 || !defined HAVE_SNPRINTF + sprintf(Current_IMEI, "%s", MessageBuffer+9); + sprintf(Current_Model, "%s", MessageBuffer+25); + sprintf(Current_Revision, "SW%s, HW%s", MessageBuffer+44, MessageBuffer+39); +#else + snprintf(Current_IMEI, GSM_MAX_IMEI_LENGTH, "%s", MessageBuffer+9); + snprintf(Current_Model, GSM_MAX_MODEL_LENGTH, "%s", MessageBuffer+25); + snprintf(Current_Revision, GSM_MAX_REVISION_LENGTH, "SW%s, HW%s", MessageBuffer+44, MessageBuffer+39); +#endif + +#ifdef DEBUG + fprintf(stdout, _("Message: Mobile phone identification received:\n")); + fprintf(stdout, _(" IMEI: %s\n"), Current_IMEI); + fprintf(stdout, _(" Model: %s\n"), Current_Model); + fprintf(stdout, _(" Production Code: %s\n"), MessageBuffer+31); + fprintf(stdout, _(" HW: %s\n"), MessageBuffer+39); + fprintf(stdout, _(" Firmware: %s\n"), MessageBuffer+44); + + /* These bytes are probably the source of the "Accessory not connected" + messages on the phone when trying to emulate NCDS... I hope.... + UPDATE: of course, now we have the authentication algorithm. */ + fprintf(stdout, _(" Magic bytes: %02x %02x %02x %02x\n"), MessageBuffer[50], MessageBuffer[51], MessageBuffer[52], MessageBuffer[53]); +#endif /* DEBUG */ + + MagicBytes[0]=MessageBuffer[50]; + MagicBytes[1]=MessageBuffer[51]; + MagicBytes[2]=MessageBuffer[52]; + MagicBytes[3]=MessageBuffer[53]; + + CurrentMagicError=GE_NONE; +} + +/* This function provides Nokia authentication protocol. + + This code is written specially for gnokii project by Odinokov Serge. + If you have some special requests for Serge just write him to + apskaita@post.omnitel.net or serge@takas.lt + + Reimplemented in C by Pavel Janík ml. + + Nokia authentication protocol is used in the communication between Nokia + mobile phones (e.g. Nokia 6110) and Nokia Cellular Data Suite software, + commercially sold by Nokia Corp. + + The authentication scheme is based on the token send by the phone to the + software. The software does it's magic (see the function + FB61_GetNokiaAuth()) and returns the result back to the phone. If the + result is correct the phone responds with the message "Accessory + connected!" displayed on the LCD. Otherwise it will display "Accessory not + supported" and some functions will not be available for use. + + The specification of the protocol is not publicly available, no comment. */ +void N6110_GetNokiaAuth(unsigned char *Imei, unsigned char *MagicBytes, unsigned char *MagicResponse) +{ + + int i, j, CRC=0; + + /* This is our temporary working area. */ + + unsigned char Temp[16]; + + /* Here we put FAC (Final Assembly Code) and serial number into our area. */ + + Temp[0] = Imei[6]; + Temp[1] = Imei[7]; + Temp[2] = Imei[8]; + Temp[3] = Imei[9]; + Temp[4] = Imei[10]; + Temp[5] = Imei[11]; + Temp[6] = Imei[12]; + Temp[7] = Imei[13]; + + /* And now the TAC (Type Approval Code). */ + + Temp[8] = Imei[2]; + Temp[9] = Imei[3]; + Temp[10] = Imei[4]; + Temp[11] = Imei[5]; + + /* And now we pack magic bytes from the phone. */ + + Temp[12] = MagicBytes[0]; + Temp[13] = MagicBytes[1]; + Temp[14] = MagicBytes[2]; + Temp[15] = MagicBytes[3]; + + for (i=0; i<=11; i++) + if (Temp[i + 1]& 1) + Temp[i]<<=1; + + switch (Temp[15] & 0x03) { + + case 1: + case 2: + j = Temp[13] & 0x07; + + for (i=0; i<=3; i++) + Temp[i+j] ^= Temp[i+12]; + + break; + + default: + j = Temp[14] & 0x07; + + for (i=0; i<=3; i++) + Temp[i + j] |= Temp[i + 12]; + } + + for (i=0; i<=15; i++) + CRC ^= Temp[i]; + + for (i=0; i<=15; i++) { + + switch (Temp[15 - i] & 0x06) { + + case 0: + j = Temp[i] | CRC; + break; + + case 2: + case 4: + j = Temp[i] ^ CRC; + break; + + case 6: + j = Temp[i] & CRC; + break; + } + + if (j == CRC) + j = 0x2c; + + if (Temp[i] == 0) + j = 0; + + MagicResponse[i] = j; + + } +} + +GSM_Error N6110_Authentication() +{ + unsigned char connect1[] = {N6110_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x02}; + unsigned char connect2[] = {N6110_FRAME_HEADER, 0x20, 0x02}; + unsigned char connect3[] = {N6110_FRAME_HEADER, 0x0d, 0x01, 0x00, 0x02}; + unsigned char connect4[] = {N6110_FRAME_HEADER, 0x10}; + + unsigned char magic_connect[] = {N6110_FRAME_HEADER, + 0x12, + + /* The real magic goes here ... These bytes are filled in with the + function N6110_GetNokiaAuth(). */ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* NOKIA&GNOKII Accessory */ + + 0x4e, 0x4f, 0x4b, 0x49, 0x41, 0x26, 0x4e, 0x4f, 0x4b, 0x49, 0x41, 0x20, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x79, + + 0x00, 0x00, 0x00, 0x00}; + +#ifdef DEBUG + fprintf(stdout,_("Making authentication!\n")); +#endif + + usleep(100); Protocol->SendMessage(7, 0x02, connect1); + usleep(100); Protocol->SendMessage(5, 0x02, connect2); + usleep(100); Protocol->SendMessage(7, 0x02, connect3); + + CurrentMagicError = GE_BUSY; + + usleep(100); Protocol->SendMessage(4, 0x64, connect4); + if (NULL_WaitUntil(50,&CurrentMagicError)!=GE_NONE) return GE_TIMEOUT; + + N6110_GetNokiaAuth(Current_IMEI, MagicBytes, magic_connect+4); + + Protocol->SendMessage(45, 0x64, magic_connect); + +#ifdef DEBUG + fprintf(stdout,_("End of authentication!\n")); +#endif + + return GE_NONE; +} + +/* Initialise variables and state machine. */ +GSM_Error N6110_Initialise(char *port_device, char *initlength, + GSM_ConnectionType connection, + void (*rlp_callback)(RLP_F96Frame *frame)) +{ + unsigned char init_char = N6110_SYNC_BYTE; + unsigned char end_init_char = N6110_IR_END_SYNC_BYTE; + + int count; + int InitLength; + + if (Protocol->Initialise(port_device,initlength,connection,rlp_callback)!=GE_NONE) + { + return GE_NOTSUPPORTED; + } + + switch (CurrentConnectionType) { + case GCT_Irda: + case GCT_MBUS: + /* We don't think about authentication in Irda, because + AFAIK there are no phones working over sockets + and having authentication. In MBUS it doesn't work */ + usleep(100); + + if (N6110_SendIDFrame()!=GE_NONE) return GE_TIMEOUT; + + if (N6110_SendIMEIFrame()!=GE_NONE) return GE_TIMEOUT; + + if (N6110_SendHWFrame()!=GE_NONE) return GE_TIMEOUT; + + CurrentLinkOK = true; + break; + + case GCT_FBUS: + case GCT_Infrared: + case GCT_Tekram: + InitLength = atoi(initlength); + + if ((strcmp(initlength, "default") == 0) || (InitLength == 0)) { + InitLength = 250; /* This is the usual value, lower may work. */ + } + + if (CurrentConnectionType==GCT_Infrared || + CurrentConnectionType==GCT_Tekram) { +#ifdef DEBUG + fprintf(stdout,_("Setting infrared for FBUS communication...\n")); +#endif + device_changespeed(9600); + } + +#ifdef DEBUG + fprintf(stdout,_("Writing init chars....")); +#endif + + /* Initialise link with phone or what have you */ + /* Send init string to phone, this is a bunch of 0x55 characters. Timing is + empirical. */ + for (count = 0; count < InitLength; count ++) { + if (CurrentConnectionType!=GCT_Infrared && + CurrentConnectionType!=GCT_Tekram) usleep(100); + Protocol->WritePhone(1,&init_char); + } + + if (CurrentConnectionType==GCT_Infrared || + CurrentConnectionType==GCT_Tekram) { + Protocol->WritePhone(1,&end_init_char); + usleep(200000); + } + +#ifdef DEBUG + fprintf(stdout,_("Done\n")); +#endif + + if (CurrentConnectionType==GCT_Infrared || + CurrentConnectionType==GCT_Tekram) { + device_changespeed(115200); + } + + N6110_SendStatusRequest(); + + usleep(100); + + if (N6110_SendIDFrame()!=GE_NONE) return GE_TIMEOUT; + + /* N51xx/61xx have something called authentication. + After making it phone display "Accessory connected" + and probably give access to some function (I'm not too sure about it !) + Anyway, I make it now for N51xx/61xx */ + if (GetModelFeature (FN_AUTHENTICATION)!=0) { + if (N6110_Authentication()!=GE_NONE) return GE_TIMEOUT; + } else { /* No authentication */ + if (N6110_SendIMEIFrame()!=GE_NONE) return GE_TIMEOUT; + + if (N6110_SendHWFrame()!=GE_NONE) return GE_TIMEOUT; + } + + break; + default: +#ifdef DEBUG + fprintf(stdout,_("Unknown connection type in n6110.c!\n")); +#endif + break; + } + + return (GE_NONE); +} + +/* This function translates GMT_MemoryType to N6110_MEMORY_xx */ +int N6110_GetMemoryType(GSM_MemoryType memory_type) +{ + + int result; + + switch (memory_type) { + + case GMT_MT: result = N6110_MEMORY_MT; break; + case GMT_ME: result = N6110_MEMORY_ME; break; + case GMT_SM: result = N6110_MEMORY_SM; break; + case GMT_FD: result = N6110_MEMORY_FD; break; + case GMT_ON: result = N6110_MEMORY_ON; break; + case GMT_EN: result = N6110_MEMORY_EN; break; + case GMT_DC: result = N6110_MEMORY_DC; break; + case GMT_RC: result = N6110_MEMORY_RC; break; + case GMT_MC: result = N6110_MEMORY_MC; break; + default : result = N6110_MEMORY_XX; + + } + + return (result); +} + +void N6110_ReplyCallDivert(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + switch (MessageBuffer[3]) { + + case 0x02: + +#ifdef DEBUG + fprintf(stdout, _("Message: Call divert status received\n")); + fprintf(stdout, _(" Divert type: ")); + switch (MessageBuffer[6]) { + case 0x43: fprintf(stdout, _("when busy"));break; + case 0x3d: fprintf(stdout, _("when not answered"));break; + case 0x3e: fprintf(stdout, _("when phone off or no coverage"));break; + case 0x15: fprintf(stdout, _("all types of diverts"));break; //? + case 0x02: fprintf(stdout, _("all types of diverts"));break; //? + default: fprintf(stdout, _("unknown %i"),MessageBuffer[6]);break; + } + fprintf(stdout, _("\n Calls type : ")); + if (MessageBuffer[6]==0x02) + fprintf(stdout, _("voice, fax & data")); //? + else { + switch (MessageBuffer[8]) { + case 0x0b: fprintf(stdout, _("voice"));break; + case 0x0d: fprintf(stdout, _("fax"));break; + case 0x19: fprintf(stdout, _("data"));break; + default: fprintf(stdout, _("unknown %i"),MessageBuffer[8]);break; + } + } + fprintf(stdout, _("\n")); + if (MessageBuffer[10]==0x01) { + fprintf(stdout, _(" Status : active\n")); + fprintf(stdout, _(" Timeout : %i seconds\n"),MessageBuffer[45]); + fprintf(stdout, _(" Number : %s\n"),GSM_UnpackSemiOctetNumber(MessageBuffer+12,true)); + } else { + fprintf(stdout, _(" Status : deactivated\n")); + } +#endif /* DEBUG */ + + if (CurrentCallDivert!=NULL) { + switch (MessageBuffer[6]) { + case 0x43: CurrentCallDivert->DType=GSM_CDV_Busy;break; + case 0x3d: CurrentCallDivert->DType=GSM_CDV_NoAnswer;break; + case 0x3e: CurrentCallDivert->DType=GSM_CDV_OutOfReach;break; + case 0x15: CurrentCallDivert->DType=GSM_CDV_AllTypes;break; //? + case 0x02: CurrentCallDivert->DType=GSM_CDV_AllTypes;break; //? + } + + if (MessageBuffer[6]==0x02) //? + CurrentCallDivert->CType=GSM_CDV_AllCalls; + else { + switch (MessageBuffer[8]) { + case 0x0b: CurrentCallDivert->CType=GSM_CDV_VoiceCalls;break; + case 0x0d: CurrentCallDivert->CType=GSM_CDV_FaxCalls; break; + case 0x19: CurrentCallDivert->CType=GSM_CDV_DataCalls; break; + } + } + + if (MessageBuffer[10]==0x01) { + CurrentCallDivert->Enabled=true; + CurrentCallDivert->Timeout=MessageBuffer[45]; + strcpy(CurrentCallDivert->Number,GSM_UnpackSemiOctetNumber(MessageBuffer+12,true)); + } else { + CurrentCallDivert->Enabled=false; + } + CurrentCallDivertError=GE_NONE; + } + break; + + case 0x03: +#ifdef DEBUG + fprintf(stdout, _("Message: Call divert status receiving error ?\n")); +#endif + CurrentCallDivertError=GE_UNKNOWN; + break; + } +} + +GSM_Error N6110_CallDivert(GSM_CallDivert *cd) +{ + char req[55] = { N6110_FRAME_HEADER, 0x01, + 0x00, /* operation */ + 0x00, + 0x00, /* divert type */ + 0x00, /* call type */ + 0x00 }; + GSM_Error error; + + int length = 0x09; + + switch (cd->Operation) { + case GSM_CDV_Register: + case GSM_CDV_Enable: + req[4] = 0x03; + req[8] = 0x01; + req[29]= GSM_PackSemiOctetNumber(cd->Number, req + 9, false); + req[52]= cd->Timeout; + length = 55; + break; + case GSM_CDV_Erasure: + case GSM_CDV_Disable: + req[4] = 0x04; + break; + case GSM_CDV_Query: + req[4] = 0x05; + break; + default: + return GE_NOTIMPLEMENTED; + } + + switch (cd->DType) { + case GSM_CDV_AllTypes : req[6] = 0x15; break; + case GSM_CDV_Busy : req[6] = 0x43; break; + case GSM_CDV_NoAnswer : req[6] = 0x3d; break; + case GSM_CDV_OutOfReach: req[6] = 0x3e; break; + default: return GE_NOTIMPLEMENTED; + } + + if ((cd->DType == GSM_CDV_AllTypes) && + (cd->CType == GSM_CDV_AllCalls)) + req[6] = 0x02; + + switch (cd->CType) { + case GSM_CDV_AllCalls : break; + case GSM_CDV_VoiceCalls: req[7] = 0x0b; break; + case GSM_CDV_FaxCalls : req[7] = 0x0d; break; + case GSM_CDV_DataCalls : req[7] = 0x19; break; + default: return GE_NOTIMPLEMENTED; + } + + CurrentCallDivert = cd; + + error=NULL_SendMessageSequence + (100, &CurrentCallDivertError, length, 0x06, req); + + CurrentCallDivert = NULL; + + return error; +} + +GSM_Error N6110_Tests() +{ + unsigned char buffer[3]={0x00,0x01,0xcf}; + unsigned char buffer3[8]={0x00,0x01,0xce,0x1d,0xfe,0x23,0x00,0x00}; + + GSM_Error error; + + error=N6110_EnableExtendedCommands(0x01); + if (error!=GE_NONE) return error; + + //make almost all tests + Protocol->SendMessage(8, 0x40, buffer3); + + while (GSM->Initialise(PortDevice, "50", CurrentConnectionType, CurrentRLP_RXCallback)!=GE_NONE) {}; + + sleep(2); + + return NULL_SendMessageSequence + (200, &CurrentNetworkInfoError, 3, 0x40, buffer); +} + +void N6110_DisplayTestsInfo(u8 *MessageBuffer) { + + int i; + + CurrentNetworkInfoError=GE_NONE; + + for (i=0;i> 4))); + j++; + } + if (j==5 || j==15) fprintf(stdout, _("\n")); + if (j!=15) { + if (j<24) { + fprintf(stdout,_("%c"), ('0' + (MessageBuffer[9+i] & 0x0f))); + j++; + } + } else j++; + if (j==20 || j==24) fprintf(stdout, _("\n")); + } + + if ((MessageBuffer[6] & 1) == 1) fprintf(stdout,_("lock 1 closed\n")); + if ((MessageBuffer[6] & 2) == 2) fprintf(stdout,_("lock 2 closed\n")); + if ((MessageBuffer[6] & 4) == 4) fprintf(stdout,_("lock 3 closed\n")); + if ((MessageBuffer[6] & 8) == 8) fprintf(stdout,_("lock 4 closed\n")); + + /* I'm not sure here at all */ + if ((MessageBuffer[5] & 1) == 1) fprintf(stdout,_("lock 1 - user\n")); + if ((MessageBuffer[5] & 2) == 2) fprintf(stdout,_("lock 2 - user\n")); + if ((MessageBuffer[5] & 4) == 4) fprintf(stdout,_("lock 3 - user\n")); + if ((MessageBuffer[5] & 8) == 8) fprintf(stdout,_("lock 4 - user\n")); + + fprintf(stdout,_("counter for lock1: %i\n"),MessageBuffer[21]); + fprintf(stdout,_("counter for lock2: %i\n"),MessageBuffer[22]); + fprintf(stdout,_("counter for lock3: %i\n"),MessageBuffer[23]); + fprintf(stdout,_("counter for lock4: %i\n"),MessageBuffer[24]); + +#endif + + j=0; + for (i=0; i < 12; i++) + { + if (j<24) { + uni[j]='0' + (MessageBuffer[9+i] >> 4); + j++; + } + if (j!=15) { + if (j<24) { + uni[j]='0' + (MessageBuffer[9+i] & 0x0f); + j++; + } + } else j++; + } + + strncpy(CurrentSimLock->simlocks[0].data,uni,5); + CurrentSimLock->simlocks[0].data[5]=0; + strncpy(CurrentSimLock->simlocks[3].data,uni+5,10); + CurrentSimLock->simlocks[3].data[10]=0; + strncpy(CurrentSimLock->simlocks[1].data,uni+16,4); + CurrentSimLock->simlocks[1].data[4]=0; + strncpy(CurrentSimLock->simlocks[2].data,uni+20,4); + CurrentSimLock->simlocks[2].data[4]=0; + + CurrentSimLock->simlocks[0].enabled=((MessageBuffer[6] & 1) == 1); + CurrentSimLock->simlocks[1].enabled=((MessageBuffer[6] & 2) == 2); + CurrentSimLock->simlocks[2].enabled=((MessageBuffer[6] & 4) == 4); + CurrentSimLock->simlocks[3].enabled=((MessageBuffer[6] & 8) == 8); + + CurrentSimLock->simlocks[0].factory=((MessageBuffer[5] & 1) != 1); + CurrentSimLock->simlocks[1].factory=((MessageBuffer[5] & 2) != 2); + CurrentSimLock->simlocks[2].factory=((MessageBuffer[5] & 4) != 4); + CurrentSimLock->simlocks[3].factory=((MessageBuffer[5] & 8) != 8); + + CurrentSimLock->simlocks[0].counter=MessageBuffer[21]; + CurrentSimLock->simlocks[1].counter=MessageBuffer[22]; + CurrentSimLock->simlocks[2].counter=MessageBuffer[23]; + CurrentSimLock->simlocks[3].counter=MessageBuffer[24]; + + CurrentSimlockInfoError=GE_NONE; +} + +GSM_Error N6110_SimlockInfo(GSM_AllSimlocks *siml) +{ + GSM_Error error; + unsigned char req[] = {0x00,0x01,0x8a,0x00}; + error=N6110_EnableExtendedCommands(0x01); + if (error!=GE_NONE) return error; + + CurrentSimLock=siml; + + return NULL_SendMessageSequence (50, &CurrentSimlockInfoError, 4, 0x40, req); +} + +void N6110_ReplyResetPhoneSettings(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#ifdef DEBUG + fprintf(stdout, _("Message: Resetting phone settings\n")); +#endif /* DEBUG */ + + CurrentResetPhoneSettingsError=GE_NONE; +} + +GSM_Error N6110_ResetPhoneSettings() +{ + GSM_Error error; + unsigned char req[] = {0x00,0x01,0x65,0x08,0x00}; + error=N6110_EnableExtendedCommands(0x01); + if (error!=GE_NONE) return error; + + return NULL_SendMessageSequence + (50, &CurrentResetPhoneSettingsError, 5, 0x40, req); +} +GSM_Error N6110_GetManufacturer(char *manufacturer) +{ + strcpy (manufacturer, "Nokia"); + return (GE_NONE); +} + +GSM_Error N6110_GetVoiceMailbox ( GSM_PhonebookEntry *entry) +{ + unsigned char req[] = {N6110_FRAME_HEADER, 0x01, 0x00, 0x00, 0x00}; + + GSM_Error error; + + CurrentPhonebookEntry = entry; + + req[4] = N6110_MEMORY_VOICE; + req[5] = 0x00; /* Location - isn't important, but... */ + + error=NULL_SendMessageSequence + (20, &CurrentPhonebookError, 7, 0x03, req); + + CurrentPhonebookEntry = NULL; + + return error; +} + +void N6110_ReplyGetOperatorName(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + int i, count; + + GSM_Bitmap NullBitmap; + + DecodeNetworkCode(MessageBuffer+5, NullBitmap.netcode); + + count=8; + +#ifdef DEBUG + fprintf(stdout, _("Message: Info about downloaded operator name received: %s network (for gnokii \"%s\", for phone \""), + NullBitmap.netcode, + GSM_GetNetworkName(NullBitmap.netcode)); +#endif + + i=count; + while (MessageBuffer[count]!=0) { +#ifdef DEBUG + fprintf(stdout,_("%c"),MessageBuffer[count]); +#endif + count++; + } + + strcpy(CurrentGetOperatorNameNetwork->Code, NullBitmap.netcode); + strncpy(CurrentGetOperatorNameNetwork->Name, MessageBuffer+i,count-i+1); + +#ifdef DEBUG + fprintf(stdout,_("\")\n")); +#endif + + CurrentGetOperatorNameError=GE_NONE; +} + +GSM_Error N6110_GetOperatorName (GSM_Network *operator) +{ + unsigned char req[] = { 0x00,0x01,0x8c,0x00}; + + GSM_Error error; + + error=N6110_EnableExtendedCommands(0x01); + if (error!=GE_NONE) return error; + + CurrentGetOperatorNameNetwork = operator; + + error=NULL_SendMessageSequence + (20, &CurrentGetOperatorNameError, 4, 0x40, req); + + CurrentGetOperatorNameNetwork = NULL; + + return error; +} + +void N6110_ReplySetOperatorName(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#ifdef DEBUG + fprintf(stdout, _("Message: Downloaded operator name changed\n")); +#endif + + CurrentSetOperatorNameError=GE_NONE; +} + +GSM_Error N6110_SetOperatorName (GSM_Network *operator) +{ + unsigned char req[256] = { 0x00,0x01,0x8b,0x00, + 0x00,0x00, /* MCC */ + 0x00}; /* MNC */ + + GSM_Error error; + + error=N6110_EnableExtendedCommands(0x01); + if (error!=GE_NONE) return error; + + EncodeNetworkCode(req+4,operator->Code); + + strncpy(req+7,operator->Name,200); + + return NULL_SendMessageSequence + (20, &CurrentSetOperatorNameError, 8+strlen(operator->Name), 0x40, req); +} + +void N6110_ReplyGetMemoryStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + switch (MessageBuffer[3]) { + + case 0x08: + +#ifdef DEBUG + fprintf(stdout, _("Message: Memory status received:\n")); + + fprintf(stdout, _(" Memory Type: %s\n"), N6110_MemoryType_String[MessageBuffer[4]]); + fprintf(stdout, _(" Used: %d\n"), MessageBuffer[6]); + fprintf(stdout, _(" Free: %d\n"), MessageBuffer[5]); +#endif /* DEBUG */ + + CurrentMemoryStatus->Used = MessageBuffer[6]; + CurrentMemoryStatus->Free = MessageBuffer[5]; + CurrentMemoryStatusError = GE_NONE; + + break; + + case 0x09: + +#ifdef DEBUG + switch (MessageBuffer[4]) { + case 0x6f: + fprintf(stdout, _("Message: Memory status error, phone is probably powered off.\n"));break; + case 0x7d: + fprintf(stdout, _("Message: Memory status error, memory type not supported by phone model.\n"));break; + case 0x8d: + fprintf(stdout, _("Message: Memory status error, waiting for security code.\n"));break; + default: + fprintf(stdout, _("Message: Unknown Memory status error, subtype (MessageBuffer[4]) = %02x\n"),MessageBuffer[4]);break; + } +#endif + + switch (MessageBuffer[4]) { + case 0x6f:CurrentMemoryStatusError = GE_TIMEOUT;break; + case 0x7d:CurrentMemoryStatusError = GE_INTERNALERROR;break; + case 0x8d:CurrentMemoryStatusError = GE_INVALIDSECURITYCODE;break; + default:break; + } + + break; + + } +} + +/* This function is used to get storage status from the phone. It currently + supports two different memory areas - internal and SIM. */ +GSM_Error N6110_GetMemoryStatus(GSM_MemoryStatus *Status) +{ + unsigned char req[] = { N6110_FRAME_HEADER, + 0x07, /* MemoryStatus request */ + 0x00 /* MemoryType */ + }; + + GSM_Error error; + + CurrentMemoryStatus = Status; + + req[4] = N6110_GetMemoryType(Status->MemoryType); + + error=NULL_SendMessageSequence + (20, &CurrentMemoryStatusError, 5, 0x03, req); + + CurrentMemoryStatus = NULL; + + return error; +} + +void N6110_ReplyGetNetworkInfo(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + GSM_NetworkInfo NullNetworkInfo; + + /* Make sure we are expecting NetworkInfo frame */ + if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) { +#ifdef DEBUG + fprintf(stdout, _("Message: Network informations:\n")); +#endif + } else { +#ifdef DEBUG + fprintf(stdout, _("Message: Network informations not requested, but received:\n")); +#endif + } + + sprintf(NullNetworkInfo.NetworkCode, "%x%x%x %x%x", MessageBuffer[14] & 0x0f, MessageBuffer[14] >>4, MessageBuffer[15] & 0x0f, MessageBuffer[16] & 0x0f, MessageBuffer[16] >>4); + + sprintf(NullNetworkInfo.CellID, "%02x%02x", MessageBuffer[10], MessageBuffer[11]); + + sprintf(NullNetworkInfo.LAC, "%02x%02x", MessageBuffer[12], MessageBuffer[13]); + +#ifdef DEBUG + fprintf(stdout, _(" CellID: %s\n"), NullNetworkInfo.CellID); + fprintf(stdout, _(" LAC: %s\n"), NullNetworkInfo.LAC); + fprintf(stdout, _(" Network code: %s\n"), NullNetworkInfo.NetworkCode); + fprintf(stdout, _(" Network name: %s (%s)\n"), + GSM_GetNetworkName(NullNetworkInfo.NetworkCode), + GSM_GetCountryName(NullNetworkInfo.NetworkCode)); + fprintf(stdout, _(" Status: ")); + + switch (MessageBuffer[8]) { + case 0x01: fprintf(stdout, _("home network selected")); break; + case 0x02: fprintf(stdout, _("roaming network")); break; + case 0x03: fprintf(stdout, _("requesting network")); break; + case 0x04: fprintf(stdout, _("not registered in the network")); break; + default: fprintf(stdout, _("unknown")); + } + + fprintf(stdout, "\n"); + + fprintf(stdout, _(" Network selection: %s\n"), MessageBuffer[9]==1?_("manual"):_("automatic")); +#endif /* DEBUG */ + + /* Make sure we are expecting NetworkInfo frame */ + if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) + *CurrentNetworkInfo=NullNetworkInfo; + + CurrentNetworkInfoError = GE_NONE; +} + +GSM_Error N6110_GetNetworkInfo(GSM_NetworkInfo *NetworkInfo) +{ + unsigned char req[] = { N6110_FRAME_HEADER, + 0x70 + }; + + GSM_Error error; + + CurrentNetworkInfo = NetworkInfo; + + error=NULL_SendMessageSequence + (20, &CurrentNetworkInfoError, 4, 0x0a, req); + + CurrentNetworkInfo = NULL; + + return error; +} + +void N6110_ReplyGetProductProfileSetting(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + int i; + +#ifdef DEBUG + fprintf(stdout, _("Message: Product Profile Settings received -")); + for (i=0;i<4;i++) fprintf(stdout, _(" %02x"),MessageBuffer[3+i]); + fprintf(stdout, _("\n")); +#endif + + for (i=0;i<4;i++) CurrentPPS[i]=MessageBuffer[3+i]; + + CurrentProductProfileSettingsError=GE_NONE; +} + +GSM_Error N6110_GetProductProfileSetting (GSM_PPS *PPS) +{ + unsigned char req[] = { 0x00, 0x01,0x6a }; + + int i,j; + + GSM_Error error; + + error=N6110_EnableExtendedCommands(0x01); + if (error!=GE_NONE) return error; + + error=NULL_SendMessageSequence + (20, &CurrentProductProfileSettingsError, 3, 0x40, req); + if (error!=GE_NONE) return error; + + switch (PPS->Name) { + case PPS_ALS : PPS->bool_value=(CurrentPPS[1]&32); break; + case PPS_GamesMenu: PPS->bool_value=(CurrentPPS[3]&64); break; + case PPS_HRData : PPS->bool_value=(CurrentPPS[0]&64); break; + case PPS_14400Data: PPS->bool_value=(CurrentPPS[0]&128);break; + case PPS_EFR : PPS->int_value =(CurrentPPS[0]&1) +(CurrentPPS[0]&2); break; + case PPS_FR : PPS->int_value =(CurrentPPS[0]&16)/16+(CurrentPPS[0]&32)/16;break; + case PPS_HR : PPS->int_value =(CurrentPPS[0]&4)/4 +(CurrentPPS[0]&8)/4; break; + case PPS_VibraMenu: PPS->bool_value=(CurrentPPS[4]&64); break; + case PPS_LCDContrast: + PPS->int_value=0; + j=1; + for (i=0;i<5;i++) { + if (CurrentPPS[3]&j) PPS->int_value=PPS->int_value+j; + j=j*2; + } + PPS->int_value=PPS->int_value*100/32; + break; + + } + + return (GE_NONE); +} + +void N6110_ReplySetProductProfileSetting(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#ifdef DEBUG + int i; + + fprintf(stdout, _("Message: Product Profile Settings set to")); + for (i=0;i<4;i++) fprintf(stdout, _(" %02x"),CurrentPPS[i]); + fprintf(stdout, _("\n")); +#endif + + CurrentProductProfileSettingsError=GE_NONE; +} + +GSM_Error N6110_SetProductProfileSetting (GSM_PPS *PPS) +{ + unsigned char req[] = { 0x00, 0x01,0x6b, + 0x00, 0x00, 0x00, 0x00 }; /* bytes with Product Profile Setings */ + unsigned char settings[32]; + + GSM_PPS OldPPS; + + int i,j,z; + + GSM_Error error; + + error=N6110_EnableExtendedCommands(0x01); + if (error!=GE_NONE) return error; + + OldPPS.Name=PPS_ALS; + error=N6110_GetProductProfileSetting(&OldPPS); + if (error!=GE_NONE) return error; + + j=128;z=0; + for (i=0;i<32;i++) { + if (CurrentPPS[z]&j) + settings[i]='1'; + else + settings[i]='0'; + if (j==1) { + j=128; + z++; + } else j=j/2; + } + +#ifdef DEBUG + fprintf(stdout,_("Current settings: ")); + for (i=0;i<32;i++) { + fprintf(stdout,_("%c"),settings[i]); + } + fprintf(stdout,_("\n")); +#endif + + switch (PPS->Name) { + case PPS_ALS :settings[10]=PPS->bool_value?'1':'0';break; + case PPS_HRData :settings[ 5]=PPS->bool_value?'1':'0';break; + case PPS_14400Data:settings[ 6]=PPS->bool_value?'1':'0';break; + default :break; + } + + j=128;z=0; + for (i=0;i<32;i++) { + if (settings[i]=='1') req[z+3]=req[z+3]+j; + if (j==1) { + j=128; + z++; + } else j=j/2; + } + +#ifdef DEBUG + fprintf(stdout,_("Current settings: ")); + for (i=0;i<4;i++) { + fprintf(stdout,_("%i "),req[i+3]); + } + fprintf(stdout,_("\n")); +#endif + + for (i=0;i<4;i++) { + CurrentPPS[i]=req[i+3]; + } + + return NULL_SendMessageSequence + (20, &CurrentProductProfileSettingsError, 7, 0x40, req); +} + +void N6110_ReplyPressKey(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + if (MessageBuffer[4]==CurrentPressKeyEvent) CurrentPressKeyError=GE_NONE; + else CurrentPressKeyError=GE_UNKNOWN; /* MessageBuffer[4] = 0x05 */ +#ifdef DEBUG + fprintf(stdout, _("Message: Result of key ")); + switch (MessageBuffer[4]) + { + case PRESSPHONEKEY: fprintf(stdout, _("press OK\n"));break; + case RELEASEPHONEKEY: fprintf(stdout, _("release OK\n"));break; + default: fprintf(stdout, _("press or release - error\n"));break; + } +#endif /* DEBUG */ +} + +GSM_Error N6110_PressKey(int key, int event) +{ + unsigned char req[] = {N6110_FRAME_HEADER, 0x42, 0x01, 0x00, 0x01}; + + req[4]=event; /* if we press or release key */ + req[5]=key; + + CurrentPressKeyEvent=event; + + return NULL_SendMessageSequence + (10, &CurrentPressKeyError, 7, 0x0c, req); +} + +void N6110_ReplyDisplayOutput(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + /* Hopefully is 64 larger as FB38_MAX* / N6110_MAX* */ + char model[64]; + + int i, j; + + char uni[100]; + + switch(MessageBuffer[3]) { + + /* Phone sends displayed texts */ + case 0x50: + NewX=MessageBuffer[6]; + NewY=MessageBuffer[5]; + + DecodeUnicode (uni, MessageBuffer+8, MessageBuffer[7]); + +#ifdef DEBUG + fprintf(stdout, _("New displayed text (%i %i): \"%s\"\n"),NewX,NewY,uni); +#endif /* DEBUG */ + + while (N6110_GetModel(model) != GE_NONE) + sleep(1); + + /* With these rules it works almost excellent with my N5110 */ + /* I don't have general rule :-(, that's why you must experiment */ + /* with your phone. Nokia could make it better. MW */ + /* It's almost OK for N5110*/ + /* FIX ME: it will be the same for N5130 and 3210 too*/ + if (!strcmp(model,"NSE-1")) + { + /* OldX==1000 means - it's first time */ + if (OldX==1000) { + + /* Clean table */ + for (i=0;i<5+1;i++) { + for (j=0;j<27+1;j++) {PhoneScreen[i][j]=' ';} + } + OldX=0; + } + + if ((OldX==0 && OldY==31 && NewX==29 && NewY==46) || + (OldX==0 && OldY==13 && NewX==23 && NewY==46)) { + /* Clean the line with current text */ + for (j=0;j<27+1;j++) {PhoneScreen[NewY/(47/5)][j]=' ';} + + /* Inserts text into table */ + for (i=0; iSendMessage(sizeof(req0), 0x01, req0); + sleep(1); + + return NULL_SendMessageSequence + (20, &CurrentMagicError, sizeof(req) , 0x01, req); +} + +void N6110_ReplyGetProfile(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + switch (MessageBuffer[3]) { + + /* Profile feature */ + case 0x14: + + switch(GetModelFeature (FN_PROFILES)) { + case F_PROF33: + switch (MessageBuffer[6]) { + case 0x00: CurrentProfile->KeypadTone = MessageBuffer[8]; break; + case 0x01: CurrentProfile->CallAlert = MessageBuffer[8]; break; + case 0x02: CurrentProfile->Ringtone = MessageBuffer[8]; break; + case 0x03: CurrentProfile->Volume = MessageBuffer[8]; break; + case 0x04: CurrentProfile->MessageTone = MessageBuffer[8]; break; + case 0x05: CurrentProfile->Vibration = MessageBuffer[8]; break; + case 0x06: CurrentProfile->WarningTone = MessageBuffer[8]; break; + case 0x07: CurrentProfile->ScreenSaver = MessageBuffer[8]; break; + default: +#ifdef DEBUG + fprintf(stdout,_("feature %i = value %i\n\n"),MessageBuffer[6],MessageBuffer[8]); +#endif + break; + } + break; + default: + switch (MessageBuffer[6]) { + case 0x00: CurrentProfile->KeypadTone = MessageBuffer[8];break; + case 0x01: CurrentProfile->Lights = MessageBuffer[8];break; + case 0x02: CurrentProfile->CallAlert = MessageBuffer[8];break; + case 0x03: CurrentProfile->Ringtone = MessageBuffer[8];break; + case 0x04: CurrentProfile->Volume = MessageBuffer[8];break; + case 0x05: CurrentProfile->MessageTone = MessageBuffer[8];break; + case 0x06: CurrentProfile->Vibration = MessageBuffer[8];break; + case 0x07: CurrentProfile->WarningTone = MessageBuffer[8];break; + case 0x08: CurrentProfile->CallerGroups = MessageBuffer[8];break; + case 0x09: CurrentProfile->AutomaticAnswer = MessageBuffer[8];break; + default: +#ifdef DEBUG + fprintf(stdout,_("feature %i = value %i\n\n"),MessageBuffer[6],MessageBuffer[8]); +#endif + break; + } + break; + } + + CurrentProfileError = GE_NONE; + break; + + /* Incoming profile name */ + case 0x1b: + + if (MessageBuffer[9] == 0x00) { + CurrentProfile->DefaultName=MessageBuffer[8]; + } else { + CurrentProfile->DefaultName=-1; + + /* Here name is in Unicode */ + if (GetModelFeature (FN_PROFILES)==F_PROF33) { + DecodeUnicode (CurrentProfile->Name, MessageBuffer+10, MessageBuffer[9]/2); + } else { + /* ...here not */ + sprintf(CurrentProfile->Name, MessageBuffer + 10, MessageBuffer[9]); + CurrentProfile->Name[MessageBuffer[9]] = '\0'; + } + } + + CurrentProfileError = GE_NONE; + break; + + } +} + +/* Needs SIM card with PIN in phone */ +GSM_Error N6110_GetProfile(GSM_Profile *Profile) +{ + int i; + + unsigned char name_req[] = { N6110_FRAME_HEADER, 0x1a, 0x00}; + unsigned char feat_req[] = { N6110_FRAME_HEADER, 0x13, 0x01, 0x00, 0x00}; + + GSM_Error error; + + CurrentProfile = Profile; + + /* When after sending all frames feature==253, it means, that it is not + supported */ + CurrentProfile->KeypadTone=253; + CurrentProfile->Lights=253; + CurrentProfile->CallAlert=253; + CurrentProfile->Ringtone=253; + CurrentProfile->Volume=253; + CurrentProfile->MessageTone=253; + CurrentProfile->WarningTone=253; + CurrentProfile->Vibration=253; + CurrentProfile->CallerGroups=253; + CurrentProfile->ScreenSaver=253; + CurrentProfile->AutomaticAnswer=253; + + name_req[4] = Profile->Number; + + error=NULL_SendMessageSequence + (20, &CurrentProfileError, 5, 0x05, name_req); + if (error!=GE_NONE) return error; + + for (i = 0x00; i <= 0x09; i++) { + + feat_req[5] = Profile->Number; + + feat_req[6] = i; + + error=NULL_SendMessageSequence + (20, &CurrentProfileError, 7, 0x05, feat_req); + if (error!=GE_NONE) return error; + } + + if (Profile->DefaultName > -1) + { + switch(GetModelFeature (FN_PROFILES)) { + case F_PROF33: + switch (Profile->DefaultName) { + case 0x00: sprintf(Profile->Name, "General");break; + case 0x01: sprintf(Profile->Name, "Silent");break; + case 0x02: sprintf(Profile->Name, "Descreet");break; + case 0x03: sprintf(Profile->Name, "Loud");break; + case 0x04: sprintf(Profile->Name, "My style");break; + case 0x05: Profile->Name[0]=0;break; + default : sprintf(Profile->Name, "Unknown (%i)", Profile->DefaultName);break; + } + break; + case F_PROF51: + switch (Profile->DefaultName) { + case 0x00: sprintf(Profile->Name, "Personal");break; + case 0x01: sprintf(Profile->Name, "Car");break; + case 0x02: sprintf(Profile->Name, "Headset");break; + default : sprintf(Profile->Name, "Unknown (%i)", Profile->DefaultName);break; + } + break; + case F_PROF61: + switch (Profile->DefaultName) { + case 0x00: sprintf(Profile->Name, "General");break; + case 0x01: sprintf(Profile->Name, "Silent");break; + case 0x02: sprintf(Profile->Name, "Meeting");break; + case 0x03: sprintf(Profile->Name, "Outdoor");break; + case 0x04: sprintf(Profile->Name, "Pager");break; + case 0x05: sprintf(Profile->Name, "Car");break; + case 0x06: sprintf(Profile->Name, "Headset");break; + default : sprintf(Profile->Name, "Unknown (%i)", Profile->DefaultName);break; + } + break; + } + } + + return (GE_NONE); + +} + +void N6110_ReplySetProfile(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + switch (MessageBuffer[3]) { + + /* Profile feature change result */ + case 0x11: +#ifdef DEBUG + fprintf(stdout, _("Message: Profile feature change result.\n")); +#endif /* DEBUG */ + CurrentProfileError = GE_NONE; + break; + + /* Profile name set result */ + case 0x1d: +#ifdef DEBUG + fprintf(stdout, _("Message: Profile name change result.\n")); +#endif /* DEBUG */ + CurrentProfileError = GE_NONE; + break; + + } +} + +GSM_Error N6110_SetProfileFeature(u8 profile, u8 feature, u8 value) +{ + unsigned char feat_req[] = { N6110_FRAME_HEADER, 0x10, 0x01, + 0x00, 0x00, 0x00}; + + feat_req[5]=profile; + feat_req[6]=feature; + feat_req[7]=value; + + return NULL_SendMessageSequence + (20, &CurrentProfileError, 8, 0x05, feat_req); +} + +GSM_Error N6110_SetProfile(GSM_Profile *Profile) +{ + int i,value; + + unsigned char name_req[40] = { N6110_FRAME_HEADER, 0x1c, 0x01, 0x03, + 0x00, 0x00, 0x00}; + + GSM_Error error; + + name_req[7] = Profile->Number; + name_req[8] = strlen(Profile->Name); + name_req[6] = name_req[8] + 2; + + for (i = 0; i < name_req[8]; i++) + name_req[9 + i] = Profile->Name[i]; + + error=NULL_SendMessageSequence + (20, &CurrentProfileError, name_req[8] + 9, 0x05, name_req); + if (error!=GE_NONE) return error; + + for (i = 0x00; i <= 0x09; i++) { + + switch (i) { + case 0x00: value = Profile->KeypadTone; break; + case 0x01: value = Profile->Lights; break; + case 0x02: value = Profile->CallAlert; break; + case 0x03: value = Profile->Ringtone; break; + case 0x04: value = Profile->Volume; break; + case 0x05: value = Profile->MessageTone; break; + case 0x06: value = Profile->Vibration; break; + case 0x07: value = Profile->WarningTone; break; + case 0x08: value = Profile->CallerGroups; break; + case 0x09: value = Profile->AutomaticAnswer; break; + default : value = 0; break; + } + + error=N6110_SetProfileFeature(Profile->Number,i,value); + if (error!=GE_NONE) return error; + } + + return (GE_NONE); +} + +bool N6110_SendRLPFrame(RLP_F96Frame *frame, bool out_dtx) +{ + u8 req[60] = { 0x00, 0xd9 }; + + /* Discontinuos transmission (DTX). See section 5.6 of GSM 04.22 version + 7.0.1. */ + + if (out_dtx) + req[1]=0x01; + + memcpy(req+2, (u8 *) frame, 32); + + return (Protocol->SendFrame(32, 0xf0, req)); +} + +void N6110_ReplyGetCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + int i, j; + + u8 mychar1; + + wchar_t wc; + + switch (MessageBuffer[4]) { + + case 0x01: + + CurrentCalendarNote->Type=MessageBuffer[8]; + + DecodeDateTime(MessageBuffer+9, &CurrentCalendarNote->Time); + + DecodeDateTime(MessageBuffer+16, &CurrentCalendarNote->Alarm); + + CurrentCalendarNote->Text[0]=0; + + if (GetModelFeature (FN_CALENDAR)==F_CAL33) { + i=0; + if (CurrentCalendarNote->Type == GCN_REMINDER) i=1; //first char is subset + switch (MessageBuffer[24]) { + case 3: +#ifdef DEBUG + fprintf(stdout,_("Subset 3 in reminder note !\n")); +#endif + while (i!=MessageBuffer[23]) { + j=0; + if (i!=MessageBuffer[23]-1) { + if (MessageBuffer[24+i]>=0xc2) { + DecodeWithUTF8Alphabet(MessageBuffer[24+i], MessageBuffer[24+i+1], &mychar1); + CurrentCalendarNote->Text[strlen(CurrentCalendarNote->Text)+1]=0; + CurrentCalendarNote->Text[strlen(CurrentCalendarNote->Text)]=mychar1; + j=-1; + i++; + } + } + if (j!=-1) { + CurrentCalendarNote->Text[strlen(CurrentCalendarNote->Text)+1]=0; + CurrentCalendarNote->Text[strlen(CurrentCalendarNote->Text)]=MessageBuffer[24+i]; + } + i++; + } + break; + case 2: +#ifdef DEBUG + fprintf(stdout,_("Subset 2 in reminder note !\n")); +#endif + while (i!=MessageBuffer[23]) { + wc = MessageBuffer[24+i] | (0x00 << 8); + CurrentCalendarNote->Text[strlen(CurrentCalendarNote->Text)+1]=0; + CurrentCalendarNote->Text[strlen(CurrentCalendarNote->Text)]= + DecodeWithUnicodeAlphabet(wc); + i++; + } + break; + case 1: +#ifdef DEBUG + fprintf(stdout,_("Subset 1 in reminder note !\n")); +#endif + memcpy(CurrentCalendarNote->Text,MessageBuffer+24+i,MessageBuffer[23]-i); + CurrentCalendarNote->Text[MessageBuffer[23]-i]=0; + break; + default: +#ifdef DEBUG + fprintf(stdout,_("Unknown subset in reminder note !\n")); +#endif + memcpy(CurrentCalendarNote->Text,MessageBuffer+24+i,MessageBuffer[23]-i); + CurrentCalendarNote->Text[MessageBuffer[23]-i]=0; + break; + } + } else { + memcpy(CurrentCalendarNote->Text,MessageBuffer+24,MessageBuffer[23]); + CurrentCalendarNote->Text[MessageBuffer[23]]=0; + } + + if (CurrentCalendarNote->Type == GCN_CALL) { + memcpy(CurrentCalendarNote->Phone,MessageBuffer+24+MessageBuffer[23]+1,MessageBuffer[24+MessageBuffer[23]]); + CurrentCalendarNote->Phone[MessageBuffer[24+MessageBuffer[23]]]=0; + } + + CurrentCalendarNote->Recurrance=0; + + CurrentCalendarNote->AlarmType=0; + +#ifdef DEBUG + fprintf(stdout, _("Message: Calendar note received.\n")); + + fprintf(stdout, _(" Date: %d-%02d-%02d\n"), CurrentCalendarNote->Time.Year, + CurrentCalendarNote->Time.Month, + CurrentCalendarNote->Time.Day); + + fprintf(stdout, _(" Time: %02d:%02d:%02d\n"), CurrentCalendarNote->Time.Hour, + CurrentCalendarNote->Time.Minute, + CurrentCalendarNote->Time.Second); + + /* Some messages do not have alarm set up */ + if (CurrentCalendarNote->Alarm.Year != 0) { + fprintf(stdout, _(" Alarm date: %d-%02d-%02d\n"), CurrentCalendarNote->Alarm.Year, + CurrentCalendarNote->Alarm.Month, + CurrentCalendarNote->Alarm.Day); + + fprintf(stdout, _(" Alarm time: %02d:%02d:%02d\n"), CurrentCalendarNote->Alarm.Hour, + CurrentCalendarNote->Alarm.Minute, + CurrentCalendarNote->Alarm.Second); + } + + fprintf(stdout, _(" Type: %d\n"), CurrentCalendarNote->Type); + fprintf(stdout, _(" Text: %s\n"), CurrentCalendarNote->Text); + + if (CurrentCalendarNote->Type == GCN_CALL) + fprintf(stdout, _(" Phone: %s\n"), CurrentCalendarNote->Phone); +#endif /* DEBUG */ + + CurrentCalendarNoteError=GE_NONE; + break; + + case 0x93: + +#ifdef DEBUG + fprintf(stdout, _("Message: Calendar note not available\n")); +#endif /* DEBUG */ + + CurrentCalendarNoteError=GE_INVALIDCALNOTELOCATION; + break; + + default: + +#ifdef DEBUG + fprintf(stdout, _("Message: Calendar note error\n")); +#endif /* DEBUG */ + + CurrentCalendarNoteError=GE_INTERNALERROR; + break; + + } +} + +GSM_Error N6110_GetCalendarNote(GSM_CalendarNote *CalendarNote) +{ + + unsigned char req[] = { N6110_FRAME_HEADER, + 0x66, 0x00 + }; + GSM_Error error; + + req[4]=CalendarNote->Location; + + CurrentCalendarNote = CalendarNote; + + error=NULL_SendMessageSequence + (20, &CurrentCalendarNoteError, 5, 0x13, req); + + CurrentCalendarNote = NULL; + + return error; +} + +void N6110_ReplyWriteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#ifdef DEBUG + switch(MessageBuffer[4]) { + /* This message is also sent when the user enters the new entry on keypad */ + case 0x01: + fprintf(stdout, _("Message: Calendar note write succesfull!\n"));break; + case 0x73: + fprintf(stdout, _("Message: Calendar note write failed!\n"));break; + case 0x7d: + fprintf(stdout, _("Message: Calendar note write failed!\n"));break; + default: + fprintf(stdout, _("Unknown message of type 0x13 and subtype 0x65\n"));break; + } +#endif + + switch(MessageBuffer[4]) { + case 0x01: CurrentCalendarNoteError=GE_NONE; break; + case 0x73: CurrentCalendarNoteError=GE_INTERNALERROR; break; + case 0x7d: CurrentCalendarNoteError=GE_INTERNALERROR; break; + default : AppendLogText("Unknown msg\n",false); break; + } +} + +GSM_Error N6110_WriteCalendarNote(GSM_CalendarNote *CalendarNote) +{ + + unsigned char req[200] = { N6110_FRAME_HEADER, + 0x64, 0x01, 0x10, + 0x00, /* Length of the rest of the frame. */ + 0x00, /* The type of calendar note */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + typedef struct { + char *model; + unsigned char call; + unsigned char meeting; + unsigned char birthday; + unsigned char reminder; + } calendar_model_length; + + /* Length of entries */ + calendar_model_length calendar_lengths[] = + { + /*model,CallTo,Meeting,Birthday,Reminder*/ + {"NHM-5",0x24,0x24,0x24,0x24}, //Reminder from phone, other quesses + {"NHM-6",0x24,0x24,0x24,0x24}, //Reminder from phone, other quesses + {"NSE-3",0x1e,0x14,0x14,0x1e}, //from NCDS3 [HKEY_LOCAL_MACHINE\Software\Nokia\Data Suite\3.0\Calendar] + {"NSM-1",0x1e,0x18,0x18,0x24}, //from NCDS3 + {"NSK-3",0x1e,0x14,0x14,0x1e}, //from NCDS3 + {"NSB-3",0x20,0x14,0x14,0x1e}, //from NCDS3 + {"", 0, 0, 0, 0 } //end of table + }; + + int i, j, current; + + u8 mychar; + + u8 mychar1,mychar2; + + GSM_Error error; + + /* Hopefully is 64 larger as FB38_MAX* / N6110_MAX* */ + char model[64]; + + req[7]=CalendarNote->Type; + + EncodeDateTime(req+8, &CalendarNote->Time); + req[14] = CalendarNote->Time.Timezone; + + if (CalendarNote->Alarm.Year) { + EncodeDateTime(req+15, &CalendarNote->Alarm); + req[21] = CalendarNote->Alarm.Timezone; + } + + req[22]=strlen(CalendarNote->Text); + + current=23; + + if (GetModelFeature (FN_CALENDAR)==F_CAL33 && CalendarNote->Type==GCN_REMINDER) { + req[22]++; // one additional char + req[current++]=0x01; //we use now subset 1 + } + + for (i=0; iText); i++) { + j=0; + mychar=CalendarNote->Text[i]; + if (GetModelFeature (FN_CALENDAR)==F_CAL33 && CalendarNote->Type==GCN_REMINDER) { + if (EncodeWithUTF8Alphabet(mychar,&mychar1,&mychar2)) { + req[current++]=mychar1; + req[current++]=mychar2; + req[23]=0x03; //use subset 3 + req[22]++; // one additional char + j=-1; + } + } + if (j!=-1) { + /* Enables/disables blinking */ + if (mychar=='~') req[current++]=0x01; + else req[current++]=mychar; + } + } + + req[current++]=strlen(CalendarNote->Phone); + + for (i=0; iPhone); i++) + req[current++]=CalendarNote->Phone[i]; + + while (N6110_GetModel(model) != GE_NONE) + sleep(1); + + /* Checking maximal length */ + i=0; + while (strcmp(calendar_lengths[i].model,"")) { + if (!strcmp(calendar_lengths[i].model,model)) { + switch (CalendarNote->Type) { + case GCN_REMINDER:if (req[22]>calendar_lengths[i].reminder) return GE_TOOLONG;break; + case GCN_MEETING :if (req[22]>calendar_lengths[i].meeting) return GE_TOOLONG;break; + case GCN_BIRTHDAY:if (req[22]>calendar_lengths[i].birthday) return GE_TOOLONG;break; + case GCN_CALL :if (strlen(CalendarNote->Phone)>calendar_lengths[i].call) return GE_TOOLONG;break; + } + break; + } + i++; + } + + CurrentCalendarNote = CalendarNote; + + error=NULL_SendMessageSequence + (20, &CurrentCalendarNoteError, current, 0x13, req); + + CurrentCalendarNote = NULL; + + return error; +} + +void N6110_ReplyDeleteCalendarNote(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#ifdef DEBUG + switch (MessageBuffer[4]) { + /* This message is also sent when the user deletes an old entry on + keypad or moves an old entry somewhere (there is also `write' + message). */ + case 0x01:fprintf(stdout, _("Message: Calendar note deleted\n"));break; + case 0x93:fprintf(stdout, _("Message: Calendar note can't be deleted\n"));break; + default :fprintf(stdout, _("Message: Calendar note deleting error\n"));break; + } +#endif + + switch (MessageBuffer[4]) { + case 0x01:CurrentCalendarNoteError=GE_NONE;break; + case 0x93:CurrentCalendarNoteError=GE_INVALIDCALNOTELOCATION;break; + default :CurrentCalendarNoteError=GE_INTERNALERROR;break; + } +} + +GSM_Error N6110_DeleteCalendarNote(GSM_CalendarNote *CalendarNote) +{ + + unsigned char req[] = { N6110_FRAME_HEADER, + 0x68, 0x00 + }; + + req[4]=CalendarNote->Location; + + return NULL_SendMessageSequence (20, &CurrentCalendarNoteError, 5, 0x13, req); +} + +void N6110_ReplyRFBatteryLevel(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#ifdef DEBUG + fprintf(stdout, _("Message: Phone status received:\n")); + fprintf(stdout, _(" Mode: ")); + + switch (MessageBuffer[4]) { + + case 0x01: + + fprintf(stdout, _("registered within the network\n")); + break; + + /* I was really amazing why is there a hole in the type of 0x02, now I + know... */ + case 0x02: fprintf(stdout, _("call in progress\n")); break; /* ringing or already answered call */ + case 0x03: fprintf(stdout, _("waiting for security code\n")); break; + case 0x04: fprintf(stdout, _("powered off\n")); break; + default : fprintf(stdout, _("unknown\n")); + + } + + fprintf(stdout, _(" Power source: ")); + + switch (MessageBuffer[7]) { + + case 0x01: fprintf(stdout, _("AC/DC\n")); break; + case 0x02: fprintf(stdout, _("battery\n")); break; + default : fprintf(stdout, _("unknown\n")); + + } + + fprintf(stdout, _(" Battery Level: %d\n"), MessageBuffer[8]); + fprintf(stdout, _(" Signal strength: %d\n"), MessageBuffer[5]); +#endif /* DEBUG */ + + CurrentRFLevel=MessageBuffer[5]; + CurrentBatteryLevel=MessageBuffer[8]; + CurrentPowerSource=MessageBuffer[7]; +} + + +GSM_Error N6110_GetRFLevel(GSM_RFUnits *units, float *level) +{ + + /* FIXME - these values are from 3810 code, may be incorrect. Map from + values returned in status packet to the the values returned by the AT+CSQ + command. */ + float csq_map[5] = {0, 8, 16, 24, 31}; + + int timeout=10; + int rf_level; + + char screen[NM_MAX_SCREEN_WIDTH]; + + CurrentRFLevel=-1; + + if (GetModelFeature (FN_NOPOWERFRAME)==F_NOPOWER) { + + if (N6110_NetMonitor(1, screen)!=GE_NONE) + return GE_INTERNALERROR; + + rf_level=4; + + if (screen[4]!='-') { + if (screen[5]=='9' && screen[6]>'4') rf_level=1; + if (screen[5]=='9' && screen[6]<'5') rf_level=2; + if (screen[5]=='8' && screen[6]>'4') rf_level=3; + } else rf_level=0; + + /* Arbitrary units. */ + if (*units == GRF_Arbitrary) { + *level = rf_level; + return (GE_NONE); + } + + } else { + N6110_SendStatusRequest(); + + /* Wait for timeout or other error. */ + while (timeout != 0 && CurrentRFLevel == -1 ) { + + if (--timeout == 0) + return (GE_TIMEOUT); + + usleep (100000); + } + + /* Make copy in case it changes. */ + rf_level = CurrentRFLevel; + + if (rf_level == -1) + return (GE_NOLINK); + + /* Now convert between the different units we support. */ + + /* Arbitrary units. */ + if (*units == GRF_Arbitrary) { + *level = rf_level; + return (GE_NONE); + } + + /* CSQ units. */ + if (*units == GRF_CSQ) { + + if (rf_level <=4) + *level = csq_map[rf_level]; + else + *level = 99; /* Unknown/undefined */ + + return (GE_NONE); + } + } + + /* Unit type is one we don't handle so return error */ + return (GE_INTERNALERROR); +} + + +GSM_Error N6110_GetBatteryLevel(GSM_BatteryUnits *units, float *level) +{ + int timeout=10; + int batt_level; + + char screen[NM_MAX_SCREEN_WIDTH]; + + CurrentBatteryLevel=-1; + + if (GetModelFeature (FN_NOPOWERFRAME)==F_NOPOWER) { + + if (N6110_NetMonitor(23, screen)!=GE_NONE) + return GE_NOLINK; + + batt_level=4; + + if (screen[29]=='7') batt_level=3; + if (screen[29]=='5') batt_level=2; + if (screen[29]=='2') batt_level=1; + + /* Only units we handle at present are GBU_Arbitrary */ + if (*units == GBU_Arbitrary) { + *level = batt_level; + return (GE_NONE); + } + + return (GE_INTERNALERROR); + + } else { + N6110_SendStatusRequest(); + + /* Wait for timeout or other error. */ + while (timeout != 0 && CurrentBatteryLevel == -1 ) { + + if (--timeout == 0) + return (GE_TIMEOUT); + + usleep (100000); + } + + /* Take copy in case it changes. */ + batt_level = CurrentBatteryLevel; + + if (batt_level != -1) { + + /* Only units we handle at present are GBU_Arbitrary */ + if (*units == GBU_Arbitrary) { + *level = batt_level; + return (GE_NONE); + } + + return (GE_INTERNALERROR); + } + else + return (GE_NOLINK); + } +} + +GSM_Error N6110_GetPowerSource(GSM_PowerSource *source) +{ + + int timeout=10; + + char screen[NM_MAX_SCREEN_WIDTH]; + + CurrentPowerSource=-1; + + if (GetModelFeature (FN_NOPOWERFRAME)==F_NOPOWER) { + + if (N6110_NetMonitor(20, screen)!=GE_NONE) + return GE_NOLINK; + + CurrentPowerSource=GPS_ACDC; + + if (screen[6]=='x') CurrentPowerSource=GPS_BATTERY; + + *source=CurrentPowerSource; + + return GE_NONE; + } else { + N6110_SendStatusRequest(); + + /* Wait for timeout or other error. */ + while (timeout != 0 && CurrentPowerSource == -1 ) { + + if (--timeout == 0) + return (GE_TIMEOUT); + + usleep (100000); + } + + if (CurrentPowerSource != -1) { + *source=CurrentPowerSource; + return (GE_NONE); + } + else + return (GE_NOLINK); + } +} + +void N6110_ReplyGetDisplayStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + int i; + + for (i=0; iSendMessage(sizeof(req3), 0x01, req3); + usleep(1000000); + Protocol->SendMessage(sizeof(req4), 0x01, req4); + usleep(1000000); + req_end = req_end1; + size = sizeof(req_end1); + break; + case -1: /* Just used to set the call passup */ + return GE_NONE; + break; + default: + req_end = req_end0; + size = sizeof(req_end0); + break; + } + + req[4] = strlen(Number); + + for(i = 0; i < strlen(Number) ; i++) + req[5+i] = Number[i]; + + memcpy(req + 5 + strlen(Number), req_end, size); + + Protocol->SendMessage(5 + size + strlen(Number), 0x01, req); + usleep(1000000); + + if (type != 1) { + Protocol->SendMessage(26, 0x01, req2); + usleep(1000000); + } + + return (GE_NONE); +} + +GSM_Error N6110_GetIncomingCallNr(char *Number) +{ + + if (*CurrentIncomingCall != ' ') { + strcpy(Number, CurrentIncomingCall); + return GE_NONE; + } + else + return GE_BUSY; +} + +GSM_Error N6110_CancelCall(void) +{ +// This frame & method works only on 61xx/51xx +// unsigned char req[] = { N6110_FRAME_HEADER, 0x08, 0x00, 0x85}; +// req[4]=CurrentCallSequenceNumber; +// Protocol->SendMessage(6, 0x01, req); +// return GE_NONE; + + GSM_Error error; + + unsigned char req[]={0x00,0x01,0x7c,0x03}; + + /* Checking */ + error=N6110_EnableExtendedCommands(0x01); + if (error!=GE_NONE) return error; + + return NULL_SendMessageSequence (20, &CurrentDialVoiceError, 4, 0x40, req); +} + +void N6110_ReplyEnterSecurityCode(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + switch(MessageBuffer[3]) { + + case 0x0b: +#ifdef DEBUG + fprintf(stdout, _("Message: Security code accepted.\n")); +#endif /* DEBUG */ + CurrentSecurityCodeError = GE_NONE; + break; + + default: +#ifdef DEBUG + fprintf(stdout, _("Message: Security code is wrong. You're not my big owner :-)\n")); +#endif /* DEBUG */ + CurrentSecurityCodeError = GE_INVALIDSECURITYCODE; + } +} + +GSM_Error N6110_EnterSecurityCode(GSM_SecurityCode SecurityCode) +{ + + unsigned char req[15] = { N6110_FRAME_HEADER, + 0x0a, /* Enter code request. */ + 0x00 /* Type of the entered code. */ + }; + int i=0; + + req[4]=SecurityCode.Type; + + for (i=0; iType==MessageBuffer[3] /* We wanted this code */ + && MessageBuffer[4]==1) { /* It's allowed */ + if (MessageBuffer[3]==GSCT_SecurityCode) { + for (i=0;i<5;i++) {CurrentSecurityCode->Code[i]=MessageBuffer[5+i];} + CurrentSecurityCode->Code[5]=0; + } + if (MessageBuffer[3]==GSCT_Pin || MessageBuffer[3]==GSCT_Pin2 || + MessageBuffer[3]==GSCT_Puk || MessageBuffer[3]==GSCT_Puk2) { + for (i=0;i<4;i++) {CurrentSecurityCode->Code[i]=MessageBuffer[5+i];} + CurrentSecurityCode->Code[4]=0; + } + CurrentSecurityCodeError=GE_NONE; + } else + CurrentSecurityCodeError=GE_INVALIDSECURITYCODE; +} + +GSM_Error N6110_GetSecurityCode(GSM_SecurityCode *SecurityCode) +{ + + unsigned char req[4] = { 0x00, + 0x01,0x6e, /* Get code request. */ + 0x00 }; /* Type of the requested code. */ + + GSM_Error error; + + error=N6110_EnableExtendedCommands(0x01); + if (error!=GE_NONE) return error; + + req[3]=SecurityCode->Type; + + CurrentSecurityCode=SecurityCode; + + return NULL_SendMessageSequence + (20, &CurrentSecurityCodeError, 4, 0x40, req); +} + +void N6110_ReplyPlayTone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#ifdef DEBUG + fprintf(stdout, _("Message: answer for PlayTone frame\n")); +#endif + + CurrentPlayToneError=GE_NONE; +} + +GSM_Error N6110_PlayTone(int Herz, u8 Volume) +{ + unsigned char req[6] = { 0x00,0x01,0x8f, + 0x00, /* Volume */ + 0x00, /* HerzLo */ + 0x00 }; /* HerzHi */ + + GSM_Error error; + + /* PlayTone wasn't used earlier */ + if (CurrentPlayToneError==GE_UNKNOWN) { + if (CurrentConnectionType!=GCT_MBUS) + CurrentDisableKeepAlive=true; + + error=N6110_EnableExtendedCommands(0x01); + if (error!=GE_NONE) return error; + } + + /* For Herz==255*255 we have silent */ + if (Herz!=255*255) { + req[3]=Volume; + + req[5]=Herz%256; + req[4]=Herz/256; + } else { + req[3]=0; + + req[5]=0; + req[4]=0; + } + +#ifdef WIN32 + /* For Herz==255*255 we have silent and additionaly + we wait for phone answer - it's important for MBUS */ + if (Herz==255*255) { + error=NULL_SendMessageSequence + (20, &CurrentPlayToneError, 6, 0x40, req); + + CurrentPlayToneError=GE_UNKNOWN; + CurrentDisableKeepAlive=false; + + if (error!=GE_NONE) return error; + } else { + Protocol->SendMessage(6,0x40,req); + } +#else + error=NULL_SendMessageSequence + (20, &CurrentPlayToneError, 6, 0x40, req); + + /* For Herz==255*255 we wait for phone answer - it's important for MBUS */ + if (Herz==255*255) { + CurrentPlayToneError=GE_UNKNOWN; + CurrentDisableKeepAlive=false; + } + + if (error!=GE_NONE) return error; + +#endif + + return(GE_NONE); +} + +void N6110_ReplyGetDateTime(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + if (MessageBuffer[4]==0x01) { + DecodeDateTime(MessageBuffer+8, CurrentDateTime); + +#ifdef DEBUG + fprintf(stdout, _("Message: Date and time\n")); + fprintf(stdout, _(" Time: %02d:%02d:%02d\n"), CurrentDateTime->Hour, CurrentDateTime->Minute, CurrentDateTime->Second); + fprintf(stdout, _(" Date: %4d/%02d/%02d\n"), CurrentDateTime->Year, CurrentDateTime->Month, CurrentDateTime->Day); +#endif /* DEBUG */ + + CurrentDateTime->IsSet=true; + } else { + +#ifdef DEBUG + fprintf(stdout, _("Message: Date and time not set in phone\n")); +#endif + + CurrentDateTime->IsSet=false; + } + + CurrentDateTimeError=GE_NONE; +} + +GSM_Error N6110_GetDateTime(GSM_DateTime *date_time) +{ + return N6110_PrivGetDateTime(date_time,0x11); +} + +GSM_Error N6110_PrivGetDateTime(GSM_DateTime *date_time, int msgtype) +{ + unsigned char req[] = {N6110_FRAME_HEADER, 0x62}; + + CurrentDateTime=date_time; + + return NULL_SendMessageSequence + (50, &CurrentDateTimeError, 4, msgtype, req); +} + +void N6110_ReplyGetAlarm(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#ifdef DEBUG + fprintf(stdout, _("Message: Alarm\n")); + fprintf(stdout, _(" Alarm: %02d:%02d\n"), MessageBuffer[9], MessageBuffer[10]); + fprintf(stdout, _(" Alarm is %s\n"), (MessageBuffer[8]==2) ? _("on"):_("off")); +#endif /* DEBUG */ + + CurrentAlarm->Hour=MessageBuffer[9]; + CurrentAlarm->Minute=MessageBuffer[10]; + CurrentAlarm->Second=0; + + CurrentAlarm->IsSet=(MessageBuffer[8]==2); + + CurrentAlarmError=GE_NONE; +} + +GSM_Error N6110_GetAlarm(int alarm_number, GSM_DateTime *date_time) +{ + return N6110_PrivGetAlarm(alarm_number,date_time,0x11); +} + +GSM_Error N6110_PrivGetAlarm(int alarm_number, GSM_DateTime *date_time, int msgtype) +{ + unsigned char req[] = {N6110_FRAME_HEADER, 0x6d}; + + CurrentAlarm=date_time; + + return NULL_SendMessageSequence + (50, &CurrentAlarmError, 4, msgtype, req); +} + +void N6110_ReplyGetSMSCenter(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + switch (MessageBuffer[3]) { + + case 0x34: + + CurrentMessageCenter->No=MessageBuffer[4]; + CurrentMessageCenter->Format=MessageBuffer[6]; + CurrentMessageCenter->Validity=MessageBuffer[8]; + sprintf(CurrentMessageCenter->Name, "%s", MessageBuffer+33); + + sprintf(CurrentMessageCenter->DefaultRecipient, "%s", GSM_UnpackSemiOctetNumber(MessageBuffer+9,false)); + + sprintf(CurrentMessageCenter->Number, "%s", GSM_UnpackSemiOctetNumber(MessageBuffer+21,false)); + +#ifdef DEBUG + fprintf(stdout, _("Message: SMS Center received:\n")); + fprintf(stdout, _(" %d. SMS Center name is %s\n"), CurrentMessageCenter->No, CurrentMessageCenter->Name); + fprintf(stdout, _(" SMS Center number is %s\n"), CurrentMessageCenter->Number); + fprintf(stdout, _(" Default recipient number is %s\n"), CurrentMessageCenter->DefaultRecipient); + + fprintf(stdout, _(" SMS Center message format is ")); + + switch (CurrentMessageCenter->Format) { + + case GSMF_Text : fprintf(stdout, _("Text")); break; + case GSMF_Paging: fprintf(stdout, _("Paging")); break; + case GSMF_Fax : fprintf(stdout, _("Fax")); break; + case GSMF_Email : fprintf(stdout, _("Email")); break; + default : fprintf(stdout, _("Unknown")); + } + + fprintf(stdout, "\n"); + + fprintf(stdout, _(" SMS Center message validity is ")); + + switch (CurrentMessageCenter->Validity) { + + case GSMV_1_Hour : fprintf(stdout, _("1 hour")); break; + case GSMV_6_Hours : fprintf(stdout, _("6 hours")); break; + case GSMV_24_Hours: fprintf(stdout, _("24 hours")); break; + case GSMV_72_Hours: fprintf(stdout, _("72 hours")); break; + case GSMV_1_Week : fprintf(stdout, _("1 week")); break; + case GSMV_Max_Time: fprintf(stdout, _("Maximum time"));break; + default : fprintf(stdout, _("Unknown")); + } + + fprintf(stdout, "\n"); + +#endif /* DEBUG */ + + CurrentMessageCenterError=GE_NONE; + + break; + + case 0x35: + + /* Number of entries depends on SIM card */ + +#ifdef DEBUG + fprintf(stdout, _("Message: SMS Center error received:\n")); + fprintf(stdout, _(" The request for SMS Center failed.\n")); +#endif /* DEBUG */ + + /* FIXME: appropriate error. */ + CurrentMessageCenterError=GE_INTERNALERROR; + + break; + + } +} + +/* This function sends to the mobile phone a request for the SMS Center */ +GSM_Error N6110_GetSMSCenter(GSM_MessageCenter *MessageCenter) +{ + unsigned char req[] = { N6110_FRAME_HEADER, 0x33, 0x64, + 0x00 /* SMS Center Number. */ + }; + + req[5]=MessageCenter->No; + + CurrentMessageCenter=MessageCenter; + + return NULL_SendMessageSequence + (50, &CurrentMessageCenterError, 6, 0x02, req); +} + +void N6110_ReplySetSMSCenter(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#ifdef DEBUG + fprintf(stdout, _("Message: SMS Center correctly set.\n")); +#endif + CurrentMessageCenterError=GE_NONE; +} + +/* This function set the SMS Center profile on the phone. */ +GSM_Error N6110_SetSMSCenter(GSM_MessageCenter *MessageCenter) +{ + unsigned char req[64] = { N6110_FRAME_HEADER, 0x30, 0x64, + 0x00, /* SMS Center Number. */ + 0x00, /* Unknown. */ + 0x00, /* SMS Message Format. */ + 0x00, /* Unknown. */ + 0x00, /* Validity. */ + 0,0,0,0,0,0,0,0,0,0,0,0, /* Default recipient number */ + 0,0,0,0,0,0,0,0,0,0,0,0 /* Message Center Number. */ + /* Message Center Name. */ + }; + + req[5]=MessageCenter->No; + req[7]=MessageCenter->Format; + req[9]=MessageCenter->Validity; + + req[10]=GSM_PackSemiOctetNumber(MessageCenter->DefaultRecipient, req+11, false); + + req[22]=GSM_PackSemiOctetNumber(MessageCenter->Number, req+23, false); + + sprintf(req+34, "%s", MessageCenter->Name); + + CurrentMessageCenter=MessageCenter; + + return NULL_SendMessageSequence + (50, &CurrentMessageCenterError, 35+strlen(MessageCenter->Name), 0x02, req); +} + +void N6110_ReplyGetSMSStatus(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + switch (MessageBuffer[3]) { + + case 0x37: + +#ifdef DEBUG + fprintf(stdout, _("Message: SMS Status Received\n")); + fprintf(stdout, _(" The number of messages: %d\n"), MessageBuffer[10]); + fprintf(stdout, _(" Unread messages: %d\n"), MessageBuffer[11]); +#endif /* DEBUG */ + + CurrentSMSStatus->UnRead = MessageBuffer[11]; + CurrentSMSStatus->Number = MessageBuffer[10]; + + CurrentSMSStatusError = GE_NONE; + break; + + case 0x38: + +#ifdef DEBUG + fprintf(stdout, _("Message: SMS Status error, probably not authorized by PIN\n")); +#endif /* DEBUG */ + + CurrentSMSStatusError = GE_INTERNALERROR; + break; + + } +} + +GSM_Error N6110_GetSMSStatus(GSM_SMSStatus *Status) +{ + unsigned char req[] = {N6110_FRAME_HEADER, 0x36, 0x64}; + + CurrentSMSStatus = Status; + + return NULL_SendMessageSequence + (10, &CurrentSMSStatusError, 5, 0x14, req); +} + +GSM_Error N6110_GetSMSFolders ( GSM_SMSFolders *folders) +{ + folders->number=2; + + strcpy(folders->Folder[0].Name,"Inbox"); + strcpy(folders->Folder[1].Name,"Outbox"); + + return GE_NONE; +} + +GSM_Error N6110_GetIMEI(char *imei) +{ + if (strlen(Current_IMEI)>0) { + strncpy (imei, Current_IMEI, GSM_MAX_IMEI_LENGTH); + return (GE_NONE); + } + else + return (GE_TRYAGAIN); +} + +GSM_Error N6110_GetRevision(char *revision) +{ + + if (strlen(Current_Revision)>0) { + strncpy (revision, Current_Revision, GSM_MAX_REVISION_LENGTH); + return (GE_NONE); + } + else + return (GE_TRYAGAIN); +} + +GSM_Error N6110_GetModel(char *model) +{ + if (strlen(Current_Model)>0) { + strncpy (model, Current_Model, GSM_MAX_MODEL_LENGTH); + return (GE_NONE); + } + else + return (GE_TRYAGAIN); +} + +void N6110_ReplySetDateTime(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + switch (MessageBuffer[4]) { + + case 0x01: +#ifdef DEBUG + fprintf(stdout, _("Message: Date and time set correctly\n")); +#endif /* DEBUG */ + CurrentSetDateTimeError=GE_NONE; + break; + + default: +#ifdef DEBUG + fprintf(stdout, _("Message: Date and time setting error\n")); +#endif /* DEBUG */ + CurrentSetDateTimeError=GE_INVALIDDATETIME; + + } +} + +/* Needs SIM card with PIN in phone */ +GSM_Error N6110_SetDateTime(GSM_DateTime *date_time) +{ + return N6110_PrivSetDateTime(date_time,0x11); +} + +/* Needs SIM card with PIN in phone */ +GSM_Error N6110_PrivSetDateTime(GSM_DateTime *date_time, int msgtype) +{ + + unsigned char req[] = { N6110_FRAME_HEADER, + 0x60, /* set-time subtype */ + 0x01, 0x01, 0x07, /* unknown */ + 0x00, 0x00, /* Year (0x07cf = 1999) */ + 0x00, 0x00, /* Month Day */ + 0x00, 0x00, /* Hours Minutes */ + 0x00 /* Unknown, but not seconds - try 59 and wait 1 sec. */ + }; + + EncodeDateTime(req+7, date_time); + + return NULL_SendMessageSequence + (20, &CurrentSetDateTimeError, 14, msgtype, req); +} + +void N6110_ReplySetAlarm(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + switch (MessageBuffer[4]) { + + case 0x01: +#ifdef DEBUG + fprintf(stdout, _("Message: Alarm set correctly\n")); +#endif /* DEBUG */ + CurrentSetAlarmError=GE_NONE; + break; + + default: +#ifdef DEBUG + fprintf(stdout, _("Message: Alarm setting error\n")); +#endif /* DEBUG */ + CurrentSetAlarmError=GE_INVALIDDATETIME; + + } +} + +/* FIXME: we should also allow to set the alarm off :-) */ +GSM_Error N6110_SetAlarm(int alarm_number, GSM_DateTime *date_time) +{ + return N6110_PrivSetAlarm(alarm_number,date_time, 0x11); +} + +/* FIXME: we should also allow to set the alarm off :-) */ +GSM_Error N6110_PrivSetAlarm(int alarm_number, GSM_DateTime *date_time, int msgtype) +{ + + unsigned char req[] = { N6110_FRAME_HEADER, + 0x6b, /* set-alarm subtype */ + 0x01, 0x20, 0x03, /* unknown */ + 0x02, /* should be alarm on/off, but it don't works */ + 0x00, 0x00, /* Hours Minutes */ + 0x00 /* Unknown, but not seconds - try 59 and wait 1 sec. */ + }; + + req[8] = date_time->Hour; + req[9] = date_time->Minute; + + return NULL_SendMessageSequence + (50, &CurrentSetAlarmError, 11, msgtype, req); +} + +void N6110_ReplyGetMemoryLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + /* Hopefully is 64 larger as FB38_MAX* / N6110_MAX* */ + char model[64]; + + int i, tmp, count; + + switch (MessageBuffer[3]) { + + case 0x02: + + CurrentPhonebookEntry->Empty = true; + + count=MessageBuffer[5]; + +#ifdef DEBUG + fprintf(stdout, _("Message: Phonebook entry received:\n")); + fprintf(stdout, _(" Name: ")); + + for (tmp=0; tmp Name, MessageBuffer+6, count/2); + CurrentPhonebookEntry->Name[count/2] = 0x00; + } else { + memcpy(CurrentPhonebookEntry->Name, MessageBuffer + 6, count); + CurrentPhonebookEntry->Name[count] = 0x00; + } + + CurrentPhonebookEntry->Empty = false; + + for (tmp=0; tmp Name[tmp/2]='~'; //enables/disables blinking + if (tmp%2!=0 && MessageBuffer[6+tmp]==0) CurrentPhonebookEntry->Name[tmp/2]='`'; //hides rest ot contents + } else { + if (MessageBuffer[6+tmp]==1) CurrentPhonebookEntry->Name[tmp]='~'; //enables/disables blinking + if (MessageBuffer[6+tmp]==0) CurrentPhonebookEntry->Name[tmp]='`'; //hides rest ot contents + } + } + + i=7+count; + count=MessageBuffer[6+count]; + +#ifdef DEBUG + fprintf(stdout, _(" Number: ")); + + for (tmp=0; tmp Number, MessageBuffer + i, count); + CurrentPhonebookEntry->Number[count] = 0x00; + CurrentPhonebookEntry->Group = MessageBuffer[i+count]; + + /* Phone doesn't have entended phonebook */ + CurrentPhonebookEntry->SubEntriesCount = 0; + + /* But for these memories data is saved and we can save it using 7110/6210 style */ + if (CurrentPhonebookEntry->MemoryType==GMT_DC || + CurrentPhonebookEntry->MemoryType==GMT_RC || + CurrentPhonebookEntry->MemoryType==GMT_MC) { + CurrentPhonebookEntry->SubEntriesCount = 1; + CurrentPhonebookEntry->SubEntries[0].EntryType=N7110_ENTRYTYPE_DATE; + CurrentPhonebookEntry->SubEntries[0].NumberType=0; + CurrentPhonebookEntry->SubEntries[0].BlockNumber=1; + DecodeDateTime(MessageBuffer+(i+count+2),&CurrentPhonebookEntry->SubEntries[0].data.Date); + +#ifdef DEBUG + fprintf(stdout, _(" Date: ")); + fprintf(stdout, "%02u.%02u.%04u\n", + CurrentPhonebookEntry->SubEntries[0].data.Date.Day, + CurrentPhonebookEntry->SubEntries[0].data.Date.Month, + CurrentPhonebookEntry->SubEntries[0].data.Date.Year); + fprintf(stdout, _(" Time: ")); + fprintf(stdout, "%02u:%02u:%02u\n", + CurrentPhonebookEntry->SubEntries[0].data.Date.Hour, + CurrentPhonebookEntry->SubEntries[0].data.Date.Minute, + CurrentPhonebookEntry->SubEntries[0].data.Date.Second); +#endif /* DEBUG */ + + /* These values are set, when date and time unavailable in phone. + Values from 3310 - in other can be different */ + if (CurrentPhonebookEntry->SubEntries[0].data.Date.Day==20 && + CurrentPhonebookEntry->SubEntries[0].data.Date.Month==1 && + CurrentPhonebookEntry->SubEntries[0].data.Date.Year==2118 && + CurrentPhonebookEntry->SubEntries[0].data.Date.Hour==3 && + CurrentPhonebookEntry->SubEntries[0].data.Date.Minute==14 && + CurrentPhonebookEntry->SubEntries[0].data.Date.Second==7) + CurrentPhonebookEntry->SubEntriesCount = 0; + } + + /* Signal no error to calling code. */ + CurrentPhonebookError = GE_NONE; + + break; + + case 0x03: + +#ifdef DEBUG + fprintf(stdout, _("Message: Phonebook read entry error received:\n")); +#endif /* DEBUG */ + + switch (MessageBuffer[4]) { + + case 0x7d: +#ifdef DEBUG + fprintf(stdout, _(" Invalid memory type!\n")); +#endif /* DEBUG */ + CurrentPhonebookError = GE_INVALIDMEMORYTYPE; + break; + + default: +#ifdef DEBUG + fprintf(stdout, _(" Unknown error!\n")); +#endif /* DEBUG */ + CurrentPhonebookError = GE_INTERNALERROR; + } + + break; + + } +} + +/* Routine to get specifed phone book location. Designed to be called by + application. Will block until location is retrieved or a timeout/error + occurs. */ +GSM_Error N6110_GetMemoryLocation(GSM_PhonebookEntry *entry) +{ + unsigned char req[] = {N6110_FRAME_HEADER, 0x01, 0x00, 0x00, 0x00}; + + CurrentPhonebookEntry = entry; + + req[4] = N6110_GetMemoryType(entry->MemoryType); + req[5] = entry->Location; + + return NULL_SendMessageSequence + (50, &CurrentPhonebookError, 7, 0x03, req); +} + +void N6110_ReplyWritePhonebookLocation(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + switch (MessageBuffer[3]) { + + case 0x05: + +#ifdef DEBUG + fprintf(stdout, _("Message: Phonebook written correctly.\n")); +#endif /* DEBUG */ + CurrentPhonebookError = GE_NONE; + break; + + case 0x06: + + switch (MessageBuffer[4]) { + /* FIXME: other errors? When I send the phonebook with index of 350 it + still report error 0x7d :-( */ + case 0x7d: +#ifdef DEBUG + fprintf(stdout, _("Message: Phonebook not written - name is too long.\n")); +#endif /* DEBUG */ + CurrentPhonebookError = GE_PHBOOKNAMETOOLONG; + break; + + default: +#ifdef DEBUG + fprintf(stdout, _(" Unknown error!\n")); +#endif /* DEBUG */ + CurrentPhonebookError = GE_INTERNALERROR; + } + } +} + +/* Routine to write phonebook location in phone. Designed to be called by + application code. Will block until location is written or timeout + occurs. */ +GSM_Error N6110_WritePhonebookLocation(GSM_PhonebookEntry *entry) +{ + unsigned char req[128] = { N6110_FRAME_HEADER, 0x04, 0x00, 0x00 }; + int i=0, current=0; + + req[4] = N6110_GetMemoryType(entry->MemoryType); + req[5] = entry->Location; + + current=7; + + if (GetModelFeature (FN_PHONEBOOK)==F_PBK33INT || + GetModelFeature (FN_PHONEBOOK)==F_PBK33SIM) { + + req[6] = strlen(entry->Name)*2; + + EncodeUnicode (req+current,entry->Name ,strlen(entry->Name)); + + for (i=0; iName); i++) + { + /* here we encode "special" chars */ + if (entry->Name[i]=='~') req[current+i*2]=1; //enables/disables blinking + if (entry->Name[i]=='`') req[current+i*2]=0; //hides rest ot contents + } + + current+=strlen(entry->Name)*2; + } else { + + req[6] = strlen(entry->Name); + + for (i=0; iName); i++) + { + req[current+i] = entry->Name[i]; + + /* here we encode "special" chars */ + if (entry->Name[i]=='~') req[current+i]=1; //enables/disables blinking + if (entry->Name[i]=='`') req[current+i]=0; //hides rest ot contents + } + + current+=strlen(entry->Name); + } + + req[current++]=strlen(entry->Number); + + for (i=0; iNumber); i++) + req[current+i] = entry->Number[i]; + + current+=strlen(entry->Number); + + /* Jano: This allow to save 14 characters name into SIM memory, when + No Group is selected. */ + if (entry->Group == 5) + req[current++]=0xff; + else + req[current++]=entry->Group; + + return NULL_SendMessageSequence + (50, &CurrentPhonebookError, current, 0x03, req); +} + +void N6110_ReplyNetmonitor(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + switch(MessageBuffer[3]) { + + case 0x00: +#ifdef DEBUG + fprintf(stdout, _("Message: Netmonitor correctly set.\n")); +#endif /* DEBUG */ + CurrentNetmonitorError=GE_NONE; + break; + + default: +#ifdef DEBUG + fprintf(stdout, _("Message: Netmonitor menu %d received:\n"), MessageBuffer[3]); + fprintf(stdout, "%s\n", MessageBuffer+4); +#endif /* DEBUG */ + + strcpy(CurrentNetmonitor, MessageBuffer+4); + + CurrentNetmonitorError=GE_NONE; + } +} + +GSM_Error N6110_NetMonitor(unsigned char mode, char *Screen) +{ + unsigned char req[] = { 0x00, 0x01, 0x7e, 0x00 }; + + GSM_Error error; + + error=N6110_EnableExtendedCommands(0x01); + if (error!=GE_NONE) return error; + + CurrentNetmonitor=Screen; + + req[3]=mode; + + return NULL_SendMessageSequence + (20, &CurrentNetmonitorError, 4, 0x40, req); +} + +/* Doesn't work in N3210. */ +/* In other allow to access phone menu without SIM card (just send any sequence) */ +GSM_Error N6110_SendDTMF(char *String) +{ + unsigned char req[64] = { N6110_FRAME_HEADER, 0x50, + 0x00 /* Length of DTMF string. */ + }; + + u8 length=strlen(String); + + if (length>59) length=59; + + req[4] = length; + + memcpy(req+5,String,length); + + return NULL_SendMessageSequence + (20, &CurrentSendDTMFError, 5+length, 0x01, req); +} + +void N6110_ReplyGetSpeedDial(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + switch (MessageBuffer[3]) { + + case 0x17: + + switch (MessageBuffer[4]) { + case 0x02: CurrentSpeedDialEntry->MemoryType = GMT_ME; + default : CurrentSpeedDialEntry->MemoryType = GMT_SM; + } + + CurrentSpeedDialEntry->Location = MessageBuffer[5]; + +#ifdef DEBUG + fprintf(stdout, _("Message: Speed dial entry received:\n")); + fprintf(stdout, _(" Location: %d\n"), CurrentSpeedDialEntry->Location); + fprintf(stdout, _(" MemoryType: %s\n"), N6110_MemoryType_String[CurrentSpeedDialEntry->MemoryType]); + fprintf(stdout, _(" Number: %d\n"), CurrentSpeedDialEntry->Number); +#endif /* DEBUG */ + + CurrentSpeedDialError=GE_NONE; + break; + + case 0x18: + +#ifdef DEBUG + fprintf(stdout, _("Message: Speed dial entry error\n")); +#endif /* DEBUG */ + CurrentSpeedDialError=GE_INVALIDSPEEDDIALLOCATION; + break; + + } +} + +GSM_Error N6110_GetSpeedDial(GSM_SpeedDial *entry) +{ + + unsigned char req[] = { N6110_FRAME_HEADER, + 0x16, + 0x00 /* The number of speed dial. */ + }; + + CurrentSpeedDialEntry = entry; + + req[4] = entry->Number; + + return NULL_SendMessageSequence + (20, &CurrentSpeedDialError, 5, 0x03, req); +} + +void N6110_ReplySetSpeedDial(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + switch (MessageBuffer[3]) { + + case 0x1a: + +#ifdef DEBUG + fprintf(stdout, _("Message: Speed dial entry set.\n")); +#endif /* DEBUG */ + CurrentSpeedDialError=GE_NONE; + break; + + case 0x1b: + +#ifdef DEBUG + fprintf(stdout, _("Message: Speed dial entry setting error.\n")); +#endif /* DEBUG */ + CurrentSpeedDialError=GE_INVALIDSPEEDDIALLOCATION; + break; + + } +} + +GSM_Error N6110_SetSpeedDial(GSM_SpeedDial *entry) +{ + + unsigned char req[] = { N6110_FRAME_HEADER, + 0x19, + 0x00, /* Number */ + 0x00, /* Memory Type */ + 0x00 /* Location */ + }; + + req[4] = entry->Number; + + switch (entry->MemoryType) { + case GMT_ME: req[5] = 0x02; + default : req[5] = 0x03; + } + + req[6] = entry->Location; + + return NULL_SendMessageSequence + (20, &CurrentSpeedDialError, 7, 0x03, req); +} + +/* This function finds parts of SMS in frame used in new Nokia phones + in internal protocols (they're coded according to GSM 03.40), copies them + to GSM_ETSISMSMessage and calls GSM_DecodeETSISMS to decode + GSM_ETSISMSMessage to GSM_SMSMessage structure */ +GSM_Error GSM_DecodeNokiaSMSFrame(GSM_SMSMessage *SMS, unsigned char *req, int length) +{ + SMS_MessageType PDU=SMS_Deliver; + GSM_ETSISMSMessage ETSI; + int offset=0,i; + + ETSI.firstbyte=req[12]; + + /* See GSM 03.40 section 9.2.3.1 */ + if ((ETSI.firstbyte & 0x03) == 0x01) PDU=SMS_Submit; + if ((ETSI.firstbyte & 0x03) == 0x02) PDU=SMS_Status_Report; + + switch (PDU) { + case SMS_Submit : offset=5;break; + case SMS_Deliver : offset=4;break; + case SMS_Status_Report: offset=3;break; + default: break; + } + + for (i=0;iName[0]=0; + + return GE_NONE; +} + +void N6110_ReplyGetSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + int offset; + + switch (MessageBuffer[3]) { + + case 0x08: + + switch (MessageBuffer[7]) { + + case 0x00: + CurrentSMSMessage->Type = GST_SMS; + CurrentSMSMessage->folder=GST_INBOX; + offset=4; + break; + + case 0x01: + CurrentSMSMessage->Type = GST_DR; + CurrentSMSMessage->folder=GST_INBOX; + offset=3; + break; + + case 0x02: + CurrentSMSMessage->Type = GST_SMS; + CurrentSMSMessage->folder=GST_OUTBOX; + offset=5; + break; + + default: + CurrentSMSMessage->Type = GST_UN; + offset=4; + break; + + } + + /* Field Short Message Status - MessageBuffer[4] seems not to be + compliant with GSM 07.05 spec. + Meaning Nokia protocol GMS spec + ---------------------------------------------------- + MO Sent 0x05 0x07 or 0x01 + MO Not sent 0x07 0x06 or 0x00 + MT Read 0x01 0x05 or 0x01 + MT Not read 0x03 0x04 or 0x00 + ---------------------------------------------------- + See GSM 07.05 section 2.5.2.6 and correct me if I'm wrong. + + Pawel Kot */ + + if (MessageBuffer[4] & 0x02) CurrentSMSMessage->Status = GSS_NOTSENTREAD; + else CurrentSMSMessage->Status = GSS_SENTREAD; + +#ifdef DEBUG + fprintf(stdout, _("Number: %d\n"), MessageBuffer[6]); + + if (CurrentSMSMessage->folder!=1) { //GST_OUTBOX + fprintf(stdout, _("Message: Received SMS (mobile terminated)\n")); + } else { + fprintf(stdout, _("Message: Outbox message (mobile originated)\n")); + } + + if (CurrentSMSMessage->Type == GST_DR) fprintf(stdout, _(" Delivery Report\n")); + if (CurrentSMSMessage->Type == GST_UN) fprintf(stdout, _(" Unknown type\n")); + + if (CurrentSMSMessage->folder==1) { //GST_OUTBOX + if (CurrentSMSMessage->Status) fprintf(stdout, _(" Sent\n")); + else fprintf(stdout, _(" Not sent\n")); + } else { + if (CurrentSMSMessage->Status) fprintf(stdout, _(" Read\n")); + else fprintf(stdout, _(" Not read\n")); + } +#endif + + CurrentSMSPointer=GSM_DecodeNokiaSMSFrame(CurrentSMSMessage, MessageBuffer+8, MessageLength-8); + + CurrentSMSMessage->MemoryType = MessageBuffer[5]; + CurrentSMSMessage->MessageNumber = MessageBuffer[6]; + + /* Signal no error to calling code. */ + CurrentSMSMessageError = GE_NONE; + +#ifdef DEBUG + fprintf(stdout, "\n"); +#endif + + break; + + case 0x09: + + /* We have requested invalid or empty location. */ + +#ifdef DEBUG + fprintf(stdout, _("Message: SMS reading failed\n")); + + switch (MessageBuffer[4]) { + case 0x02: + fprintf(stdout, _(" Invalid location!\n"));break; + case 0x07: + fprintf(stdout, _(" Empty SMS location.\n"));break; + case 0x0c: + fprintf(stdout, _(" No access to memory (no PIN on card ?)\n"));break; + default: + fprintf(stdout, _(" Error code %i - please report it \n"),MessageBuffer[4]);break; + } +#endif /* DEBUG */ + + switch (MessageBuffer[4]) { + case 0x02:CurrentSMSMessageError = GE_INVALIDSMSLOCATION;break; + case 0x07:CurrentSMSMessageError = GE_EMPTYSMSLOCATION;break; + case 0x0c:CurrentSMSMessageError = GE_NOACCESS;break; + default :CurrentSMSMessageError = GE_UNKNOWN;break; + } + + break; + + } +} + +GSM_Error N6110_GetSMSMessage(GSM_SMSMessage *message) +{ + + unsigned char req[] = { N6110_FRAME_HEADER, + 0x07, + 0x02, /* Unknown */ + 0x00, /* Location */ + 0x01, 0x64}; + + int timeout = 60; + + /* State machine code writes data to these variables when it comes in. */ + + CurrentSMSMessage = message; + CurrentSMSMessageError = GE_BUSY; + + req[5] = message->Location; + + /* Send request */ + Protocol->SendMessage(8, 0x02, req); + + /* Wait for timeout or other error. */ + while (timeout != 0 && (CurrentSMSMessageError == GE_BUSY || CurrentSMSMessageError == GE_SMSWAITING)) { + + if (--timeout == 0) + return (GE_TIMEOUT); + + usleep (100000); + } + + return (CurrentSMSMessageError); +} + +void N6110_ReplyDeleteSMSMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#ifdef DEBUG + fprintf(stdout, _("Message: SMS deleted successfully.\n")); +#endif /* DEBUG */ + + CurrentSMSMessageError = GE_NONE; +} + +GSM_Error N6110_DeleteSMSMessage(GSM_SMSMessage *message) +{ + unsigned char req[] = {N6110_FRAME_HEADER, 0x0a, 0x02, 0x00}; + + req[5] = message->Location; + + return NULL_SendMessageSequence + (50, &CurrentSMSMessageError, 6, 0x14, req); +} + +/* FIXME: do we need more than SMS_Submit and SMS_Deliver ? */ +GSM_Error GSM_EncodeNokiaSMSFrame(GSM_SMSMessage *SMS, unsigned char *req, int *length, SMS_MessageType PDU) +{ + GSM_ETSISMSMessage ETSI; + int i,offset=0; + + GSM_EncodeETSISMS(SMS, &ETSI, PDU, length); + + /* Cleaning */ + for (i=0;i<36;i++) req[i]=0; + + req[12]=ETSI.firstbyte; + + for (i=0;iMessageNumber=MessageBuffer[5]; + + CurrentSMSMessageError = GE_NONE; + break; + + case 0x06: +#ifdef DEBUG + fprintf(stdout, _("SMS saving failed\n")); + switch (MessageBuffer[4]) { + case 0x02:fprintf(stdout, _(" All locations busy.\n"));break; + case 0x03:fprintf(stdout, _(" Invalid location!\n"));break; + default :fprintf(stdout, _(" Unknown error.\n"));break; + } +#endif + + switch (MessageBuffer[4]) { + case 0x02:CurrentSMSMessageError = GE_MEMORYFULL;break; + case 0x03:CurrentSMSMessageError = GE_INVALIDSMSLOCATION;break; + default :CurrentSMSMessageError = GE_UNKNOWN;break; + } + } +} + +/* GST_DR and GST_UN not supported ! */ +GSM_Error N6110_SaveSMSMessage(GSM_SMSMessage *SMS) +{ + unsigned char req[256] = { + N6110_FRAME_HEADER, 0x04, /* SMS save request*/ + 0x00, /* SMS Status. Different for Inbox and Outbox */ + 0x02, /* ?? */ + 0x00, /* SMS Location */ + 0x02, /* SMS Type */ + }; + + int length; + SMS_MessageType PDU; + GSM_Error error; + + if (SMS->Location) req[6] = SMS->Location; + + if (SMS->folder==0) { /*Inbox*/ + req[4]=1; /* SMS Status */ + req[7] = 0x00; /* SMS Type */ + PDU=SMS_Deliver; + } else { + req[4]=5; /* SMS Status */ + req[7] = 0x02; /* SMS Type */ + PDU=SMS_Submit; + } + + if (SMS->Status == GSS_NOTSENTREAD) req[4] |= 0x02; + + error=GSM_EncodeNokiaSMSFrame(SMS, req+8, &length, PDU); + if (error != GE_NONE) return error; + + CurrentSMSMessage = SMS; + + return NULL_SendMessageSequence + (70, &CurrentSMSMessageError, 39+length, 0x14, req); +} + +void N6110_ReplySetCellBroadcast(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#ifdef DEBUG + fprintf(stdout, _("Message: Cell Broadcast enabled/disabled successfully.\n")); fflush (stdout); +#endif + + CurrentCBError = GE_NONE; +} + +/* Enable and disable Cell Broadcasting */ +GSM_Error N6110_EnableCellBroadcast(void) +{ + unsigned char req[] = {N6110_FRAME_HEADER, 0x20, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01}; + +#ifdef DEBUG + fprintf (stdout,"Enabling CB\n"); +#endif + + CurrentCBMessage = (GSM_CBMessage *)malloc(sizeof (GSM_CBMessage)); + CurrentCBMessage->Channel = 0; + CurrentCBMessage->New = false; + strcpy (CurrentCBMessage->Message,""); + + return NULL_SendMessageSequence + (10, &CurrentCBError, 10, 0x02, req); +} + + +GSM_Error N6110_DisableCellBroadcast(void) +{ + /* Should work, but not tested fully */ + + unsigned char req[] = {N6110_FRAME_HEADER, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /*VERIFY*/ + + return NULL_SendMessageSequence + (10, &CurrentCBError, 10, 0x02, req); +} + +void N6110_ReplyReadCellBroadcast(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + int i, tmp; + unsigned char output[160]; + + CurrentCBMessage->Channel = MessageBuffer[7]; + CurrentCBMessage->New = true; + tmp=GSM_UnpackEightBitsToSeven(0, MessageBuffer[9], MessageBuffer[9], MessageBuffer+10, output); + +#ifdef DEBUG + fprintf(stdout, _("Message: CB received.\n")); fflush (stdout); + + fprintf(stdout, _("Message: channel number %i\n"),MessageBuffer[7]); + + fflush (stdout); + + for (i=0; iMessage[i] = DecodeWithDefaultAlphabet(output[i]); + } + CurrentCBMessage->Message[i]=0; +} + +GSM_Error N6110_ReadCellBroadcast(GSM_CBMessage *Message) +{ +#ifdef DEBUG + fprintf(stdout,"Reading CB\n"); +#endif + + if (CurrentCBMessage != NULL) + { + if (CurrentCBMessage->New == true) + { +#ifdef DEBUG + fprintf(stdout,"New CB received\n"); +#endif + Message->Channel = CurrentCBMessage->Channel; + strcpy(Message->Message,CurrentCBMessage->Message); + CurrentCBMessage->New = false; + return (GE_NONE); + } + } + return (GE_NONEWCBRECEIVED); +} + +int N6110_MakeCallerGroupFrame(unsigned char *req,GSM_Bitmap Bitmap) +{ + int count=0; + + req[count++]=Bitmap.number; + req[count++]=strlen(Bitmap.text); + memcpy(req+count,Bitmap.text,req[count-1]); + count+=req[count-1]; + req[count++]=Bitmap.ringtone; + + /* Setting for graphic: + 0x00 - Off + 0x01 - On + 0x02 - View Graphics + 0x03 - Send Graphics + 0x04 - Send via IR + You can even set it higher but Nokia phones (my + 6110 at least) will not show you the name of this + item in menu ;-)) Nokia is really joking here. */ + if (Bitmap.enabled) req[count++]=0x01; + else req[count++]=0x00; + + req[count++]=(Bitmap.size+4)>>8; + req[count++]=(Bitmap.size+4)%0xff; + req[count++]=0x00; /* Future extensions! */ + req[count++]=Bitmap.width; + req[count++]=Bitmap.height; + req[count++]=0x01; /* Just BW */ + memcpy(req+count,Bitmap.bitmap,Bitmap.size); + + return count+Bitmap.size; +} + +int N6110_MakeOperatorLogoFrame(unsigned char *req,GSM_Bitmap Bitmap) +{ + int count=0; + + EncodeNetworkCode(req+count, Bitmap.netcode); + count=count+3; + + req[count++]=(Bitmap.size+4)>>8; + req[count++]=(Bitmap.size+4)%0xff; + req[count++]=0x00; /* Infofield */ + req[count++]=Bitmap.width; + req[count++]=Bitmap.height; + req[count++]=0x01; /* Just BW */ + memcpy(req+count,Bitmap.bitmap,Bitmap.size); + + return count+Bitmap.size; +} + +int N6110_MakeStartupLogoFrame(unsigned char *req,GSM_Bitmap Bitmap) +{ + int count=0; + + req[count++]=0x01; + req[count++]=Bitmap.height; + req[count++]=Bitmap.width; + memcpy(req+count,Bitmap.bitmap,Bitmap.size); + + return count+Bitmap.size; +} + +/* Set a bitmap or welcome-note */ +GSM_Error N6110_SetBitmap(GSM_Bitmap *Bitmap) { + + unsigned char req[600] = { N6110_FRAME_HEADER }; + u16 count=3; + u8 textlen; + + int timeout=50; + + /* Direct uploading variables */ + GSM_MultiSMSMessage SMS; + unsigned char buffer[1000] = {0x0c,0x01}; + GSM_NetworkInfo NetworkInfo; + + GSM_Error error; + + /* Uploading with preview */ + if (Bitmap->number==255 && + (Bitmap->type==GSM_OperatorLogo || Bitmap->type==GSM_CallerLogo)) { + GSM_SaveBitmapToSMS(&SMS,Bitmap,false,false); + memcpy(buffer+2,SMS.SMS[0].UDH,SMS.SMS[0].UDH[0]+1); + + memcpy(buffer+2+SMS.SMS[0].UDH[0]+1,SMS.SMS[0].MessageText,SMS.SMS[0].Length); + + buffer[2+SMS.SMS[0].UDH[0]+1+SMS.SMS[0].Length]=0x00; + + Protocol->SendMessage(2+SMS.SMS[0].UDH[0]+1+SMS.SMS[0].Length+1, 0x12, buffer); + + GSM->GetNetworkInfo(&NetworkInfo); //need to make something + return GE_NONE; //no answer from phone + } + + CurrentSetBitmapError = GE_BUSY; + + switch (Bitmap->type) { + case GSM_WelcomeNoteText: + case GSM_DealerNoteText: + req[count++]=0x18; + req[count++]=0x01; /* Only one block */ + + if (Bitmap->type==GSM_WelcomeNoteText) + req[count++]=0x02; /* Welcome text */ + else + req[count++]=0x03; /* Dealer Welcome Note */ + + textlen=strlen(Bitmap->text); + req[count++]=textlen; + memcpy(req+count,Bitmap->text,textlen); + + count+=textlen; + + Protocol->SendMessage(count, 0x05, req); + + break; + + case GSM_StartupLogo: + if (Bitmap->number==0) { + + /* For 33xx we first set animated logo to default */ + if (GetModelFeature (FN_STARTUP)==F_STANIM) { + error=N6110_SetProfileFeature(0, 0x29, Bitmap->number); + if (error!=GE_NONE) return error; + } + + req[count++]=0x18; + req[count++]=0x01; /* Only one block */ + count=count+N6110_MakeStartupLogoFrame(req+5,*Bitmap); + Protocol->SendMessage(count, 0x05, req); + } else { + return N6110_SetProfileFeature(0, 0x29, Bitmap->number); + } + break; + + case GSM_OperatorLogo: + req[count++]=0x30; /* Store Op Logo */ + req[count++]=0x01; /* Location */ + count=count+N6110_MakeOperatorLogoFrame(req+5,*Bitmap); + Protocol->SendMessage(count, 0x05, req); + break; + + case GSM_CallerLogo: + req[count++]=0x13; + count=count+N6110_MakeCallerGroupFrame(req+4,*Bitmap); + Protocol->SendMessage(count, 0x03, req); + break; + + case GSM_PictureImage: + req[count++]=0x03; + req[count++]=Bitmap->number; + if (strcmp(Bitmap->Sender,"")) { + req[count]=GSM_PackSemiOctetNumber(Bitmap->Sender, req+count+1,true); + + /* Convert number of semioctets to number of chars and add count */ + textlen=req[count]; + if (textlen % 2) textlen++; + count+=textlen / 2 + 1; + + count++; + } else { + req[count++]=0x00; + req[count++]=0x00; + } + req[count++]=0x00; + req[count++]=strlen(Bitmap->text); + memcpy(req+count,Bitmap->text,strlen(Bitmap->text)); + count+=strlen(Bitmap->text); + req[count++]=0x00; + req[count++]=Bitmap->width; + req[count++]=Bitmap->height; + req[count++]=0x01; + memcpy(req+count,Bitmap->bitmap,Bitmap->size); + Protocol->SendMessage(count+Bitmap->size, 0x47, req); + break; + + case GSM_7110OperatorLogo: + case GSM_7110StartupLogo: + case GSM_6210StartupLogo: + return GE_NOTSUPPORTED; + + case GSM_None: + return GE_NONE; + } + + /* Wait for timeout or other error. */ + while (timeout != 0 && CurrentSetBitmapError == GE_BUSY ) { + + if (--timeout == 0) + return (GE_TIMEOUT); + + usleep (100000); + } + + return CurrentSetBitmapError; +} + +/* Get a bitmap from the phone */ +GSM_Error N6110_GetBitmap(GSM_Bitmap *Bitmap) { + + unsigned char req[10] = { N6110_FRAME_HEADER }; + u8 count=3; + + int timeout=100; + + CurrentGetBitmap=Bitmap; + CurrentGetBitmapError = GE_BUSY; + + switch (CurrentGetBitmap->type) { + case GSM_StartupLogo: + case GSM_WelcomeNoteText: + case GSM_DealerNoteText: + req[count++]=0x16; + Protocol->SendMessage(count, 0x05, req); + break; + case GSM_OperatorLogo: + req[count++]=0x33; + req[count++]=0x01; /* Location 1 */ + Protocol->SendMessage(count, 0x05, req); + break; + case GSM_CallerLogo: + req[count++]=0x10; + req[count++]=Bitmap->number; + Protocol->SendMessage(count, 0x03, req); + break; + case GSM_PictureImage: + req[count++]=0x01; + req[count++]=Bitmap->number; + Protocol->SendMessage(count, 0x47, req); + break; + case GSM_7110OperatorLogo: + case GSM_7110StartupLogo: + case GSM_6210StartupLogo: + default: + return GE_NOTSUPPORTED; + } + + /* Wait for timeout or other error. */ + while (timeout != 0 && CurrentGetBitmapError == GE_BUSY ) { + + if (--timeout == 0) + return (GE_TIMEOUT); + + usleep (100000); + } + + CurrentGetBitmap=NULL; + + return CurrentGetBitmapError; +} + +void N6110_ReplySetRingtone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + switch (MessageBuffer[3]) { + + /* Set ringtone OK */ + case 0x37: +#ifdef DEBUG + fprintf(stdout, _("Message: Ringtone set OK!\n")); +#endif + CurrentRingtoneError=GE_NONE; + break; + + /* Set ringtone error */ + case 0x38: +#ifdef DEBUG + fprintf(stdout, _("Message: Ringtone setting error !\n")); +#endif + CurrentRingtoneError=GE_NOTSUPPORTED; + break; + } +} + +GSM_Error N6110_SetRingTone(GSM_Ringtone *ringtone, int *maxlength) +{ + + char req[FB61_MAX_RINGTONE_FRAME_LENGTH+10] = + {N6110_FRAME_HEADER, + 0x36, + 0x00, /* Location */ + 0x00,0x78}; + + int size=FB61_MAX_RINGTONE_FRAME_LENGTH; + + /* Variables for preview uploading */ + unsigned char buffer[FB61_MAX_RINGTONE_FRAME_LENGTH+50]; + unsigned char buffer2[20]; + GSM_NetworkInfo NetworkInfo; + + /* Setting ringtone with preview */ + if (ringtone->location==255) { + buffer[0]=0x0c; + buffer[1]=0x01; + EncodeUDHHeader(buffer2, GSM_RingtoneUDH); + memcpy(buffer+2,buffer2,buffer2[0]+1); //copying UDH + *maxlength=GSM_PackRingtone(ringtone, buffer+2+buffer2[0]+1, &size); //packing ringtone + Protocol->SendMessage(2+buffer2[0]+1+size, 0x12, buffer); //sending frame + GSM->GetNetworkInfo(&NetworkInfo); //need to make something + sleep(1); + return GE_NONE; //no answer from phone + } + + *maxlength=GSM_PackRingtone(ringtone, req+7, &size); + + req[4]=ringtone->location-1; + + return NULL_SendMessageSequence + (50, &CurrentRingtoneError, (size+7), 0x05, req); +} + +void N6110_ReplyGetBinRingtone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + int i; + + switch (MessageBuffer[4]) { + case 0x00: /* location supported. We have ringtone */ + + /* Binary format used in N6150 */ + if (MessageBuffer[5]==0x0c && MessageBuffer[6]==0x01 && MessageBuffer[7]==0x2c) { +#ifdef DEBUG + fprintf(stdout,_("Message: ringtone \"")); +#endif + + /* Copying name */ + i=8; + while (true) { +#ifdef DEBUG + if (MessageBuffer[i]!=0) + fprintf(stdout,_("%c"),MessageBuffer[i]); +#endif + CurrentGetBinRingtone->name[i-8]=MessageBuffer[i]; + if (MessageBuffer[i]==0) break; + i++; + } + +#ifdef DEBUG + fprintf(stdout,_("\" received from location %i\n"),MessageBuffer[3]+1); +#endif + + /* Looking for end */ + i=0; + while (true) { + if (MessageBuffer[i]==0x07 && MessageBuffer[i+1]==0x0b) { + i=i+2;break; + } + if (MessageBuffer[i]==0x0e && MessageBuffer[i+1]==0x0b) { + i=i+2;break; + } + i++; + if (i==MessageLength) break; + } + + /* Copying frame */ + memcpy(CurrentGetBinRingtone->frame,MessageBuffer+3,i-3); + CurrentGetBinRingtone->length=i-3; + + CurrentBinRingtoneError=GE_NONE; + break; + } + + /* Binary format used in N3210 */ + if (MessageBuffer[5]==0x10 && MessageBuffer[6]==0x01 && MessageBuffer[7]==0x2c) { + +#ifdef DEBUG + fprintf(stdout,_("Message: ringtone \"")); +#endif + + /* Copying name */ + i=8; + while (true) { +#ifdef DEBUG + if (MessageBuffer[i]!=0) + fprintf(stdout,_("%c"),MessageBuffer[i]); +#endif + CurrentGetBinRingtone->name[i-8]=MessageBuffer[i]; + if (MessageBuffer[i]==0) break; + i++; + } + +#ifdef DEBUG + fprintf(stdout,_("\" received from location %i\n"),MessageBuffer[3]+1); +#endif + + /* Here changes to get full compatibility with binary format used in N6150 */ + MessageBuffer[3]=0; + MessageBuffer[4]=0; + MessageBuffer[5]=0x0c; + MessageBuffer[6]=0x01; + MessageBuffer[7]=0x2c; + + /* Looking for end */ + i=0; + while (true) { + if (MessageBuffer[i]==0x07 && MessageBuffer[i+1]==0x0b) { + i=i+2;break; + } + if (MessageBuffer[i]==0x0e && MessageBuffer[i+1]==0x0b) { + i=i+2;break; + } + i++; + if (i==MessageLength) break; + } + + /* Copying frame */ + memcpy(CurrentGetBinRingtone->frame,MessageBuffer+3,i-3); + + CurrentGetBinRingtone->length=i-3; + + CurrentBinRingtoneError=GE_NONE; + break; + } + + /* Copying frame */ + memcpy(CurrentGetBinRingtone->frame,MessageBuffer,MessageLength); + + CurrentGetBinRingtone->length=MessageLength; + +#ifdef DEBUG + fprintf(stdout,_("Message: unknown binary format for ringtone received from location %i\n"),MessageBuffer[3]+1); +#endif + CurrentBinRingtoneError=GE_UNKNOWNMODEL; + break; + + default: + +#ifdef DEBUG + fprintf(stdout,_("Message: Phone doesn't support downloaded ringtones at location %i\n"),MessageBuffer[3]+1); +#endif + + CurrentBinRingtoneError=GE_INVALIDRINGLOCATION; + } +} + +GSM_Error N6110_GetBinRingTone(GSM_BinRingtone *ringtone) +{ + unsigned char req[] = { 0x00,0x01,0x9e, + 0x00 }; //location + + GSM_Error error; + + CurrentGetBinRingtone=ringtone; + + error=N6110_EnableExtendedCommands(0x01); + if (error!=GE_NONE) return error; + + req[3]=ringtone->location-1; + + return NULL_SendMessageSequence + (50, &CurrentBinRingtoneError, 4, 0x40, req); +} + +void N6110_ReplySetBinRingtone(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + switch (MessageBuffer[4]) { + case 0x00: /* location supported. We set ringtone */ +#ifdef DEBUG + fprintf(stdout,_("Message: downloaded ringtone set at location %i\n"),MessageBuffer[3]+1); +#endif + CurrentBinRingtoneError=GE_NONE; + break; + + default: +#ifdef DEBUG + fprintf(stdout,_("Message: Phone doesn't support downloaded ringtones at location %i\n"),MessageBuffer[3]+1); +#endif + CurrentBinRingtoneError=GE_NOTSUPPORTED; + break; + } +} + +GSM_Error N6110_SetBinRingTone(GSM_BinRingtone *ringtone) +{ + unsigned char req[1000] = { 0x00,0x01,0xa0}; + + GSM_Error error; + + GSM_BinRingtone ring; + + /* Must be sure, that can upload ringtone to this phone */ + ring.location=ringtone->location; + error=N6110_GetBinRingTone(&ring); + if (error!=GE_NONE) return error; + + error=N6110_EnableExtendedCommands(0x01); + if (error!=GE_NONE) return error; + + memcpy(req+3,ringtone->frame,ringtone->length); + + req[3]=ringtone->location-1; + + return NULL_SendMessageSequence + (50, &CurrentBinRingtoneError, ringtone->length+3, 0x40, req); +} + +GSM_Error N6110_Reset(unsigned char type) +{ + return N6110_EnableExtendedCommands(type); +} + +void N6110_Dispatch0x01Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + int tmp, count; + + switch (MessageBuffer[3]) { + + /* Unknown message - it has been seen after the 0x07 message (call + answered). Probably it has similar meaning. If you can solve + this - just mail me. Pavel Janík ml. + + The message looks like this: + + Msg Destination: PC + Msg Source: Phone + Msg Type: 01 + Msg Unknown: 00 + Msg Len: 0e + + Phone: [01 ][08 ][00 ] is the header of the frame + + [03 ] is the call message subtype + + [05 ] is the call sequence number + + [05 ] unknown + + [00 ][01 ][03 ][02 ][91][00] are unknown but has been + seen in the Incoming call message (just after the + caller's name from the phonebook). But never change + between phone calls :-( + */ + + /* This may mean sequence number of 'just made' call - CK */ + case 0x02: + +#ifdef DEBUG + fprintf(stdout, _("Message: Call message, type 0x02:")); + fprintf(stdout, _(" Exact meaning not known yet, sorry :-(\n")); +#endif /* DEBUG */ + + break; + + /* Possibly call OK */ + /* JD: I think that this means "call in progress" (incomming or outgoing) */ + case 0x03: + +#ifdef DEBUG + fprintf(stdout, _("Message: Call message, type 0x03:")); + fprintf(stdout, _(" Sequence nr. of the call: %d\n"), MessageBuffer[4]); + fprintf(stdout, _(" Exact meaning not known yet, sorry :-(\n")); +#endif /* DEBUG */ + + CurrentCallSequenceNumber=MessageBuffer[4]; + CurrentIncomingCall[0]='D'; + if (CurrentCallPassup) CurrentCallPassup('D'); + + break; + + /* Remote end has gone away before you answer the call. Probably your + mother-in-law or banker (which is worse?) ... */ + case 0x04: + +#ifdef DEBUG + fprintf(stdout, _("Message: Remote end hang up.\n")); + fprintf(stdout, _(" Sequence nr. of the call: %d, error: %i"), MessageBuffer[4],MessageBuffer[6]); + + switch (MessageBuffer[6]) { + case 28: fprintf(stdout,_(" (info \"Invalid phone number\")"));break; + case 34: fprintf(stdout,_(" (info \"Network busy\")"));break; + case 42: fprintf(stdout,_(" (info \"Network busy\")"));break; + case 47: fprintf(stdout,_(" (info \"Error in connection\")"));break; + case 50: fprintf(stdout,_(" (info \"Check operator services\")"));break; case 76: fprintf(stdout,_(" (info \"Check operator services\")"));break; + case 111: fprintf(stdout,_(" (info \"Error in connection\")"));break; + } + + fprintf(stdout,_("\n For more details with errors see netmonitor manual (test 39) on www.marcin-wiacek.topnet.pl")); + fprintf(stdout,_("\n If know their meaning, GSM specs decribing them, contact with me on marcin-wiacek@topnet.pl. THX\n")); +#endif /* DEBUG */ + + CurrentIncomingCall[0] = ' '; + if (CurrentCallPassup) CurrentCallPassup(' '); + + break; + + /* Incoming call alert */ + case 0x05: + +#ifdef DEBUG + fprintf(stdout, _("Message: Incoming call alert:\n")); + + /* We can have more then one call ringing - we can distinguish between + them */ + + fprintf(stdout, _(" Sequence nr. of the call: %d\n"), MessageBuffer[4]); + fprintf(stdout, _(" Number: ")); + + count=MessageBuffer[6]; + + for (tmp=0; tmp SendMessage(4, 0x04, connect5); */ + + /* Marcin-Wiacek@TopNet.PL */ + +#ifdef WIN32 + sprintf(Current_IMEI, "%s", MessageBuffer+5); + sprintf(Current_Model, "%s", MessageBuffer+21); + sprintf(Current_Revision, "SW%s, HW%s", MessageBuffer+41, MessageBuffer+35); +#else + snprintf(Current_IMEI, GSM_MAX_IMEI_LENGTH, "%s", MessageBuffer+5); + snprintf(Current_Model, GSM_MAX_MODEL_LENGTH, "%s", MessageBuffer+21); + snprintf(Current_Revision, GSM_MAX_REVISION_LENGTH, "SW%s, HW%s", MessageBuffer+41, MessageBuffer+35); +#endif + +#ifdef DEBUG + fprintf(stdout, _("Message: Mobile phone identification received:\n")); + fprintf(stdout, _(" IMEI: %s\n"), Current_IMEI); + fprintf(stdout, _(" Model: %s\n"), Current_Model); + fprintf(stdout, _(" Production Code: %s\n"), MessageBuffer+27); + fprintf(stdout, _(" HW: %s\n"), MessageBuffer+35); + fprintf(stdout, _(" Firmware: %s\n"), MessageBuffer+41); +#endif /* DEBUG */ + + break; + + /* Get group data */ + /* [ID],[name_len],[name].,[ringtone],[graphicon],[lenhi],[lenlo],[bitmap] */ + case 0x11: + + if (CurrentGetBitmap!=NULL) { + if (CurrentGetBitmap->number==MessageBuffer[4]) { + count=MessageBuffer[5]; + memcpy(CurrentGetBitmap->text,MessageBuffer+6,count); + CurrentGetBitmap->text[count]=0; + +#ifdef DEBUG + fprintf(stdout, _("Message: Caller group datas\n")); + fprintf(stdout, _("Caller group name: %s\n"),CurrentGetBitmap->text); +#endif /* DEBUG */ + + count+=6; + + CurrentGetBitmap->ringtone=MessageBuffer[count++]; +#ifdef DEBUG + fprintf(stdout, _("Caller group ringtone ID: %i"),CurrentGetBitmap->ringtone); + if (CurrentGetBitmap->ringtone==16) fprintf(stdout,_(" (default)")); + fprintf(stdout,_("\n")); +#endif /* DEBUG */ + + CurrentGetBitmap->enabled=(MessageBuffer[count++]==1); +#ifdef DEBUG + fprintf(stdout, _("Caller group logo ")); + if (CurrentGetBitmap->enabled) + fprintf(stdout, _("enabled \n")); + else + fprintf(stdout, _("disabled \n")); +#endif /* DEBUG */ + + CurrentGetBitmap->size=MessageBuffer[count++]<<8; + CurrentGetBitmap->size+=MessageBuffer[count++]; +#ifdef DEBUG + fprintf(stdout, _("Bitmap size=%i\n"),CurrentGetBitmap->size); +#endif /* DEBUG */ + + count++; + CurrentGetBitmap->width=MessageBuffer[count++]; + CurrentGetBitmap->height=MessageBuffer[count++]; + count++; + tmp=GSM_GetBitmapSize(CurrentGetBitmap); + if (CurrentGetBitmap->size>tmp) CurrentGetBitmap->size=tmp; + memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count,CurrentGetBitmap->size); + CurrentGetBitmapError=GE_NONE; + } else { +#ifdef DEBUG + fprintf(stdout, _("Message: Caller group datas received, but group number does not match (%i is not %i)\n"),MessageBuffer[4],CurrentGetBitmap->number); +#endif + } + } else { +#ifdef DEBUG + fprintf(stdout, _("Message: Caller group data received but not requested!\n")); +#endif + } + break; + + /* Get group data error */ + case 0x12: + + CurrentGetBitmapError=GE_UNKNOWN; +#ifdef DEBUG + fprintf(stdout, _("Message: Error attempting to get caller group data.\n")); +#endif + break; + + /* Set group data OK */ + case 0x14: + + CurrentSetBitmapError=GE_NONE; +#ifdef DEBUG + fprintf(stdout, _("Message: Caller group data set correctly.\n")); +#endif + break; + + /* Set group data error */ + case 0x15: + + CurrentSetBitmapError=GE_UNKNOWN; +#ifdef DEBUG + fprintf(stdout, _("Message: Error attempting to set caller group data\n")); +#endif + break; + + default: + +#ifdef DEBUG + fprintf(stdout, _("Message: Unknown message of type 0x03\n")); +#endif /* DEBUG */ + AppendLogText("Unknown msg\n",false); + + break; /* Visual C Don't like empty cases */ + } +} + +void N6110_Dispatch0x05Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + int tmp, count, length; + bool issupported; + +#ifdef DEBUG + int i; +#endif + + switch (MessageBuffer[3]) { + + /* Startup Logo */ + case 0x17: + +#ifdef DEBUG + fprintf(stdout, _("Message: Startup Logo, welcome note and dealer welcome note received.\n")); +#endif + + if (CurrentGetBitmap!=NULL) { + + issupported=false; + + count=5; + + for (tmp=0;tmptype==GSM_StartupLogo) { + CurrentGetBitmap->height=MessageBuffer[count++]; + CurrentGetBitmap->width=MessageBuffer[count++]; + CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap); + length=CurrentGetBitmap->size; + memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count,length); + } else { + //bitmap size + length=MessageBuffer[count++]; + length=length*MessageBuffer[count++]/8; + } + count+=length; +#ifdef DEBUG + fprintf(stdout, _("Startup logo supported - ")); + if (length!=0) { fprintf(stdout, _("currently set\n")); } + else { fprintf(stdout, _("currently empty\n")); } +#endif + if (CurrentGetBitmap->type==GSM_StartupLogo) issupported=true; + break; + case 0x02: + length=MessageBuffer[count]; + if (CurrentGetBitmap->type==GSM_WelcomeNoteText) { + memcpy(CurrentGetBitmap->text,MessageBuffer+count+1,length); + CurrentGetBitmap->text[length]=0; + } +#ifdef DEBUG + fprintf(stdout, _("Startup Text supported - ")); + if (length!=0) + { + fprintf(stdout, _("currently set to \"")); + for (i=0;itype==GSM_WelcomeNoteText) issupported=true; + break; + case 0x03: + length=MessageBuffer[count]; + if (CurrentGetBitmap->type==GSM_DealerNoteText) { + memcpy(CurrentGetBitmap->text,MessageBuffer+count+1,length); + CurrentGetBitmap->text[length]=0; + } +#ifdef DEBUG + fprintf(stdout, _("Dealer Welcome supported - ")); + if (length!=0) + { + fprintf(stdout, _("currently set to \"")); + for (i=0;itype==GSM_DealerNoteText) issupported=true; + break; + } + } + if (issupported) CurrentGetBitmapError=GE_NONE; + else CurrentGetBitmapError=GE_NOTSUPPORTED; + } else { +#ifdef DEBUG + fprintf(stdout, _("Message: Startup logo received but not requested!\n")); +#endif + } + break; + + /* Set startup OK */ + case 0x19: + + CurrentSetBitmapError=GE_NONE; +#ifdef DEBUG + fprintf(stdout, _("Message: Startup logo, welcome note or dealer welcome note correctly set.\n")); +#endif + break; + + /* Set Operator Logo OK */ + case 0x31: + +#ifdef DEBUG + fprintf(stdout, _("Message: Operator logo correctly set.\n")); +#endif + + CurrentSetBitmapError=GE_NONE; + break; + + /* Set Operator Logo Error */ + case 0x32: + +#ifdef DEBUG + fprintf(stdout, _("Message: Error setting operator logo!\n")); +#endif + + CurrentSetBitmapError=GE_UNKNOWN; + break; + + /* Operator Logo */ + /* [location],[netcode x 3],[lenhi],[lenlo],[bitmap] */ + case 0x34: + + if (CurrentGetBitmap!=NULL) { + + count=5; /* Location ignored. */ + + DecodeNetworkCode(MessageBuffer+count, CurrentGetBitmap->netcode); + count=count+3; + +#ifdef DEBUG + fprintf(stdout, _("Message: Operator Logo for %s (%s) network received.\n"), + CurrentGetBitmap->netcode, + GSM_GetNetworkName(CurrentGetBitmap->netcode)); +#endif + + CurrentGetBitmap->size=MessageBuffer[count++]<<8; + CurrentGetBitmap->size+=MessageBuffer[count++]; + count++; + CurrentGetBitmap->width=MessageBuffer[count++]; + CurrentGetBitmap->height=MessageBuffer[count++]; + count++; + tmp=GSM_GetBitmapSize(CurrentGetBitmap); + if (CurrentGetBitmap->size>tmp) CurrentGetBitmap->size=tmp; + memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count,CurrentGetBitmap->size); + CurrentGetBitmapError=GE_NONE; + } else { +#ifdef DEBUG + fprintf(stdout, _("Message: Operator logo received but not requested!\n")); +#endif + } + + break; + + /* Get op logo error */ + case 0x35: + +#ifdef DEBUG + fprintf(stdout, _("Message: Error getting operator logo!\n")); +#endif + CurrentGetBitmapError=GE_UNKNOWN; + break; + + default: + +#ifdef DEBUG + fprintf(stdout, _("Message: Unknown message of type 0x05\n")); +#endif /* DEBUG */ + AppendLogText("Unknown msg\n",false); + + break; + } +} + +void N6110_Dispatch0x06Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + int tmp; + unsigned char output[160]; + +#ifdef DEBUG + int i; +#endif + + switch (MessageBuffer[3]) { + + case 0x05: + + /* MessageBuffer[3] = 0x05 + MessageBuffer[4] = 0x00 + MessageBuffer[5] = 0x0f + MessageBuffer[6] = 0x03 + MessageBuffer[7] = length of packed message + + This is all I have seen - Gerry Anderson */ + + tmp=GSM_UnpackEightBitsToSeven(0, 82, 82, MessageBuffer+8, output); + +#ifdef DEBUG + + fprintf(stdout, _("Message from Network operator: ")); + + for (i=0; iSender,GSM_UnpackSemiOctetNumber(MessageBuffer+5,true)); + + while (MessageBuffer[count]!=0) { + count++; + } + + count++; + } else { + strcpy(CurrentGetBitmap->Sender,"\0"); + + count+=3; + } + + memcpy(CurrentGetBitmap->text,MessageBuffer+count+1,MessageBuffer[count]); + CurrentGetBitmap->text[MessageBuffer[count]]=0; + + if (MessageBuffer[count]!=0) + count+=MessageBuffer[count]; + + count++; + +#ifdef DEBUG + fprintf(stdout,_("Picture Image received, text \"%s\", sender %s\n"),CurrentGetBitmap->text,CurrentGetBitmap->Sender); +#endif + + CurrentGetBitmap->width=MessageBuffer[count+1]; + CurrentGetBitmap->height=MessageBuffer[count+2]; + CurrentGetBitmap->size=GSM_GetBitmapSize(CurrentGetBitmap); + + memcpy(CurrentGetBitmap->bitmap,MessageBuffer+count+4,CurrentGetBitmap->size); + + CurrentGetBitmapError=GE_NONE; + break; + + case 0x04: + +#ifdef DEBUG + fprintf(stdout,_("Getting or setting Picture Image - OK\n")); +#endif + CurrentSetBitmapError=GE_NONE; + CurrentGetBitmapError=GE_NONE; + break; + + case 0x05: + +#ifdef DEBUG + fprintf(stdout,_("Setting Picture Image - invalid location or other error\n")); +#endif + CurrentSetBitmapError=GE_UNKNOWN; + break; + + case 0x06: + +#ifdef DEBUG + fprintf(stdout,_("Getting Picture Image - invalid location or other error\n")); +#endif + CurrentGetBitmapError=GE_UNKNOWN; + break; + + default: + +#ifdef DEBUG + fprintf(stdout, _("Unknown message of type 0x47.\n")); +#endif /* DEBUG */ + AppendLogText("Unknown msg\n",false); + break; /* Visual C Don't like empty cases */ + } +} + +void N6110_DispatchACKMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + char buffer[50]; + + sprintf(buffer,"Received ACK %02x %02x\n",MessageBuffer[0],MessageBuffer[1]); + AppendLog(buffer,strlen(buffer),false); + +#ifdef DEBUG + fprintf(stdout, _("[Received Ack of type %02x, seq: %2x]\n"), MessageBuffer[0], + MessageBuffer[1]); +#endif /* DEBUG */ + + CurrentLinkOK = true; +} + +void N6110_Dispatch0xD0Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#ifdef DEBUG + fprintf(stdout, _("Message: The phone is powered on - seq 1.\n")); +#endif /* DEBUG */ + +} + +/* This function is used for parsing the RLP frame into fields. */ +void N6110_RX_HandleRLPMessage(u8 *MessageBuffer) +{ + + RLP_F96Frame frame; + int count; + int valid = true; + + /* We do not need RLP frame parsing to be done when we do not have callback + specified. */ + if (CurrentRLP_RXCallback == NULL) + exit; + + /* Anybody know the official meaning of the first two bytes? + Nokia 6150 sends junk frames starting D9 01, and real frames starting + D9 00. We'd drop the junk frames anyway because the FCS is bad, but + it's tidier to do it here. We still need to call the callback function + to give it a chance to handle timeouts and/or transmit a frame */ + if (MessageBuffer[0] == 0xd9 && MessageBuffer[1] == 0x01) + valid = false; + + /* Nokia uses 240 bit frame size of RLP frames as per GSM 04.22 + specification, so Header consists of 16 bits (2 bytes). See section 4.1 + of the specification. */ + + frame.Header[0] = MessageBuffer[2]; + frame.Header[1] = MessageBuffer[3]; + + /* Next 200 bits (25 bytes) contain the Information. We store the + information in the Data array. */ + + for (count = 0; count < 25; count ++) + frame.Data[count] = MessageBuffer[4 + count]; + + /* The last 24 bits (3 bytes) contain FCS. */ + + frame.FCS[0] = MessageBuffer[29]; + frame.FCS[1] = MessageBuffer[30]; + frame.FCS[2] = MessageBuffer[31]; + + /* Here we pass the frame down in the input stream. */ + CurrentRLP_RXCallback(valid ? &frame : NULL); +} + +void N6110_Dispatch0xF4Message(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + +#ifdef DEBUG + fprintf(stdout, _("Message: The phone is powered on - seq 2.\n")); +#endif /* DEBUG */ + +} + +void N6110_ReplyIncomingSMS(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + GSM_SMSMessage NullSMS; + + switch (MessageBuffer[6]) { + + case 0x00: NullSMS.Type = GST_SMS; NullSMS.folder = GST_INBOX; break; + case 0x01: NullSMS.Type = GST_DR; NullSMS.folder = GST_INBOX; break; + + /* Is it possible ? */ + case 0x02: NullSMS.Type = GST_SMS; NullSMS.folder = GST_OUTBOX; break; + default: NullSMS.Type = GST_UN; break; + } + +#ifdef DEBUG + if (NullSMS.Type == GST_DR) + fprintf(stdout, _("Message: SMS Message (Report) Received\n")); + else + fprintf(stdout, _("Message: SMS Message Received\n")); +#endif /* DEBUG */ + + GSM_DecodeNokiaSMSFrame(&NullSMS, MessageBuffer+7, MessageLength-7); + +#ifdef DEBUG + fprintf(stdout, _("\n")); +#endif /* DEBUG */ +} + +void N6110_DispatchMessage(u16 MessageLength, u8 *MessageBuffer, u8 MessageType) { + + bool unknown=false; + + /* Switch on the basis of the message type byte */ + switch (MessageType) { + + /* Call information */ + case 0x01: + + N6110_Dispatch0x01Message(MessageLength, MessageBuffer, MessageType); + break; + + /* SMS handling */ + case 0x02: + switch (MessageBuffer[3]) { + case 0x02: + case 0x03:N6110_ReplySendSMSMessage(MessageLength,MessageBuffer,MessageType);break; + case 0x10:N6110_ReplyIncomingSMS(MessageLength,MessageBuffer,MessageType);break; + case 0x21:N6110_ReplySetCellBroadcast(MessageLength, MessageBuffer, MessageType);break; + case 0x23:N6110_ReplyReadCellBroadcast(MessageLength, MessageBuffer, MessageType);break; + case 0x31:N6110_ReplySetSMSCenter(MessageLength,MessageBuffer,MessageType);break; + case 0x34: + case 0x35:N6110_ReplyGetSMSCenter(MessageLength,MessageBuffer,MessageType);break; + default :unknown=true;break; + } + break; + + /* Phonebook handling */ + case 0x03: + switch (MessageBuffer[3]) { + case 0x02: + case 0x03:N6110_ReplyGetMemoryLocation(MessageLength,MessageBuffer,MessageType);break; + case 0x05: + case 0x06:N6110_ReplyWritePhonebookLocation(MessageLength,MessageBuffer,MessageType);break; + case 0x08: + case 0x09:N6110_ReplyGetMemoryStatus(MessageLength,MessageBuffer,MessageType);break; + case 0x17: + case 0x18:N6110_ReplyGetSpeedDial(MessageLength,MessageBuffer,MessageType);break; + case 0x1a: + case 0x1b:N6110_ReplySetSpeedDial(MessageLength,MessageBuffer,MessageType);break; + default :N6110_Dispatch0x03Message(MessageLength,MessageBuffer,MessageType);break; + } + break; + + /* Phone status */ + case 0x04: + switch (MessageBuffer[3]) { + case 0x02:N6110_ReplyRFBatteryLevel(MessageLength,MessageBuffer,MessageType);break; + default :unknown=true;break; + } + break; + + /* Startup Logo, Operator Logo and Profiles. */ + case 0x05: + switch (MessageBuffer[3]) { + case 0x11:N6110_ReplySetProfile (MessageLength,MessageBuffer,MessageType);break; + case 0x14:N6110_ReplyGetProfile (MessageLength,MessageBuffer,MessageType);break; + case 0x1b:N6110_ReplyGetProfile (MessageLength,MessageBuffer,MessageType);break; + case 0x1d:N6110_ReplySetProfile (MessageLength,MessageBuffer,MessageType);break; + case 0x37:N6110_ReplySetRingtone (MessageLength,MessageBuffer,MessageType);break; + case 0x38:N6110_ReplySetRingtone (MessageLength,MessageBuffer,MessageType);break; + default :N6110_Dispatch0x05Message(MessageLength,MessageBuffer,MessageType);break; + } + break; + + /* Network Operator Message to handset -> Gerry Anderson & prepaid info */ + /* Call diverts */ + case 0x06: + switch (MessageBuffer[3]) { + case 0x02: + case 0x03:N6110_ReplyCallDivert (MessageLength,MessageBuffer,MessageType);break; + default :N6110_Dispatch0x06Message(MessageLength,MessageBuffer,MessageType);break; + } + break; + + /* Security code requests */ + case 0x08: + switch (MessageBuffer[3]) { + case 0x08:N6110_ReplyGetSecurityCodeStatus(MessageLength,MessageBuffer,MessageType);break; + case 0x0b:N6110_ReplyEnterSecurityCode (MessageLength,MessageBuffer,MessageType);break; + default :N6110_ReplyEnterSecurityCode (MessageLength,MessageBuffer,MessageType);break; + } + break; + + /* SIM login */ + case 0x09: + + N6110_Dispatch0x09Message(MessageLength, MessageBuffer, MessageType); + break; + + /* Network info */ + case 0x0a: + switch (MessageBuffer[3]) { + case 0x71:N6110_ReplyGetNetworkInfo(MessageLength,MessageBuffer,MessageType);break; + default :unknown=true;break; + } + break; + + /* Simulating key pressing */ + case 0x0c: + switch (MessageBuffer[3]) { + case 0x43:N6110_ReplyPressKey(MessageLength,MessageBuffer,MessageType);break; + default :unknown=true;break; + } + break; + + /* Display */ + case 0x0d: + switch (MessageBuffer[3]) { + case 0x50:N6110_ReplyDisplayOutput (MessageLength,MessageBuffer,MessageType);break; + case 0x52:N6110_ReplyGetDisplayStatus(MessageLength,MessageBuffer,MessageType);break; + case 0x54:N6110_ReplyDisplayOutput (MessageLength,MessageBuffer,MessageType);break; + default :unknown=true;break; + } + break; + + /* Phone Clock and Alarm */ + case 0x11: + switch (MessageBuffer[3]) { + case 0x61:N6110_ReplySetDateTime(MessageLength,MessageBuffer,MessageType);break; + case 0x63:N6110_ReplyGetDateTime(MessageLength,MessageBuffer,MessageType);break; + case 0x6c:N6110_ReplySetAlarm (MessageLength,MessageBuffer,MessageType);break; + case 0x6e:N6110_ReplyGetAlarm (MessageLength,MessageBuffer,MessageType);break; + default :unknown=true;break; + } + break; + + /* Calendar notes handling */ + case 0x13: + switch (MessageBuffer[3]) { + case 0x65:N6110_ReplyWriteCalendarNote (MessageLength,MessageBuffer,MessageType);break; + case 0x67:N6110_ReplyGetCalendarNote (MessageLength,MessageBuffer,MessageType);break; + case 0x69:N6110_ReplyDeleteCalendarNote(MessageLength,MessageBuffer,MessageType);break; + default :N6110_Dispatch0x13Message (MessageLength,MessageBuffer,MessageType);break; + } + break; + + /* SMS Messages */ + case 0x14: + switch (MessageBuffer[3]) { + case 0x05: + case 0x06:N6110_ReplySaveSMSMessage (MessageLength,MessageBuffer,MessageType);break; + case 0x08: + case 0x09:N6110_ReplyGetSMSMessage (MessageLength,MessageBuffer,MessageType);break; + case 0x0b:N6110_ReplyDeleteSMSMessage(MessageLength,MessageBuffer,MessageType);break; + case 0x37: + case 0x38:N6110_ReplyGetSMSStatus (MessageLength,MessageBuffer,MessageType);break; + default :unknown=true;break; + } + break; + + /* WAP */ + case 0x3f: + switch (MessageBuffer[3]) { + case 0x01: + case 0x02:N7110_ReplyEnableWAPCommands(MessageLength,MessageBuffer,MessageType);break; + case 0x07: + case 0x08:N7110_ReplyGetWAPBookmark (MessageLength,MessageBuffer,MessageType);break; + case 0x0a: + case 0x0b:N7110_ReplySetWAPBookmark (MessageLength,MessageBuffer,MessageType);break; + case 0x16: + case 0x17: + case 0x1c:N7110_ReplyGetWAPSettings (MessageLength,MessageBuffer,MessageType);break; + default :unknown=true;break; + } + break; + + /* Internal phone functions? */ + case 0x40: + switch (MessageBuffer[2]) { + case 0x64:N6110_ReplyEnableExtendedCommands (MessageLength,MessageBuffer,MessageType);break; + case 0x65:N6110_ReplyResetPhoneSettings (MessageLength,MessageBuffer,MessageType);break; + case 0x66:N6110_ReplyIMEI (MessageLength,MessageBuffer,MessageType);break; + case 0x6a:N6110_ReplyGetProductProfileSetting(MessageLength,MessageBuffer,MessageType);break; + case 0x6b:N6110_ReplySetProductProfileSetting(MessageLength,MessageBuffer,MessageType);break; + case 0x6e:N6110_ReplyGetSecurityCode (MessageLength,MessageBuffer,MessageType);break; + case 0x7e:N6110_ReplyNetmonitor (MessageLength,MessageBuffer,MessageType);break; + case 0x8a:N6110_ReplySimlockInfo (MessageLength,MessageBuffer,MessageType);break; + case 0x8b:N6110_ReplySetOperatorName (MessageLength,MessageBuffer,MessageType);break; + case 0x8c:N6110_ReplyGetOperatorName (MessageLength,MessageBuffer,MessageType);break; + case 0x8f:N6110_ReplyPlayTone (MessageLength,MessageBuffer,MessageType);break; + case 0x9e:N6110_ReplyGetBinRingtone (MessageLength,MessageBuffer,MessageType);break; + case 0xa0:N6110_ReplySetBinRingtone (MessageLength,MessageBuffer,MessageType);break; + case 0xc8:N6110_ReplyHW (MessageLength,MessageBuffer,MessageType);break; + default :N6110_Dispatch0x40Message (MessageLength,MessageBuffer,MessageType);break; + } + break; + + /* Picture Images */ + case 0x47: + + N6110_Dispatch0x47Message(MessageLength, MessageBuffer, MessageType); + break; + + /* Mobile phone identification */ + case 0x64: + + N6110_ReplyGetAuthentication(MessageLength, MessageBuffer, MessageType); + break; + + /***** Acknowlegment of our frames. *****/ + case FBUS_FRTYPE_ACK: + + N6110_DispatchACKMessage(MessageLength, MessageBuffer, MessageType); + break; + + /***** Power on message. *****/ + case 0xd0: + + N6110_Dispatch0xD0Message(MessageLength, MessageBuffer, MessageType); + break; + + case 0xd2: + + N6110_ReplyID(MessageLength, MessageBuffer, MessageType); + break; + + /***** RLP frame received. *****/ + case 0xf1: + + N6110_RX_HandleRLPMessage(MessageBuffer); + break; + + /***** Power on message. *****/ + case 0xf4: + + N6110_Dispatch0xF4Message(MessageLength, MessageBuffer, MessageType); + break; + + /***** Unknown message *****/ + /* If you think that you know the exact meaning of other messages - please + let us know. */ + default: + +#ifdef DEBUG + fprintf(stdout, _("Message: Unknown message type.\n")); +#endif /* DEBUG */ + AppendLogText("Unknown msg type\n",false); + + unknown=false; + break; + + } + + if (unknown) { +#ifdef DEBUG + fprintf(stdout, _("Unknown message of type %02x.\n"),MessageType); +#endif + AppendLogText("Unknown msg\n",false); + } +} diff --git a/common/protocol/fbus.c b/common/protocol/fbus.c new file mode 100644 index 0000000..87e98fe --- /dev/null +++ b/common/protocol/fbus.c @@ -0,0 +1,654 @@ +/* + + G N O K I I + + A Linux/Unix toolset and driver for Nokia mobile phones. + + Released under the terms of the GNU GPL, see file COPYING for more details. + + This file provides an API for support for FBUS protocol + +*/ + +/* "Turn on" prototypes in fbus.h */ +#define __fbus_c + +/* System header files */ +#include +#include +#include + +#ifdef WIN32 + #include + #include "misc_win32.h" +#else + #include +#endif + +/* Various header file */ +#include "devices/device.h" +#include "gsm-api.h" +#include "protocol/fbus.h" +#include "protocol/at.h" +#include "newmodules/newat.h" +#include "newmodules/n6110.h" +#include "misc.h" + +GSM_Protocol FBUS_Functions = { + FBUS_Initialise, + FBUS_SendMessage, + FBUS_SendFrame, + NULL_WritePhone, + FBUS_Terminate, + FBUS_RX_StateMachine +}; + +/* Local variables */ +enum FBUS_RX_States RX_State; + +u8 MessageDestination, MessageSource; + +u16 BufferCount, MultiBufferCount; + +u16 MessageLength, MultiMessageLength; + +bool RX_Multiple = false; + +u8 MessageType,MultiMessageType; + +u8 MessageBuffer[FBUS_MAX_RECEIVE_LENGTH * 6],MultiMessageBuffer[FBUS_MAX_RECEIVE_LENGTH * 6]; + +u8 RequestSequenceNumber = 0x00; + +#ifdef DEBUG +char *N61_PrintDevice(int Device) +{ + switch (Device) { + + case FBUS_DEVICE_PHONE:return _("Phone"); + case FBUS_DEVICE_PC :return _("PC"); + default :return _("Unknown"); + } +} +#endif /* DEBUG */ + +/* N61_RX_DisplayMessage is called when a message we don't know about is + received so that the user can see what is going back and forth, and perhaps + shed some more light/explain another message type! */ +void N61_RX_DisplayMessage() +{ +#ifdef DEBUG + fprintf(stdout, _("Msg Dest: %s\n"), N61_PrintDevice(MessageDestination)); + fprintf(stdout, _("Msg Source: %s\n"), N61_PrintDevice(MessageSource)); + fprintf(stdout, _("Msg Type: %02x\n"), MessageType); + + hexdump(MessageLength-2,MessageBuffer); +#endif + + AppendLog(MessageBuffer,MessageLength-2,true); +} + +/* Prepares the message header and sends it, prepends the message start byte + (0x1e) and other values according the value specified when called. + Calculates checksum and then sends the lot down the pipe... */ +int FBUS_SendFrame(u16 message_length, u8 message_type, u8 *buffer) { + + /* Originally out_buffer[FBUS_MAX_CONTENT_LENGTH + 2], + but it made problems with MBUS */ + u8 out_buffer[1000]; + + int count, current=0; + unsigned char checksum; + + /* FIXME - we should check for the message length ... */ + + /* Now construct the message header. */ + + if (CurrentConnectionType==GCT_FBUS) + out_buffer[current++] = FBUS_FRAME_ID; /* Start of the frame indicator */ + else + out_buffer[current++] = FBUS_IR_FRAME_ID; /* Start of the frame indicator */ + + out_buffer[current++] = FBUS_DEVICE_PHONE; /* Destination */ + + out_buffer[current++] = FBUS_DEVICE_PC; /* Source */ + + out_buffer[current++] = message_type; /* Type */ + + out_buffer[current++] = 0; /* Length1 */ + out_buffer[current++] = message_length; /* Length2 */ + + /* Copy in data if any. */ + if (message_length != 0) { + memcpy(out_buffer + current, buffer, message_length); + current+=message_length; + } + + /* If the message length is odd we should add pad byte 0x00 */ + if (message_length % 2) + out_buffer[current++]=0x00; + + /* Now calculate checksums over entire message and append to message. */ + + /* Odd bytes */ + checksum = 0; + for (count = 0; count < current; count+=2) + checksum ^= out_buffer[count]; + + out_buffer[current++] = checksum; + + /* Even bytes */ + checksum = 0; + for (count = 1; count < current; count+=2) + checksum ^= out_buffer[count]; + + out_buffer[current++] = checksum; + +#ifdef DEBUG + NULL_TX_DisplayMessage(current, out_buffer); +#endif /* DEBUG */ + + /* Send it out... */ + if (!NULL_WritePhone(current,out_buffer)) + return (false); + + return (true); +} + +int FBUS_SendMessage(u16 message_length, u8 message_type, u8 *buffer) { + + u8 seqnum; + + u8 frame_buffer[FBUS_MAX_CONTENT_LENGTH + 2]; + + u8 nom, lml; /* number of messages, last message len */ + int i; + + seqnum = 0x40 + RequestSequenceNumber; + RequestSequenceNumber = (RequestSequenceNumber + 1) & 0x07; + + if (message_length > FBUS_MAX_CONTENT_LENGTH) { + + nom = (message_length + FBUS_MAX_CONTENT_LENGTH - 1) + / FBUS_MAX_CONTENT_LENGTH; + lml = message_length - ((nom - 1) * FBUS_MAX_CONTENT_LENGTH); + + for (i = 0; i < nom - 1; i++) { + + memcpy(frame_buffer, buffer + (i * FBUS_MAX_CONTENT_LENGTH), + FBUS_MAX_CONTENT_LENGTH); + frame_buffer[FBUS_MAX_CONTENT_LENGTH] = nom - i; + frame_buffer[FBUS_MAX_CONTENT_LENGTH + 1] = seqnum; + + FBUS_SendFrame(FBUS_MAX_CONTENT_LENGTH + 2, message_type, + frame_buffer); + + seqnum = RequestSequenceNumber; + RequestSequenceNumber = (RequestSequenceNumber + 1) & 0x07; + } + + memcpy(frame_buffer, buffer + ((nom - 1) * FBUS_MAX_CONTENT_LENGTH), lml); + frame_buffer[lml] = 0x01; + frame_buffer[lml + 1] = seqnum; + FBUS_SendFrame(lml + 2, message_type, frame_buffer); + + } else { + + memcpy(frame_buffer, buffer, message_length); + frame_buffer[message_length] = 0x01; + frame_buffer[message_length + 1] = seqnum; + FBUS_SendFrame(message_length + 2, message_type, frame_buffer); + } + + return (true); +} + +int FBUS_SendAck(u8 message_type, u8 message_seq) { + + unsigned char request[6]; + + request[0] = message_type; + request[1] = message_seq; + +#ifdef DEBUG + fprintf(stdout, _("[Sending Ack of type %02x, seq: %x]\n"), message_type, message_seq); +#endif /* DEBUG */ + + return FBUS_SendFrame(2, FBUS_FRTYPE_ACK, request); +} + +/* Applications should call FBUS_Terminate to shut down the FBUS thread and + close the serial port. */ +void FBUS_Terminate(void) +{ + /* Request termination of thread */ + CurrentRequestTerminate = true; + + /* Close serial port. */ + device_close(); +} + +/* RX_State machine for receive handling. Called once for each character + received from the phone/phone. */ + +void FBUS_RX_StateMachine(unsigned char rx_byte) { + + static struct timeval time_now, time_last, time_diff; + + static int checksum[2]; + + int i=0; + +// if (CurrentConnectionType==GCT_DLR3) { +// AT_RX_StateMachine(rx_byte); +// } else { + +#ifdef DEBUG + /* For model sniff only display received bytes */ + if (strcmp(GSM_Info->FBUSModels, "sniff")) + { +#endif + + /* XOR the byte with the current checksum */ + checksum[BufferCount&1] ^= rx_byte; + + switch (RX_State) { + + /* Messages from the phone start with an 0x1e (FBUS) or 0x1c (IR) or 0x1f (MBUS). + We use this to "synchronise" with the incoming data stream. However, + if we see something else, we assume we have lost sync and we require + a gap of at least 5ms before we start looking again. This is because + the data part of the frame could contain a byte which looks like the + sync byte */ + + case FBUS_RX_Discarding: + +#ifndef VC6 + gettimeofday(&time_now, NULL); + timersub(&time_now, &time_last, &time_diff); + if (time_diff.tv_sec == 0 && time_diff.tv_usec < 5000) { + time_last = time_now; /* no gap seen, continue discarding */ + break; + } + /* else fall through to... */ +#endif + + case FBUS_RX_Sync: + + if ((CurrentConnectionType==GCT_FBUS && rx_byte == FBUS_FRAME_ID) || + ((CurrentConnectionType==GCT_Infrared || + CurrentConnectionType==GCT_Tekram) && rx_byte == FBUS_IR_FRAME_ID)) { + + BufferCount = 0; + + RX_State = FBUS_RX_GetDestination; + + /* Initialize checksums. */ + checksum[0] = rx_byte; + checksum[1] = 0; + } else { + /* Lost frame sync */ + RX_State = FBUS_RX_Discarding; +#ifndef VC6 + gettimeofday(&time_last, NULL); +#endif + } + break; + + case FBUS_RX_GetDestination: + + MessageDestination=rx_byte; + RX_State = FBUS_RX_GetSource; + + /* When there is a checksum error and things get out of sync we have to manage to resync */ + /* If doing a data call at the time, finding a 0x1e etc is really quite likely in the data stream */ + /* Then all sorts of horrible things happen because the packet length etc is wrong... */ + /* Therefore we test here for a destination of 0x0c and return to the top if it is not */ + if (rx_byte!=FBUS_DEVICE_PC && strstr(GSM_Info->FBUSModels, "sniff")==NULL) { + RX_State=FBUS_RX_Sync; +#ifdef DEBUG + fprintf(stdout,"The fbus stream is out of sync - expected 0x0c, got %2x\n",rx_byte); +#endif + AppendLogText("SYNC\n",false); + } + + break; + + case FBUS_RX_GetSource: + + MessageSource=rx_byte; + RX_State = FBUS_RX_GetType; + + /* Source should be 0x00 */ + if (rx_byte!=FBUS_DEVICE_PHONE && strstr(GSM_Info->FBUSModels, "sniff")==NULL) { + RX_State=FBUS_RX_Sync; +#ifdef DEBUG + fprintf(stdout,"The fbus stream is out of sync - expected 0x00, got %2x\n",rx_byte); +#endif + AppendLogText("SYNC\n",false); + } + + break; + + case FBUS_RX_GetType: + + MessageType=rx_byte; + + RX_State = FBUS_RX_GetLength1; + + break; + + case FBUS_RX_GetLength1: + + MessageLength = 0; + + RX_State = FBUS_RX_GetLength2; + + break; + + case FBUS_RX_GetLength2: + + /* MW:Here are problems with conversion. For chars 0-127 it's OK, for + higher not (probably because rx_byte is char type) - improtant + for MBUS. So, I make it double and strange - generally it should be + more simple and make simple convert rx_byte into MessageLength */ +#if defined(__svr4__) || defined(__FreeBSD__) + if (rx_byte!=0) { + for (i=0;iFBUS_MAX_RECEIVE_LENGTH*6) { +#ifdef DEBUG + fprintf(stdout, "FB61: Message buffer overun - resetting\n"); +#endif + AppendLogText("OVERUN\n",false); + RX_Multiple=false; + RX_State = FBUS_RX_Sync; + break; + } + + /* If this is the last byte, it's the checksum. */ + if (BufferCount == MessageLength+(MessageLength%2)+2) { + + /* Is the checksum correct? */ + if (checksum[0] == checksum[1]) { + + if (RX_Multiple) { + + if (MessageType==MultiMessageType) { + + if (MessageLength+MultiMessageLength>FBUS_MAX_RECEIVE_LENGTH*6) { +#ifdef DEBUG + fprintf(stdout, "FB61: Message buffer overun - resetting\n"); +#endif + AppendLogText("OVERUN\n",false); + RX_Multiple=false; + RX_State = FBUS_RX_Sync; + break; + } + + /* We copy next part of multiframe message into special buffer */ + for (i=0;i 1) && (MessageBuffer[MessageLength-2] != 0x01)) + { + } else { + for (i=0;iDispatchMessage(MessageLength-2, MessageBuffer, MessageType); + } + + } else { + + /* We do not want to send ACK of ACKs and ACK of RLP frames. */ + if (MessageType != FBUS_FRTYPE_ACK && MessageType != 0xf1) { + FBUS_SendAck(MessageType, MessageBuffer[MessageLength-1] & 0x0f); + + if ((MessageLength > 1) && (MessageBuffer[MessageLength-2] != 0x01)) + { +#ifdef DEBUG + fprintf(stdout,_("Multiframe message in multiframe message !\n")); + fprintf(stdout,_("Please report it !\n")); +#endif + RX_State = FBUS_RX_Sync; + } + } + } + } else { + + /* We do not want to send ACK of ACKs and ACK of RLP frames. */ + if (MessageType != FBUS_FRTYPE_ACK && MessageType != 0xf1) { + FBUS_SendAck(MessageType, MessageBuffer[MessageLength-1] & 0x0f); + + if ((MessageLength > 1) && (MessageBuffer[MessageLength-2] != 0x01)) + { + /* We copy previous part of multiframe message into special buffer */ + RX_Multiple = true; + for (i=0;iDispatchMessage(MessageLength-2, MessageBuffer, MessageType); + } + +#ifdef DEBUG + /* When make debug and message is to phone display it */ + if (MessageDestination==FBUS_DEVICE_PHONE) { + for (i=MessageLength;i>=0;i--) + MessageBuffer[i+6]=MessageBuffer[i]; + MessageBuffer[0]=FBUS_FRAME_ID; + MessageBuffer[1]=FBUS_DEVICE_PHONE; + MessageBuffer[2]=FBUS_DEVICE_PC; + MessageBuffer[3]=MessageType; + MessageBuffer[4]=0; + MessageBuffer[5]=MessageLength; + MessageLength=MessageLength+8; + if (MessageLength % 2) MessageLength++; + NULL_TX_DisplayMessage(MessageLength, MessageBuffer); + } +#endif + } + } else { +#ifdef DEBUG + fprintf(stdout, _("Bad checksum %02x (should be %02x), msg len=%i !\n"),checksum[0],checksum[1],MessageLength); +#endif /* DEBUG */ + AppendLogText("CHECKSUM\n",false); + + /* Just to be sure! */ + RX_Multiple=false; + } + RX_State = FBUS_RX_Sync; + } + break; + } + +#ifdef DEBUG + } else { + if (isprint(rx_byte)) + fprintf(stdout, "[%02x%c]", rx_byte, rx_byte); + else + fprintf(stdout, "[%02x ]", rx_byte); + + } +#endif + +// } +} + +/* Called by initialisation code to open comm port in asynchronous mode. */ +bool FBUS_OpenSerial(void) +{ + /* Uncomment, if want to test first method for DLR3 */ +// unsigned char req[3] = {"AT\r"}; +// unsigned char req2[5] = {"AT&F\r"}; +// unsigned char req3[13] = {"AT*NOKIAFBUS\r"}; + +// GSM_Error error; + +// GSM_Information *GSMINFOCOPY; +// GSM_Functions *GSMCOPY; + + switch (CurrentConnectionType) { + case GCT_FBUS: + +#ifdef DEBUG + fprintf(stdout, _("Setting cable for FBUS communication...\n")); +#endif /* DEBUG */ + + device_changespeed(115200); + + /* Colin wrote: + The data suite cable has some electronics built into the connector. This of + course needs a power supply of some sorts to operate properly. + + In this case power is drawn off the handshaking lines of the PC. DTR has to + be set and RTS have to be cleared, thus if you use a terminal program (that + does not set the handshaking lines to these conditions) you will get weird + results. It will not set them like this since if Request To Send (RTS) is + not set the other party will not send any data (in hardware handshaking) + and if DTS is not set (handshaking = none) the cable will not receive + power. */ + /* clearing the RTS bit and setting the DTR bit*/ + device_setdtrrts(1, 0); + + break; + case GCT_DLR3: + +#ifdef DEBUG + fprintf(stdout, _("Setting DLR3 cable for FBUS communication...\n")); +#endif /* DEBUG */ + + /* There are 2 ways to init DLR in FBUS: Here is first described by + Reuben Harris [reuben.harris@snowvalley.com] and used in Logo Manager, + 1. Firstly set the connection baud to 19200, DTR off, RTS off, + Parity on, one stop bit, + 2. Send "AT\r\n". The response should be "AT\r\n\r\nOK\r\n". + 3. Send "AT&F\r\n". The response should be "AT&F\r\n\r\nOK\r\n". + 4. Send "AT*NOKIAFBUS\r\n". The response should be + "AT*NOKIAFBUS\r\n\r\nOK\r\n". + 5. Set speed to 115200 + + This is one should be used by us, because seems to be compatible with more + phones. But we make something wrong and often phones don't want to start transmision */ + + /* Uncomment and test if want */ +// device_changespeed(19200); + + /*leave RTS low, DTR low for duration of session.*/ +// device_setdtrrts(0, 0); + + /* Making copy of pointers */ +// GSMCOPY = GSM; +// GSMINFOCOPY =GSM_Info; + + /* Set pointers to relevant addresses - new "AT" module here is required */ +// GSM = &Nat_Functions; +// GSM_Info = &Nat_Information; + + /* Note: We change Protocol inside function pointed by it. + That's why in FBUS_RX_StateMachine we must check it (changing + Protocol is not enough), This is for correct work and be sure... */ +// Protocol = &AT_Functions; + +// error=N6110_SendMessageSequence (50, &CurrentGetHWError, 3, 0x00, req); +// if (error!=GE_NONE) return false; + +// error=N6110_SendMessageSequence (50, &CurrentGetHWError, 5, 0x00, req2); +// if (error!=GE_NONE) return false; + +// error=N6110_SendMessageSequence (50, &CurrentGetHWError, 13, 0x00, req3); +// if (error!=GE_NONE) return false; + + /* Returning to old protocol */ +// Protocol = &FBUS_Functions; + + /* Returning to old module */ +// GSM = GSMCOPY; +// GSM_Info = GSMINFOCOPY; + +// device_changespeed(115200); + + /* Second method for DLR3: + Used by some 7110 soft, but not compatible with some other + phones supporting DLR3 - 7160, NCP2.0 + Used in this moment in mygnokii + */ + + device_changespeed(115200); + + /*leave RTS low, DTR low for duration of session.*/ + device_setdtrrts(0, 0); + + usleep(100000); + + CurrentConnectionType=GCT_FBUS; + + break; + case GCT_Infrared: + /* It's more complicated and not done here */ + break; + + case GCT_Tekram: + /* It's more complicated and not done here */ + break; + + default: +#ifdef DEBUG + fprintf(stdout,_("Wrong connection type for fbus module. Inform marcin-wiacek@topnet.pl about it\n")); +#endif + break; + } + + return (true); +} + +/* Initialise variables and state machine. */ +GSM_Error FBUS_Initialise(char *port_device, char *initlength, + GSM_ConnectionType connection, + void (*rlp_callback)(RLP_F96Frame *frame)) +{ + + if (!StartConnection (port_device,false,connection)) + return GE_INTERNALERROR; + + CurrentConnectionType = connection; + + if (FBUS_OpenSerial() != true) return GE_INTERNALERROR; + + return (GE_NONE); +} diff --git a/gnokii/gnokii.c b/gnokii/gnokii.c new file mode 100644 index 0000000..c8db700 --- /dev/null +++ b/gnokii/gnokii.c @@ -0,0 +1,8913 @@ +/* + + G N O K I I + + A Linux/Unix toolset and driver for Nokia mobile phones. + + Released under the terms of the GNU GPL, see file COPYING for more details. + + Mainline code for gnokii utility. Handles command line parsing and + reading/writing phonebook entries and other stuff. + +*/ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef VC6 + #if defined(__svr4__) || defined(__FreeBSD__) + # include /* for bzero */ + #endif +#else + /* for VC6 make scripts save VERSION constant in mversion.h file */ + #include "mversion.h" +#endif + +#ifdef WIN32 + + #include + + #include "misc_win32.h" + #include "getopt.h" + + #define DEV_CONSOLE "CON:" + +#else + + #include + #include + #include + #include + #include + #include + + #define DEV_CONSOLE "/dev/tty" +#endif + +#include "misc.h" +#include "gsm-common.h" +#include "gsm-api.h" +#include "gsm-networks.h" +#include "gsm-ringtones.h" +#include "gsm-bitmaps.h" +#include "gsm-wap.h" +#include "gsm-sms.h" +#include "gsm-datetime.h" +#include "gsm-phonebook.h" +#include "gsm-calendar.h" +#include "gsm-coding.h" +#include "newmodules/n6110.h" +#include "files/cfgreader.h" +#include "files/gsm-filetypes.h" +#include "gnokii.h" + +#ifdef USE_NLS + #include +#endif + +char *model; /* Model from .gnokiirc file. */ +char *Port; /* Port from .gnokiirc file */ +char *Initlength; /* Init length from .gnokiirc file */ +char *Connection; /* Connection type from .gnokiirc file */ +char *SynchronizeTime; /* If we set date and time from computer to phone (from .gnokiirc file) */ +char *BinDir; /* Binaries directory from .gnokiirc file - not used here yet */ + +GSM_SMSMessage SMS[4]; + +char *GetProfileCallAlertString(int code) { + + switch (code) { + case PROFILE_CALLALERT_RINGING : return "Ringing"; + case PROFILE_CALLALERT_ASCENDING : return "Ascending"; + case PROFILE_CALLALERT_RINGONCE : return "Ring once"; + case PROFILE_CALLALERT_BEEPONCE : return "Beep once"; + case PROFILE_CALLALERT_CALLERGROUPS: return "Caller groups"; + case PROFILE_CALLALERT_OFF : return "Off"; + default : return "Unknown"; + } +} + +char *GetProfileVolumeString(int code) { + + switch (code) { + case PROFILE_VOLUME_LEVEL1 : return "Level 1"; + case PROFILE_VOLUME_LEVEL2 : return "Level 2"; + case PROFILE_VOLUME_LEVEL3 : return "Level 3"; + case PROFILE_VOLUME_LEVEL4 : return "Level 4"; + case PROFILE_VOLUME_LEVEL5 : return "Level 5"; + default : return "Unknown"; + } +} + +char *GetProfileKeypadToneString(int code) { + + switch (code) { + case PROFILE_KEYPAD_OFF : return "Off"; + case PROFILE_KEYPAD_LEVEL1 : return "Level 1"; + case PROFILE_KEYPAD_LEVEL2 : return "Level 2"; + case PROFILE_KEYPAD_LEVEL3 : return "Level 3"; + default : return "Unknown"; + } +} + +char *GetProfileMessageToneString(int code) { + + switch (code) { + case PROFILE_MESSAGE_NOTONE : return "No tone"; + case PROFILE_MESSAGE_STANDARD : return "Standard"; + case PROFILE_MESSAGE_SPECIAL : return "Special"; + case PROFILE_MESSAGE_BEEPONCE : return "Beep once"; + case PROFILE_MESSAGE_ASCENDING : return "Ascending"; + default : return "Unknown"; + } +} + +char *GetProfileWarningToneString(int code) { + + switch (code) { + case PROFILE_WARNING_OFF : return "Off"; + case PROFILE_WARNING_ON : return "On"; + default : return "Unknown"; + } +} + +char *GetProfileOnOffString(int code) { + + switch (code) { + case 0x00 : return "Off"; + case 0x01 : return "On"; + default : return "Unknown"; + } +} + +static char *GetProfileVibrationString(int code) +{ + switch (code) { + case PROFILE_VIBRATION_OFF: return "Off"; + case PROFILE_VIBRATION_ON: return "On"; + case PROFILE_VIBRATION_FIRST: return "Vibrate first"; + default: return "Unknown"; + } +} + +char BufferProfileGroups[90]; + +char *GetProfileCallerGroups(int code) +{ + static char az_group_name[5][MAX_BITMAP_TEXT_LENGTH]; + static bool enteronce=false; + register int i; + GSM_Bitmap bitmap; + + if( code == PROFILE_CALLERGROUPS_ALL ) + return _("All calls alert"); + + if( !enteronce ) { + for(i=0;i<5;i++) az_group_name[i][0]='\0'; + enteronce=true; + } + + BufferProfileGroups[0]=0; + + for(i=0;i<5;i++) + { + int code2test; + char z_gtype[12]; + + code2test=(i==0) ? 1 : 2<<(i-1); + + if( code & code2test ) + { + if (!strcmp(az_group_name[i],"")) + { + if (GetModelFeature (FN_CALLERGROUPS)!=0) { + bitmap.type=GSM_CallerLogo; + bitmap.number=i; + strcpy(z_gtype,_("unknown")); + if (GSM->GetBitmap(&bitmap)==GE_NONE) + strcpy( az_group_name[i], bitmap.text ); + } + if ((!strcmp(az_group_name[i],""))) { + switch(i) { + case 0:strcpy(az_group_name[i],_("Family"));break; + case 1:strcpy(az_group_name[i],_("VIP"));break; + case 2:strcpy(az_group_name[i],_("Friends"));break; + case 3:strcpy(az_group_name[i],_("Colleagues"));break; + case 4:strcpy(az_group_name[i],_("Other"));break; + default:break; + } + } + } + strcpy(z_gtype,az_group_name[i]); + + if( strlen(BufferProfileGroups) ) strcat(BufferProfileGroups,"+"); + strcat(BufferProfileGroups, z_gtype); + } + + } + + return BufferProfileGroups; +} + +char *print_error(GSM_Error e) +{ + +// case GE_DEVICEOPENFAILED: return "Couldn't open specified serial device."; +// case GE_UNKNOWNMODEL: return "Model specified isn't known/supported."; +// case GE_NOLINK: return "Couldn't establish link with phone."; +// case GE_TRYAGAIN: return "Try again."; +// case GE_INVALIDSMSLOCATION: return "Invalid SMS location."; +// case GE_INVALIDPHBOOKLOCATION: return "Invalid phonebook location."; +// case GE_INVALIDMEMORYTYPE: return "Invalid type of memory."; +// case GE_INVALIDSPEEDDIALLOCATION: return "Invalid speed dial location."; +// case GE_INVALIDCALNOTELOCATION: return "Invalid calendar note location."; +// case GE_INVALIDDATETIME: return "Invalid date, time or alarm specification."; +// case GE_EMPTYSMSLOCATION: return "SMS location is empty."; +// case GE_PHBOOKNAMETOOLONG: return "Phonebook name is too long."; +// case GE_PHBOOKNUMBERTOOLONG: return "Phonebook number is too long."; +// case GE_PHBOOKWRITEFAILED: return "Phonebook write failed."; +// case GE_SMSSENDOK: return "SMS was send correctly."; +// case GE_SMSSENDFAILED: return "SMS send fail."; +// case GE_SMSTOOLONG: return "SMS message too long."; +// case GE_NONEWCBRECEIVED: return "Attempt to read CB when no new CB received"; +// case GE_INTERNALERROR: return "Problem occured internal to model specific code."; +// case GE_NOTSUPPORTED: return "Function not supported by the phone"; +// case GE_BUSY: return "Command is still being executed."; +// case GE_USERCANCELED: return "User has cancelled the action."; +// case GE_UNKNOWN: return "Unknown error - well better than nothing!!"; +// case GE_MEMORYFULL: return "Memory is full"; +// case GE_LINEBUSY: return "Outgoing call requested reported line busy"; +// case GE_NOCARRIER: return "No Carrier error during data call setup ?"; + + switch (e) { + case GE_NONE: return "No error, done OK"; + case GE_INVALIDSECURITYCODE: return "Invalid Security code."; + case GE_NOTIMPLEMENTED: return "Called command is not implemented for the used model. Please contact marcin-wiacek@topnet.pl, if you want to help in implementing it"; + case GE_TIMEOUT: return "Command timed out."; + case GE_CANTOPENFILE: return "Can't open file with bitmap/ringtone"; + case GE_SUBFORMATNOTSUPPORTED: return "Subformat of file not supported"; + case GE_WRONGNUMBEROFCOLORS: return "Wrong number of colors in specified bitmap file (only 2 colors files supported)"; + case GE_WRONGCOLORS: return "Wrong colors in bitmap file"; + case GE_INVALIDIMAGESIZE: return "Invalid size of bitmap (in file, sms etc.)"; + case GE_INVALIDFILEFORMAT: return "Invalid format of file"; + case GE_TOOSHORT: return "File too short"; + case GE_INSIDEBOOKMARKSMENU: return "Inside WAP Bookmarks menu. Please leave it and try again"; + case GE_INVALIDBOOKMARKLOCATION: return "Invalid or empty WAP bookmark location"; + case GE_INSIDESETTINGSMENU: return "Inside WAP Settings menu. Please leave it and try again"; + case GE_INVALIDSETTINGSLOCATION: return "Invalid or empty WAP settings location"; + default: return "Unknown error."; + } +} + + +GSM_Error GSM_ReadRingtoneFileOnConsole(char *FileName, GSM_Ringtone *ringtone) +{ + GSM_Error error; + + error=GSM_ReadRingtoneFile(FileName, ringtone); + + switch (error) { + case GE_CANTOPENFILE: + case GE_SUBFORMATNOTSUPPORTED: + fprintf(stderr, _("File \"%s\"\nError: %s\n"),FileName,print_error(error)); + break; + default: + break; + } + + return error; +} + +GSM_Error GSM_SaveRingtoneFileOnConsole(char *FileName, GSM_Ringtone *ringtone) +{ + int confirm,confirm2; + char ans[4]; + struct stat buf; + GSM_Error error; + + /* Ask before overwriting */ + while (stat(FileName, &buf) == 0) { + + confirm=-1; + confirm2=-1; + + while (confirm < 0) { + fprintf(stderr, _("Saving ringtone. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "),FileName); + GetLine(stdin, ans, 4); + if (!strcmp(ans, "O") || !strcmp(ans, "o")) confirm = 1; + if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm = 2; + if (!strcmp(ans, "S") || !strcmp(ans, "s")) return GE_USERCANCELED; + } + if (confirm==1) break; + if (confirm==2) { + while (confirm2 < 0) { + fprintf(stderr, _("Enter name of new file: ")); + GetLine(stdin, FileName, 50); + if (&FileName[0]==0) return GE_USERCANCELED; + confirm2=1; + } + } + } + + error=GSM_SaveRingtoneFile(FileName,ringtone); + + switch (error) { + case GE_CANTOPENFILE: fprintf(stderr, _("Failed to write file \"%s\"\n"),FileName); + break; + default: break; + } + + return error; +} + +GSM_Error GSM_ReadBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap) +{ + GSM_Error error; + + error=GSM_ReadBitmapFile(FileName, bitmap); + + switch (error) { + case GE_CANTOPENFILE: + case GE_WRONGNUMBEROFCOLORS: + case GE_WRONGCOLORS: + case GE_INVALIDFILEFORMAT: + case GE_SUBFORMATNOTSUPPORTED: + case GE_TOOSHORT: + case GE_INVALIDIMAGESIZE: + fprintf(stderr, _("File \"%s\"\nError: %s\n"),FileName,print_error(error)); + break; + default: + break; + } + + return error; +} + +GSM_Error GSM_SaveBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap) +{ + int confirm,confirm2; + char ans[4]; + struct stat buf; + GSM_Error error; + + /* Ask before overwriting */ + while (stat(FileName, &buf) == 0) { + + confirm=-1; + confirm2=-1; + + while (confirm < 0) { + fprintf(stderr, _("Saving logo. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "),FileName); + GetLine(stdin, ans, 4); + if (!strcmp(ans, "O") || !strcmp(ans, "o")) confirm = 1; + if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm = 2; + if (!strcmp(ans, "S") || !strcmp(ans, "s")) return GE_USERCANCELED; + } + if (confirm==1) break; + if (confirm==2) { + while (confirm2 < 0) { + fprintf(stderr, _("Enter name of new file: ")); + GetLine(stdin, FileName, 50); + if (&FileName[0]==0) return GE_USERCANCELED; + confirm2=1; + } + } + } + + error=GSM_SaveBitmapFile(FileName,bitmap); + + switch (error) { + case GE_CANTOPENFILE: fprintf(stderr, _("Failed to write file \"%s\"\n"),FileName); + break; + default: break; + } + + return error; +} + +/* mode == 0 -> overwrite + * mode == 1 -> ask + * mode == 2 -> append + */ +int GSM_SaveTextFileOnConsole(char *FileName, char *text, int mode) +{ + int confirm, confirm2; + char ans[4]; + struct stat buf; + int error; + + /* Ask before overwriting */ + if (mode==1) { + while (stat(FileName, &buf) == 0 && mode==1) { + + confirm=-1; + confirm2=-1; + + while (confirm < 0) { + fprintf(stderr, _("File \"%s\" exists. (O)verwrite, (a)ppend, create (n)ew or (s)kip ? "),FileName); + GetLine(stdin, ans, 4); + if (!strcmp(ans, "O") || !strcmp(ans, "o")) { + mode = 0; + confirm = 1; + } + if (!strcmp(ans, "A") || !strcmp(ans, "a")) { + mode = 2; + confirm = 1; + } + if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm=2; + if (!strcmp(ans, "S") || !strcmp(ans, "s")) return -1; + } + + if (confirm==2) { + while (confirm2 < 0) { + fprintf(stderr, _("Enter name of new file: ")); + GetLine(stdin, FileName, 50); + if (&FileName[0]==0) return -1; + mode=1; + confirm2=1; + } + } + + } + } + + error=GSM_SaveTextFile(FileName, text, mode); + + switch (error) { + case -1: fprintf(stderr, _("Failed to write file \"%s\"\n"), FileName); + break; + default: break; + } + + return error; +} + +int GSM_SendMultiPartSMSOnConsole(GSM_MultiSMSMessage *MultiSMS, int argnum, int argc, char *argv[], + bool unicode, bool profile, bool scale) { + + int w,i; + + struct option options[] = { + { "smscno", required_argument, NULL, '1'}, + { "smsc", required_argument, NULL, '2'}, + { "name", required_argument, NULL, '3'}, + { "unicode", no_argument, NULL, '4'}, + { "profilestyle", no_argument, NULL, '5'}, + { "scale", no_argument, NULL, '6'}, + { NULL, 0, NULL, 0 } + }; + + GSM_Error error; + + for (w=0;wnumber;w++) { + + if (argnum!=0) { + optarg = NULL; + + /* We check optional parameters from ... */ + optind = argnum; + + while ((i = getopt_long(argc, argv, "v:ds", options, NULL)) != -1) { + switch (i) { + + case '1': /* SMSC number */ + MultiSMS->SMS[w].MessageCenter.No = 0; + strcpy(MultiSMS->SMS[w].MessageCenter.Number,optarg); + break; + + case '2': /* SMSC number index in phone memory */ + MultiSMS->SMS[w].MessageCenter.No = atoi(optarg); + + if (MultiSMS->SMS[w].MessageCenter.No < 1 || MultiSMS->SMS[w].MessageCenter.No > 5) { + fprintf(stderr, _("Incorrect SMSC number with \"smscno\" option (can't be <1 and >5) !\n")); + GSM->Terminate(); + return -1; + } + break; + + case '3': /* Receiver/recipient */ + strncpy(MultiSMS->SMS[w].Destination,optarg,11); break; + + case '4': /* Unicode */ + if (unicode) break; + + case '5': /* Profile */ + if (profile) break; + + case '6': /* Scale */ + if (scale) break; + + case 'v': /* Set validaty of SMS */ + MultiSMS->SMS[w].Validity = atoi(optarg); + break; + + case 'd': /* delivery report */ + MultiSMS->SMS[w].Type=GST_DR; + break; + + case 's': /* Set replying via the same SMSC */ + MultiSMS->SMS[w].ReplyViaSameSMSC = true; break; + + default: + fprintf(stderr,_("Unknown option number %i\n"),argc); + GSM->Terminate(); + return -1; + + } + } + } + + error=GSM->SendSMSMessage(&MultiSMS->SMS[w]); + + if (error == GE_SMSSENDOK) { + fprintf(stdout, _("SMS %i/%i sent OK !\n"),w+1,MultiSMS->number); + } else { + fprintf(stdout, _("SMS %i/%i, sending failed (error=%d)\n"),w+1,MultiSMS->number, error); + } + + } + + GSM->Terminate(); + + return 0; +} + +int GSM_SaveMultiPartSMSOnConsole(GSM_MultiSMSMessage *MultiSMS, int argnum, int argc, char *argv[], + bool inter, bool unicode, bool profile, bool scale) { + + int w,i; + + GSM_SMSMessage SMSold; + + struct option options[] = { + { "smscno", required_argument, NULL, '1'}, + { "smsc", required_argument, NULL, '2'}, + { "name", required_argument, NULL, '3'}, + { "unicode", no_argument, NULL, '4'}, + { "profilestyle", no_argument, NULL, '5'}, + { "scale", no_argument, NULL, '6'}, + { NULL, 0, NULL, 0 } + }; + + int interactive; + int confirm = -1; + char ans[8]; + + GSM_Error error; + + interactive = inter; + + for (w=0;wnumber;w++) { + + if (argnum!=0) { + optarg = NULL; + + /* We check optional parameters from ... */ + optind = argnum; + + while ((i = getopt_long(argc, argv, "risal:", options, NULL)) != -1) { + switch (i) { + + case '1': /* SMSC number */ + MultiSMS->SMS[w].MessageCenter.No = 0; + strcpy(MultiSMS->SMS[w].MessageCenter.Number,optarg); + break; + + case '2': /* SMSC number index in phone memory */ + MultiSMS->SMS[w].MessageCenter.No = atoi(optarg); + + if (MultiSMS->SMS[w].MessageCenter.No < 1 || MultiSMS->SMS[w].MessageCenter.No > 5) { + fprintf(stderr, _("Incorrect SMSC number with \"smscno\" option (can't be <1 and >5) !\n")); + GSM->Terminate(); + return -1; + } + break; + + case '3': /* Receiver/recipient */ + strncpy(MultiSMS->SMS[w].Destination,optarg,11); break; + + case '4': /* Unicode */ + if (unicode) break; + + case '5': /* Profile */ + if (profile) break; + + case '6': /* Scale */ + if (scale) break; + + case 'r': /* mark as read */ + MultiSMS->SMS[w].Status = GSS_SENTREAD; break; + + case 'i': /* Save into Inbox */ + MultiSMS->SMS[w].folder = GST_INBOX; break; + + case 's': /* Set replying via the same SMSC */ + MultiSMS->SMS[w].ReplyViaSameSMSC = true; break; + + case 'a': /* Ask before overwriting */ + interactive=true;break; + + case 'l': /* Specify location */ + MultiSMS->SMS[0].Location = atoi(optarg); break; + + default: + fprintf(stderr,_("Unknown option number %i\n"),argc); + GSM->Terminate(); + return -1; + } + } + } + + if (interactive && MultiSMS->SMS[0].Location!=0 && w==0) { + SMSold.Location=MultiSMS->SMS[0].Location; + error = GSM->GetSMSMessage(&SMSold); + switch (error) { + case GE_NONE: + fprintf(stderr, _("Message at specified location exists. ")); + while (confirm < 0) { + fprintf(stderr, _("Overwrite? (yes/no) ")); + GetLine(stdin, ans, 7); + if (!strcmp(ans, "yes")) confirm = 1; + if (!strcmp(ans, "no")) confirm = 0; + } + if (!confirm) { GSM->Terminate(); return 0; } + else break; + case GE_INVALIDSMSLOCATION: + fprintf(stderr, _("Invalid location\n")); + GSM->Terminate(); + return -1; + default: +/* FIXME: Remove this fprintf when the function is thoroughly tested */ +#ifdef DEBUG + fprintf(stderr, _("Location %d empty. Saving\n"), SMS[w].Location); +#endif + break; + } + } + + error=GSM->SaveSMSMessage(&MultiSMS->SMS[w]); + + if (error == GE_NONE) + fprintf(stdout, _("SMS %i/%i saved at location %i !\n"),w+1,MultiSMS->number,MultiSMS->SMS[w].MessageNumber); + else + fprintf(stdout, _("SMS %i/%i saving failed (error=%d, location=%i)\n"), w+1, MultiSMS->number, error,MultiSMS->SMS[w].Location); + } + + GSM->Terminate(); + + return 0; +} + +void GSM_PlayRingtoneOnConsole(GSM_Ringtone *ringtone) +{ + int i; +#ifdef VC6 + char mychar; +#endif + + for (i=0;iNrNotes;i++) { +#ifdef VC6 + if (_kbhit()) { + mychar=_getch(); + break; + } +#endif + GSM_PlayOneNote (ringtone->notes[i]); + } + GSM->PlayTone(255*255,0); +} + +/* This function shows the copyright and some informations usefull for + debugging. */ +int version(void) +{ + + fprintf(stdout, _("GNOKII Version %s\n" +"Copyright (C) Hugh Blemings , 1999, 2000\n" +"Copyright (C) Pavel Janík ml. , 1999, 2000\n" +"Built %s %s for %s on %s \n"), VERSION, __TIME__, __DATE__, model, Port); + + return 0; +} + +/* The function usage is only informative - it prints this program's usage and + command-line options. */ + +int usage(void) +{ + + fprintf(stdout, _(" usage: gnokii [--help|--monitor [-noloop|-nl]|--version]\n" +" gnokii --getmemory memory_type [start [end]] [-short|-v30|-v21|-v]\n" +" gnokii --writephonebook [-i]\n" +" gnokii --sendphonebookentry destination memory_type location\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-s] [-v n] [-d]\n" +" gnokii --savephonebookentry memory_type location\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-r] [-i] [-s] [-a] [--name name]\n" +" gnokii --getvoicemailbox\n" +" gnokii --getspeeddial number\n" +" gnokii --setspeeddial number memory_type location\n\n" + +" gnokii --getsms memory_type start [end] [-f file]\n" +" gnokii --getsmsstatus\n" +" gnokii --getsmsfolders\n" +" gnokii --deletesms memory_type start [end]\n" +" gnokii --sendsms destination [--smsc message_center_number |\n" +" --smscno message_center_index] [--long n] [-s] [-C n]\n" +" [--enablevoice|--disablevoice|--enablefax|--disablefax|\n" +" --enableemail|--disableemail|--void][--unicode][-v n][-d]\n" +" gnokii --savesms destination|\"\" [--smsc \n" +" message_center_number] [--smscno message_center_index]\n" +" [--long n] [-r] [-i] [-s][-C n][-a][-l][F n][--smsname name]\n" +" [--enablevoice|--disablevoice|--enablefax|--disablefax|\n" +" --enableemail|--disableemail|--void|--hang|--bug][--unicode]\n" +" gnokii --receivesms\n" +" gnokii --getsmsc message_center_number\n" +" gnokii --renamesmsc number new_name\n\n" + +" gnokii --setdatetime [YYYY [MM [DD [HH [MM]]]]]\n" +" gnokii --getdatetime\n" +" gnokii --setalarm HH MM\n" +" gnokii --getalarm\n\n" + +" gnokii --getcalendarnote { start end [-v30|-v10] | --short|-s }\n" +" gnokii --writecalendarnote vcardfile number\n" +" gnokii --deletecalendarnote index\n" +" gnokii --sendcalendarnote destination vcardfile number\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-s] [-v n] [-d]\n" +" gnokii --savecalendarnote vcardfile number\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-r] [-i] [-s] [-a] [--name name]\n\n" + +" gnokii --netmonitor {reset|off|field|devel|next|nr}\n" +" gnokii --nm_collect screen1|-d [screen2|-d]...\n" +" gnokii --netmonitordata [-S file] [-I file] [-h] [-n n] [-ts n][-tm n]\n" +" [-fs str] [-ls str] FLD1:FLD2:FLDn:... \n" +" (see files netmonitordata_????_??? for details)\n\n" + +" gnokii --bitmapconvert source destination\n" +" gnokii --bitmapconvert source destination op|7110op [network code]\n" +" gnokii --bitmapconvert source destination caller [caller group number]\n" +" gnokii --bitmapconvert source destination\n" +" startup|7110startup|6210startup\n" +" gnokii --bitmapconvert source destination picture\n" +" gnokii --showbitmap logofile\n" +" gnokii --sendlogo op destination logofile network_code\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-s] [-v n] [-d]\n" +" gnokii --sendlogo picture destination logofile text\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-s] [-v n] [-d] [--unicode]\n" +" gnokii --sendlogo screensaver destination logofile\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-s] [-v n] [-d]\n" +" gnokii --sendlogo caller destination logofile\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-s] [-v n] [-d]\n" +" gnokii --savelogo op logofile network_code\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-r] [-i] [-s] [-a] [-l] [--name name]\n" +" gnokii --savelogo picture logofile text\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-r] [-i] [-s] [-a] [-l] [--name name] [--unicode]\n" +" gnokii --savelogo screensaver logofile\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-r] [-i] [-s] [-a] [-l] [--name name]\n" +" gnokii --savelogo caller logofile\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-r] [-i] [-s] [-a] [-l] [--name name]\n" +" gnokii --setlogo op|7110op [logofile] [network code]\n" +" gnokii --setlogo startup|7110startup|6210startup [logofile]\n" +" gnokii --setlogo startup 1|2|3\n" +" gnokii --setlogo caller [logofile] [caller group number] [group name]\n" +" gnokii --setlogo picture [logofile] [number] [text] [sender]\n" +" gnokii --setlogo {dealer|text} [text]\n" +" gnokii --getlogo op|7110op [logofile] [network code]\n" +" gnokii --getlogo startup|7110startup|6210startup [logofile]\n" +" gnokii --getlogo caller [logofile][caller group number]\n" +" gnokii --getlogo picture [logofile][number]\n" +" gnokii --getlogo {dealer|text}\n\n" + +" gnokii --sendringtone destination ringtonefile\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-s] [-v n] [-d] [--scale] [--profilestyle]\n" +" gnokii --saveringtone ringtonefile\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-r] [-i] [-s] [-a] [--name name] [--scale] [--profilestyle]\n" +" gnokii --setringtone ringtonefile [location]\n" +" gnokii --getringtone ringtonefile [location]\n" +" gnokii --ringtoneconvert source destination\n" +" gnokii --binringtoneconvert source destination\n" +" gnokii --playringtone ringtonefile\n" +" gnokii --composer ringtonefile\n" +" gnokii --allringtones\n\n" + +" gnokii --getprofile [number]\n" +" gnokii --setprofile number feature value\n" +" gnokii --sendprofile destination profile_name ringtonefile\n" +" picturefile [--smsc message_center_number]\n" +" [--smscno message_center_index] [-s] [-v n] [-d] [--scale]\n\n" + +" gnokii --reset [soft|hard]\n" +" gnokii --dialvoice number\n" +" gnokii --cancelcall\n" +" gnokii --displayoutput\n" +" gnokii --presskeysequence sequence\n" +" gnokii --backupsettings file\n" +" gnokii --restoresettings file\n" +" gnokii --getphoneprofile\n" +" gnokii --setphoneprofile feature value\n" +" gnokii --getoperatorname\n" +" gnokii --setoperatorname code name\n" +" gnokii --senddtmf string\n" +" gnokii --divert register|enable|query|disable|erasure\n" +" all|busy|noans|outofreach all|voice|fax|data\n" +" [number timeout]\n\n" + +" gnokii --phonetests\n" +" gnokii --simlock\n" +" gnokii --getdisplaystatus\n" +" gnokii --identify\n\n" + +" gnokii --getwapbookmark location\n" +" gnokii --setwapbookmark title url [location]\n" +" gnokii --sendwapbookmark location destination\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-s] [-v n] [-d]\n" +" gnokii --savewapbookmark location\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-r] [-i] [-s] [-a] [-l] [--name name]\n" +" gnokii --getwapsettings location\n" +" gnokii --savewapsettings location\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-r] [-i] [-s] [-a] [-l] [--name name]\n" +" gnokii --sendwapsettings location destination\n" +" [--smsc message_center_number] [--smscno message_center_index]\n" +" [-s] [-v n] [-d]\n" + )); + +#ifdef SECURITY + fprintf(stdout, _( +"\n gnokii --entersecuritycode PIN|PIN2|PUK|PUK2\n" +" gnokii --getsecuritycodestatus\n" +" gnokii --getsecuritycode PIN|PIN2|PUK|PUK2|SecurityCode\n" +" gnokii --geteeprom\n" +" gnokii --resetphonesettings\n" + )); +#endif + +#ifdef DEBUG + fprintf(stdout, _( +" gnokii --sniff [port]\n" +" gnokii --decodefile file\n" +" gnokii --getbinringfromfile file name offset file2\n" + )); +#endif + + return 0; +} + +/* fbusinit is the generic function which waits for the FBUS link. The limit + is 10 seconds. After 10 seconds we quit. */ + +void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame)) +{ + + int count=0; + GSM_Error error; + +#ifndef WIN32 + if (strcmp(GetMygnokiiVersion(),VERSION)!=0) + fprintf(stderr,_("WARNING: version of installed libmygnokii.so (%s) is different to version of gnokii (%s)\n"),GetMygnokiiVersion(),VERSION); +#endif + + /* Initialise the code for the GSM interface. */ + error = GSM_Initialise(model, Port, Initlength, GetConnectionTypeFromString(Connection), rlp_handler, SynchronizeTime); + + if (error != GE_NONE) { + fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n")); + exit(-1); + } + + /* First (and important!) wait for GSM link to be active. We allow 10 + seconds... */ + while (count++ < 200 && *GSM_LinkOK == false) + usleep(50000); + + if (*GSM_LinkOK == false) { + fprintf (stderr, _("Hmmm... GSM_LinkOK never went true. Quitting.\n")); + exit(-1); + } +} + +/* This function checks that the argument count for a given options is withing + an allowed range. */ + +int checkargs(int opt, struct gnokii_arg_len gals[], int argc) +{ + + int i; + + /* Walk through the whole array with options requiring arguments. */ + + for(i = 0;!(gals[i].gal_min == 0 && gals[i].gal_max == 0); i++) { + + /* Current option. */ + + if(gals[i].gal_opt == opt) { + + /* Argument count checking. */ + + if(gals[i].gal_flags == GAL_XOR) { + if(gals[i].gal_min == argc || gals[i].gal_max == argc) return 0; + } + else { + if(gals[i].gal_min <= argc && gals[i].gal_max >= argc) return 0; + } + + return 1; + + } + + } + + /* We do not have options without arguments in the array, so check them. */ + + if (argc==0) return 0; + else return 1; +} + +/* Main function - handles command line arguments, passes them to separate + functions accordingly. */ + +int main(int argc, char *argv[]) +{ + + int c, i, rc = -1; + int nargc = argc-2; + char **nargv; + + /* Every option should be in this array. */ + + static struct option long_options[] = + { + + { "help", no_argument, NULL, OPT_HELP },// Display usage. + { "version", no_argument, NULL, OPT_VERSION },// Display version and build information. + { "getsmsfolders", no_argument, NULL, OPT_GETSMSFOLDERS },// Gets SMS folders + { "getsmsstatus", no_argument, NULL, OPT_GETSMSSTATUS },// Get SMS Folder Status + { "identify", no_argument, NULL, OPT_IDENTIFY },// Identify + { "pmon", no_argument, NULL, OPT_PMON },// For development purposes: run in passive monitoring mode + { "foogle", no_argument, NULL, OPT_FOOGLE },// For development purposes: insert you function calls here + { "getdatetime", no_argument, NULL, OPT_GETDATETIME },// Get date and time mode + { "getalarm", no_argument, NULL, OPT_GETALARM },// Get alarm + { "cancelcall", no_argument, NULL, OPT_CANCELCALL },// Cancel Call + { "getdisplaystatus", no_argument, NULL, OPT_GETDISPLAYSTATUS },// Get display status mode + { "allringtones", no_argument, NULL, OPT_ALLRINGTONES },/* Displays names of available ringtones */ + { "displayoutput", no_argument, NULL, OPT_DISPLAYOUTPUT },/* Show texts from phone's display */ + { "getphoneprofile", no_argument, NULL, OPT_GETPHONEPROFILE },/* Get/Set phone profile settings */ + { "getoperatorname", no_argument, NULL, OPT_GETOPERATORNAME },/* Get downloaded operator name */ + { "getvoicemailbox", no_argument, NULL, OPT_GETVOICEMAILBOX },/* Gets voice mailbox number */ + { "phonetests", no_argument, NULL, OPT_PHONETESTS }, + { "simlockinfo", no_argument, NULL, OPT_SIMLOCKINFO }, + { "receivesms", no_argument, NULL, OPT_RECEIVESMS }, + { "setoperatorname", optional_argument, NULL, OPT_SETOPERATORNAME },/* Set downloaded operator name */ + { "setdatetime", optional_argument, NULL, OPT_SETDATETIME },// Set date and time + { "writephonebook", optional_argument, NULL, OPT_WRITEPHONEBOOK },// Write phonebook (memory) mode + { "reset", optional_argument, NULL, OPT_RESET },// Resets the phone + { "monitor", optional_argument, NULL, OPT_MONITOR },// Monitor mode + { "setlogo", optional_argument, NULL, OPT_SETLOGO },// Set logo + { "getprofile", optional_argument, NULL, OPT_GETPROFILE },// Show profile + { "setalarm", required_argument, NULL, OPT_SETALARM },// Set alarm + { "dialvoice", required_argument, NULL, OPT_DIALVOICE },// Voice call mode + { "getcalendarnote", required_argument, NULL, OPT_GETCALENDARNOTE },// Get calendar note mode + { "writecalendarnote", required_argument, NULL, OPT_WRITECALENDARNOTE},// Write calendar note mode + { "sendcalendarnote", required_argument, NULL, OPT_SENDCALENDARNOTE }, + { "savecalendarnote", required_argument, NULL, OPT_SAVECALENDARNOTE }, + { "sendphonebookentry", required_argument, NULL, OPT_SENDPHONEBOOKENTRY}, + { "savephonebookentry", required_argument, NULL, OPT_SAVEPHONEBOOKENTRY}, + { "deletecalendarnote", required_argument, NULL, OPT_DELCALENDARNOTE },// Delete calendar note mode + { "getmemory", required_argument, NULL, OPT_GETMEMORY },// Get memory mode + { "getspeeddial", required_argument, NULL, OPT_GETSPEEDDIAL },// Get speed dial mode + { "setspeeddial", required_argument, NULL, OPT_SETSPEEDDIAL },// Set speed dial mode + { "getsms", required_argument, NULL, OPT_GETSMS },// Get SMS message mode + { "deletesms", required_argument, NULL, OPT_DELETESMS },// Delete SMS message mode + { "sendsms", required_argument, NULL, OPT_SENDSMS },// Send SMS message mode + { "savesms", required_argument, NULL, OPT_SAVESMS },// Save SMS message mode + { "sendlogo", required_argument, NULL, OPT_SENDLOGO },// Send logo as SMS message mode + { "savelogo", required_argument, NULL, OPT_SAVELOGO },// Save logo on SIM + { "sendringtone", required_argument, NULL, OPT_SENDRINGTONE },// Send ringtone as SMS message + { "saveringtone", required_argument, NULL, OPT_SAVERINGTONE },// Saves ringtone on SIM + { "setringtone", required_argument, NULL, OPT_SETRINGTONE },// Set ringtone + { "getringtone", required_argument, NULL, OPT_GETRINGTONE },// Get bin/normal ringtone + { "presskeysequence", required_argument, NULL, OPT_PRESSKEYSEQUENCE },/* Presses keys in phone's display */ + { "getsmsc", required_argument, NULL, OPT_GETSMSC },// Get SMS center number mode + { "renamesmsc", required_argument, NULL, OPT_RENAMESMSC },// Rename SMSC + { "netmonitor", required_argument, NULL, OPT_NETMONITOR },// NetMonitor mode + { "senddtmf", required_argument, NULL, OPT_SENDDTMF },// Send DTMF sequence + { "getlogo", required_argument, NULL, OPT_GETLOGO },// Get logo + { "setprofile", required_argument, NULL, OPT_SETPROFILE },// Set profile feature + { "sendprofile", required_argument, NULL, OPT_SENDPROFILE },// Send profile via SMS + { "setphoneprofile", required_argument, NULL, OPT_SETPHONEPROFILE },/* Get/Set phone profile settings */ + { "restoresettings", required_argument, NULL, OPT_RESTORESETTINGS },//Restore various settings from one file + { "backupsettings", required_argument, NULL, OPT_BACKUPSETTINGS },//Backup various settings to one file + { "playringtone", required_argument, NULL, OPT_PLAYRINGTONE },/* Plays ringtones */ + { "composer", required_argument, NULL, OPT_COMPOSER },/* Shows ringtone like in Nokia Composer */ + { "ringtoneconvert", required_argument, NULL, OPT_RINGTONECONVERT },/* Convert ringtone files */ + { "binringtoneconvert", required_argument, NULL, OPT_BINRINGTONECONVERT},/* Convert binary ringtone files */ + { "bitmapconvert", required_argument, NULL, OPT_BITMAPCONVERT },/* Convert bitmap files */ + { "showbitmap", required_argument, NULL, OPT_SHOWBITMAP }, + { "nm_collect", required_argument, NULL, OPT_NM_COLLECT },// NetMonitor periodical data collection mode (newbiee) + { "netmonitordata", required_argument, NULL, OPT_NETMONITORDATA },// NetMonitor periodical data collection mode (advanced) + { "getwapbookmark", required_argument, NULL, OPT_GETWAPBOOKMARK }, + { "setwapbookmark", required_argument, NULL, OPT_SETWAPBOOKMARK }, + { "savewapbookmark", required_argument, NULL, OPT_SAVEWAPBOOKMARK }, + { "savewapsettings", required_argument, NULL, OPT_SAVEWAPSETTINGS }, + { "sendwapsettings", required_argument, NULL, OPT_SENDWAPSETTINGS }, + { "sendwapbookmark", required_argument, NULL, OPT_SENDWAPBOOKMARK }, + { "getwapsettings", required_argument, NULL, OPT_GETWAPSETTINGS }, + { "divert", required_argument, NULL, OPT_DIVERT }, + +#ifdef SECURITY + { "entersecuritycode", required_argument, NULL, OPT_ENTERSECURITYCODE },// Enter Security Code mode + { "getsecuritycode", required_argument, NULL, OPT_GETSECURITYCODE },// Get Security Code + { "getsecuritycodestatus",no_argument, NULL, OPT_GETSECURITYCODESTATUS},// Get Security Code status + { "geteeprom", no_argument, NULL, OPT_GETEEPROM },// Gets EEPROM + { "resetphonesettings", no_argument, NULL, OPT_RESETPHONESETTINGS },// Reset phone settings + { "setsimlock", no_argument, NULL, OPT_SETSIMLOCK },// Sets simlock +#endif + +#ifdef DEBUG + { "sniff", optional_argument, NULL, OPT_SNIFFER },// Will show datas from port + { "decodefile", required_argument, NULL, OPT_DECODEFILE },//decode input file + { "getbinringfromfile", required_argument, NULL, OPT_GETBINRINGFROMFILE }, +#endif + + { 0, 0, 0, 0}, + }; + + /* Every command which requires arguments should have an appropriate entry + in this array. */ + + struct gnokii_arg_len gals[] = + { + + { OPT_MONITOR, 0, 1, 0 }, + +#ifdef SECURITY + { OPT_ENTERSECURITYCODE, 1, 1, 0 }, + { OPT_GETSECURITYCODE, 1, 1, 0 }, +#endif + +#ifdef DEBUG + { OPT_SNIFFER, 0, 1, 0 }, + { OPT_DECODEFILE, 1, 1, 0 }, + { OPT_GETBINRINGFROMFILE,4, 4, 0 }, +#endif + + { OPT_SETDATETIME, 0, 5, 0 }, + { OPT_BACKUPSETTINGS, 1, 1, 0 }, + { OPT_RESTORESETTINGS, 1, 1, 0 }, + { OPT_SETALARM, 2, 2, 0 }, + { OPT_DIALVOICE, 1, 1, 0 }, + { OPT_GETCALENDARNOTE, 1, 3, 0 }, + { OPT_WRITECALENDARNOTE, 2, 2, 0 }, + { OPT_SAVECALENDARNOTE, 2, 9, 0 }, + { OPT_SENDCALENDARNOTE, 3, 9, 0 }, + { OPT_SAVEPHONEBOOKENTRY,2, 9, 0 }, + { OPT_SENDPHONEBOOKENTRY,3, 9, 0 }, + { OPT_DELCALENDARNOTE, 1, 1, 0 }, + { OPT_GETMEMORY, 2, 4, 0 }, + { OPT_GETSPEEDDIAL, 1, 1, 0 }, + { OPT_SETSPEEDDIAL, 3, 3, 0 }, + { OPT_GETSMS, 2, 5, 0 }, + { OPT_DELETESMS, 2, 3, 0 }, + { OPT_SENDSMS, 1,10, 0 }, + { OPT_SAVESMS, 1,11, 0 }, + { OPT_SENDLOGO, 3, 9, 0 }, + { OPT_SAVELOGO, 2,10, 0 }, + { OPT_SENDRINGTONE, 2, 7, 0 }, + { OPT_SAVERINGTONE, 1, 9, 0 }, + { OPT_GETSMSC, 1, 1, 0 }, + { OPT_RENAMESMSC, 2, 2, 0 }, + { OPT_NETMONITOR, 1, 1, 0 }, + { OPT_SENDDTMF, 1, 1, 0 }, + { OPT_SETLOGO, 1, 5, 0 }, + { OPT_GETLOGO, 1, 4, 0 }, + { OPT_SETRINGTONE, 1, 3, 0 }, + { OPT_GETRINGTONE, 1, 2, 0 }, + { OPT_PRESSKEYSEQUENCE, 1, 1, 0 }, + { OPT_RESET, 0, 1, 0 }, + { OPT_GETPROFILE, 0, 1, 0 }, + { OPT_SETPROFILE, 3, 3, 0 }, + { OPT_SENDPROFILE, 4,10, 0 }, + { OPT_WRITEPHONEBOOK, 0, 1, 0 }, + { OPT_PLAYRINGTONE, 1, 1, 0 }, + { OPT_COMPOSER, 1, 1, 0 }, + { OPT_RINGTONECONVERT, 2, 2, 0 }, + { OPT_BINRINGTONECONVERT,2, 2, 0 }, + { OPT_BITMAPCONVERT, 2, 4, 0 }, + { OPT_SHOWBITMAP, 1, 1, 0 }, + { OPT_SETOPERATORNAME, 0, 2, 0 }, + { OPT_SETPHONEPROFILE, 2, 2, 0 }, + { OPT_NM_COLLECT, 1, MAX_NM_COLLECT, 0 }, + { OPT_NETMONITORDATA, 0,99, 0 }, + { OPT_GETWAPBOOKMARK, 1, 1, 0 }, + { OPT_SETWAPBOOKMARK, 2, 3, 0 }, + { OPT_SAVEWAPBOOKMARK, 1, 9, 0 }, + { OPT_SENDWAPBOOKMARK, 2, 9, 0 }, + { OPT_GETWAPSETTINGS, 1, 1, 0 }, + { OPT_SAVEWAPSETTINGS, 1, 9, 0 }, + { OPT_SENDWAPSETTINGS, 2, 9, 0 }, + { OPT_DIVERT, 3, 5, 0 }, + + { 0, 0, 0, 0 }, + }; + + opterr = 0; + + /* For GNU gettext */ + +#ifdef USE_NLS +#ifndef VC6 + textdomain("gnokii"); + setlocale(LC_ALL, "pl_PL"); //here is string for Polish localisation +#else + setlocale(LC_ALL, ".852"); //Polish codepage for console, not "real" WIN CP +#endif + +#endif + + /* Read config file */ + if (CFG_ReadConfig(&model, &Port, &Initlength, &Connection, &BinDir, &SynchronizeTime,false) < 0) { + exit(-1); + } + + /* Handle command line arguments. */ + + c = getopt_long(argc, argv, "", long_options, NULL); + + if (c == -1) { + + /* No argument given - we should display usage. */ + usage(); + exit(-1); + } + + /* We have to build an array of the arguments which will be passed to the + functions. Please note that every text after the --command will be + passed as arguments. A syntax like gnokii --cmd1 args --cmd2 args will + not work as expected; instead args --cmd2 args is passed as a + parameter. */ + + if((nargv = malloc(sizeof(char *) * argc)) != NULL) { + + for(i = 2; i < argc; i++) + nargv[i-2] = argv[i]; + + if(checkargs(c, gals, nargc)) { + + free(nargv); + + /* Wrong number of arguments - we should display usage. */ + usage(); + exit(-1); + } + +#ifndef VC6 +#if defined(__svr4__) + /* have to ignore SIGALARM */ + sigignore(SIGALRM); +#endif +#endif + + switch(c) { + + // First, error conditions + case '?': + fprintf(stderr, _("Use '%s --help' for usage informations.\n"), argv[0]); + break; + + // Then, options with no arguments + case OPT_HELP: rc = usage(); break; + case OPT_VERSION: rc = version(); break; + case OPT_MONITOR: rc = monitormode(nargc, nargv); break; + case OPT_GETSMSFOLDERS: rc = getsmsfolders(); break; + case OPT_GETDATETIME: rc = getdatetime(); break; + case OPT_GETALARM: rc = getalarm(); break; + case OPT_GETDISPLAYSTATUS: rc = getdisplaystatus(); break; + case OPT_PMON: rc = pmon(); break; + case OPT_WRITEPHONEBOOK: rc = writephonebook(nargc, nargv);break; + +#ifdef SECURITY + case OPT_ENTERSECURITYCODE: rc = entersecuritycode(optarg); break; + case OPT_GETSECURITYCODESTATUS: rc = getsecuritycodestatus(); break; + case OPT_GETSECURITYCODE: rc = getsecuritycode(optarg); break; + case OPT_GETEEPROM: rc = geteeprom(); break; + case OPT_RESETPHONESETTINGS: rc = resetphonesettings(); break; + case OPT_SETSIMLOCK: rc = setsimlock(); break; +#endif + +#ifdef DEBUG + case OPT_SNIFFER: rc = sniff(nargc, nargv); break; + case OPT_DECODEFILE: rc = decodefile(nargc, nargv); break; + case OPT_GETBINRINGFROMFILE: rc = getbinringfromfile(nargc, nargv);break; +#endif + + // Now, options with arguments + case OPT_SETDATETIME: rc = setdatetime(nargc, nargv); break; + case OPT_SETALARM: rc = setalarm(nargv); break; + case OPT_DIALVOICE: rc = dialvoice(optarg); break; + case OPT_CANCELCALL: rc = cancelcall(); break; + case OPT_GETCALENDARNOTE: rc = getcalendarnote(nargc, nargv);break; + case OPT_DELCALENDARNOTE: rc = deletecalendarnote(optarg);break; + case OPT_SAVECALENDARNOTE: rc = savecalendarnote(nargc, nargv);break; + case OPT_SENDCALENDARNOTE: rc = sendcalendarnote(nargc, nargv);break; + case OPT_SAVEPHONEBOOKENTRY: rc = savephonebookentry(nargc, nargv);break; + case OPT_SENDPHONEBOOKENTRY: rc = sendphonebookentry(nargc, nargv);break; + case OPT_WRITECALENDARNOTE: rc = writecalendarnote(nargv); break; + case OPT_GETMEMORY: rc = getmemory(nargc, nargv); break; + case OPT_GETSPEEDDIAL: rc = getspeeddial(optarg); break; + case OPT_SETSPEEDDIAL: rc = setspeeddial(nargv); break; + case OPT_GETSMS: rc = getsms(argc, argv); break; + case OPT_GETSMSSTATUS: rc = getsmsstatus(argc, argv); break; + case OPT_DELETESMS: rc = deletesms(nargc, nargv); break; + case OPT_SENDSMS: rc = sendsms(nargc, nargv); break; + case OPT_SAVESMS: rc = savesms(nargc, nargv); break; + case OPT_DIVERT: rc = divert(nargc, nargv); break; + case OPT_SENDLOGO: rc = sendlogo(nargc, nargv); break; + case OPT_SAVELOGO: rc = savelogo(nargc, nargv); break; + case OPT_GETSMSC: rc = getsmsc(optarg); break; + case OPT_RENAMESMSC: rc = renamesmsc(nargc,nargv); break; + case OPT_NETMONITOR: rc = netmonitor(optarg); break; + case OPT_IDENTIFY: rc = identify(); break; + case OPT_SETLOGO: rc = setlogo(nargc, nargv); break; + case OPT_GETLOGO: rc = getlogo(nargc, nargv); break; + case OPT_RECEIVESMS: rc = receivesms(nargc, nargv); break; + case OPT_SETRINGTONE: rc = setringtone(nargc, nargv); break; + case OPT_GETRINGTONE: rc = getringtone(nargc, nargv); break; + case OPT_PRESSKEYSEQUENCE: rc = presskeysequence(nargv); break; + case OPT_SENDRINGTONE: rc = sendringtone(nargc, nargv);break; + case OPT_SAVERINGTONE: rc = saveringtone(nargc, nargv);break; + case OPT_GETPROFILE: rc = getprofile(nargc, nargv); break; + case OPT_SETPROFILE: rc = setprofile(nargc, nargv); break; + case OPT_SENDPROFILE: rc = sendprofile(nargc, nargv); break; + case OPT_DISPLAYOUTPUT: rc = displayoutput(); break; + case OPT_RESTORESETTINGS: rc = restoresettings(nargv); break; + case OPT_BACKUPSETTINGS: rc = backupsettings(nargv); break; + case OPT_RINGTONECONVERT: rc = ringtoneconvert(nargc, nargv);break; + case OPT_BINRINGTONECONVERT: rc = binringtoneconvert(nargc, nargv);break; + case OPT_BITMAPCONVERT: rc = bitmapconvert(nargc, nargv);break; + case OPT_SHOWBITMAP: rc = showbitmap(nargc, nargv); break; + case OPT_PLAYRINGTONE: rc = playringtone(nargc, nargv);break; + case OPT_COMPOSER: rc = composer(nargc, nargv); break; + case OPT_FOOGLE: rc = foogle(nargv); break; + case OPT_PHONETESTS: rc = phonetests(); break; + case OPT_SIMLOCKINFO: rc = simlockinfo(); break; + case OPT_SENDDTMF: rc = senddtmf(optarg); break; + case OPT_RESET: rc = reset(nargc,nargv); break; + case OPT_GETOPERATORNAME: rc = getoperatorname(); break; + case OPT_SETOPERATORNAME: rc = setoperatorname(nargc,nargv);break; + case OPT_GETWAPBOOKMARK: rc = getwapbookmark(nargc,nargv);break; + case OPT_SETWAPBOOKMARK: rc = setwapbookmark(nargc,nargv);break; + case OPT_SAVEWAPBOOKMARK: rc = savewapbookmark(nargc,nargv);break; + case OPT_SENDWAPBOOKMARK: rc = sendwapbookmark(nargc,nargv);break; + case OPT_GETWAPSETTINGS: rc = getwapsettings(nargc,nargv);break; + case OPT_SAVEWAPSETTINGS: rc = savewapsettings(nargc,nargv);break; + case OPT_SENDWAPSETTINGS: rc = sendwapsettings(nargc,nargv);break; + case OPT_ALLRINGTONES: rc = allringtones(); break; + case OPT_GETPHONEPROFILE: rc = getphoneprofile(); break; + case OPT_SETPHONEPROFILE: rc = setphoneprofile(nargc,nargv);break; + case OPT_GETVOICEMAILBOX: rc = getvoicemailbox(); break; + case OPT_NM_COLLECT: rc = nm_collect(nargc, nargv); break; + case OPT_NETMONITORDATA: rc = netmonitordata(nargc, nargv);break; + + default: fprintf(stderr, _("Unknown option: %d\n"), c); break; + + } + + free(nargv); + + return(rc); + } + + fprintf(stderr, _("Wrong number of arguments\n")); + + exit(-1); +} + +/* Restores various phone settings from one file */ +int restoresettings(char *argv[]) +{ + GSM_Backup Backup; + GSM_PhonebookEntry pbk; + + int confirm; + char ans[4]; + + int i,pos; + + GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0}; + GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0}; + + if (GSM_ReadBackupFile(argv[0], &Backup)!=GE_NONE) return 1; + + fbusinit(NULL); + + if (Backup.SIMPhonebookUsed!=0) { + confirm=-1; + while (confirm < 0) { + fprintf(stderr, _("Restore SIM phonebook ? ")); + GetLine(stdin, ans, 99); + if (!strcmp(ans, "yes")) confirm = 1; + if (!strcmp(ans, "no" )) confirm = 0; + } + if (confirm==1) { + if (GSM->GetMemoryStatus(&SIMMemoryStatus) != GE_NONE) { + fprintf(stderr,_("Error getting memory status !\n")); + GSM->Terminate(); + } + i=0;pos=1; + + while ((pos-1)!=SIMMemoryStatus.Used+SIMMemoryStatus.Free) { + pbk.Location=pos; + pbk.MemoryType=GMT_SM; + pbk.Name[0]=0; + pbk.Number[0]=0; + pbk.SubEntriesCount = 0; + if (iWritePhonebookLocation(&pbk); + fprintf(stderr,_(".")); + pos++; + } + fprintf(stderr,_("\n")); + } + } + if (Backup.PhonePhonebookUsed!=0) { + confirm=-1; + while (confirm < 0) { + fprintf(stderr, _("Restore phone phonebook ? ")); + GetLine(stdin, ans, 99); + if (!strcmp(ans, "yes")) confirm = 1; + if (!strcmp(ans, "no" )) confirm = 0; + } + if (confirm==1) { + if (GSM->GetMemoryStatus(&PhoneMemoryStatus) != GE_NONE) { + fprintf(stderr,_("Error getting memory status !\n")); + GSM->Terminate(); + } + + i=0;pos=1; + + while ((pos-1)!=PhoneMemoryStatus.Used+PhoneMemoryStatus.Free) { + pbk.Location=pos; + pbk.MemoryType=GMT_ME; + pbk.Name[0]=0; + pbk.Number[0]=0; + pbk.SubEntriesCount = 0; + if (iWritePhonebookLocation(&pbk); + fprintf(stderr,_(".")); + pos++; + } + fprintf(stderr,_("\n")); + } + } + if (Backup.CallerAvailable==true) { + confirm=-1; + while (confirm < 0) { + fprintf(stderr, _("Restore caller groups ? ")); + GetLine(stdin, ans, 99); + if (!strcmp(ans, "yes")) confirm = 1; + if (!strcmp(ans, "no" )) confirm = 0; + } + if (confirm==1) { + for (i=0;i<5;i++) GSM->SetBitmap(&Backup.CallerGroups[i]); + } + } + if (Backup.OperatorLogoAvailable==true) { + confirm=-1; + while (confirm < 0) { + fprintf(stderr, _("Restore operator logo ? ")); + GetLine(stdin, ans, 99); + if (!strcmp(ans, "yes")) confirm = 1; + if (!strcmp(ans, "no" )) confirm = 0; + } + if (confirm==1) { + GSM->SetBitmap(&Backup.OperatorLogo); + } + } + if (Backup.StartupLogoAvailable==true) { + confirm=-1; + while (confirm < 0) { + fprintf(stderr, _("Restore startup logo ? ")); + GetLine(stdin, ans, 99); + if (!strcmp(ans, "yes")) confirm = 1; + if (!strcmp(ans, "no" )) confirm = 0; + } + if (confirm==1) { + GSM->SetBitmap(&Backup.StartupLogo); + } + } + + GSM->Terminate(); + + return 0; +} + +/* Backup various phone settings from one file */ +int backupsettings(char *argv[]) +{ + GSM_PhonebookEntry PbkEntry; + GSM_Error error; + GSM_Backup Backup; + int i; + + GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0}; + GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0}; + + fbusinit(NULL); + + fprintf(stderr,_("Backup phonebook from SIM...")); + Backup.SIMPhonebookUsed=0; + if (GSM->GetMemoryStatus(&SIMMemoryStatus) == GE_NONE) { + Backup.SIMPhonebookSize=SIMMemoryStatus.Used+SIMMemoryStatus.Free; + + PbkEntry.MemoryType=GMT_SM; + + for (i=0;iGetMemoryLocation(&PbkEntry); + switch (error) { + case GE_NONE: + Backup.SIMPhonebook[Backup.SIMPhonebookUsed]=PbkEntry; + Backup.SIMPhonebookUsed++; + fprintf(stderr,_(".")); + break; + default: + break; + } + } + fprintf(stderr,_("Done\n")); + } else fprintf(stderr,_("ERROR\n")); + + fprintf(stderr,_("Backup phonebook from phone...")); + Backup.PhonePhonebookUsed=0; + if (GSM->GetMemoryStatus(&PhoneMemoryStatus) == GE_NONE) { + Backup.PhonePhonebookSize=PhoneMemoryStatus.Used+PhoneMemoryStatus.Free; + + PbkEntry.MemoryType=GMT_ME; + + for (i=0;iGetMemoryLocation(&PbkEntry); + switch (error) { + case GE_NONE: + Backup.PhonePhonebook[Backup.PhonePhonebookUsed]=PbkEntry; + Backup.PhonePhonebookUsed++; + fprintf(stderr,_(".")); + break; + default: + break; + } + } + fprintf(stderr,_("Done\n")); + } else fprintf(stderr,_("ERROR\n")); + + if( GetModelFeature (FN_CALLERGROUPS)!=0) { + fprintf(stderr,_("Backup caller logos...")); + Backup.CallerAvailable=true; + for (i=0;i<5;i++) { + Backup.CallerGroups[i].number=i; + Backup.CallerGroups[i].type=GSM_CallerLogo; + if (GSM->GetBitmap(&Backup.CallerGroups[i])!=GE_NONE) return 1; + } + fprintf(stderr,_("Done\n")); + } else Backup.CallerAvailable=false; + +// fprintf(stderr,_("Backup speed dials...")); + Backup.SpeedAvailable=false; +// for (i=0;i<8;i++) { +// Backup.SpeedDials[i].Number=i+1; +// if (GSM->GetSpeedDial(&Backup.SpeedDials[i])!=GE_NONE) return 1; +// } +// fprintf(stderr,_("Done\n")); + + fprintf(stderr,_("Backup operator logo...")); + Backup.OperatorLogoAvailable=true; + Backup.OperatorLogo.type=GSM_7110OperatorLogo; + if (GSM->GetBitmap(&Backup.OperatorLogo)!=GE_NONE) { + Backup.OperatorLogo.type=GSM_OperatorLogo; + if (GSM->GetBitmap(&Backup.OperatorLogo)!=GE_NONE) { + Backup.OperatorLogoAvailable=false; + fprintf(stderr,_("Error\n")); + } else fprintf(stderr,_("Done\n")); + } else fprintf(stderr,_("Done\n")); + + Backup.StartupLogoAvailable=false; + if( GetModelFeature (FN_STARTUP)!=0) { + fprintf(stderr,_("Backup startup logo...")); + Backup.StartupLogoAvailable=true; + switch (GetModelFeature (FN_STARTUP)) { + case F_STA62: Backup.StartupLogo.type=GSM_6210StartupLogo;break; + case F_STA71: Backup.StartupLogo.type=GSM_7110StartupLogo;break; + default : Backup.StartupLogo.type=GSM_StartupLogo;break; + } + if (GSM->GetBitmap(&Backup.StartupLogo)!=GE_NONE) { + Backup.StartupLogoAvailable=false; + fprintf(stderr,_("Error\n")); + } else fprintf(stderr,_("Done\n")); + } + + fprintf(stderr,_("Backup welcome note...")); + Backup.StartupText.type=GSM_WelcomeNoteText; + if (GSM->GetBitmap(&Backup.StartupText)!=GE_NONE) { + fprintf(stderr,_("Error\n")); + } else fprintf(stderr,_("Done\n")); + + GSM->Terminate(); + + GSM_SaveBackupFile(argv[0], &Backup); + + return 0; +} + +/* Presses keys on phone's keyboard */ + +int presskeysequence(char *argv[]) +{ + int i,j; + int keycode; + char key; + + sleep(1); + + fbusinit(NULL); + + for (i=0;iTerminate(); + return -1; + } + + if (GSM->PressKey(keycode,PRESSPHONEKEY)!=GE_NONE) + { + fprintf(stderr,_("Can't press key !\n")); + GSM->Terminate(); + return -1; + } + if (GSM->PressKey(keycode,RELEASEPHONEKEY)!=GE_NONE) + { + fprintf(stderr,_("Can't release key !\n")); + GSM->Terminate(); + return -1; + } + } else + { + sleep(2); + } + } + + GSM->Terminate(); + + return 0; +} + +/* Send SMS messages. */ +int sendsms(int argc, char *argv[]) +{ + GSM_MultiSMSMessage MultiSMS; + char message_buffer[GSM_MAX_CONCATENATED_SMS_LENGTH]; + int input_len, chars_read,i,msgnum; + + GSM_SMSMessageType SMSType=GST_SMS; + int SMSValidity= 4320; /* 4320 minutes == 72 hours */ + bool SMSReply=false; + int SMSClass=-1,SMSCenter=1; + char SMSCNumber[100]; + GSM_Coding_Type SMSCoding=GSM_Coding_Default; + GSM_UDH SMSUDHType=GSM_NoUDH; + + struct option options[] = { + { "smscno", required_argument, NULL, '1'}, + { "smsc", required_argument, NULL, '2'}, + { "long", required_argument, NULL, '3'}, + { "enablevoice", no_argument, NULL, '4'}, + { "disablevoice", no_argument, NULL, '5'}, + { "enableemail", no_argument, NULL, '6'}, + { "disableemail", no_argument, NULL, '7'}, + { "enablefax", no_argument, NULL, '8'}, + { "disablefax", no_argument, NULL, '9'}, + { "unicode", no_argument, NULL, '-'}, + { "void", no_argument, NULL, '+'}, + { "hang", no_argument, NULL, '('}, + { "bug", no_argument, NULL, ')'}, + { NULL, 0, NULL, 0} + }; + + input_len = GSM_MAX_SMS_LENGTH; + + if (argc!=0) { + + optarg = NULL; + optind = 0; + + while ((i = getopt_long(argc, argv, "v:dsC:", options, NULL)) != -1) { + switch (i) { + + case '1': /* SMSC number */ + SMSCenter = 0; + strcpy(SMSCNumber,optarg); + break; + + case '2': /* SMSC number index in phone memory */ + SMSCenter = atoi(optarg); + + if (SMSCenter < 1 || SMSCenter > 5) { + fprintf(stderr, _("Incorrect SMSC number with \"smscno\" option (can't be <1 and >5) !\n")); + GSM->Terminate(); + return -1; + } + break; + + case '3': /* we send long message */ + SMSUDHType=GSM_ConcatenatedMessages; + input_len = atoi(optarg); + if (input_len > GSM_MAX_CONCATENATED_SMS_LENGTH) { + fprintf(stderr, _("Input too long, max %i!\n"),GSM_MAX_CONCATENATED_SMS_LENGTH); + exit(-1); + } + break; + + case '4': /* SMS enables voice indicator */ + SMSUDHType=GSM_EnableVoice; break; + + case '5': /* SMS disables voice indicator */ + SMSUDHType=GSM_DisableVoice; break; + + case '6': /* SMS enables email indicator */ + SMSUDHType=GSM_EnableEmail; break; + + case '7': /* SMS disables email indicator */ + SMSUDHType=GSM_DisableEmail; break; + + case '8': /* SMS enables fax indicator */ + SMSUDHType=GSM_EnableFax; break; + + case '9': /* SMS disables fax indicator */ + SMSUDHType=GSM_DisableFax; break; + + case '-': /* SMS coding type */ + SMSCoding=GSM_Coding_Unicode; break; + + case '+': /* SMS ghost */ + SMSUDHType=GSM_VoidSMS; break; + + case '(': /* SMS hanging phone, when saved to Outbox */ + SMSUDHType=GSM_HangSMS; break; + + case ')': /* SMS showed incorrectly in phone */ + SMSUDHType=GSM_BugSMS; break; + + case 'v': /* Set validaty of SMS */ + SMSValidity = atoi(optarg); break; + + case 'd': /* delivery report */ + SMSType=GST_DR; break; + + case 's': /* Set replying via the same SMSC */ + SMSReply = true; break; + + case 'C': /* class Message */ + + if (SMSUDHType!=GSM_NoUDH) { + fprintf(stderr, _("Can't specify SMS Class with --enablevoice, --disablevoice, --enableemail, --disableemail, --enablefax, --disablefax options !\n")); + return -1; + } + + switch (*optarg) { + case '0': SMSClass = 0; break; + case '1': SMSClass = 1; break; + case '2': SMSClass = 2; break; + case '3': SMSClass = 3; break; + default: + fprintf(stderr, _("SMS Class (\"C\" option) can be 0, 1, 2 or 3 only !\n")); + return -1; + } + break; + + default: + fprintf(stderr,_("Unknown option number %i\n"),argc); + return -1; + } + } + } + + /* Get message text from stdin. */ + chars_read = fread(message_buffer, 1, input_len, stdin); + + if (chars_read == 0) { + fprintf(stderr, _("Couldn't read from stdin!\n")); + return -1; + } + if (chars_read > input_len) { + fprintf(stderr, _("Input too long!\n")); + return -1; + } + + /* Null terminate. */ + message_buffer[chars_read] = 0x00; + + GSM_MakeMultiPartSMS2(&MultiSMS,message_buffer,chars_read,SMSUDHType,SMSCoding); + msgnum=MultiSMS.number; + + switch (SMSUDHType) { + case GSM_NoUDH: + case GSM_BugSMS: + case GSM_VoidSMS: + case GSM_HangSMS: + case GSM_EnableVoice: + case GSM_DisableVoice: + case GSM_EnableFax: + case GSM_DisableFax: + case GSM_EnableEmail: + case GSM_DisableEmail: + fprintf(stdout,_("Warning: saving %i chars\n"),strlen(MultiSMS.SMS[0].MessageText)); + msgnum=1; + break; + default: + break; + } + + for (i=0;i 5) { + fprintf(stderr, _("Incorrect SMSC number with \"smscno\" option (can't be <1 and >5) !\n")); + GSM->Terminate(); + return -1; + } + break; + + case '3': /* we send long message */ + SMSUDHType=GSM_ConcatenatedMessages; + input_len = atoi(optarg); + if (input_len > GSM_MAX_CONCATENATED_SMS_LENGTH) { + fprintf(stderr, _("Input too long, max %i!\n"),GSM_MAX_CONCATENATED_SMS_LENGTH); + exit(-1); + } + break; + + case '4': /* SMS enables voice indicator */ + SMSUDHType=GSM_EnableVoice; break; + + case '5': /* SMS disables voice indicator */ + SMSUDHType=GSM_DisableVoice; break; + + case '6': /* SMS enables email indicator */ + SMSUDHType=GSM_EnableEmail; break; + + case '7': /* SMS disables email indicator */ + SMSUDHType=GSM_DisableEmail; break; + + case '8': /* SMS enables fax indicator */ + SMSUDHType=GSM_EnableFax; break; + + case '9': /* SMS disables fax indicator */ + SMSUDHType=GSM_DisableFax; break; + + case '-': /* SMS coding type */ + SMSCoding=GSM_Coding_Unicode; break; + + case '+': /* SMS ghost */ + SMSUDHType=GSM_VoidSMS; break; + + case '(': /* SMS hanging phone, when saved to Outbox */ + SMSUDHType=GSM_HangSMS; break; + + case ')': /* SMS showed incorrectly in phone */ + SMSUDHType=GSM_BugSMS; break; + + case 'r': /* mark as read */ + SMSStatus = GSS_SENTREAD; break; + + case 'i': /* Save into Inbox */ + SMSFolder = GST_INBOX; break; + + case 's': /* Set replying via the same SMSC */ + SMSReply = true; break; + + case 'a': /* Ask before overwriting */ + interactive=true;break; + + case 'l': /* Specify location */ + SMSLocation = atoi(optarg); break; + + case '/': /* Name */ + strncpy(SMSName,optarg,25);break; + + case 'C': /* class Message */ + + if (SMSUDHType!=GSM_NoUDH) { + fprintf(stderr, _("Can't specify SMS Class with --enablevoice, --disablevoice, --enableemail, --disableemail, --enablefax, --disablefax options !\n")); + return -1; + } + + switch (*optarg) { + case '0': SMSClass = 0; break; + case '1': SMSClass = 1; break; + case '2': SMSClass = 2; break; + case '3': SMSClass = 3; break; + default: + fprintf(stderr, _("SMS Class (\"C\" option) can be 0, 1, 2 or 3 only !\n")); + return -1; + } + break; + + case 'F': /* save into folder n */ + SMSFolder = atoi(optarg); + break; + + default: + fprintf(stderr,_("Unknown option number %i\n"),argc); + return -1; + } + } + } + + /* Get message text from stdin. */ + chars_read = fread(message_buffer, 1, input_len, stdin); + + if (chars_read == 0) { + fprintf(stderr, _("Couldn't read from stdin!\n")); + return -1; + } + if (chars_read > input_len) { + fprintf(stderr, _("Input too long!\n")); + return -1; + } + + /* Null terminate. */ + message_buffer[chars_read] = 0x00; + + GSM_MakeMultiPartSMS2(&MultiSMS,message_buffer,chars_read,SMSUDHType,SMSCoding); + msgnum=MultiSMS.number; + + switch (SMSUDHType) { + case GSM_NoUDH: + case GSM_BugSMS: + case GSM_VoidSMS: + case GSM_HangSMS: + case GSM_EnableVoice: + case GSM_DisableVoice: + case GSM_EnableFax: + case GSM_DisableFax: + case GSM_EnableEmail: + case GSM_DisableEmail: + fprintf(stdout,_("Warning: saving %i chars\n"),strlen(MultiSMS.SMS[0].MessageText)); + msgnum=1; + break; + default: + break; + } + + for (i=0;iGetSMSCenter(&MessageCenter) == GE_NONE) { + + fprintf(stdout, _("%d. SMS center ("),MessageCenter.No); + + if (!strcmp(MessageCenter.Name,"")) + fprintf(stdout,_("Set %d"),MessageCenter.No); + else fprintf(stdout,_("%s"),MessageCenter.Name); + + fprintf(stdout,_(") number is ")); + + if (!strcmp(MessageCenter.Number,"")) fprintf(stdout,_("not set\n")); + else fprintf(stdout,_("%s\n"),MessageCenter.Number); + + fprintf(stdout,_("Default recipient number is ")); + + if (!strcmp(MessageCenter.DefaultRecipient,"")) + fprintf(stdout,_("not set\n")); + else fprintf(stdout,_("%s\n"),MessageCenter.DefaultRecipient); + + fprintf(stdout, _("Messages sent as ")); + + switch (MessageCenter.Format) { + case GSMF_Text :fprintf(stdout, _("Text"));break; + case GSMF_Paging:fprintf(stdout, _("Paging"));break; + case GSMF_Fax :fprintf(stdout, _("Fax"));break; + case GSMF_Email : + case GSMF_UCI :fprintf(stdout, _("Email"));break; + case GSMF_ERMES :fprintf(stdout, _("ERMES"));break; + case GSMF_X400 :fprintf(stdout, _("X.400"));break; + default :fprintf(stdout, _("Unknown")); + } + + printf("\n"); + + fprintf(stdout, _("Message validity is ")); + + switch (MessageCenter.Validity) { + case GSMV_1_Hour :fprintf(stdout, _("1 hour"));break; + case GSMV_6_Hours :fprintf(stdout, _("6 hours"));break; + case GSMV_24_Hours:fprintf(stdout, _("24 hours"));break; + case GSMV_72_Hours:fprintf(stdout, _("72 hours"));break; + case GSMV_1_Week :fprintf(stdout, _("1 week"));break; + case GSMV_Max_Time:fprintf(stdout, _("Maximum time"));break; + default :fprintf(stdout, _("Unknown")); + } + + fprintf(stdout, "\n"); + + } + else + fprintf(stdout, _("SMS center can not be found :-(\n")); + + GSM->Terminate(); + + return 0; +} + +/* Get SMS messages. */ +int getsms(int argc, char *argv[]) +{ + + GSM_SMSMessage message; + GSM_WAPBookmark bookmark; + char memory_type_string[20]; + int start_message, end_message, count, mode = 1; + char filename[64]; + GSM_Error error; + GSM_Bitmap bitmap; + GSM_Ringtone ringtone; + GSM_SMSFolders folders; + + int confirm = -1, i; + char ans[8]; + + /* Handle command line args that set type, start and end locations. */ + if (!GetMemoryTypeID(argv[2], &message.MemoryType)) + { + fprintf(stderr, _("Unknown memory type %s!\n"), argv[2]); + return (-1); + } + GetMemoryTypeString(memory_type_string, &message.MemoryType); + + for (i=0;i<64;i++) filename[i]=0; + + start_message = atoi(argv[3]); + if (argc > 4) { + int i; + + /* [end] can be only argv[4] */ + if (argv[4][0] == '-') { end_message = start_message; } + else { end_message = atoi(argv[4]); } + + /* parse all options (beginning with '-' */ + while ((i = getopt(argc, argv, "f:")) != -1) { + switch (i) { + case 'f': + if (optarg) { +#ifdef DEBUG + fprintf(stderr, _("Saving into file \"%s\"\n"), optarg); +#endif /* DEBUG */ + strncpy(filename, optarg, 64); + if (strlen(optarg) > 63) { + fprintf(stderr, _("Filename too long - will be truncated to 63 characters.\n")); + filename[63] = 0; + } else { + filename[strlen(optarg)] = 0; + } + } else { + usage(); + exit(1); + } + break; + default: + usage(); + exit(1); + } + } + } else { + end_message = start_message; + } + + /* Initialise the code for the GSM interface. */ + + fbusinit(NULL); + + GSM->GetSMSFolders(&folders); + + + /* Now retrieve the requested entries. */ + + for (count = start_message; count <= end_message; count ++) { + + message.Location = count; + + error = GSM->GetSMSMessage(&message); + + switch (error) { + + case GE_NONE: + + switch (message.Type) { + + case GST_DR: + + /* RTH FIXME: Test that out ! */ + fprintf(stdout, _("%d. Delivery Report "), message.MessageNumber); + switch (message.Status) + { + case GSS_SENTREAD: + if (message.folder==0) fprintf(stdout, _("(read)\n")); //GST_INBOX + else fprintf(stdout, _("(sent)\n")); + break; + case GSS_NOTSENTREAD: + if (message.folder==0) fprintf(stdout, _("(unread)\n")); //GST_INBOX + else fprintf(stdout, _("(not sent)\n")); + break; + case GSS_UNKNOWN: + fprintf(stdout, _("(not known :-()\n")); + break; + case GSS_TEMPLATE: + fprintf(stdout, _("(template)\n")); + break; + default: + fprintf(stdout, _("(unknown: %d)\n"),message.Status); + break; + } + + fprintf(stdout, _("Sending date/time : %s %02d/%02d/%02d %d:%02d:%02d "), \ + DayOfWeek(message.Time.Year, message.Time.Month, message.Time.Day), \ + message.Time.Day, message.Time.Month, message.Time.Year, \ + message.Time.Hour, message.Time.Minute, message.Time.Second); + + if (message.Time.Timezone) { + if (message.Time.Timezone > 0) + fprintf(stdout,_("+%02d00"), message.Time.Timezone); + else + fprintf(stdout,_("%02d00"), message.Time.Timezone); + } + + fprintf(stdout, "\n"); + + fprintf(stdout, _("Response date/time: %s %02d/%02d/%02d %d:%02d:%02d "), \ + DayOfWeek(message.SMSCTime.Year, message.SMSCTime.Month, message.SMSCTime.Day), \ + message.SMSCTime.Day, message.SMSCTime.Month, message.SMSCTime.Year, \ + message.SMSCTime.Hour, message.SMSCTime.Minute, message.SMSCTime.Second); + + if (message.SMSCTime.Timezone) { + if (message.SMSCTime.Timezone > 0) + fprintf(stdout,_("+%02d00"),message.SMSCTime.Timezone); + else + fprintf(stdout,_("%02d00"),message.SMSCTime.Timezone); + } + + fprintf(stdout, "\n"); + + fprintf(stdout, _("Receiver: %s Msg Center: %s\n"), message.Sender, message.MessageCenter.Number); + fprintf(stdout, _("Text: %s\n\n"), message.MessageText); + + break; + + case GST_SMS: + fprintf(stdout, _("%d. %s Message "), message.MessageNumber, + folders.Folder[message.folder].Name); + + switch (message.Status) + { + case GSS_SENTREAD: + if (message.folder==0) fprintf(stdout, _("(read)\n")); //GST_INBOX + else fprintf(stdout, _("(sent)\n")); + break; + case GSS_NOTSENTREAD: + if (message.folder==0) fprintf(stdout, _("(unread)\n")); //GST_INBOX + else fprintf(stdout, _("(not sent)\n")); + break; + case GSS_UNKNOWN: + fprintf(stdout, _("(not known :-()\n")); + break; + case GSS_TEMPLATE: + fprintf(stdout, _("(template)\n")); + break; + default: + fprintf(stdout, _("(unknown: %d)\n"),message.Status); + break; + } + + /* RTH FIXME: date for other status ok ? */ + if (message.SMSData) { + + fprintf(stdout, _("Date/time: %s %02d/%02d/%02d %d:%02d:%02d "), \ + DayOfWeek(message.Time.Year, message.Time.Month, message.Time.Day), \ + message.Time.Day, message.Time.Month, message.Time.Year, \ + message.Time.Hour, message.Time.Minute, message.Time.Second); + + if (message.Time.Timezone) { + if (message.Time.Timezone > 0) + fprintf(stdout,_("+%02d00"),message.Time.Timezone); + else + fprintf(stdout,_("%02d00"),message.Time.Timezone); + } + + fprintf(stdout, "\n"); + + fprintf(stdout, _("Msg Center: %s "), message.MessageCenter.Number); + + if (message.ReplyViaSameSMSC) + fprintf(stdout, _("(centre set for reply) ")); + } + + if (strcmp(message.Sender,"")) { + if (message.folder==1) { //GST_OUTBOX + fprintf(stdout, _("Recipient: %s"),message.Sender); + } else { + fprintf(stdout, _("Sender: %s"),message.Sender); + } + } + + if (strcmp(message.Sender,"") || message.folder==0) + fprintf(stdout, "\n"); + + switch (message.UDHType) { + + case GSM_OpLogo: + + /* put bitmap into bitmap structure */ + switch (GSM_ReadBitmap(&message, &bitmap)) { + case GE_INVALIDIMAGESIZE: + fprintf(stdout,_("Image size not supported\n")); + break; + case GE_NONE: + fprintf(stdout, _("GSM operator logo for %s (%s) network.\n"), bitmap.netcode, GSM_GetNetworkName(bitmap.netcode)); + + GSM_PrintBitmap(&bitmap); + + if (filename[0]!=0) { + GSM_SaveBitmapFileOnConsole(filename, &bitmap); + } + + break; + default: + fprintf(stdout,_("Error reading image\n")); + break; + } + +#ifdef DEBUG + if (message.folder==0) { //GST_INBOX + if (!strcmp(message.Sender, "+998000005") && + !strcmp(message.MessageCenter.Number, "+886935074443") && + message.Time.Day==27 && + message.Time.Month==7 && + message.Time.Year==99 && + message.Time.Hour==0 && + message.Time.Minute==10 && + message.Time.Second==48) fprintf(stdout, _("Saved by Logo Express\n")); + + /* Is it changed in next versions ? Or what ? */ + if (!strcmp(message.Sender, "+998000002") || + !strcmp(message.Sender, "+998000003") || + !strcmp(message.Sender, "+998000004")) fprintf(stdout, _("Saved by Operator Logo Uploader by Thomas Kessler\n")); + } else { + if (!strcmp(message.Sender, "+8861234567890") && + !strcmp(message.MessageCenter.Number, "+886935074443")) fprintf(stdout, _("Saved by Logo Express\n")); + } + if (!strncmp(message.Sender, "OpLogo",6) && + strlen(message.Sender)==11) + fprintf(stdout, _("Saved by gnokii\n")); +#endif + + break; + + case GSM_WAPBookmarkUDH: + + /* put bookmark into bookmark structure */ + switch (GSM_ReadWAPBookmark(&message, &bookmark)) { + case GE_NONE: + fprintf(stdout, ("WAP Bookmark\n")); + + fprintf(stdout,_("Address: \"%s\"\n"),bookmark.address); + + if (bookmark.title[0]==0) + fprintf(stdout,_("Title: \"%s\"\n"),bookmark.address); + else + fprintf(stdout,_("Title: \"%s\"\n"),bookmark.title); + + break; + default: + fprintf(stdout,_("Error reading WAP Bookmark\n")); + break; + } + +#ifdef DEBUG + if (!strcmp(message.Sender, "WAPBookmark")) + fprintf(stdout, _("Saved by gnokii\n")); +#endif + + break; + + case GSM_CallerIDLogo: + + /* put bitmap into bitmap structure */ + switch (GSM_ReadBitmap(&message, &bitmap)) { + case GE_INVALIDIMAGESIZE: + fprintf(stdout,_("Image size not supported\n")); + break; + case GE_NONE: + fprintf(stdout, ("Caller Logo\n")); + + GSM_PrintBitmap(&bitmap); + + if (filename[0]!=0) { + GSM_SaveBitmapFileOnConsole(filename, &bitmap); + } + + break; + default: + fprintf(stdout,_("Error reading image\n")); + break; + } + +#ifdef DEBUG + if (message.folder==0) { //GST_INBOX + if (!strcmp(message.Sender, "+998000005") && + !strcmp(message.MessageCenter.Number, "+886935074443") && + message.Time.Day==27 && + message.Time.Month==7 && + message.Time.Year==99 && + message.Time.Hour==0 && + message.Time.Minute==10 && + message.Time.Second==48) fprintf(stdout, _("Saved by Logo Express\n")); + } else { + if (!strcmp(message.Sender, "+8861234567890") && + !strcmp(message.MessageCenter.Number, "+886935074443")) fprintf(stdout, _("Saved by Logo Express\n")); + } + if (!strcmp(message.Sender, "GroupLogo")) + fprintf(stdout, _("Saved by gnokii\n")); +#endif + + break; + + case GSM_ProfileUDH: + fprintf(stdout, ("Profile SMS, part %i/%i\n"),message.UDH[11],message.UDH[10]); + break; + + case GSM_WAPBookmarkUDHLong: + fprintf(stdout, ("WAP Bookmark, part %i/%i\n"),message.UDH[11],message.UDH[10]); + break; + + case GSM_WAPSettingsUDH: + fprintf(stdout, ("WAP Settings, part %i/%i\n"),message.UDH[11],message.UDH[10]); + break; + + case GSM_RingtoneUDH: + + /* put ringtone into ringtone structure */ + switch (GSM_ReadRingtone(&message, &ringtone)) { + case GE_NONE: + + fprintf(stdout, ("Ringtone \"%s\"\n"),ringtone.name); + + while (confirm < 0) { + fprintf(stderr, _("Do you want to play it ? (yes/no) ")); + GetLine(stdin, ans, 7); + if (!strcmp(ans, "yes")) confirm = 1; + if (!strcmp(ans, "no")) confirm = 0; + } + + if (confirm==1) GSM_PlayRingtoneOnConsole(&ringtone); + + if (filename[0]!=0) GSM_SaveRingtoneFileOnConsole(filename, &ringtone); + + break; + + default: + fprintf(stdout,_("Gnokii can't read this ringtone - there is probably error inside\n")); + break; + } + + break; + + case GSM_CalendarNoteUDH: + fprintf(stdout, ("Calendar note SMS, part %i/%i\n"),message.UDH[11],message.UDH[10]); + fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText); + if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode); + break; + + case GSM_ConcatenatedMessages: + fprintf(stdout, _("Linked (%d/%d)\nText:\n%s\n\n"),message.UDH[5],message.UDH[4], message.MessageText); + if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode); + break; + + case GSM_EnableVoice: + fprintf(stdout, _("Enables voice indicator\nText:\n%s\n\n"), message.MessageText); + if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode); + break; + + case GSM_DisableVoice: + fprintf(stdout, _("Disables voice indicator\nText:\n%s\n\n"), message.MessageText); + if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode); + break; + + case GSM_EnableFax: + fprintf(stdout, _("Enables fax indicator\nText:\n%s\n\n"), message.MessageText); + if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode); + break; + + case GSM_DisableFax: + fprintf(stdout, _("Disables fax indicator\nText:\n%s\n\n"), message.MessageText); + if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode); + break; + + case GSM_EnableEmail: + fprintf(stdout, _("Enables email indicator\nText:\n%s\n\n"), message.MessageText); + if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode); + break; + + case GSM_DisableEmail: + fprintf(stdout, _("Disables email indicator\nText:\n%s\n\n"), message.MessageText); + if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode); + break; + + case GSM_VoidSMS: + fprintf(stdout, _("Void SMS\nText:\n%s\n\n"), message.MessageText); + if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode); + break; + + case GSM_NoUDH: + if (message.Coding!=GSM_Coding_8bit) { + fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText); + if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode); + } else { + fprintf(stdout, _("Message cannot be displayed here\n")); // like in phone :-) + } + break; + + default: //GSM_UnknownUDH and other + fprintf(stderr, _("Unknown\n")); + } + + break; + + default: + fprintf(stdout,_("Unknown SMS type. Report it\n")); + break; + } + + break; + + case GE_NOTIMPLEMENTED: + + fprintf(stderr, _("Function not implemented in %s model!\n"), model); + GSM->Terminate(); + return -1; + + case GE_INVALIDSMSLOCATION: + + fprintf(stderr, _("Invalid location: %s %d\n"), memory_type_string, count); + + break; + + case GE_EMPTYSMSLOCATION: + + fprintf(stderr, _("SMS location %s %d empty.\n"), memory_type_string, count); + + break; + + case GE_NOACCESS: + + fprintf(stderr, _("No access to %s memory.\n"), memory_type_string); + + break; + + default: + + fprintf(stderr, _("GetSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error); + } + } + + GSM->Terminate(); + + return 0; +} + +int getsmsstatus(int argc, char *argv[]) +{ + GSM_SMSStatus SMSStatus; + GSM_SMSFolders folders; + GSM_Error error; + GSM_SMSMessage SMS; + + int i,j; + + /* Initialise the code for the GSM interface. */ + fbusinit(NULL); + + error = GSM->GetSMSStatus(&SMSStatus); + if (error!=GE_NONE) return error; + + fprintf(stdout, _("SMS Messages: UnRead %d, Number %d\n"),SMSStatus.UnRead, SMSStatus.Number); + + error=GSM->GetSMSFolders(&folders); + if (error!=GE_NONE) return error; + + /* For not 7110 compatible phones we have to read all SMS and prepare sms table */ + if( GetModelFeature (FN_SMS)!=F_SMS71 ) + { + i=1;j=0; + while (true) { + if (j==SMSStatus.Number) break; + SMS.Location=i; + if (GSM->GetSMSMessage(&SMS)==GE_NONE) { + SMSStatus.foldertable[j].smsnum=i; + + /* We set such folders ID like in 7110 compatible phones */ + if (SMS.Status==GSS_NOTSENTREAD && SMS.folder==0) //GST_INBOX + SMSStatus.foldertable[j].folder=0; + else { + switch (SMS.folder) { + case 0://GST_INBOX + SMSStatus.foldertable[j].folder=GST_7110_INBOX; + break; + case 1://GST_OUTBOX + SMSStatus.foldertable[j].folder=GST_7110_OUTBOX; + break; + } + } + j++; + } + i++; + } + } + + printf("0.Unread : "); + for(j=0; jTerminate(); + + return 0; +} + +/* Delete SMS messages. */ +int deletesms(int argc, char *argv[]) +{ + + GSM_SMSMessage message; + char memory_type_string[20]; + int start_message, end_message, count; + GSM_Error error; + + /* Handle command line args that set type, start and end locations. */ + if (!GetMemoryTypeID(argv[0], &message.MemoryType)) + { + fprintf(stderr, _("Unknown memory type %s!\n"), argv[0]); + return (-1); + } + GetMemoryTypeString(memory_type_string, &message.MemoryType); + + start_message = atoi (argv[1]); + if (argc > 2) end_message = atoi (argv[2]); + else end_message = start_message; + + /* Initialise the code for the GSM interface. */ + + fbusinit(NULL); + + /* Now delete the requested entries. */ + + for (count = start_message; count <= end_message; count ++) { + + message.Location = count; + + error = GSM->DeleteSMSMessage(&message); + + if (error == GE_NONE) + fprintf(stdout, _("Deleted SMS %s %d\n"), memory_type_string, count); + else { + if (error == GE_NOTIMPLEMENTED) { + fprintf(stderr, _("Function not implemented in %s model!\n"), model); + GSM->Terminate(); + return -1; + } + fprintf(stdout, _("DeleteSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error); + } + } + + GSM->Terminate(); + + return 0; +} + +static volatile bool bshutdown = false; + +/* SIGINT signal handler. */ + +static void interrupted(int sig) +{ + + signal(sig, SIG_IGN); + bshutdown = true; + +} + +#ifdef SECURITY + +/* In this mode we get the code from the keyboard and send it to the mobile + phone. */ + +int entersecuritycode(char *type) +{ + GSM_Error test; + GSM_SecurityCode SecurityCode; + + if (!strcmp(type,"PIN")) SecurityCode.Type=GSCT_Pin; + else if (!strcmp(type,"PUK")) SecurityCode.Type=GSCT_Puk; + else if (!strcmp(type,"PIN2"))SecurityCode.Type=GSCT_Pin2; + else if (!strcmp(type,"PUK2"))SecurityCode.Type=GSCT_Puk2; + + // FIXME: Entering of SecurityCode does not work :-( + // else if (!strcmp(type,"SecurityCode")) + // SecurityCode.Type=GSCT_SecurityCode; + + else { + fprintf(stdout, _("Wrong code in second parameter (allowed: PIN,PUK,PIN2,PUK2,SecurityCode)\n")); + return -1; + } + +#ifdef WIN32 + printf("Enter your code: "); + gets(SecurityCode.Code); +#else + strcpy(SecurityCode.Code,getpass(_("Enter your code: "))); +#endif + + fbusinit(NULL); + + test = GSM->EnterSecurityCode(SecurityCode); + if (test==GE_NONE) + fprintf(stdout,_("Code OK !\n")); + else + fprintf(stderr,_("%s\n"),print_error(test)); + + GSM->Terminate(); + + return 0; +} + +int getsecuritycodestatus(void) +{ + + int Status; + + fbusinit(NULL); + + if (GSM->GetSecurityCodeStatus(&Status) == GE_NONE) { + + fprintf(stdout, _("Security code status: ")); + + switch(Status) { + case GSCT_SecurityCode:fprintf(stdout, _("waiting for Security Code.\n"));break; + case GSCT_Pin: fprintf(stdout, _("waiting for PIN.\n")); break; + case GSCT_Pin2: fprintf(stdout, _("waiting for PIN2.\n")); break; + case GSCT_Puk: fprintf(stdout, _("waiting for PUK.\n")); break; + case GSCT_Puk2: fprintf(stdout, _("waiting for PUK2.\n")); break; + case GSCT_None: fprintf(stdout, _("nothing to enter.\n")); break; + default: fprintf(stdout, _("Unknown!\n")); + } + } + + GSM->Terminate(); + + return 0; +} + +int getsecuritycode(char *type) +{ + + GSM_SecurityCode SecurityCode; + GSM_Error error; + + if (!strcmp(type,"PIN")) SecurityCode.Type=GSCT_Pin; + else if (!strcmp(type,"PUK")) SecurityCode.Type=GSCT_Puk; + else if (!strcmp(type,"PIN2")) SecurityCode.Type=GSCT_Pin2; + else if (!strcmp(type,"PUK2")) SecurityCode.Type=GSCT_Puk2; + else if (!strcmp(type,"SecurityCode"))SecurityCode.Type=GSCT_SecurityCode; + else { + fprintf(stdout, _("Wrong code in second parameter (allowed: PIN,PUK,PIN2,PUK2,SecurityCode)\n")); + return -1; + } + + fbusinit(NULL); + + error=GSM->GetSecurityCode(&SecurityCode); + + switch (error) { + case GE_INVALIDSECURITYCODE: + fprintf(stdout, _("Error: getting ")); + switch (SecurityCode.Type) { + case GSCT_SecurityCode:fprintf(stdout, _("security code"));break; + case GSCT_Pin :fprintf(stdout, _("PIN"));break; + case GSCT_Pin2:fprintf(stdout, _("PIN2"));break; + case GSCT_Puk :fprintf(stdout, _("PUK"));break; + case GSCT_Puk2:fprintf(stdout, _("PUK2"));break; + default:break; + } + fprintf(stdout, _(" not allowed\n")); + break; + case GE_NONE: + switch (SecurityCode.Type) { + case GSCT_SecurityCode:fprintf(stdout, _("Security code"));break; + case GSCT_Pin :fprintf(stdout, _("PIN"));break; + case GSCT_Pin2:fprintf(stdout, _("PIN2"));break; + case GSCT_Puk :fprintf(stdout, _("PUK"));break; + case GSCT_Puk2:fprintf(stdout, _("PUK2"));break; + default:break; + } + fprintf(stdout, _(" is %s\n"),SecurityCode.Code); + break; + default: + fprintf(stderr, _("%s\n"),print_error(error)); + break; + } + + GSM->Terminate(); + + return 0; +} + +#endif + +/* Voice dialing mode. */ + +int dialvoice(char *Number) +{ + fbusinit(NULL); + + if (GSM->DialVoice(Number)!=GE_NONE) fprintf(stdout,_("Error!\n")); + + GSM->Terminate(); + + return 0; +} + +/* Cancel a call */ +int cancelcall(void) +{ + fbusinit(NULL); + + if (GSM->CancelCall()!=GE_NONE) fprintf(stdout,_("Error!\n")); + + GSM->Terminate(); + + return 0; +} + +int savelogo(int argc, char *argv[]) +{ + GSM_Bitmap bitmap; + GSM_NetworkInfo NetworkInfo; + GSM_MultiSMSMessage MultiSMS; + + /* Operator logos will be saved with this number */ + char oplogonumber[]={'O','p','L','o','g','o', + '0','0','0','0','0', /* MMC+MNC */ + '\0'}; + int i=0; + + bool UnicodeText=false; + + /* The first argument is the type of the logo. */ + if (!strcmp(argv[0], "op")) { + fprintf(stdout, _("Saving operator logo.\n")); + } else if (!strcmp(argv[0], "caller")) { + fprintf(stdout, _("Saving caller line identification logo.\n")); + } else if (!strcmp(argv[0], "startup")) { + fprintf(stderr, _("It isn't possible to save startup logo!\n")); + return (-1); + } else if (!strcmp(argv[0], "7110startup")) { + fprintf(stderr, _("It isn't possible to save startup logo!\n")); + return (-1); + } else if (!strcmp(argv[0], "6210startup")) { + fprintf(stderr, _("It isn't possible to save startup logo!\n")); + return (-1); + } else if (!strcmp(argv[0], "7110op")) { + fprintf(stderr, _("It isn't possible to save big operator logos!\n")); + return (-1); + } else if (!strcmp(argv[0], "picture")) { + fprintf(stderr, _("Saving picture image.\n")); + } else if (!strcmp(argv[0], "screensaver")) { + fprintf(stderr, _("Saving screen saver.\n")); + } else { + fprintf(stderr, _("You should specify what kind of logo to save!\n")); + return (-1); + } + + /* The second argument is the bitmap file. */ + if (GSM_ReadBitmapFileOnConsole(argv[1], &bitmap)!=GE_NONE) return -1; + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + /* We check optional parameters from 2'rd */ + optind = 2; + + if (!strcmp(argv[0], "op")) { + GSM_ResizeBitmap(&bitmap,GSM_CallerLogo); + + /* The third argument, if present, is the Network code of the operator. + * Network code is in this format: "xxx yy" */ + if (argc > 2) { + strcpy(bitmap.netcode, argv[2]); +#ifdef DEBUG + fprintf(stdout, _("Operator code: %s\n"), argv[2]); +#endif + if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown")) { + fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode); + GSM->Terminate(); + return -1; + } + optind++; + } else + { + if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7); + } + bitmap.type=GSM_OperatorLogo; + + /* Put bitmap into SMS structure */ + GSM_SaveBitmapToSMS(&MultiSMS,&bitmap,false,false); + + oplogonumber[6]=bitmap.netcode[0]; + oplogonumber[7]=bitmap.netcode[1]; + oplogonumber[8]=bitmap.netcode[2]; + oplogonumber[9]=bitmap.netcode[4]; + oplogonumber[10]=bitmap.netcode[5]; + for(i=0;i2) { + optind++; + if (strlen(argv[2])>121) { + fprintf(stdout,_("Sorry: length of text (parameter \"%s\") can be 121 chars or shorter only !\n"),argv[2]); + return -1; + } + strcpy(bitmap.text,argv[2]); + } + + /* Put bitmap into SMS structure */ + GSM_SaveBitmapToSMS(&MultiSMS,&bitmap,false,UnicodeText); + + for(i=0;i 3) { + strcpy(bitmap.netcode, argv[3]); +#ifdef DEBUG + fprintf(stdout, _("Operator code: %s\n"), argv[3]); +#endif + if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown")) { + fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode); + GSM->Terminate(); + return -1; + } + optind++; + } else + { + if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7); + } + bitmap.type=GSM_OperatorLogo; + } + if (!strcmp(argv[0], "caller")) { + GSM_ResizeBitmap(&bitmap,GSM_CallerLogo); + + bitmap.type=GSM_CallerLogo; + } + if (!strcmp(argv[0], "screensaver")) { + GSM_ResizeBitmap(&bitmap,GSM_PictureImage); + + bitmap.text[0]=0; + + for(i=0;i3) { + optind++; + if (strlen(argv[3])>121) { + fprintf(stdout,_("Sorry: length of text (parameter \"%s\") can be 121 chars or shorter only !\n"),argv[3]); + return -1; + } + strcpy(bitmap.text,argv[3]); + } + } + + /* Put bitmap into SMS structure */ + GSM_SaveBitmapToSMS(&MultiSMS,&bitmap,ScreenSaver,UnicodeText); + + /* The second argument is the destination, ie the phone number of recipient. */ + for(i=0;i9)) num=1; + bitmap.number=num; + } else + { + bitmap.number=1; + } + bitmap.number--; + bitmap.type=GSM_CallerLogo; + } + + if (!strcmp(argv[0],"picture")) { + /* There is a number missing in argument list. */ + if (argc==3) { + if (strlen(argv[2])==2) { + num=(argv[2][0]-'0')*10+(argv[2][1]-'0'); + } else { + num=argv[2][0]-'0'; + } + if (num<1) num=1; + bitmap.number=num; + } else + { + bitmap.number=1; + } + bitmap.number--; + bitmap.type=GSM_PictureImage; + } + + if (!strcmp(argv[0],"startup")) + bitmap.type=GSM_StartupLogo; + + if (!strcmp(argv[0],"7110startup")) + bitmap.type=GSM_7110StartupLogo; + + if (!strcmp(argv[0],"6210startup")) + bitmap.type=GSM_6210StartupLogo; + + if (!strcmp(argv[0],"dealer")) + bitmap.type=GSM_DealerNoteText; + + if (!strcmp(argv[0],"text")) + bitmap.type=GSM_WelcomeNoteText; + + if (bitmap.type!=GSM_None) { + + fbusinit(NULL); + + fprintf(stdout, _("Getting Logo\n")); + + error=GSM->GetBitmap(&bitmap); + + GSM->Terminate(); + + switch (error) + { + case GE_NONE: + if (bitmap.type==GSM_DealerNoteText) fprintf(stdout, _("Dealer welcome note ")); + if (bitmap.type==GSM_WelcomeNoteText) fprintf(stdout, _("Welcome note ")); + if (bitmap.type==GSM_DealerNoteText || bitmap.type==GSM_WelcomeNoteText) + { + if (bitmap.text[0]!=0) + { + fprintf(stdout, _("currently set to \"%s\"\n"), bitmap.text); + } else { + fprintf(stdout, _("currently empty\n")); + } + } else + { + if (bitmap.width!=0) + { + if (bitmap.type==GSM_OperatorLogo || bitmap.type==GSM_7110OperatorLogo) + { + fprintf(stdout,"Operator logo for %s (%s) network got succesfully\n",bitmap.netcode,GSM_GetNetworkName(bitmap.netcode)); + } + if (bitmap.type==GSM_StartupLogo || bitmap.type==GSM_7110StartupLogo || bitmap.type==GSM_6210StartupLogo) + { + fprintf(stdout,"Startup logo got successfully\n"); + } + if (bitmap.type==GSM_CallerLogo) + { + fprintf(stdout,"Caller logo got successfully\n"); + } + if (bitmap.type==GSM_PictureImage) + { + fprintf(stdout,"Picture Image got successfully"); + if (strcmp(bitmap.text,"")) + fprintf(stdout,_(", text \"%s\""),bitmap.text); + if (strcmp(bitmap.Sender,"")) + fprintf(stdout,_(", sender \"%s\""),bitmap.Sender); + fprintf(stdout,"\n"); + } + if (argc>1) + { + if (GSM_SaveBitmapFileOnConsole(argv[1], &bitmap)!=GE_NONE) return(-1); + } + } else + { + fprintf(stdout,"Your phone doesn't have logo uploaded !\n"); + return -1; + } + } + break; + case GE_NOTIMPLEMENTED: + fprintf(stderr, _("Function not implemented !\n")); + return -1; + case GE_NOTSUPPORTED: + fprintf(stderr, _("This kind of logo is not supported !\n")); + return -1; + default: + fprintf(stderr, _("Error getting logo (wrong location ?) !\n")); + return -1; + } + } else + { + fprintf(stderr, _("What kind of logo do you want to get ?\n")); + return -1; + } + + return 0; +} + +/* Setting logos. */ + +int setlogo(int argc, char *argv[]) +{ + + GSM_Bitmap bitmap,oldbit; + GSM_NetworkInfo NetworkInfo; + GSM_Error error; + char model[64]; + int num; + + bool ok=true; + + int i; + + fbusinit(NULL); + + if (!strcmp(argv[0],"text") || !strcmp(argv[0],"dealer")) + { + if (!strcmp(argv[0],"text")) bitmap.type=GSM_WelcomeNoteText; + else bitmap.type=GSM_DealerNoteText; + bitmap.text[0]=0x00; + if (argc>1) strncpy(bitmap.text,argv[1],255); + } else + { + if (!strcmp(argv[0],"op") || !strcmp(argv[0],"startup") || !strcmp(argv[0],"caller") || + !strcmp(argv[0],"7110op") || !strcmp(argv[0],"6210startup") || !strcmp(argv[0],"7110startup") || + !strcmp(argv[0],"picture")) + { + if (argc>1) + { + if (!strcmp(argv[0],"startup")) + { + bitmap.type=GSM_StartupLogo; + bitmap.width=84; + bitmap.height=48; + bitmap.size=GSM_GetBitmapSize(&bitmap); + num=argv[1][0]-'0'; + if (num>=1 && num<=3) { + bitmap.number=num; + } else { + if (GSM_ReadBitmapFileOnConsole(argv[1], &bitmap)!=GE_NONE) { + GSM->Terminate(); + return(-1); + } + bitmap.number=0; + GSM_ResizeBitmap(&bitmap,GSM_StartupLogo); + } + } else { + if (GSM_ReadBitmapFileOnConsole(argv[1], &bitmap)!=GE_NONE) { + GSM->Terminate(); + return(-1); + } + } + if (!strcmp(argv[0],"op")) + { + if (bitmap.type!=GSM_OperatorLogo || argc<3) + { + if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7); + } + GSM_ResizeBitmap(&bitmap,GSM_OperatorLogo); + if (argc==3) + { + strncpy(bitmap.netcode,argv[2],7); + if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown")) + { + fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode); + return -1; + } + } + } + if (!strcmp(argv[0],"7110op")) + { + if (bitmap.type!=GSM_7110OperatorLogo || argc<3) + { + if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7); + } + GSM_ResizeBitmap(&bitmap,GSM_7110OperatorLogo); + if (argc==3) + { + strncpy(bitmap.netcode,argv[2],7); + if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown")) + { + fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode); + return -1; + } + } + } + if (!strcmp(argv[0],"picture")) + { + GSM_ResizeBitmap(&bitmap,GSM_PictureImage); + bitmap.number=1; + if (argc>2) + { + if (strlen(argv[2])==2) { + num=(argv[2][0]-'0')*10+(argv[2][1]-'0'); + } else { + num=argv[2][0]-'0'; + } + if (num<1) num=1; + bitmap.number=num; + } + bitmap.number--; + bitmap.text[0]=0; + if (argc>3) + strncpy(bitmap.text,argv[3],121); + strcpy(bitmap.Sender,"\0"); + if (argc>4) + strncpy(bitmap.Sender,argv[4],GSM_MAX_SENDER_LENGTH); + } + if (!strcmp(argv[0],"7110startup")) + { + GSM_ResizeBitmap(&bitmap,GSM_7110StartupLogo); + } + if (!strcmp(argv[0],"6210startup")) + { + GSM_ResizeBitmap(&bitmap,GSM_6210StartupLogo); + } + if (!strcmp(argv[0],"caller")) + { + GSM_ResizeBitmap(&bitmap,GSM_CallerLogo); + if (argc>2) + { + num=argv[2][0]-'0'; + if ((num<0)||(num>9)) num=0; + bitmap.number=num; + } else + { + bitmap.number=0; + } + oldbit.type=GSM_CallerLogo; + oldbit.number=bitmap.number; + if (GSM->GetBitmap(&oldbit)==GE_NONE) + { + /* We have to get the old name and ringtone!! */ + bitmap.ringtone=oldbit.ringtone; + strncpy(bitmap.text,oldbit.text,255); + } + if (argc>3) strncpy(bitmap.text,argv[3],255); + } + fprintf(stdout, _("Setting Logo.\n")); + } else + { + /* FIX ME: is it possible to permanently remove op logo ? */ + if (!strcmp(argv[0],"op")) + { + bitmap.type=GSM_OperatorLogo; + strncpy(bitmap.netcode,"000 00",7); + bitmap.width=72; + bitmap.height=14; + bitmap.size=GSM_GetBitmapSize(&bitmap); + GSM_ClearBitmap(&bitmap); + } + if (!strcmp(argv[0],"7110op")) + { + bitmap.type=GSM_7110OperatorLogo; + strncpy(bitmap.netcode,"000 00",7); + bitmap.width=78; + bitmap.height=21; + bitmap.size=GSM_GetBitmapSize(&bitmap); + GSM_ClearBitmap(&bitmap); + } + /* FIX ME: how to remove startup and group logos ? */ + fprintf(stdout, _("Removing Logo.\n")); + } + } else + { + fprintf(stderr, _("What kind of logo do you want to set ?\n")); + GSM->Terminate(); + return -1; + } + } + + while (GSM->GetModel(model) != GE_NONE) + sleep(1); + + /* For Nokia 6110/6130/6150 we use different method of uploading. + Phone will display menu, when received it */ + if (!strcmp(model,"NSE-3") || !strcmp(model,"NSK-3") || !strcmp(model,"NSM-1")) + { + if (!strcmp(argv[0],"caller") && argc<3) + bitmap.number=255; + if (!strcmp(argv[0],"op") && argc<3) + bitmap.number=255; + } + + error=GSM->SetBitmap(&bitmap); + + switch (error) + { + case GE_NONE: oldbit.type=bitmap.type; + oldbit.number=bitmap.number; + if (GSM->GetBitmap(&oldbit)==GE_NONE) { + if (bitmap.type==GSM_WelcomeNoteText || + bitmap.type==GSM_DealerNoteText) { + if (strcmp(bitmap.text,oldbit.text)) { + fprintf(stderr, _("Error setting")); + if (bitmap.type==GSM_DealerNoteText) fprintf(stderr, _(" dealer")); + fprintf(stderr, _(" welcome note - ")); + + /* I know, it looks horrible, but... */ + /* I set it to the short string - if it won't be set */ + /* it means, PIN is required. If it will be correct, previous */ + /* (user) text was too long */ + + /* Without it, I could have such thing: */ + /* user set text to very short string (for example, "Marcin") */ + /* then enable phone without PIN and try to set it to the very long (too long for phone) */ + /* string (which start with "Marcin"). If we compare them as only length different, we could think, */ + /* that phone accepts strings 6 chars length only (length of "Marcin") */ + /* When we make it correct, we don't have this mistake */ + + strcpy(oldbit.text,"!\0"); + GSM->SetBitmap(&oldbit); + GSM->GetBitmap(&oldbit); + if (oldbit.text[0]!='!') { + fprintf(stderr, _("SIM card and PIN is required\n")); + } else { + GSM->SetBitmap(&bitmap); + GSM->GetBitmap(&oldbit); + fprintf(stderr, _("too long, truncated to \"%s\" (length %i)\n"),oldbit.text,strlen(oldbit.text)); + } + ok=false; + } + } else { + if (bitmap.type==GSM_StartupLogo) { + for (i=0;iTerminate(); + + return 0; +} + +/* Calendar notes receiving. */ + +int getcalendarnote(int argc, char *argv[]) +{ + GSM_CalendarNote CalendarNote; + GSM_NotesInfo NotesInfo; + GSM_Error error; + int i; + int vCalVer=0; + bool vInfo=false; + int start, stop; + bool was_note=false; + char z_text[MAX_CALENDAR_TEXT_LENGTH+11]; + + /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */ + char model[64]; + + struct tm *now; + time_t nowh; + GSM_DateTime Date; + + nowh=time(NULL); + now=localtime(&nowh); + + Date.Year = now->tm_year; + + /* I have 100 (for 2000) Year now :-) */ + if (Date.Year>99 && Date.Year<1900) { + Date.Year=Date.Year+1900; + } + + start=atoi(argv[0]); + stop=start; + + switch (argc) { + case 2: + if (!strcmp(argv[argc-1],"-v10")) { + vCalVer=10; + } else { + if (!strcmp(argv[argc-1],"-v30")) { + vCalVer=30; + } else { + stop=atoi(argv[1]); + } + } + break; + case 3: + stop=atoi(argv[1]); + if (!strcmp(argv[argc-1],"-v10")) { + vCalVer=10; + } else { + if (!strcmp(argv[argc-1],"-v30")) { + vCalVer=30; + } else { + usage(); + return -1; + } + } + break; + } + + fbusinit(NULL); + + while (GSM->GetModel(model) != GE_NONE) + sleep(1); + + if (!strcmp(argv[0],"-s") || !strcmp(argv[0],"--short")) + vInfo=true; + else if (!isdigit(argv[0][0])) { + usage(); + return -1; + } + + error=GSM->GetCalendarNotesInfo(&NotesInfo); + if ( error == GE_NONE ) { + if( NotesInfo.HowMany == 0 ) { + fprintf(stderr, _("Sorry! No Calendar Notes present on phone.\n")); + start=0; stop=(-1); /* This for skipping next 'for' loop ;-> */ + } +#ifdef DEBUG + fprintf(stdout, _(" CALENDAR NOTES INFO \n")); + fprintf(stdout, _("---------------------\n")); + fprintf(stdout, _("How Many Locations :%d\n"), NotesInfo.HowMany); + + /* For 6210 (NPE-3) and 7110 (NSE-5), Locations have a different behaviour */ + if ( GetModelFeature (FN_CALENDAR)==F_CAL71 ) { + fprintf(stdout, _("Locations are :\n")); + for(i=0;i */ + } + } + + if (GetModelFeature (FN_CALENDAR)!=F_CAL71) { + error=GE_NONE; + NotesInfo.HowMany=200; + for (i=0;i<200;i++) { + NotesInfo.Location[i]=i+1; + } + } + + if( vInfo && stop!=(-1) && error==GE_NONE ) + { + /* Info datas (for 7110 and comp.) */ + fprintf(stdout, _(" CALENDAR NOTES SUMMARY INFORMATION \n")); + fprintf(stdout, _(" ==================================\n")); + if (GetModelFeature (FN_CALENDAR)==F_CAL71) { + fprintf(stdout, _("Calendar notes present on phone: %d\n"), NotesInfo.HowMany); + fprintf(stdout, _("Locations are :\n")); + } + fprintf(stdout, "----------------------------------------------------------------------------\n"); + fprintf(stdout,_(" Loc Phys Type Summary description Dt start Alarm Recurs\n") ); + fprintf(stdout, "----------------------------------------------------------------------------\n"); + + for(i=0;iGetCalendarNote(&CalendarNote) == GE_NONE) { + char z_type[11]; + char z_recur[15]; + switch (CalendarNote.Type) { + case GCN_REMINDER:strcpy(z_type, "REMIND"); break; + case GCN_CALL: strcpy(z_type, "CALL"); break; + case GCN_MEETING: strcpy(z_type, "MEETING"); break; + case GCN_BIRTHDAY:strcpy(z_type, "BDAY"); break; + default: strcpy(z_type, "UNKNOWN"); break; + } + + if( CalendarNote.Recurrance ) { + sprintf( z_recur,"%d ", CalendarNote.Recurrance/24 ); + strcat( z_recur, CalendarNote.Recurrance == 1 ? "day" : "days" ); + } + else + strcpy( z_recur, "No" ); + + strcpy(z_text,""); + + if( CalendarNote.Type == GCN_CALL ) + sprintf(z_text, "\"%s\"", CalendarNote.Phone ); + + if (CalendarNote.Text[0]!=0) + sprintf(z_text, "\"%s\"", CalendarNote.Text ); + + if(CalendarNote.Type == GCN_BIRTHDAY) { + int i_age; + i_age = Date.Year - CalendarNote.Time.Year; + sprintf(z_text, "\"%s (%d %s)\"", CalendarNote.Text, + i_age, (i_age==1)?"year":"years"); + strcpy( z_recur, "-" ); + if (GetModelFeature (FN_CALENDAR)==F_CAL71) + fprintf(stdout, + _("%4d %4d %-7.7s %-32.32s %04d-%02d-%02d %s %s\n"), + i+1,NotesInfo.Location[i], z_type, z_text, + CalendarNote.Time.Year, + CalendarNote.Time.Month, + CalendarNote.Time.Day, + (CalendarNote.AlarmType==0x00) ? "Tone " : "Silent", + " " ); + else + fprintf(stdout, + _("%4d %4d %-7.7s %-32.32s %04d-%02d-%02d %s %s\n"), + i+1,NotesInfo.Location[i], z_type, z_text, + CalendarNote.Time.Year, + CalendarNote.Time.Month, + CalendarNote.Time.Day, + (CalendarNote.Alarm.Year) ? "Yes" : "No ", + " " ); + } else + if (GetModelFeature (FN_CALENDAR)==F_CAL71) + fprintf(stdout, + _("%4d %4d %-7.7s %-32.32s %04d-%02d-%02d %s %s\n"), + i+1,NotesInfo.Location[i], z_type, z_text, + CalendarNote.Time.Year, + CalendarNote.Time.Month, + CalendarNote.Time.Day, + (CalendarNote.Alarm.Year) ? "Yes" : "No ", + z_recur ); + else + fprintf(stdout, + _("%4d %4d %-7.7s %-32.32s %04d-%02d-%02d %s\n"), + i+1,NotesInfo.Location[i], z_type, z_text, + CalendarNote.Time.Year, + CalendarNote.Time.Month, + CalendarNote.Time.Day, + (CalendarNote.Alarm.Year) ? "Yes" : "No "); + } else { + if (GetModelFeature (FN_CALENDAR)!=F_CAL71) break; + } + } + } + else + for (i=start;i<=stop;i++) { + if (error==GE_NONE) { + if( i>NotesInfo.HowMany ) { + fprintf(stderr, _("Only %d Calendar Notes present on phone!\n"),NotesInfo.HowMany); + break; + } + if( i==0 ) { + fprintf(stderr, _("Calendar Notes location can't be zero... skipping.\n")); + continue; + } + } + + CalendarNote.Location=i; + CalendarNote.ReadNotesInfo=false; + + if (GSM->GetCalendarNote(&CalendarNote) == GE_NONE) { + + if (vCalVer!=0) { + if (!was_note) { + fprintf(stdout, GSM_GetVCALENDARStart(vCalVer)); + was_note=true; + } + + fprintf(stdout, GSM_GetVCALENDARNote(&CalendarNote,vCalVer)); + + } else { /* not vCal */ + + if (was_note) { + fprintf(stdout, "\n"); + } else { + was_note=true; + } + + fprintf(stdout, _(" Type of the note: ")); + + switch (CalendarNote.Type) { + + case GCN_REMINDER:fprintf(stdout, _("Reminder\n"));break; + case GCN_CALL :fprintf(stdout, _("Call\n")); break; + case GCN_MEETING :fprintf(stdout, _("Meeting\n")); break; + case GCN_BIRTHDAY:fprintf(stdout, _("Birthday\n"));break; + default: fprintf(stdout, _("Unknown\n")); + + } + + /* For 3310: set date to 2090! */ + if (GetModelFeature (FN_CALENDAR)==F_CAL33) { + fprintf(stdout, _(" Date: xxxx-%02d-%02d\n"), CalendarNote.Time.Month, + CalendarNote.Time.Day); + } else { + fprintf(stdout, _(" Date: %s %d-%02d-%02d\n"), + DayOfWeek(CalendarNote.Time.Year, CalendarNote.Time.Month, CalendarNote.Time.Day), + CalendarNote.Time.Year, + CalendarNote.Time.Month, + CalendarNote.Time.Day); + } + + fprintf(stdout, _(" Time: %02d:%02d:%02d\n"), CalendarNote.Time.Hour, + CalendarNote.Time.Minute, + CalendarNote.Time.Second); + + if (CalendarNote.Alarm.Year!=0) { + fprintf(stdout, _(" Alarm date: %s %d-%02d-%02d\n"), + DayOfWeek(CalendarNote.Alarm.Year, CalendarNote.Alarm.Month, CalendarNote.Alarm.Day), + CalendarNote.Alarm.Year, + CalendarNote.Alarm.Month, + CalendarNote.Alarm.Day); + + fprintf(stdout, _(" Alarm time: %02d:%02d:%02d\n"), CalendarNote.Alarm.Hour, + CalendarNote.Alarm.Minute, + CalendarNote.Alarm.Second); + if ( GetModelFeature (FN_CALENDAR)==F_CAL71 ) + fprintf(stdout, _(" Alarm type: %s\n"), (CalendarNote.AlarmType==0x00) ? + "With Tone" : "Silent" ); + } + + if ( GetModelFeature (FN_CALENDAR)==F_CAL71 && CalendarNote.Recurrance!= 0 ) + fprintf(stdout, " It repeat every %d day%s\n", CalendarNote.Recurrance/24, + ((CalendarNote.Recurrance/24)>1) ? "s":"" ); + + if (CalendarNote.Type == GCN_BIRTHDAY) + { + int i_age; + i_age = Date.Year - CalendarNote.Time.Year; + fprintf(stdout, _(" Text: %s (%d %s)\n"), CalendarNote.Text, + i_age, (i_age==1)?"year":"years"); + } else { + if (CalendarNote.Text[0]!=0) + fprintf(stdout, _(" Text: %s\n"), CalendarNote.Text); + } + + if (CalendarNote.Type == GCN_CALL) + fprintf(stdout, _(" Phone: %s\n"), CalendarNote.Phone); + } + } else { + fprintf(stderr, _("The calendar note %i can not be read\n"),i); + } + } + + if (was_note && vCalVer!=0) { + fprintf(stdout, GSM_GetVCALENDAREnd(vCalVer)); + } + + GSM->Terminate(); + + return 0; +} + +/* Writing calendar notes. */ + +int writecalendarnote(char *argv[]) +{ + GSM_CalendarNote CalendarNote; + GSM_Error error; + int number; + + number=atoi(argv[1]); + + if (number<1) { + fprintf(stdout, _("Number of calendar note must be 1 or higher\n")); + return -1; + } + + switch ( GSM_ReadVCalendarFile(argv[0], &CalendarNote, &number) ) { + case GE_NONE: + break; + case GE_CANTOPENFILE: + fprintf(stdout, _("Failed to open vCalendar file \"%s\"\n"),argv[0]); + return -1; + case GE_TOOSHORT: + fprintf(stdout, _("Number of given calendar note is too high (max=%i)\n"),number); + return(-1); + default: + fprintf(stdout, _("Failed to parse vCalendar file \"%s\"\n"),argv[0]); + return -1; + } + + fbusinit(NULL); + + /* Error 22=Calendar full ;-) */ + + error=GSM->WriteCalendarNote(&CalendarNote); + switch (error) { + case GE_NONE: + fprintf(stdout, _("Succesfully written!\n"));break; + case GE_TOOLONG: + fprintf(stdout, _("Too long text in calendar note!\n"));break; + default: + fprintf(stdout, _("Failed to write calendar note!\n"));break; + } + + GSM->Terminate(); + + return 0; +} + +/* Calendar note deleting. */ + +int deletecalendarnote(char *Index) +{ + + GSM_CalendarNote CalendarNote; + + CalendarNote.Location=atoi(Index); + + fbusinit(NULL); + + if (GSM->DeleteCalendarNote(&CalendarNote) == GE_NONE) { + fprintf(stdout, _(" Calendar note deleted.\n")); + } + else { + fprintf(stderr, _("The calendar note can not be deleted\n")); + + GSM->Terminate(); + return -1; + } + + GSM->Terminate(); + + return 0; +} + +/* Setting the date and time. */ + +int setdatetime(int argc, char *argv[]) +{ + struct tm *now; + time_t nowh; + GSM_DateTime Date; + + fbusinit(NULL); + + nowh=time(NULL); + now=localtime(&nowh); + + Date.Year = now->tm_year; + Date.Month = now->tm_mon+1; + Date.Day = now->tm_mday; + Date.Hour = now->tm_hour; + Date.Minute = now->tm_min; + Date.Second = now->tm_sec; + + if (argc>0) Date.Year = atoi (argv[0]); + if (argc>1) Date.Month = atoi (argv[1]); + if (argc>2) Date.Day = atoi (argv[2]); + if (argc>3) Date.Hour = atoi (argv[3]); + if (argc>4) Date.Minute = atoi (argv[4]); + + if (Date.Year<1900) + { + + /* Well, this thing is copyrighted in U.S. This technique is known as + Windowing and you can read something about it in LinuxWeekly News: + http://lwn.net/1999/features/Windowing.phtml. This thing is beeing + written in Czech republic and Poland where algorithms are not allowed + to be patented. */ + + if (Date.Year>90) + Date.Year = Date.Year+1900; + else + Date.Year = Date.Year+2000; + } + + /* FIXME: Error checking should be here. */ + GSM->SetDateTime(&Date); + + GSM->Terminate(); + + return 0; +} + +/* In this mode we receive the date and time from mobile phone. */ + +int getdatetime(void) { + + GSM_DateTime date_time; + + fbusinit(NULL); + + if (GSM->GetDateTime(&date_time)==GE_NONE) { + if (date_time.IsSet) { + fprintf(stdout, _("Date: %s %4d/%02d/%02d\n"), + DayOfWeek(date_time.Year, date_time.Month, date_time.Day), + date_time.Year, date_time.Month, date_time.Day); + fprintf(stdout, _("Time: %02d:%02d:%02d\n"), date_time.Hour, date_time.Minute, date_time.Second); + } else { + fprintf(stdout, _("Date and time not set in phone\n")); + } + } else { + fprintf(stdout,_("Error!\n")); + } + + GSM->Terminate(); + + return 0; +} + +/* Setting the alarm. */ + +int setalarm(char *argv[]) +{ + + GSM_DateTime Date; + + fbusinit(NULL); + + Date.Hour = atoi(argv[0]); + Date.Minute = atoi(argv[1]); + + GSM->SetAlarm(1, &Date); + + GSM->Terminate(); + + return 0; +} + +/* Getting the alarm. */ + +int getalarm(void) { + + GSM_DateTime date_time; + + fbusinit(NULL); + + if (GSM->GetAlarm(0, &date_time)==GE_NONE) { + fprintf(stdout, _("Alarm: %s\n"), (date_time.IsSet)?"on":"off"); + fprintf(stdout, _("Time: %02d:%02d\n"), date_time.Hour, date_time.Minute); + } else { + fprintf(stdout,_("Error!\n")); + } + + GSM->Terminate(); + + return 0; +} + +/* In monitor mode we don't do much, we just initialise the fbus code. + Note that the fbus code no longer has an internal monitor mode switch, + instead compile with DEBUG enabled to get all the gumpf. */ + +int monitormode(int argc, char *argv[]) +{ + + float rflevel=-1, batterylevel=-1; + unsigned char loop=1; + + GSM_PowerSource powersource=-1; + GSM_RFUnits rf_units = GRF_Arbitrary; + GSM_BatteryUnits batt_units = GBU_Arbitrary; + + GSM_NetworkInfo NetworkInfo; + GSM_CBMessage CBMessage; + + GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0}; + GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0}; + GSM_MemoryStatus DC_MemoryStatus = {GMT_DC, 0, 0}; + GSM_MemoryStatus EN_MemoryStatus = {GMT_EN, 0, 0}; + GSM_MemoryStatus FD_MemoryStatus = {GMT_FD, 0, 0}; + GSM_MemoryStatus LD_MemoryStatus = {GMT_LD, 0, 0}; + GSM_MemoryStatus MC_MemoryStatus = {GMT_MC, 0, 0}; + GSM_MemoryStatus ON_MemoryStatus = {GMT_ON, 0, 0}; + GSM_MemoryStatus RC_MemoryStatus = {GMT_RC, 0, 0}; + + GSM_SMSStatus SMSStatus = {0, 0}; + + char Number[20]; + + /* evaluate for presence of "-noloop" argument in parameter */ + if(argc>0) + { + if( strcmp(argv[0],"-noloop" ) && strcmp(argv[0],"-nl" )) + { + usage(); + return -1; + } + else + loop=0; + } + + /* We do not want to monitor serial line forever - press Ctrl+C to stop the + monitoring mode. */ + + signal(SIGINT, interrupted); + + fprintf (stderr, _("Entering monitor mode...\n")); + fprintf (stderr, _("Initialising GSM interface...\n")); + + /* Initialise the code for the GSM interface. */ + + fbusinit(NULL); + + sleep(1); + GSM->EnableCellBroadcast(); + + /* Loop here indefinitely - allows you to see messages from GSM code in + response to unknown messages etc. The loops ends after pressing the + Ctrl+C. */ + while (!bshutdown) { + if (GSM->GetRFLevel(&rf_units, &rflevel) == GE_NONE) + fprintf(stdout, _("RFLevel: %d\n"), (int)rflevel); + + if (GSM->GetBatteryLevel(&batt_units, &batterylevel) == GE_NONE) + fprintf(stdout, _("Battery: %d\n"), (int)batterylevel); + + if (GSM->GetPowerSource(&powersource) == GE_NONE) + fprintf(stdout, _("Power Source: %s\n"), (powersource==GPS_ACDC)?_("AC/DC"):_("battery")); + + if (GSM->GetMemoryStatus(&SIMMemoryStatus) == GE_NONE) + fprintf(stdout, _("SIM: Used %d, Free %d\n"), SIMMemoryStatus.Used, SIMMemoryStatus.Free); + + if (GSM->GetMemoryStatus(&PhoneMemoryStatus) == GE_NONE) + fprintf(stdout, _("Phone: Used %d, Free %d\n"), PhoneMemoryStatus.Used, PhoneMemoryStatus.Free); + + if (GSM->GetMemoryStatus(&DC_MemoryStatus) == GE_NONE) + fprintf(stdout, _("DC: Used %d, Free %d\n"), DC_MemoryStatus.Used, DC_MemoryStatus.Free); + + if (GSM->GetMemoryStatus(&EN_MemoryStatus) == GE_NONE) + fprintf(stdout, _("EN: Used %d, Free %d\n"), EN_MemoryStatus.Used, EN_MemoryStatus.Free); + + if (GSM->GetMemoryStatus(&FD_MemoryStatus) == GE_NONE) + fprintf(stdout, _("FD: Used %d, Free %d\n"), FD_MemoryStatus.Used, FD_MemoryStatus.Free); + + if (GSM->GetMemoryStatus(&LD_MemoryStatus) == GE_NONE) + fprintf(stdout, _("LD: Used %d, Free %d\n"), LD_MemoryStatus.Used, LD_MemoryStatus.Free); + + if (GSM->GetMemoryStatus(&MC_MemoryStatus) == GE_NONE) + fprintf(stdout, _("MC: Used %d, Free %d\n"), MC_MemoryStatus.Used, MC_MemoryStatus.Free); + + if (GSM->GetMemoryStatus(&ON_MemoryStatus) == GE_NONE) + fprintf(stdout, _("ON: Used %d, Free %d\n"), ON_MemoryStatus.Used, ON_MemoryStatus.Free); + + if (GSM->GetMemoryStatus(&RC_MemoryStatus) == GE_NONE) + fprintf(stdout, _("RC: Used %d, Free %d\n"), RC_MemoryStatus.Used, RC_MemoryStatus.Free); + + if (GSM->GetSMSStatus(&SMSStatus) == GE_NONE) + fprintf(stdout, _("SMS Messages: UnRead %d, Number %d\n"), SMSStatus.UnRead, SMSStatus.Number); + + if (GSM->GetIncomingCallNr(Number) == GE_NONE) + fprintf(stdout, _("Incoming call: %s\n"), Number); + + if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) + fprintf(stdout, _("Network: %s (%s), LAC: %s, CellID: %s\n"), GSM_GetNetworkName (NetworkInfo.NetworkCode), GSM_GetCountryName(NetworkInfo.NetworkCode), NetworkInfo.LAC, NetworkInfo.CellID); + + if (GSM->ReadCellBroadcast(&CBMessage) == GE_NONE) + fprintf(stdout, _("Cell broadcast received on channel %d: %s\n"), CBMessage.Channel, CBMessage.Message); + + if( !loop ) break; + + sleep(1); + } + + if( loop ) fprintf (stderr, _("Leaving monitor mode...\n")); + + GSM->Terminate(); + + return 0; +} + +/* Shows texts from phone's display */ + +int displayoutput() +{ + + GSM_Error error; + + fbusinit(NULL); + + error=GSM->EnableDisplayOutput(); + + if (error == GE_NONE) + { + + /* We do not want to see texts forever - press Ctrl+C to stop. */ + + signal(SIGINT, interrupted); + + fprintf (stderr, _("Entering display monitoring mode...\n")); + + /* Loop here indefinitely - allows you to read texts from phone's + display. The loops ends after pressing the Ctrl+C. */ + + while (!bshutdown) + sleep(1); + + fprintf (stderr, _("Leaving display monitor mode...\n")); + + error=GSM->DisableDisplayOutput(); + if (error!=GE_NONE) + fprintf (stderr, _("Error!\n")); + } else + fprintf (stderr, _("Error!\n")); + + GSM->Terminate(); + + return 0; +} + +/* Displays names of available ringtones */ +int allringtones() +{ + char model[64], rev[64]; + int i; + + fbusinit(NULL); + + while (GSM->GetRevision(rev) != GE_NONE) + sleep(1); + + while (GSM->GetModel(model) != GE_NONE) + sleep(1); + + strncpy(rev,rev+2,5); + rev[5]=0; + PrepareRingingTones(model,rev); + + for (i=1;i<=NumberOfRingtones();i++) + { + fprintf(stdout,_("%i. %s\n"),i,RingingToneName(0,i)); + } + + GSM->Terminate(); + + return 0; + +} + +/* Reads profile from phone and displays its' settings */ + +int getprofile(int argc, char *argv[]) +{ + + int max_profiles; + int start, stop, i; + GSM_Profile profile; + GSM_Error error; + + /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */ + char model[64], rev[64]; + + /* Initialise the code for the GSM interface. */ + + fbusinit(NULL); + + profile.Number = 0; + error=GSM->GetProfile(&profile); + + if (error == GE_NONE) + { + + while (GSM->GetModel(model) != GE_NONE) sleep(1); + + while (GSM->GetRevision(rev) != GE_NONE) sleep(1); + + strncpy(rev,rev+2,5); + rev[5]=0; + PrepareRingingTones(model,rev); + + switch(GetModelFeature (FN_PROFILES)) { + case F_PROF33:max_profiles=6;break; + case F_PROF51:max_profiles=3;break; + default :max_profiles=7;break; + } + + if (argc>0) + { + profile.Number=atoi(argv[0])-1; + start=profile.Number; + stop=start+1; + + if (profile.Number < 0) + { + fprintf(stderr, _("Profile number must be value from 1 to %d!\n"), max_profiles); + GSM->Terminate(); + return -1; + } + + if (profile.Number >= max_profiles) + { + fprintf(stderr, _("This phone supports only %d profiles!\n"), max_profiles); + GSM->Terminate(); + return -1; + } + } else { + start=0; + stop=max_profiles; + } + + i=start; + while (iGetProfile(&profile); + + printf("%d. \"%s\"", (profile.Number+1), profile.Name); + if (profile.DefaultName==-1) printf(" (name defined)"); + printf("\n"); + +#ifdef DEBUG + printf("Incoming call alert: %d\n", profile.CallAlert); + printf("Ringtone ID: %d\n", profile.Ringtone); + printf("Ringing volume: %d\n", profile.Volume); + printf("Message alert tone: %d\n", profile.MessageTone); + printf("Keypad tones: %d\n", profile.KeypadTone); + printf("Warning and game tones: %d\n", profile.WarningTone); + printf("Lights: %d\n", profile.Lights); + printf("Vibration: %d\n", profile.Vibration); + printf("Caller groups: 0x%02x\n", profile.CallerGroups); + printf("Automatic answer: %d\n", profile.AutomaticAnswer); + printf("Screen saver: %d\n", profile.ScreenSaver); + printf("\n"); +#endif + + printf("Incoming call alert: %s\n", GetProfileCallAlertString(profile.CallAlert)); + + /* For different phones different ringtones names */ + if (strcmp(RingingToneName(profile.Ringtone,0),"")) + printf(_("Ringing tone: %s (number %d in phone menu)\n"), + RingingToneName(profile.Ringtone,0), RingingToneMenu(profile.Ringtone)); + else + printf(_("Ringtone number: %d\n"), profile.Ringtone); + + printf(_("Ringing volume: %s\n"), GetProfileVolumeString(profile.Volume)); + + printf(_("Message alert tone: %s\n"), GetProfileMessageToneString(profile.MessageTone)); + + printf(_("Keypad tones: %s\n"), GetProfileKeypadToneString(profile.KeypadTone)); + + printf(_("Warning and game tones: %s\n"), GetProfileWarningToneString(profile.WarningTone)); + + if (GetModelFeature (FN_SCREENSAVER)!=0) + printf(_("Screen saver: %s\n"), GetProfileOnOffString(profile.ScreenSaver)); + + printf(_("Vibration: %s\n"), GetProfileVibrationString(profile.Vibration)); + + /* It has been nice to add here reading caller group name. ;^) */ + if (GetModelFeature (FN_CALENDAR)==F_CAL71) + printf(_("Caller groups: %s\n"), + GetProfileCallerGroups(profile.CallerGroups) ); + + /* FIXME: need make investigation for 3310 for these features. For now unknown */ + if (GetModelFeature (FN_PROFILES)!=F_PROF33) { + /* FIXME: Light settings is only used for Car */ + if (profile.Number==(max_profiles-2)) printf(_("Lights: %s\n"), profile.Lights ? _("On") : _("Automatic")); + + /* FIXME: Automatic answer is only used for Car and Headset. */ + if (profile.Number>=(max_profiles-2)) printf(_("Automatic answer: %s\n"), GetProfileOnOffString(profile.AutomaticAnswer)); + } + + printf("\n"); + + i++; + } + } else { + if (error == GE_NOTIMPLEMENTED) { + fprintf(stderr, _("Function not implemented in %s model!\n"), model); + GSM->Terminate(); + return -1; + } else + { + fprintf(stderr, _("Unspecified error\n")); + GSM->Terminate(); + return -1; + } + } + + GSM->Terminate(); + + return 0; + +} + +/* Sets profile feature */ + +int setprofile(int argc, char *argv[]) +{ + +/* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */ + char model[64], rev[64]; + + int max_profiles; + GSM_Profile profile; + GSM_Profile profile2, profile3; + GSM_Error error; + bool correct_arg1; + bool correct_arg2; + +/* Initialise the code for the GSM interface. */ + + fbusinit(NULL); + + profile.Number = 0; + + error = GSM->GetProfile(&profile); + + if (error == GE_NONE) + { + + while (GSM->GetModel(model) != GE_NONE) sleep(1); + + while (GSM->GetRevision(rev) != GE_NONE) sleep(1); + + strncpy(rev,rev+2,5); + rev[5]=0; + PrepareRingingTones(model,rev); + + switch(GetModelFeature (FN_PROFILES)) { + case F_PROF33:max_profiles=6;break; + case F_PROF51:max_profiles=3;break; + default :max_profiles=7;break; + } + + profile.Number=atoi (argv[0]); + profile.Number=profile.Number-1; + + if (profile.Number < 0) + { + fprintf(stderr, _("Profile number must be value from 1 to %i!\n"), max_profiles); + GSM->Terminate(); + return -1; + } + + if (profile.Number >= max_profiles) + { + fprintf(stderr, _("This phone supports only %i profiles!\n"), max_profiles); + GSM->Terminate(); + return -1; + } + + if (profile.Number!=0) GSM->GetProfile(&profile); + + correct_arg1=false; + correct_arg2=false; + + if (strcmp(argv[1], "callalert")==0) + { + if (strcmp(argv[2], "ringing")==0) {profile.CallAlert=PROFILE_CALLALERT_RINGING;correct_arg2=true;} + if (strcmp(argv[2], "ascending")==0) {profile.CallAlert=PROFILE_CALLALERT_ASCENDING;correct_arg2=true;} + if (strcmp(argv[2], "ringonce")==0) {profile.CallAlert=PROFILE_CALLALERT_RINGONCE;correct_arg2=true;} + if (strcmp(argv[2], "beeponce")==0) {profile.CallAlert=PROFILE_CALLALERT_BEEPONCE;correct_arg2=true;} + if (strcmp(argv[2], "groups")==0) + { + profile.CallAlert=PROFILE_CALLALERT_CALLERGROUPS; + correct_arg2=true; + /*Ignored by N5110*/ + /*FIX ME: it's ignored by N5130 and 3210 too*/ + if (max_profiles==3) fprintf(stdout, _("Warning: value \"groups\" for profile feature \"callalert\" will be ignored in this phone model !\n")); + } + if (strcmp(argv[2], "off")==0 || strcmp(argv[2], "0")==0) {profile.CallAlert=PROFILE_CALLALERT_OFF;correct_arg2=true;} + if (!correct_arg2) + { + fprintf(stderr, _("Correct parameters for profile feature \"callalert\" are ringing|ascending|ringonce|beeponce|groups|off|0 !\n")); + GSM->Terminate(); + return -1; + } + correct_arg1=true; + } + if (strcmp(argv[1], "volume")==0) + { + if (strcmp(argv[2], "1")==0) {profile.Volume=PROFILE_VOLUME_LEVEL1;correct_arg2=true;} + if (strcmp(argv[2], "2")==0) {profile.Volume=PROFILE_VOLUME_LEVEL2;correct_arg2=true;} + if (strcmp(argv[2], "3")==0) {profile.Volume=PROFILE_VOLUME_LEVEL3;correct_arg2=true;} + if (strcmp(argv[2], "4")==0) {profile.Volume=PROFILE_VOLUME_LEVEL4;correct_arg2=true;} + if (strcmp(argv[2], "5")==0) {profile.Volume=PROFILE_VOLUME_LEVEL5;correct_arg2=true;} + if (!correct_arg2) + { + fprintf(stderr, _("Correct parameters for profile feature \"volume\" are 0|1|2|3|4|5 !\n")); + GSM->Terminate(); + return -1; + } + correct_arg1=true; + } + if (strcmp(argv[1], "keypad")==0 || strcmp(argv[1], "keypadtone")==0) + { + if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.KeypadTone=PROFILE_KEYPAD_OFF;correct_arg2=true;} + if (strcmp(argv[2], "1")==0) {profile.KeypadTone=PROFILE_KEYPAD_LEVEL1;correct_arg2=true;} + if (strcmp(argv[2], "2")==0) {profile.KeypadTone=PROFILE_KEYPAD_LEVEL2;correct_arg2=true;} + if (strcmp(argv[2], "3")==0) {profile.KeypadTone=PROFILE_KEYPAD_LEVEL3;correct_arg2=true;} + if (!correct_arg2) + { + fprintf(stderr, _("Correct parameters for profile feature \"keypad|keypadtone\" are off|0|1|2|3 !\n")); + GSM->Terminate(); + return -1; + } + correct_arg1=true; + } + if (strcmp(argv[1], "messagetone")==0 || strcmp(argv[1], "smstone")==0 || strcmp(argv[1], "sms")==0 || strcmp(argv[1], "message")==0) + { + if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.MessageTone=PROFILE_MESSAGE_NOTONE;correct_arg2=true;} + if (strcmp(argv[2], "standard")==0) {profile.MessageTone=PROFILE_MESSAGE_STANDARD;correct_arg2=true;} + if (strcmp(argv[2], "special")==0) {profile.MessageTone=PROFILE_MESSAGE_SPECIAL;correct_arg2=true;} + if (strcmp(argv[2], "beeponce")==0 || strcmp(argv[2], "once")==0) {profile.MessageTone=PROFILE_MESSAGE_BEEPONCE;correct_arg2=true;} + if (strcmp(argv[2], "ascending")==0) {profile.MessageTone=PROFILE_MESSAGE_ASCENDING;correct_arg2=true;} + if (!correct_arg2) + { + fprintf(stderr, _("Correct parameters for profile feature \"messagetone|smstone|message|sms\" are 0|off|standard|special|beeponce|once|ascending !\n")); + GSM->Terminate(); + return -1; + } + correct_arg1=true; + } + if (strcmp(argv[1], "warningtone")==0 || strcmp(argv[1], "warning")==0) + { + if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.WarningTone=PROFILE_WARNING_OFF;correct_arg2=true;} + if (strcmp(argv[2], "1")==0 || strcmp(argv[2], "on")==0) {profile.WarningTone=PROFILE_WARNING_ON;correct_arg2=true;} + if (!correct_arg2) + { + fprintf(stderr, _("Correct parameters for profile feature \"warningtone|warning\" are 0|off|1|on !\n")); + GSM->Terminate(); + return -1; + } + correct_arg1=true; + } + if (strcmp(argv[1], "vibra")==0 || strcmp(argv[1], "vibration")==0) + { + if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.Vibration=PROFILE_VIBRATION_OFF;correct_arg2=true;} + if (strcmp(argv[2], "1")==0 || strcmp(argv[2], "on")==0) {profile.Vibration=PROFILE_VIBRATION_ON;correct_arg2=true;} + if (!correct_arg2) + { + fprintf(stderr, _("Correct parameters for profile feature \"vibration|vibra\" are 0|off|1|on !\n")); + GSM->Terminate(); + return -1; + } + correct_arg1=true; + } + if (strcmp(argv[1], "lights")==0) + { + if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.Lights=-1;correct_arg2=true;} + if (strcmp(argv[2], "1")==0 || strcmp(argv[2], "on")==0) {profile.Lights=0;correct_arg2=true;} + if (!correct_arg2) + { + fprintf(stderr, _("Correct parameters for profile feature \"lights\" are 0|off|1|on !\n")); + GSM->Terminate(); + return -1; + } + if (profile.Number!=(max_profiles-2)) + { + profile2.Number=max_profiles-2; + if (GSM->GetProfile(&profile2)==GE_NONE) + { + fprintf(stdout, _("Warning: \"Lights\" feature is ignored in this profile (only setting it for \"%s\" profile get some results) !\n"), profile2.Name); + } + } + correct_arg1=true; + } + if (strcmp(argv[1], "answer")==0) + { + if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.AutomaticAnswer=-1;correct_arg2=true;} + if (strcmp(argv[2], "1")==0 || strcmp(argv[2], "on")==0) {profile.AutomaticAnswer=0;correct_arg2=true;} + if (!correct_arg2) + { + fprintf(stderr, _("Correct parameters for profile feature \"answer\" are 0|off|1|on !\n")); + GSM->Terminate(); + return -1; + } + if (profile.Number<(max_profiles-2)) + { + profile2.Number=max_profiles-2; + if (GSM->GetProfile(&profile2)==GE_NONE) + { + profile3.Number=max_profiles-1; + if (GSM->GetProfile(&profile3)==GE_NONE) + { + fprintf(stdout, _("Warning: \"Automatic Answer\" feature is ignored in this profile (only setting it for \"%s\" and \"%s\" profiles get some results) !\n"), profile2.Name, profile3.Name); + } + } + } + correct_arg1=true; + } + if (strcmp(argv[1], "name")==0) + { + strcpy(profile.Name,argv[2]); + /*Ignored by N5110*/ + /*FIX ME: it's ignored by N5130 and 3210 too*/ + if (max_profiles==3) fprintf(stdout, _("Warning: this phone model doesn't allow to change profile name !\n")); + correct_arg1=true; + } + if (strcmp(argv[1], "ringtone")==0) + { + profile.Ringtone=atoi(argv[2]); + if (profile.Ringtone<1) + { + /*With value 0 results are interesting in N5110, but can't be used for anything*/ + fprintf(stderr, _("Ringtone number must be higher than 0 !\n")); + GSM->Terminate(); + return -1; + } else + { + if (profile.Ringtone>NumberOfRingtones()) + { + fprintf(stderr, _("Ringtone number too high (max %i) !\n"),NumberOfRingtones()); + GSM->Terminate(); + return -1; + } + profile.Ringtone=RingingToneCode(profile.Ringtone); + if (profile.Ringtone==0) + { + fprintf(stderr, _("Warning: we don't know ringtones codes for this model ! Can you contact with gnokii authors to add it into source ?\n")); + GSM->Terminate(); + return -1; + } + if (max_profiles==3) fprintf(stdout, _("Warning: ringtone is changed for all profiles. You must reset phone or select profile in phone againg to see result.\n")); + } + correct_arg1=true; + } + if (strcmp(argv[1], "groups")==0) + { + /*Ignored by N5110*/ + /*FIX ME: it's ignored by N5130 and 3210 too*/ + if (max_profiles==3) fprintf(stdout, _("Warning: this phone model doesn't allow to change caller group name !\n")); + profile.CallerGroups=atoi(argv[2]); + correct_arg1=true; + } + + if (!correct_arg1) + { + fprintf(stderr, _("Correct profile feature names are callalert|volume|keypad|keypadtone|messagetone|smstone|message|sms|warningtone|warning|vibra|vibration|lights|answer|name|groups !\n")); + GSM->Terminate(); + return -1; + } + + GSM->SetProfile(&profile); + + } else { + if (error == GE_NOTIMPLEMENTED) { + fprintf(stderr, _("Function not implemented in %s model!\n"), model); + GSM->Terminate(); + return -1; + } else + { + fprintf(stderr, _("Unspecified error\n")); + GSM->Terminate(); + return -1; + } + } + + GSM->Terminate(); + + return 0; + +} + +/* Get requested range of memory storage entries and output to stdout in + easy-to-parse format */ + +int getmemory(int argc, char *argv[]) +{ + + GSM_PhonebookEntry entry; + int count; + register int i; + GSM_Error error; + GSM_Bitmap bitmap; + char memory_type_string[20]; + int start_entry; + int end_entry; + int i_used = 0, n_used=0; + int do_all; + char *output_opt = NULL; + bool wasdate=false; + char az_group_name[5][MAX_BITMAP_TEXT_LENGTH]; + bool formatdone=false; + char buf[64]; + + /* group names init */ + for(i=0;i<5;i++) az_group_name[i][0]='\0'; + + /* Handle command line args that set type, start and end locations. */ + if (!GetMemoryTypeID(argv[0], &entry.MemoryType)) + { + fprintf(stderr, _("Unknown memory type %s!\n"), argv[0]); + return (-1); + } + GetMemoryTypeString(memory_type_string, &entry.MemoryType); + + if (argv[argc-1][0] == '-') + output_opt = argv[--argc]; + + /* Do generic initialisation routine */ + + fbusinit(NULL); + + while ((error = GSM->GetModel(buf)) != GE_NONE && i++ < 15) + sleep(1); + + if (argc > 1) { + do_all = 0; + start_entry = atoi (argv[1]); + end_entry = argc > 2 ? atoi( argv[2]) : start_entry; + } else { + GSM_MemoryStatus stats = {entry.MemoryType, 0, 0}; + + do_all = 1; + start_entry = 1; + if (GSM->GetMemoryStatus( &stats) != GE_NONE) { + fprintf( stderr, _("Error reading memory status.\n")); + GSM->Terminate(); + return -1; + } + n_used = stats.Used; + end_entry = stats.Used + stats.Free; + } + + + /* Now retrieve the requested entries. */ + + for (count = start_entry; + count <= end_entry && (!do_all || i_used < n_used); + count++) { + + entry.Location=count; + + error=GSM->GetMemoryLocation(&entry); + + switch (error) { + case GE_NONE: + if (entry.SubEntriesCount || strcmp( entry.Number, "")) + i_used++; + else if (do_all) + break; + if (output_opt && !strcmp( output_opt,"-v30")) { + semicolon_pipe_substitution( &entry, 0 ); + fprintf(stdout,_("%s"),GSM_GetVCARD(&entry,30)); + formatdone=true; + } + if (output_opt && !strcmp(output_opt,"-v21")) { + semicolon_pipe_substitution( &entry, 0 ); + fprintf(stdout,_("%s"),GSM_GetVCARD(&entry,21)); + formatdone=true; + } + if (output_opt && !strcmp(output_opt,"-v")) { + semicolon_pipe_substitution( &entry, 0 ); + fprintf(stdout,_("%s"),GSM_GetVCARD(&entry,10)); + formatdone=true; + } + if (output_opt && !strcmp(output_opt,"-short")) { + semicolon_pipe_substitution( &entry, 0 ); + fprintf(stdout, "%s;%s;%s;%d;%d;", entry.Name, entry.Number, memory_type_string, entry.Location, entry.Group); + for( i = 0; i < entry.SubEntriesCount; i++ ) + { + if( entry.SubEntries[i].EntryType == GSM_Date ) + fprintf(stdout,_("%u;%u;%u;%02u.%02u.%04u;%02u:%02u:%02u;"), + entry.SubEntries[i].EntryType, + entry.SubEntries[i].NumberType, + entry.SubEntries[i].BlockNumber, + entry.SubEntries[i].data.Date.Day, + entry.SubEntries[i].data.Date.Month, + entry.SubEntries[i].data.Date.Year, + entry.SubEntries[i].data.Date.Hour, + entry.SubEntries[i].data.Date.Minute, + entry.SubEntries[i].data.Date.Second ); + else + fprintf(stdout,_("%u;%u;%u;%s;"), + entry.SubEntries[i].EntryType, + entry.SubEntries[i].NumberType, + entry.SubEntries[i].BlockNumber, + entry.SubEntries[i].data.Number ); + } + fprintf(stdout,_("\n")); + formatdone=true; + } + if (!formatdone) { + char z_gtype[12]; + wasdate=false; + fprintf(stdout, "Memory %s, location %d\n",memory_type_string, entry.Location); + + // check if some info in subentries + for( i = 0; i < entry.SubEntriesCount; i++ ) + if( entry.SubEntries[i].EntryType != GSM_Date && + strcmp(entry.SubEntries[i].data.Number,"") ) + break; + + if (strcmp(entry.Number,"") || i < entry.SubEntriesCount) { + if (strcmp(entry.Name,"")) fprintf(stdout,_(" Name: %s\n"),entry.Name); + if (strcmp(entry.Number,"")) fprintf(stdout,_(" Number: %s\n"),entry.Number); + bitmap.type=GSM_CallerLogo; + bitmap.number=entry.Group; + strcpy(z_gtype,"unknown"); + if (entry.Group==5) strcpy(z_gtype,"No group"); + if (entry.Group<5 && entry.Group>=0) { + if (!strcmp(az_group_name[entry.Group],"")) { + if (GetModelFeature (FN_CALLERGROUPS)!=0) { + if (GSM->GetBitmap(&bitmap)==GE_NONE) + strcpy( az_group_name[entry.Group], bitmap.text ); + } + if ((!strcmp(az_group_name[entry.Group],""))) { + switch(entry.Group) { + case 0:strcpy(az_group_name[entry.Group],"Family");break; + case 1:strcpy(az_group_name[entry.Group],"VIP");break; + case 2:strcpy(az_group_name[entry.Group],"Friends");break; + case 3:strcpy(az_group_name[entry.Group],"Colleagues");break; + case 4:strcpy(az_group_name[entry.Group],"Other");break; + default:break; + } + } + } + strcpy(z_gtype,az_group_name[entry.Group]); + } + fprintf(stdout,_(" Group: %d (%s)\n"),entry.Group+1,z_gtype); + for( i = 0; i < entry.SubEntriesCount; i++ ) + { + if( entry.SubEntries[i].EntryType == GSM_Date ) { + fprintf(stdout, " Date and time: %s %02u.%02u.%04u %02u:%02u:%02u\n", + DayOfWeek(entry.SubEntries[i].data.Date.Year, + entry.SubEntries[i].data.Date.Month, + entry.SubEntries[i].data.Date.Day), + entry.SubEntries[i].data.Date.Day, + entry.SubEntries[i].data.Date.Month, + entry.SubEntries[i].data.Date.Year, + entry.SubEntries[i].data.Date.Hour, + entry.SubEntries[i].data.Date.Minute, + entry.SubEntries[i].data.Date.Second); + wasdate=true; + } else { + if( strcmp(entry.SubEntries[i].data.Number,"") ) { + char z_etype[19]; + switch( entry.SubEntries[i].EntryType ) { + case GSM_Number: + switch( entry.SubEntries[i].NumberType ) { + case GSM_General: strcpy(z_etype,"General "); break; + case GSM_Home: strcpy(z_etype,"Home "); break; + case GSM_Mobile: strcpy(z_etype,"Mobile "); break; + case GSM_Work: strcpy(z_etype,"Work "); break; + case GSM_Fax: strcpy(z_etype,"Fax "); break; + default: strcpy(z_etype,""); break; + } + strcat(z_etype,"Number"); break; + case GSM_Note: + strcpy(z_etype,"Note"); break; + case GSM_Postal: + strcpy(z_etype,"Postal"); break; + case GSM_Email: + strcpy(z_etype,"E-Mail"); break; + default: + strcpy(z_etype,"unknown data"); break; + } +#ifdef DEBUG + fprintf(stdout,_(" ---> Subentry: %u\n"),i+1); + fprintf(stdout,_(" Entry type: %u (%s)\n"),entry.SubEntries[i].EntryType,z_etype); + fprintf(stdout,_(" Number type: %u\n"),entry.SubEntries[i].NumberType); + fprintf(stdout,_(" Block Number: %u\n"),entry.SubEntries[i].BlockNumber); +#endif + fprintf(stdout,_(" %s: %s\n"),z_etype,entry.SubEntries[i].data.Number); + } + } + } + if ((entry.MemoryType==GMT_DC || + entry.MemoryType==GMT_RC || + entry.MemoryType==GMT_MC) && !wasdate) + fprintf(stdout,_(" Date and time not available\n")); + } else + fprintf(stdout,_(" Location empty\n")); + } + break; + case GE_NOTIMPLEMENTED: + fprintf( stderr, _("Function not implemented in %s model!\n"), model); + GSM->Terminate(); + return -1; + case GE_INVALIDMEMORYTYPE: + fprintf( stderr, _("Memory type %s not supported!\n"), + memory_type_string); + GSM->Terminate(); + return -1; + default: + fprintf(stdout, _("%s|%d|Bad location or other error!(%d)\n"), + memory_type_string, count, error); + } + } + + GSM->Terminate(); + + return 0; +} + +/* Read data from stdin, parse and write to phone. The parsing is relatively + crude and doesn't allow for much variation from the stipulated format. */ + +int writephonebook(int argc, char *args[]) +{ + + GSM_PhonebookEntry entry; + GSM_Error error; + char *memory_type_string; + int line_count=0,current,i; + int subentry; + + char *Line, OLine[1024], BackLine[1024]; + char *ptr; + + /* Check argument */ + if (argc) { + if (strcmp("-i", args[0])) { + usage(); + return 0; + } + } + /* Initialise fbus code */ + + fbusinit(NULL); + + Line = OLine; + + /* Go through data from stdin. */ + + while (GetLine(stdin, Line, sizeof(OLine))!=-1) { + + current=0;BackLine[current++]=Line[0]; + for (i=1;iGetMemoryLocation(&tmp_entry); + if (error == GE_NONE) { + if (!tmp_entry.Empty) { + int confirm = -1; + char ans[8]; + FILE *input_flow; //for reading from console, even when input redir. + + input_flow = fopen(DEV_CONSOLE, "r"); + + if (!input_flow) { + fprintf(stderr, _("Can't open \"%s\" for input !\n"),DEV_CONSOLE); + return(-1); + } + + fprintf(stderr, _("Location busy. ")); + while (confirm < 0) { + fprintf(stderr, _("Overwrite? (yes/no) ")); + GetLine(input_flow, ans, 7); + if (!strcmp(ans, "yes")) confirm = 1; + else if (!strcmp(ans, "no")) confirm = 0; + } + if (!confirm) continue; + } + } else { + fprintf(stderr, _("Unknown error (%d)\n"), error); + GSM->Terminate(); + return 0; + } + } + + /* Do write and report success/failure. */ + semicolon_pipe_substitution( &entry, 1 ); + + error = GSM->WritePhonebookLocation(&entry); + + if (error == GE_NONE) + fprintf (stdout, _("Write Succeeded: memory type: %s, loc: %d, name: %s, number: %s\n"), memory_type_string, entry.Location, entry.Name, entry.Number); + else + 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); + + } + + GSM->Terminate(); + + return 0; +} + +/* Getting speed dials. */ + +int getspeeddial(char *Number) { + + GSM_SpeedDial entry; + GSM_Error error; + GSM_PhonebookEntry pbentry; + + entry.Number = atoi(Number); + + fbusinit(NULL); + + if (GSM->GetSpeedDial(&entry)==GE_NONE) { + pbentry.Location=entry.Location; + if (pbentry.Location==0) pbentry.Location=entry.Number; + pbentry.MemoryType=entry.MemoryType; + + error=GSM->GetMemoryLocation(&pbentry); + + if (error == GE_NONE) + { + fprintf(stdout, _("SpeedDial nr. %d: %d:%d (%s)\n"), entry.Number, entry.MemoryType, entry.Location,pbentry.Name); + } else + fprintf(stdout, _("Error\n")); + } else { + fprintf(stdout, _("Error\n")); + } + + GSM->Terminate(); + + return 0; +} + +/* Setting speed dials. */ + +int setspeeddial(char *argv[]) { + + GSM_SpeedDial entry; + + char *memory_type_string; + + /* Handle command line args that set type, start and end locations. */ + + if (strcmp(argv[1], "ME") == 0) { + entry.MemoryType = GMT_ME; + memory_type_string = "ME"; + } + else if (strcmp(argv[1], "SM") == 0) { + entry.MemoryType = GMT_SM; + memory_type_string = "SM"; + } + else { + fprintf(stderr, _("Unknown memory type %s!\n"), argv[1]); + + return -1; + } + + entry.Number = atoi(argv[0]); + entry.Location = atoi(argv[2]); + + fbusinit(NULL); + + if (GSM->SetSpeedDial(&entry) == GE_NONE) { + fprintf(stdout, _("Succesfully written!\n")); + } + + GSM->Terminate(); + + return 0; +} + +/* Getting the status of the display. */ + +int getdisplaystatus() +{ + + int Status; + + /* Initialise the code for the GSM interface. */ + + fbusinit(NULL); + + if (GSM->GetDisplayStatus(&Status)==GE_NONE) { + + printf(_("Call in progress: %s\n"), Status & (1<Terminate(); + + return 0; +} + +int netmonitor(char *Mode) +{ + + unsigned char mode=atoi(Mode); + char Screen[NM_MAX_SCREEN_WIDTH]; + int i; + + fbusinit(NULL); + + if (!strcmp(Mode,"reset")) mode=0xf0; + else if (!strcmp(Mode,"off")) mode=0xf1; + else if (!strcmp(Mode,"field"))mode=0xf2; + else if (!strcmp(Mode,"devel"))mode=0xf3; + else if (!strcmp(Mode,"next")) mode=0x00; + + /* We clear it */ + for (i=0;iNetMonitor(mode, Screen); + + if (Screen) + printf("%s\n", Screen); + + GSM->Terminate(); + + return 0; +} + +int identify( void ) +{ + /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */ + char imei[64], model[64], rev[64], manufacturer[64]; + + fbusinit(NULL); + + while (GSM->GetIMEI(imei) != GE_NONE) sleep(1); + while (GSM->GetRevision(rev) != GE_NONE) sleep(1); + while (GSM->GetModel(model) != GE_NONE) sleep(1); + + strcpy(manufacturer, "(unknown)"); + GSM->GetManufacturer(manufacturer); + + fprintf(stdout, _("IMEI: %s\n"), imei); + fprintf(stdout, _("Model: %s %s (%s)\n"), manufacturer, GetModelName (model), model); + fprintf(stdout, _("Revision: %s\n"), rev); + + GSM->Terminate(); + + return 0; +} + +int senddtmf(char *String) +{ + + fbusinit(NULL); + + if (GSM->SendDTMF(String)!=GE_NONE) fprintf(stdout,_("Error!\n")); + + GSM->Terminate(); + + return 0; +} + +/* Resets the phone */ +int reset(int argc, char *argv[]) +{ + + unsigned char _type=0x03; + + if (argc>0) { + _type=0x10; + + if (!strcmp(argv[0],"soft")) _type = 0x03; + + /* Doesn't work with 5110 */ + if (!strcmp(argv[0],"hard")) _type = 0x04; + + if (_type==0x10) { + fprintf(stderr, _("What kind of reset do you want (second parameter can be \"soft\" or \"hard\") ?\n")); + return -1; + } + } + + fbusinit(NULL); + + GSM->Reset(_type); + + GSM->Terminate(); + + return 0; +} + +/* This is a "convenience" function to allow quick test of new API stuff which + doesn't warrant a "proper" command line function. */ + +int foogle(char *argv[]) +{ + /* Initialise the code for the GSM interface. */ + + fbusinit(NULL); + + // Fill in what you would like to test here... + + sleep(5); + + GSM->Terminate(); + + return 0; +} + +int phonetests() +{ + /* Initialise the code for the GSM interface. */ + + fbusinit(NULL); + + if (GSM->PhoneTests()!=GE_NONE) fprintf(stderr,_("Error\n")); + + GSM->Terminate(); + + return 0; +} + +/* pmon allows fbus code to run in a passive state - it doesn't worry about + whether comms are established with the phone. A debugging/development + tool. */ + +int pmon() +{ + + GSM_Error error; + GSM_ConnectionType connection=GCT_FBUS; + + /* Initialise the code for the GSM interface. */ + + error = GSM_Initialise(model, Port, Initlength, connection, RLP_DisplayF96Frame, SynchronizeTime); + + if (error != GE_NONE) { + fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n")); + return -1; + } + + + while (1) { + usleep(50000); + } + + return 0; +} + +int setringtone(int argc, char *argv[]) +{ + GSM_Ringtone ringtone; + GSM_BinRingtone binringtone,binringtone2; + + GSM_Error error; + + int current=0; //number of packed notes or location + int i; + + char model[64]; + + /* If not binary ringtone */ + if (GSM_ReadBinRingtoneFile(argv[0],&binringtone2)!=GE_NONE) { + fprintf(stdout,_("Not binary ringtone, trying RTTL\n")); + + if (GSM_ReadRingtoneFileOnConsole(argv[0], &ringtone)!=GE_NONE) return(-1); + + ringtone.location=1; + if (argc>1) ringtone.location=atoi(argv[1]); + + ringtone.allnotesscale=false; + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + while (GSM->GetModel(model) != GE_NONE) + sleep(1); + + /* For Nokia 6110/6130/6150/6210 we use different method of uploading. + Phone will display menu, when received it */ + if ( !strcmp(model,"NSE-3") || !strcmp(model,"NSK-3") || + !strcmp(model,"NSM-1") || !strcmp(model,"NPE-3") ) { + if (argc==1) ringtone.location=255; + } + + error=GSM->SetRingtone(&ringtone,¤t); + + if (current!=ringtone.NrNotes) { + if (current>FB61_MAX_RINGTONE_NOTES) { + fprintf(stderr,_("Warning: due to phone limitation")); + } else { + fprintf(stderr,_("Warning: ringtone was too long to be saved into frame,")); + } + fprintf(stderr, _(" only %i first notes were packed (%i cut)\n"),current,ringtone.NrNotes-current); + } + + if (error==GE_NONE) + fprintf(stdout, _("Set succeeded!\n")); + else + fprintf(stdout, _("Setting failed\n")); + + } else { /* This IS binary ringtone */ + fprintf(stdout,_("Binary ringtone format\n")); + + if (argc==3) { + binringtone.frame[current++]=0x00; + binringtone.frame[current++]=0x00; + binringtone.frame[current++]=0x0c; + binringtone.frame[current++]=0x01; + binringtone.frame[current++]=0x2c; + + //copy new name + memcpy(binringtone.frame+current,argv[2],strlen(argv[2])); + current=current+strlen(argv[2]); + + /*don't use old*/ + i=2; + while(binringtone2.frame[i]!=0x00) { + if (i==binringtone.length) break; + i++; + } + + //copy binringtone + memcpy(binringtone.frame+current,binringtone2.frame+i,binringtone2.length-i); + binringtone.length=binringtone2.length-i+current; + } else + { + memcpy(binringtone.frame+current,binringtone2.frame,binringtone2.length); + binringtone.length=binringtone2.length; + } + + binringtone.location=1; + if (argc>1) binringtone.location=atoi(argv[1]); + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + error=GSM->SetBinRingtone(&binringtone); + + switch (error) { + case GE_NONE: + fprintf(stdout, _("Set succeeded!\n")); + break; + case GE_INVALIDRINGLOCATION: + fprintf(stdout, _("Invalid location %i!\n"),binringtone.location); + break; + case GE_UNKNOWNMODEL: + fprintf(stdout, _("Mygnokii doesn't know format for this model!\n")); + break; + case GE_NOTIMPLEMENTED: + fprintf(stdout, _("Not implemented for this model!\n")); + break; + default: + fprintf(stdout, _("Not supported by this model!\n")); + break; + } + } + + GSM->Terminate(); + + return 0; +} + +int ringtoneconvert(int argc, char *argv[]) +{ + GSM_Ringtone ringtone; + + if (!strcmp(argv[0],argv[1])) + { + fprintf(stderr, _("Files can't have the same names !\n")); + return -1; + } + + if (GSM_ReadRingtoneFileOnConsole(argv[0], &ringtone)!=GE_NONE) return(-1); + + ringtone.allnotesscale=false; + + GSM_SaveRingtoneFileOnConsole(argv[1], &ringtone); + + return 0; +} + +int playringtone(int argc, char *argv[]) +{ + GSM_Ringtone ringtone; + + GSM_BinRingtone binringtone; + + int i,j,z; + int Hz; + bool isok; + +//{ "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "h" }; + int binary_notes[12] = + { 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11 , 12}; + + if (GSM_ReadBinRingtoneFile(argv[0],&binringtone)!=GE_NONE) { + fprintf(stdout,_("Not binary ringtone, trying RTTL\n")); + + if (GSM_ReadRingtoneFileOnConsole(argv[0], &ringtone)!=GE_NONE) return(-1); + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + fprintf(stdout,_("Playing \"%s\" (%i notes)\n"),ringtone.name,ringtone.NrNotes); + + GSM_PlayRingtoneOnConsole(&ringtone); + + } else { + + fprintf(stdout,_("Binary ringtone format\n")); + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + i=5; + while (true) { //skipping name + if (binringtone.frame[i]==0) break; + i++; + } + + i=i+5;j=0;z=0; + while (true) { + if (binringtone.frame[i]!=j) { + if (j!=0) { +//#ifdef DEBUG + fprintf(stdout,_("Block in binary ringtone %i %i\n"),j,z); +//#endif + isok=false; + if (j==64) { + j=255;//Pause + isok=true; + } + if (!isok && j>=114 && j<=125) { + j=14*3+binary_notes[j-114]; + isok=true; + } + if (!isok && j>=126 && j<=137) { + j=14*1+binary_notes[j-126]; + isok=true; + } + if (!isok && j>=138 && j<=149) { + j=14*2+binary_notes[j-138]; + isok=true; + } + if (!isok && j>=150 && j<=161) { + j=14*4+binary_notes[j-150]; + isok=true; + } + if (!isok) { +//#ifdef DEBUG + fprintf(stdout,_("Unknown block in binary ringtone %i %i\n"),j,z); +//#endif + } else { + Hz=GSM_GetFrequency(j); + if (GSM->PlayTone(Hz,5)!=GE_NONE) fprintf(stdout,_("error during playing\n")); + usleep(z*5000); + } + } + j=binringtone.frame[i]; + z=binringtone.frame[i+1]; + } else { + z=z+binringtone.frame[i+1]; + } + i=i+2; + if (i>=binringtone.length) break; + } + + GSM->PlayTone(0,0); + } + + GSM->Terminate(); + + return 0; +} + +int composer(int argc, char *argv[]) +{ + GSM_Ringtone ringtone; + int i; + bool unknown; + int oldnoteslen=4,nownoteslen,oldnoteslen2; + int oldnotesscale=1,nownotesscale; + bool firstnote=true; + int DefNoteTempo=63; + + if (GSM_ReadRingtoneFileOnConsole(argv[0], &ringtone)!=GE_NONE) return(-1); + + if (ringtone.NrNotes!=0) + DefNoteTempo=ringtone.notes[0].tempo; + + fprintf(stdout,_("Ringtone \"%s\" (tempo = %i Beats Per Minute)\n\n"),ringtone.name,GSM_GetTempo(DefNoteTempo)); + + for (i=0;i50) + fprintf(stdout,_("WARNING: LENGTH=%i, BUT YOU WILL ENTER ONLY FIRST 50 TONES. TO ENTER FULL RINGTONE MUST SEND IT (--sendringtone) OR DOWNLOAD (--setringtone)\n\n"),ringtone.NrNotes-i); + + fprintf(stdout,_("This ringtone in Nokia Composer in phone should look: ")); + + firstnote=true; + + for (i=0;ioldnoteslen) { + while (oldnoteslen!=nownoteslen) { + fprintf(stdout,_("8")); + oldnoteslen=oldnoteslen*2; + } + } + + if (nownoteslenFB61_MAX_RINGTONE_NOTES) { + fprintf(stderr,_("Warning: due to phone limitation")); + } else { + fprintf(stderr,_("Warning: ringtone was too long to be saved into SMS,")); + } + fprintf(stderr, _(" only %i first notes were packed (%i cut)\n"),current,ringtone.NrNotes-current); + } + + for (i=0;iFB61_MAX_RINGTONE_NOTES) { + fprintf(stderr,_("Warning: due to phone limitation")); + } else { + fprintf(stderr,_("Warning: ringtone was too long to be saved into SMS,")); + } + fprintf(stderr, _(" only %i first notes were packed (%i cut)\n"),current,ringtone.NrNotes-current); + } + + for (i=0;i2) + { + doit=false; + if (!strcmp(argv[2],"op")) + { + doit=false; + if (argc<4) doit=true; + if (argc<4 && bitmap.type!=GSM_OperatorLogo) doit=true; + if (doit) + { + fbusinit(NULL); + if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7); + GSM->Terminate(); + } + GSM_ResizeBitmap(&bitmap,GSM_OperatorLogo); + if (argc==4) + { + strncpy(bitmap.netcode,argv[3],7); + if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown")) + { + fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode); + return -1; + } + } + doit=true; + } + if (!strcmp(argv[2],"7110op")) + { + doit=false; + if (argc<4) doit=true; + if (argc<4 && bitmap.type!=GSM_7110OperatorLogo) doit=true; + if (doit) + { + fbusinit(NULL); + if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7); + GSM->Terminate(); + } + GSM_ResizeBitmap(&bitmap,GSM_7110OperatorLogo); + if (argc==4) + { + strncpy(bitmap.netcode,argv[3],7); + if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown")) + { + fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode); + return -1; + } + } + doit=true; + } + if (!strcmp(argv[2],"caller")) + { + GSM_ResizeBitmap(&bitmap,GSM_CallerLogo); + if (argc>3) + { + num=argv[3][0]-'0'; + if ((num<0)||(num>9)) num=0; + bitmap.number=num; + } else + { + bitmap.number=0; + } + doit=true; + } + if (!strcmp(argv[2],"startup")) + { + GSM_ResizeBitmap(&bitmap,GSM_StartupLogo); + doit=true; + } + if (!strcmp(argv[2],"7110startup")) + { + GSM_ResizeBitmap(&bitmap,GSM_7110StartupLogo); + doit=true; + } + if (!strcmp(argv[2],"6210startup")) + { + GSM_ResizeBitmap(&bitmap,GSM_6210StartupLogo); + doit=true; + } + if (!strcmp(argv[2],"picture")) + { + GSM_ResizeBitmap(&bitmap,GSM_PictureImage); + doit=true; + } + if (!doit) + { + fprintf(stderr,"Unknown type of logo: %s !\n",argv[2]); + return -1; + } + } + + if (GSM_SaveBitmapFileOnConsole(argv[1], &bitmap)!=GE_NONE) return(-1); + + return 0; +} + +int getphoneprofile() +{ + GSM_PPS PPS; + GSM_Error error; + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + PPS.Name=PPS_ALS; + error=GSM->GetProductProfileSetting(&PPS); + if (error!=GE_NONE) { + fprintf(stdout,_("Error!\n")); + GSM->Terminate(); + return -1; + } + fprintf(stdout,_("ALS : ")); + if (PPS.bool_value) fprintf(stdout,_("on\n")); + else fprintf(stdout,_("off\n")); + + PPS.Name=PPS_VibraMenu; + GSM->GetProductProfileSetting(&PPS); + fprintf(stdout,_("Vibra menu : ")); + if (PPS.bool_value) fprintf(stdout,_("on\n")); + else fprintf(stdout,_("off\n")); + + PPS.Name=PPS_GamesMenu; + GSM->GetProductProfileSetting(&PPS); + fprintf(stdout,_("Games menu : ")); + if (PPS.bool_value) fprintf(stdout,_("on\n")); + else fprintf(stdout,_("off\n")); + + PPS.Name=PPS_HRData; + GSM->GetProductProfileSetting(&PPS); + fprintf(stdout,_("HR Data : ")); + if (PPS.bool_value) fprintf(stdout,_("on\n")); + else fprintf(stdout,_("off\n")); + + PPS.Name=PPS_14400Data; + GSM->GetProductProfileSetting(&PPS); + fprintf(stdout,_("14400 Data : ")); + if (PPS.bool_value) fprintf(stdout,_("on\n")); + else fprintf(stdout,_("off\n")); + + PPS.Name=PPS_LCDContrast; + GSM->GetProductProfileSetting(&PPS); + fprintf(stdout,_("LCD Contrast : %i%%\n"),PPS.int_value); + + PPS.Name=PPS_EFR; + GSM->GetProductProfileSetting(&PPS); + fprintf(stdout,_("EFR : ")); + switch (PPS.int_value) { + case 0: fprintf(stdout,_("off\n")); break; + case 1: fprintf(stdout,_("last\n")); break; + case 2: fprintf(stdout,_("second\n"));break; + case 3: fprintf(stdout,_("first\n")); break; + } + + PPS.Name=PPS_FR; + GSM->GetProductProfileSetting(&PPS); + fprintf(stdout,_("FR : ")); + switch (PPS.int_value) { + case 0: fprintf(stdout,_("off\n")); break; + case 1: fprintf(stdout,_("last\n")); break; + case 2: fprintf(stdout,_("second\n"));break; + case 3: fprintf(stdout,_("first\n")); break; + } + + PPS.Name=PPS_HR; + GSM->GetProductProfileSetting(&PPS); + fprintf(stdout,_("HR : ")); + switch (PPS.int_value) { + case 0: fprintf(stdout,_("off\n")); break; + case 1: fprintf(stdout,_("last\n")); break; + case 2: fprintf(stdout,_("second\n"));break; + case 3: fprintf(stdout,_("first\n")); break; + } + + GSM->Terminate(); + + return 0; + +} + +int setphoneprofile(int argc, char *argv[]) +{ + GSM_PPS PPS; + GSM_Error error; + bool correct_arg1=false, correct_arg2=false; + + if (!strcmp(argv[0],"ALS")) { + PPS.Name=PPS_ALS; + correct_arg1=true; + if (!strcmp(argv[1],"1")) { + PPS.bool_value=true; + correct_arg2=true; + } + if (!strcmp(argv[1],"0")) { + PPS.bool_value=false; + correct_arg2=true; + } + if (!correct_arg2) { + fprintf(stdout,_("Settings for ALS parameter can be \"0\" or \"1\" !\n")); + return -1; + } + } + if (!strcmp(argv[0],"HRData")) { + PPS.Name=PPS_HRData; + correct_arg1=true; + if (!strcmp(argv[1],"1")) { + PPS.bool_value=true; + correct_arg2=true; + } + if (!strcmp(argv[1],"0")) { + PPS.bool_value=false; + correct_arg2=true; + } + if (!correct_arg2) { + fprintf(stdout,_("Settings for HRData parameter can be \"0\" or \"1\" !\n")); + return -1; + } + } + if (!correct_arg1) { + fprintf(stdout,_("First parameter can be \"ALS\" or \"HRData\" only !\n")); + return -1; + } + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + error=GSM->SetProductProfileSetting(&PPS); + + if (error!=GE_NONE) { + fprintf(stdout,_("Error!\n")); + GSM->Terminate(); + return -1; + } + + GSM->Reset(0x03); + + GSM->Terminate(); + + return 0; + +} + +int getoperatorname() +{ + + GSM_Network network; + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + if (GSM->GetOperatorName(&network)==GE_NONE) + { + if (!strcmp(network.Name,"")) { + fprintf(stdout,_("Phone doesn't have downloaded operator name\n")); + } else { + fprintf(stdout,_("Phone has downloaded operator name (\"%s\") for \"%s\" (\"%s\") network\n"), + network.Name,network.Code,GSM_GetNetworkName(network.Code)); + } + } + + GSM->Terminate(); + + return 0; + +} + +int setoperatorname(int argc, char *argv[]) +{ + + GSM_Network network; + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + if (argc==2) { + strncpy(network.Code,argv[0],7); + strncpy(network.Name,argv[1],50); + } else { + strcpy(network.Code,"000 00\0"); + strcpy(network.Name,"\0"); + } + + if (GSM->SetOperatorName(&network)==GE_NONE) { + if (GSM->GetOperatorName(&network)==GE_NONE) { + if (!strcmp(network.Name,"")) { + fprintf(stdout,_("Downloaded operator name is removed\n")); + } else { + fprintf(stdout,_("Downloaded operator name changed for \"%s\" network (\"%s\") to \"%s\"\n"), + network.Code,GSM_GetNetworkName(network.Code),network.Name); + } + } + } + + GSM->Terminate(); + + return 0; + +} + +int getvoicemailbox() +{ + GSM_PhonebookEntry entry; + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + if (GSM->GetVoiceMailbox(&entry)==GE_NONE) { + fprintf(stdout,_("Voice mailbox number is ")); + if (!strcmp(entry.Number,"")) + fprintf(stdout,_("not set\n")); + else + fprintf(stdout,_("\"%s\"\n"),entry.Number); + } + + GSM->Terminate(); + + return 0; + +} + +/////////////////////////////////////////////////////////////////////////////// +// flow diagram of netmonitordata(): +/////////////////////////////////////////////////////////////////////////////// +// +// get command line argument +// | +// v +// +// if specific phone model +// use that model +// else +// identify-phone: (((((((( TO DO ))))))))))))) +// +// | +// v +// get_mon_param_info() get phone netmonitor parameters name +// specifically to a 'model' +// | +// v +// parse_check() check command line arguments +// | if all OK, go on else stop. +// | because we can have a input file +// v containing multiple +// parse_process() command lines, we process each at once +// so we can exit early on errors. +// +/////////////////////////////////////////////////////////////////////////////// + +// private functions, see netmonitordata() +void free_nm_info(PARAM_INFO_MON *info) +{ + PARAM_INFO_MON *tmp; // pointer, iterator on info + + // go to end of list + + while (info->next != NULL) + { tmp = info->next; + free(info->name); + free(info->mname); + free(info); + info = tmp; + } + free(info); +} + +/////////////////////////////////////////////////////////////////////////////// +// this func retrieve parameters info from a file +// and load it in a dynamic array, NULL terminated, +// if 2rd parameter is not NULL, it load also description of screen +// return (PARAM_INFO_MON *start) if all is OK, else NULL +/////////////////////////////////////////////////////////////////////////////// +// start->->next->next->next-> ...->next->NULL +// | | | | | +// V V V V V +// par0 par1 par2 parN +/////////////////////////////////////////////////////////////////////////////// +// this should be de-allocated from calling function, +// also, screen_name should be deallocated from calling function +/////////////////////////////////////////////////////////////////////////////// + +PARAM_INFO_MON *get_mon_param_info(char *f_name, char *screen_name[NM_MAX_SCREEN+1]) +{ + PARAM_INFO_MON *start; // pointer to netmonitor parameters info + PARAM_INFO_MON *info; // pointer, iterator on info + PARAM_INFO_MON *check; // pointer, iterator on info, for check usage + + FILE *f_info; + + char buf[256]; + char *param; + char *param_name; + char *tmp; + + char tmp_mname[55]; // very larger, but if netmon bug ... + int x, y, len, s, t; // x & y coord, len, screen nr, type + int i; + + if (screen_name != NULL) + for (i = 0; i <= NM_MAX_SCREEN; i++) + screen_name[i] = NULL; + + + if ((f_info = fopen(f_name, "r")) == NULL) + { fprintf(stderr, "Can' t open file parameter info: <%s>\n", f_name); + return(NULL); + } + + if ((start = malloc(sizeof(PARAM_INFO_MON))) == NULL) + { fprintf(stderr, "no mem\n"); + return(NULL); + } + else + { start->next = NULL; + } + + info = start; + while (fgets(buf, 256, f_info) != NULL) + { + param = buf; + + // Truncate from '#' at right of comments + if ((tmp = strchr(param, '#')) != NULL) + *tmp = '\0'; + + // Strip leading, trailing whitespace + while(isspace((int) *param)) + param++; + + while((strlen(param) > 0) && isspace((int) param[strlen(param) - 1])) + param[strlen(param) - 1] = '\0'; + + // Ignore blank lines + if ((*param == '\n') || (*param == '\0')) + continue; + + +#ifdef DEBUG + fprintf(stderr, "%s: info line: <%s>\n", f_name, param); +#endif + // check for param name + if ((param_name = strtok(param, "=\t\n")) == NULL) + continue; + + // check if screen name + if (strncmp("SCREEN", param_name, 6) == 0) + { + // if we do not want screen names ... + if (screen_name == NULL) + continue; + +// FIXME check for screen nr + if ((tmp = strtok(NULL, ":\n")) == NULL) + continue; + + i = atoi(tmp); +// FIXME: check if already defined screen + + if ((i <= 0) || (i > NM_MAX_SCREEN)) + continue; + // check for screen name + if ((tmp = strtok(NULL, ":\n")) == NULL) + continue; + + screen_name[i] = strdup(tmp); + } + else + { + // parameter + +// FIXME: check for NM_MAX_FIELDS + + // check for x coord + if ((tmp = strtok(NULL, ":\t\n")) == NULL) + continue; + x = atoi(tmp); + + // check for y coord + if ((tmp = strtok(NULL, ":\t\n")) == NULL) + continue; + y = atoi(tmp); + + // check for len + if ((tmp = strtok(NULL, ":\t\n")) == NULL) + continue; + len = atoi(tmp); + + // check for screen + if ((tmp = strtok(NULL, ":\t\n")) == NULL) + continue; + s = atoi(tmp); + + // check for netmon manual name + if ((tmp = strtok(NULL, ":\t\n")) == NULL) + { fprintf(stderr, + "%s: PARAMETER <%s> in screen <%d>, not have netmon manual reference\n", + f_name, param_name, s); + free_nm_info(start); + return(NULL); + } + strcpy(tmp_mname, tmp); + + // check for data type (optional) + if ((tmp = strtok(NULL, ":\t\n")) != NULL) + t = *tmp; + else + t = '\0'; + + // check len, here, so we print parameter name + if (len == 0) + { fprintf(stderr, + "%s: PARAMETER <%s> in screen <%d>, has invalid data lenght\n", + f_name, param_name, s); + free_nm_info(start); + return(NULL); + } + + // check if already defined same param_name + check = start; + while (check->next != NULL) + { check = check->next; + if (strcmp(param_name, check->name) == 0) + { + fprintf(stderr, + "%s: PARAMETER <%s> in screen <%d> already defined as in screen <%d>\n", + f_name, param_name, s, check->s_nr); + free_nm_info(start); + return(NULL); + } + } + + // make space, and add parameter + if ((info->next = malloc(sizeof(PARAM_INFO_MON))) != NULL) + { + info = info->next; + info->name = strdup(param_name); + info->x = x; + info->y = y; + info->len = len; + info->s_nr = s; + info->mname = strdup(tmp_mname); + info->type = t; + + info->next = NULL; // mark end + } + else + { + fprintf(stderr, "no mem"); + free_nm_info(start); + return(NULL); + } + + } + + } + + fclose(f_info); + +#ifdef DEBUG + info = start; + while (info->next != NULL) + { + info = info->next; + fprintf(stderr, "info name %s\n", info->name); + } +#endif + return(start); +} + +// 2, parse the arguments and check command(s) line +// command line, phone spec input, and output are complex, +// so we exit printing info about error instead of std help +/////////////////////////////////////////////////////////////////////////////// + +int parse_check(int argc, char *argv[], PARAM_INFO_MON *start, char *f_name, int line) +{ + int ctr; + int i; + int time_spec; + int found_data; + char *p; + char *tmp; + char *o; + PARAM_INFO_MON *info; // iterator on this list + +#ifdef DEBUG + for (i = 0; i < argc; i++) + fprintf(stderr, "argv[%d] = <%s>\n",i, argv[i]); +#endif + + time_spec = 0; + ctr = 0; + i = 0; + while (i < argc) + { + p = argv[i]; + if (*p == '-') + { // should be one of the short option + if (strcmp(argv[i], "-fs") == 0) + { // field separator, next arg should be a string + if (((i+1) < argc) && (strlen(argv[i+1]) < 10)) + { i++; + // arg OK, do nothing + } + else + { if (line) + fprintf(stderr, + "-fs: Invalid field separator in <%s> at line %d\n", + f_name, line); + else + fprintf(stderr, "-fs: Invalid field separator\n"); + return(-1); + } + } + else if (strcmp(argv[i], "-ls") == 0) + { // line separator, next arg should be a string + if (((i+1) < argc) && (strlen(argv[i+1]) < 10)) + { i++; + // arg OK, do nothing + } + else + { if (line) + fprintf(stderr, + "-ls: Invalid line separator in <%s> at line %d\n", + f_name, line); + else + fprintf(stderr, "-ls: Invalid line separator\n"); + return(-1); + } + } + else if (strcmp(argv[i], "-tm") == 0) + { // time separator, next arg should be a millisecond (200-10000) + if (time_spec) + { if (line) + fprintf(stderr, + "-tm, -ts, are mutually exclusive in <%s> at line %d\n", + f_name, line); + else + fprintf(stderr, "-tm, -ts, are mutually exclusive\n"); + return(-1); + } + + if (((i+1) < argc) && (atoi(argv[i+1]) >= 200) && (atoi(argv[i+1]) <= 10000)) + { i++; + time_spec = 1; + // arg OK, do nothing + } + else + { if (line) + fprintf(stderr, + "-tm: Invalid argument (200-10000 milliseconds), in <%s> at line %d\n", + f_name, line); + else + fprintf(stderr, "-tm: Invalid argument (200-10000 milliseconds)\n"); + return(-1); + } + } + else if (strcmp(argv[i], "-ts") == 0) + { // time separator, next arg should be a seconds (1-3600) + if (time_spec) + { if (line) + fprintf(stderr, + "-tm, -ts, are mutually exclusive, in <%s> at line %d\n", + f_name, line); + else + fprintf(stderr, "-tm, -ts, are mutually exclusive\n"); + return(-1); + } + + if (((i+1) < argc) && (atoi(argv[i+1]) >= 1) && (atoi(argv[i+1]) <= 3600)) + { i++; + time_spec = 1; + // arg OK, do nothing + } + else + { if (line) + fprintf(stderr, + "-ts: Invalid argument (1-3600 seconds) in <%s> at line %d\n", + f_name, line); + else + fprintf(stderr, "-ts: Invalid argument (1-3600 seconds)\n"); + return(-1); + } + } + else if (strcmp(argv[i], "-n") == 0) + { // nr of data pump, before stop collection, + // next arg should be a int > 0 + if (((i+1) < argc) && (atoi(argv[i+1]) >= 1) && (atoi(argv[i+1]) <= 99999)) + { i++; + // arg OK, do nothing + } + else + { if (line) + fprintf(stderr, + "-n: Invalid argument (1-99999 times) in <%s> at line %d\n", + f_name, line); + else + fprintf(stderr, "-n: Invalid argument (1-99999 times)\n"); + return(-1); + } + } + else if (strcmp(argv[i], "-h") == 0) + { // we do NOT want header (default with header) + // arg OK, do nothing + } + else if (strcmp(argv[i], "-S") == 0) + { // we have used use specs from a file instead of standard info, + // next arg is an existing readable filename + // as already parsed correctly, we skip here. + i++; + } + else if (strcmp(argv[i], "-I") == 0) + { // we have used input from a file instead of command line + // next arg is an existing readable filename + // as already parsed correctly, we skip here. + i++; + } + else + { + if (line) + fprintf(stderr, "Unrecognized option %s in <%s> at line %d\n", + argv[i], f_name, line); + else + fprintf(stderr, "Unrecognized option %s\n", argv[i]); + return(-1); + } + } + else + { // should be required data + tmp = strdup(argv[i]); + p = strtok(tmp, ":\t\n"); + while (p != NULL) + { + // check if there is an output format specification + o = p; + while (*o) + { + o++; + if (*o == '-') + { *o = '\0'; + o++; + if (strlen(o) == 0) + { + // we have 'minus', so, probably forget format ... + + if (line) + fprintf(stderr, + "Required data <%s->, without format specifiers in <%s> at line %d\n", + p, f_name, line); + else + fprintf(stderr, + "Required data <%s->, without format specifiers\n", p); + return(-1); + } + } + } + + // we check for params + found_data = 0; + info = start; + while (info->next != NULL) + { + info = info->next; + if (strcmp(p, info->name) == 0) + { + if (ctr > NM_MAX_FIELDS) + { + if (line) + fprintf(stderr, + "too much data field ... in file <%s> at line %d\n", + f_name, line); + else + fprintf(stderr, "too much data field ...\n"); + return (-1); + } +/* + data[ctr] = info; + out_f[ctr] = *o; +*/ + found_data = 1; + ctr++; + break; + } + } + + if (found_data == 0) + { + if (line) + fprintf(stderr, + "Required data <%s>, not found in info-mon specifications in <%s> at line %d\n", + p, f_name, line); + else + fprintf(stderr, + "Required data <%s>, not found in info-mon specifications\n", p); + return(-1); + } + + p = strtok(NULL, ":\t\n"); + + } // end while strtok + + } // end else '-' (short options) + + i++; + + } // end while + + if (ctr == 0) + { + if (line) + fprintf(stderr, "no required data! in <%s> at line %d\n", f_name, line); + else + fprintf(stderr, "no required data!\n"); + return(-1); + } + + return 0; +} + +// 2, parse the arguments and process the command line +// no checks are needed here, because already do in parse_check +// it return a pointer to info needed for make output, or NULL if errors +/////////////////////////////////////////////////////////////////////////////// +OUT_INFO_MON *parse_process(int argc, char *argv[], PARAM_INFO_MON *start) +{ + int ctr; + int i; + int time_spec; + int found_data; + int req_tm; + int req_ts; + char *p; + char *tmp; + char *o; + PARAM_INFO_MON *info; // iterator on this list + OUT_INFO_MON *out_param; // iterator on this list + + if ((out_param = malloc(sizeof(OUT_INFO_MON))) == NULL) + { fprintf(stderr, "no mem\n"); + return(NULL); + } + +#ifdef DEBUG + fprintf(stderr, "parse_process: argc = %d\n", argc); + for (i = 0; i < argc; i++) + fprintf(stderr, "argv[%d] = <%s>\n",i, argv[i]); +#endif + + for (i = 0; i < NM_MAX_FIELDS; i++) + out_param->data[i] = NULL; + + strcpy(out_param->req_fs, " "); +#ifdef WIN32 + strcpy(out_param->req_ls, "\n\r"); +#else + strcpy(out_param->req_ls, "\n"); +#endif + time_spec = 0; + out_param->req_n = 0; + out_param->req_header = 1; + + time_spec = 0; + req_tm = 200; /* default wait */ + req_ts = 0; + + ctr = 0; + i = 0; + while (i < argc) + { + p = argv[i]; + if (*p == '-') + { // should be one of the short option + if (strcmp(argv[i], "-fs") == 0) + { // field separator, next arg should be a string + if (((i+1) < argc) && (strlen(argv[i+1]) < 10)) + { i++; + strcpy(out_param->req_fs, argv[i]); + } + else + { fprintf(stderr, "NEVER BE:-fs: Invalid field separator\n"); + return(NULL); + } + } + else if (strcmp(argv[i], "-ls") == 0) + { // line separator, next arg should be a string + if (((i+1) < argc) && (strlen(argv[i+1]) < 10)) + { i++; + strcpy(out_param->req_ls, argv[i]); + } + else + { fprintf(stderr, "NEVER BE:-ls: Invalid line separator\n"); + return(NULL); + } + } + else if (strcmp(argv[i], "-tm") == 0) + { // time separator, next arg should be a millisecond (200-10000) + if (time_spec) + { fprintf(stderr, "NEVER BE:-tm, -ts, are mutually exclusive"); + return(NULL); + } + + if (((i+1) < argc) && (atoi(argv[i+1]) >= 200) && (atoi(argv[i+1]) <= 10000)) + { i++; + req_tm = atoi(argv[i]); + time_spec = 1; + } + else + { fprintf(stderr, "NEVER BE:-tm: Invalid argument (200-10000 milliseconds)\n"); + return(NULL); + } + } + else if (strcmp(argv[i], "-ts") == 0) + { // time separator, next arg should be a seconds (1-3600) + if (time_spec) + { fprintf(stderr, "NEVER BE:-tm, -ts, are mutually exclusive"); + return(NULL); + } + + if (((i+1) < argc) && (atoi(argv[i+1]) >= 1) && (atoi(argv[i+1]) <= 3600)) + { i++; + req_ts = atoi(argv[i]); + time_spec = 1; + + // delete default + req_tm = 0; + } + else + { fprintf(stderr, "NEVER BE:-ts: Invalid argument (1-3600 seconds)\n"); + return(NULL); + } + } + else if (strcmp(argv[i], "-n") == 0) + { // nr of data pump, before stop collection, + // next arg should be a int > 0 + if (((i+1) < argc) && (atoi(argv[i+1]) >= 1) && (atoi(argv[i+1]) <= 99999)) + { i++; + out_param->req_n = atoi(argv[i]); + } + else + { fprintf(stderr, "NEVER BE:-n: Invalid argument (1-99999 times)\n"); + return(NULL); + } + } + else if (strcmp(argv[i], "-h") == 0) + { // we do NOT want header (default with header) + out_param->req_header = 0; + } + else if (strcmp(argv[i], "-S") == 0) + { // we have used use specs from a file instead of standard info, + // next arg is an existing readable filename + // as already parsed correctly, we skip here. + i++; + } + else if (strcmp(argv[i], "-I") == 0) + { // we have used input from a file instead of command line + // next arg is an existing readable filename + // as already parsed correctly, we skip here. + i++; + } + else + { + fprintf(stderr, "NEVER BE:Unrecognized option %s\n", argv[i]); + return(NULL); + } + } + else + { // should be required data + tmp = strdup(argv[i]); + p = strtok(tmp, ":\t\n"); + while (p != NULL) + { + // check if there is an output format specification + o = p; + while (*o) + { + o++; + if (*o == '-') + { *o = '\0'; + o++; + if (strlen(o) == 0) + { + // we have 'minus', so, probably forget format ... + + fprintf(stderr, + "NEVER BE:Required data <%s->, without format specifiers\n", p); + return(NULL); + } + } + } + + // we check for params + found_data = 0; + info = start; + while (info->next != NULL) + { + info = info->next; + if (strcmp(p, info->name) == 0) + { + if (ctr > NM_MAX_FIELDS) + { + fprintf(stderr, "NEVER BE:too much data field ..."); + return(NULL); + } + out_param->data[ctr] = info; + out_param->out_f[ctr] = *o; + found_data = 1; + ctr++; + break; + } + } + + if (found_data == 0) + { + fprintf(stderr, + "NEVER BE:Required data <%s>, not found in info-mon specifications\n", p); + return(NULL); + } + + + p = strtok(NULL, ":\t\n"); + + } // end while strtok + + // here, we have an array of pointers to required data + // and an array of output specifiers, from 0 to [ctr-1] + + } // end else '-' (short options) + + i++; + + } // end while + + if (ctr == 0) + { + fprintf(stderr, "NEVER BE:no required data!\n"); + return(NULL); + } + + // now, what netmon screen we need to retrieve ? + // we need somewhat were checking is faster, as our goal is lower cicle time + + // we can have NM_MAX_SCREEN=254 screens, so we use an array, of unsigned char, + // each char contain number of needed screen, 255 is list terminator + + for (i = 0; i <= NM_MAX_SCREEN; i++) + out_param->req_screen[i] = 255; + + ctr = 0; +#ifdef DEBUG +fprintf(stderr, "Start Required data %s screen %d\n", out_param->data[ctr]->name, out_param->data[ctr]->s_nr); +#endif + while (out_param->data[ctr] != NULL) + { +#ifdef DEBUG +fprintf(stderr, "Required data %s screen %d\n", out_param->data[ctr]->name, out_param->data[ctr]->s_nr); +#endif + // check if screen already in + found_data = 0; + i = 0; + while (out_param->req_screen[i] != 255) + { + if (out_param->req_screen[i] == out_param->data[ctr]->s_nr) + { // already load, skip + found_data = 1; + break; + } + i++; + } + + if (found_data == 0) + { +#ifdef DEBUG +fprintf(stderr, "i = %d, out_param->req_screen[%d] = %d\n", i, i, out_param->data[ctr]->s_nr); +#endif + out_param->req_screen[i] = out_param->data[ctr]->s_nr; + i++; + } + + ctr++; + } + +#ifdef DEBUG +i = 0; +while (out_param->req_screen[i] != 255) +{ + fprintf(stderr, "Required screen %d\n", out_param->req_screen[i]); + i++; +} +#endif + + if (req_tm) + out_param->req_wait = req_tm * 1000; + else if (req_ts) + out_param->req_wait = req_ts * 1000000; + else + out_param->req_wait = req_tm * 1000; + + + return(out_param); +} + +int nmd_output(OUT_INFO_MON *out_param) +{ + int d; + int len; + int ctr; + int i; + int nr_line; + char *p; + int nr_chr; + int n; + char Screen[NM_MAX_SCREEN_WIDTH]; + time_t sec; + struct tm *date_time; + + if (out_param->req_header) + { +// print phone help header + d = 0; + while (out_param->data[d] != NULL) + { len = out_param->data[d]->len; + if (strlen(out_param->data[d]->name) > len) + len = strlen(out_param->data[d]->name); + if (strlen(out_param->data[d]->mname) > len) + len = strlen(out_param->data[d]->mname); + printf("%*.*s%s", len, len, out_param->data[d]->name, out_param->req_fs); + d++; + } + printf("%s", out_param->req_ls); + +// print netmon manual header + d = 0; + while (out_param->data[d] != NULL) + { len = out_param->data[d]->len; + if (strlen(out_param->data[d]->name) > len) + len = strlen(out_param->data[d]->name); + if (strlen(out_param->data[d]->mname) > len) + len = strlen(out_param->data[d]->mname); + printf("%*.*s%s", len, len, out_param->data[d]->mname, out_param->req_fs); + d++; + } + printf("%s", out_param->req_ls); + printf("%s", out_param->req_ls); + } + + ctr = 0; + while (!bshutdown) + { +// stop after n data punp + + ctr++; + if ((out_param->req_n) && (ctr > out_param->req_n)) + break; + +// datapump: for each screen, for each required data, load data info->value + + i = 0; + while(out_param->req_screen[i] != 255) + { + if (out_param->req_screen[i] == 0) + { + sec = time(0); + date_time = localtime(&sec); + sprintf(Screen, "%02d-%02d-%04d\n%02d:%02d:%02d\n", + date_time->tm_mday, + date_time->tm_mon+1, + date_time->tm_year+1900, + date_time->tm_hour, + date_time->tm_min, + date_time->tm_sec); +#ifdef DEBUG + fprintf(stderr, "%02d-%02d-%04d\n%02d:%02d:%02d\n", + date_time->tm_mday, + date_time->tm_mon+1, + date_time->tm_year+1900, + date_time->tm_hour, + date_time->tm_min, + date_time->tm_sec); +#endif + } + else + { + GSM->NetMonitor(out_param->req_screen[i], Screen); + } + +// we have one screen of data, load those required + + d = 0; + while (out_param->data[d] != NULL) + { + if (out_param->data[d]->s_nr == out_param->req_screen[i]) + { + p = Screen; +// goto req y + nr_line = out_param->data[d]->y; + while ((*p) && (nr_line)) + { + if (*p == '\n') + { nr_line--; + } + p++; + } +#ifdef DEBUG +fprintf(stderr, "\nthis line: %s\n\n", p); +#endif + +// goto req x + nr_chr = out_param->data[d]->x; + while ((*p) && (nr_chr)) + { p++; + nr_chr--; + } +// this the start of data + n = 0; + len = out_param->data[d]->len; + while ((*p) && (len)) + { out_param->data[d]->value[n] = *p; + p++; + n++; + len--; + } +// pad with space if shorter than presumed + while ((*p) && (len)) + { out_param->data[d]->value[n] = ' '; + n++; + len--; + } + + out_param->data[d]->value[n] = '\0'; + } + + d++; // next screen + } + + i++; // next screen + } + +// print row of data + d = 0; + while (out_param->data[d] != NULL) + { + len = out_param->data[d]->len; + if (out_param->req_header) + { if (strlen(out_param->data[d]->name) > len) + len = strlen(out_param->data[d]->name); + if (strlen(out_param->data[d]->mname) > len) + len = strlen(out_param->data[d]->mname); + } +// FIXME check format + printf("%*.*s%s", len, len, out_param->data[d]->value, out_param->req_fs); + d++; + } + printf("%s", out_param->req_ls); + + usleep(out_param->req_wait); + + } + + printf("%s%s", out_param->req_ls, out_param->req_ls); + + return(0); +} + +// main func +/////////////////////////////////////////////////////////////////////////////// +int netmonitordata(int argc, char *argv[]) +{ + char *loc_info = NULL; // path to --netmonitordata directory + char *f_name; // absolute path of phone info-file + int flag_phone_spec = 0; // flags, set if used -S option + + char model[20] = "phonepar"; // TO DO: PHONE AUTODETECTION +// char phver[20] = ""; + + PARAM_INFO_MON *start; // pointer to list of parsed phone params + OUT_INFO_MON *out_param; // pointer to struct of output data + + char *f_commands = NULL; // file containings input line arguments + FILE *commands; // Handle for this file + char buf[1024]; // buffer + char *f_argv[NM_MAX_FIELDS+30]; // space for parameters and cmdline options + int f_argc; + char *p, *tmp; // various counter, flags, tmp area ... + int i; + int line; + + + fbusinit(NULL); + + signal(SIGINT, interrupted); + +// FIXME model, phone_version + + // before parsing phone-info-file, we check for user specified phone-info-file + + i = 0; + while (i < argc) + { + if (strcmp(argv[i], "-S") == 0) + { + if ((i+1) < argc) + { + flag_phone_spec = 1; + loc_info = strdup(argv[i+1]); + break; + } + else + { fprintf(stderr, "option -S require an argument ...\n"); + return -1; + } + } + + i++; + } + + if (loc_info != NULL) + { f_name = strdup(loc_info); + } + else // we use standard file specification + { + if ((tmp = getenv("INFOMONPATH")) == NULL) + { loc_info = strdup("."); + } + else + { loc_info = strdup(tmp); + } + + f_name = malloc(strlen(loc_info)+strlen(model)+10); + sprintf(f_name, "%s/%s", loc_info, model); + } + + +#ifdef DEBUG +// fprintf(stderr, "Loc_info <%s> model <%s> version <%s>\n", loc_info, model, phver); + fprintf(stderr, "Info file: <%s>\n", f_name); +#endif + if ((start = get_mon_param_info(f_name, NULL)) == NULL) + return(-1); + + // option -I give us the possibility of specify a filename, + // containing a "sequence" of command line args. + // if you specify this option, you can use (on command line) only -S option. + // other options may be specified inside the input-file. + // contents of this file as the same sintax as the command line, + // except it must not contain "--netmonitordata" or "-I" or "-S" options + /////////////////////////////////////////////////////////////////////// + + i = 0; + while (i < argc) + { + if (strcmp(argv[i], "-I") == 0) + { + if ((i+1) < argc) + { + if ((argc == 2) || ((argc == 4) && flag_phone_spec == 1)) + { f_commands = strdup(argv[i+1]); + } + else + { fprintf(stderr, "option -I accept only additional -S option.\n"); + return -1; + } + + break; + } + else + { fprintf(stderr, "option -I require an argument ...\n"); + return -1; + } + } + + i++; + } + + // before all, we check all command line + + if (f_commands != NULL) + { +#ifdef DEBUG + fprintf(stderr, "netmonitordata(check): commands from <%s>\n", f_commands); +#endif + // for each line + // do + // read line, make array f_argv, and counter f_argc + // parse & check args, so errors are checked before real processing + // (-I option here is ignored) + // (-S option can be here, and it is used) + // done + + if ((commands = fopen(f_commands, "r")) == NULL) + { fprintf(stderr, "Can' t open file commands input :<%s>n", f_commands); + return(-1); + } + +// FIXME line may be be splitted + line = 0; + while (fgets(buf, 1024, commands) != NULL) + { + p = buf; + line++; + + // Truncate from '#' at right of comments + if ((tmp = strchr(p, '#')) != NULL) + *tmp = '\0'; + + // Strip leading, trailing whitespace + while(isspace((int) *p)) + p++; + + while((strlen(p) > 0) && isspace((int) p[strlen(p) - 1])) + p[strlen(p) - 1] = '\0'; + + // Ignore blank lines + if ((*p == '\n') || (*p == '\0')) + continue; + +#ifdef DEBUG +fprintf(stderr, "netmonitordata(check): row <%s>\n", p); +#endif + // make args + f_argc = 0; + + p = strtok(p, " \t"); + do + { f_argv[f_argc++] = strdup(p); +#ifdef DEBUG +fprintf(stderr, "netmonitordata(check): token <%s>\n", p); +#endif + p = strtok(NULL, " \t"); // OK p, (NULL) + } + while ((p != NULL) && (*p)); + + // here we have f_argc, f_argv, this line is OK + + if (parse_check(f_argc, f_argv, start, f_commands, line) != 0) + { free_nm_info(start); + return(-1); + } + } + + fclose(commands); + } + else // as above, but we have only command line, argv, argc. + { + if (parse_check(argc, argv, start, NULL, 0) != 0) + { free_nm_info(start); + return(-1); + } + } + + // here, all commands line are checked, and are correct + + if (f_commands != NULL) + { +#ifdef DEBUG + fprintf(stderr, "netmonitordata(process): commands from <%s>\n", f_commands); +#endif + + // for each line + // do + // read line, make array f_argv, and counter f_argc + // parse_process argument, (-I option here is ignored) + // (-S option can be here, and it is used) + // (make header // these are in nmd_output(); + // loop + // get net-mon-info + // make output + // done) + // done + + if ((commands = fopen(f_commands, "r")) == NULL) + { fprintf(stderr, "Can' t open file commands input :<%s>n", f_commands); + return(-1); + } + +// FIXME line may be be splitted + while (fgets(buf, 1024, commands) != NULL) + { + p = buf; + + // Truncate from '#' at right of comments + if ((tmp = strchr(p, '#')) != NULL) + *tmp = '\0'; + + // Strip leading, trailing whitespace + while(isspace((int) *p)) + p++; + + while((strlen(p) > 0) && isspace((int) p[strlen(p) - 1])) + p[strlen(p) - 1] = '\0'; + + // Ignore blank lines + if ((*p == '\n') || (*p == '\0')) + continue; + + // make args + + f_argc = 0; + p = strtok(p, " \t"); + do + { f_argv[f_argc++] = strdup(p); + p = strtok(NULL, " \t"); // OK p, (NULL) + } + while ((p != NULL) && (*p)); + + // here we have f_argc, f_argv, this line is OK + + if ((out_param = parse_process(f_argc, f_argv, start)) == NULL) + { free_nm_info(start); + return(-1); /* NEVER BE */ + } + + // here, command line has no error ... + + nmd_output(out_param); + + free(out_param); + } + + fclose(commands); + } + else // as above, but we have only command line, argv, argc. + { + if ((out_param = parse_process(argc, argv, start)) == NULL) + { free_nm_info(start); + return(-1); /* NEVER BE */ + } + nmd_output(out_param); + + free(out_param); + } + GSM->Terminate(); + + free(loc_info); + free(f_name); + +/* I analised this source and this should be done. But when compile with VC6 */ +/* I have error. So, commented... MW */ +#ifndef VC6 + free_nm_info(start); +#endif + + return(0); +} + + +// used by nm_collect() +/////////////////////////////////////////////////////////////////////////////// +char *rowScreen(char *s) +{ + char *p; + + // make Screen in one row + p = s; + while(*p) + { + if (*p == '\n') + *p = ' '; + p++; + } + + return(s); +} + +void printtime(void) +{ + + struct mydate { + int Year; /* The complete year specification - e.g. 1999. Y2K :-) */ + int Month; /* January = 1 */ + int Day; + int Hour; + int Minute; + int Second; + int Timezone; /* The difference between local time and GMT */ + } Date; + + struct tm *now; + time_t nowh; + nowh=time(NULL); + now=localtime(&nowh); + + Date.Year = now->tm_year; + Date.Month = now->tm_mon+1; + Date.Day = now->tm_mday; + Date.Hour = now->tm_hour; + Date.Minute = now->tm_min; + Date.Second = now->tm_sec; + + /* I have 100 (for 2000) Year now :-) */ + if (Date.Year>99 && Date.Year<1900) { + Date.Year=Date.Year+1900; + } + + printf("%d:%d:%d:%d:%d:%d ",Date.Day,Date.Month,Date.Year,Date.Hour,Date.Minute,Date.Second); + +} + +// like netmonitor(), but print in one row, 1, 2 or 3 screen, every ~0.3 s +/////////////////////////////////////////////////////////////////////////////// +int nm_collect(int argc, char *argv[]) +{ + int mode[MAX_NM_COLLECT]; + char Screen[NM_MAX_SCREEN_WIDTH]; + int i; + + for (i=0;i i ? (mode[i] = atoi(argv[i])): (mode[i] = 0); + } + + for (i=0;iNetMonitor(mode[i], Screen); + printf("%s::", rowScreen(Screen)); + } + } + + printf("\n\n"); + + usleep(150000); + } + + GSM->Terminate(); + + return 0; +} + +#ifdef DEBUG +int sniff(int argc, char *argv[]) +{ + /* base model comes from gnokiirc */ + strcat(model,"sniff"); + + if (argc>0) strcpy(Port,argv[0]); + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + /* Loop here indefinitely - allows you to see messages from GSM code in + response to unknown messages etc. The loops ends after pressing the + Ctrl+C. */ + while (!bshutdown) { + sleep(1); + } + + GSM->Terminate(); + + return 0; + +} + +int decodefile(int argc, char *argv[]) +{ + FILE *infile; + unsigned char in_buffer[255]; + int nr_read = 0; + int i = 0; + + /* base model comes from gnokiirc */ + strcat(model,"decode"); + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + printf ("open InPutFile: %s\n", argv[0]); + if ( (infile = fopen( argv[0], "rb")) == NULL ) { + printf ("Failed to open InPutFile: %s\n", argv[0]); + exit (1); } + + while ( (nr_read = fread(in_buffer, 1, 16, infile)) > 0 ) { + for (i=0; i < nr_read; i++) + Protocol->StateMachine(in_buffer[i]); + } + + return 0; +} + +#endif + +int getringtone(int argc, char *argv[]) +{ + GSM_BinRingtone ringtone; + GSM_Error error; + GSM_Ringtone SMringtone; + + ringtone.location=1; + if (argc>1) ringtone.location=atoi(argv[1]); + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + error=GSM_GetPhoneRingtone(&ringtone,&SMringtone); + + fprintf(stdout, _("Downloaded ringtone, location %i: "),ringtone.location); + + switch (error) { + case GE_NONE: + fprintf(stdout, _("get succeeded!\n")); + /* In 33.. we have normal "Smart Messaging" format */ + if (GetModelFeature (FN_RINGTONES)==F_RING_SM) { + fprintf(stdout, _("Name: %s (normal format)\n"),SMringtone.name); + GSM_SaveRingtoneFileOnConsole(argv[0], &SMringtone); + } else { + fprintf(stdout, _("Name: %s (binary format)\n"),ringtone.name); + GSM_SaveBinRingtoneFile(argv[0], &ringtone); + } + GSM->Terminate(); + return 0; + break; + case GE_INVALIDRINGLOCATION: + fprintf(stdout, _("invalid location %i!\n"),ringtone.location); + break; + case GE_UNKNOWNMODEL: + fprintf(stdout, _("mygnokii doesn't know format for this model!\n")); + break; + case GE_NOTIMPLEMENTED: + fprintf(stdout, _("not implemented for this model!\n")); + break; + default: + fprintf(stdout, _("not supported by this model!\n")); + break; + } + + GSM->Terminate(); + + return(-1); +} + +int binringtoneconvert(int argc, char *argv[]) +{ + GSM_BinRingtone ringtone; + + int i,j,z; + bool isok; + int deflen=7,m,w; + bool pause; + + FILE *file; + +//{ "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "h" }; + int binary_notes[12] = + { 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11 , 12}; + + if (GSM_ReadBinRingtoneFile(argv[0],&ringtone)!=GE_NONE) { + fprintf(stdout,_("Failed to read %s file!\n"),argv[0]); + return -1; + } + + file = fopen(argv[1], "wb"); + + if (!file) + return(GE_CANTOPENFILE); + + i=5; + while (true) { + if (ringtone.frame[i]==0) break; + fprintf(file,_("%c"),ringtone.frame[i]); + i++; + } + + fprintf(file,_(":d=32,o=5,b=300:")); + + i=i+5;j=0;z=0; + while (true) { + if (ringtone.frame[i]!=j) { + if (j!=0) { + isok=false; + if (j==64) { + j=255;//Pause + isok=true; + } + if (!isok && j>=114 && j<=125) { + j=14*3+binary_notes[j-114]; + isok=true; + } + if (!isok && j>=126 && j<=137) { + j=14*1+binary_notes[j-126]; + isok=true; + } + if (!isok && j>=138 && j<=149) { + j=14*2+binary_notes[j-138]; + isok=true; + } + if (!isok && j>=150 && j<=161) { + j=14*4+binary_notes[j-150]; + isok=true; + } + if (!isok) { + if (j!=10) { + fprintf(stdout,_("Unknown block in binary ringtone %i %i\n"),j,z); + } + } else { + w=deflen; + for (m=0;m<6;m++) { + w=w*2; + if (w>z && (w/2)<=z) { + switch (m) { + case 1:fprintf(file,_("16"));break; + case 2:fprintf(file,_("8"));break; + case 3:fprintf(file,_("4"));break; + case 4:fprintf(file,_("2"));break; + case 5:fprintf(file,_("1"));break; + } + break; + } + } + if (z>w) fprintf(file,_("1")); + pause=false; + switch (GSM_GetNote(j)) { + case Note_C :fprintf(file,_("c"));break; + case Note_Cis:fprintf(file,_("c#"));break; + case Note_D :fprintf(file,_("d"));break; + case Note_Dis:fprintf(file,_("d#"));break; + case Note_E :fprintf(file,_("e"));break; + case Note_F :fprintf(file,_("f"));break; + case Note_Fis:fprintf(file,_("f#"));break; + case Note_G :fprintf(file,_("g"));break; + case Note_Gis:fprintf(file,_("g#"));break; + case Note_A :fprintf(file,_("a"));break; + case Note_Ais:fprintf(file,_("a#"));break; + case Note_H :fprintf(file,_("h"));break; + default :pause=true;fprintf(file,_("p"));break; //Pause ? + } + w=deflen*1.5; + for (m=0;m<6;m++) { + w=w*2; + if (w>z && (w/2)<=z) { + fprintf(file,_(".")); + break; + } + } + if ((j/14)!=1 && !pause) fprintf(file,_("%i"),j/14); + fprintf(file,_(",")); + } + } + j=ringtone.frame[i]; + z=ringtone.frame[i+1]; + } else { + z=z+ringtone.frame[i+1]; + } + i=i+2; + if (i>=ringtone.length) break; + } + + fclose(file); + + return 0; + +} + +int renamesmsc(int argc, char *argv[]) +{ + GSM_MessageCenter MessageCenter; + + MessageCenter.No=atoi(argv[0]); + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + if (GSM->GetSMSCenter(&MessageCenter) == GE_NONE) { + fprintf(stdout,_("SMSC number %i get OK\n"),MessageCenter.No); + } else { + GSM->Terminate(); + fprintf(stdout,_("Error getting SMSC number %i\n"),MessageCenter.No); + return 0; + } + + strncpy(MessageCenter.Name,argv[1],10); + + if (GSM->SetSMSCenter(&MessageCenter) == GE_NONE) { + fprintf(stdout,_("SMSC number %i set OK (renamed to \"%s\")\n"),MessageCenter.No,MessageCenter.Name); + } else { + GSM->Terminate(); + fprintf(stdout,_("Error setting SMSC number %i\n"),MessageCenter.No); + return 0; + } + + GSM->Terminate(); + + return 0; +} + +/* + * Returns number of sostituited characters. + * ... may be useful one day ?? + */ +int semicolon_pipe_substitution( GSM_PhonebookEntry *pentry, unsigned int direction ) + /* direction = 0 : after reading phone memory ( + * 1 : writing phone memory + */ +{ + register int i; + register int count=0; + char charfrom, charto; + + charfrom= (direction==0) ? ';' : '|'; + charto = (direction==0) ? '|' : ';'; + + count+=str_substch(pentry->Name, charfrom, charto ); + count+=str_substch(pentry->Number, charfrom, charto ); + + for( i = 0; i < pentry->SubEntriesCount; i++ ) + { + if( pentry->SubEntries[i].EntryType != GSM_Date ) + count+=str_substch(pentry->SubEntries[i].data.Number ,charfrom,charto); + } + + return( count ); +} + +int str_substch( char *str, const char toric, const char sost ) +{ + unsigned int ct; + int i_sost=0; + + for( ct = 0; ct < strlen(str); ct++ ) + if( str[ct] == (unsigned char) toric ) + { str[ct] = sost; i_sost++; } + + return( i_sost ); +} + +/* Allows to set simlock state. + With older phone (older 51xx, 61xx) can open them, with older + and newer should be able to close them */ +/* DO NOT TRY, IF DON'T WANT, WHAT YOU DO !!!!!!!!!! */ +int setsimlock() +{ + GSM_AllSimlocks siml; + + unsigned char closebuffer[20]= + { 0x00, 0x01, 0x82, 0x01, + 0x00, /* which simlock */ + 0x00, 0x00, + 0x00, 0x00, 0x00, /* lock 1 info */ + 0x00, 0x00, 0x00, 0x00, 0x00, /* lock 4 info */ + 0x00, 0x00, /* lock 2 info */ + 0x00, 0x00, /* lock 3 info */ + 0x00}; + unsigned char openbuffer[10]= { 0x00, 0x01, 0x81, 0x01, + 0x00, /* lock number */ + 0x10, 0x10, 0x10, 0x10, 0x10 }; + unsigned char openbuffer0[10]= {0x00, 0x01, 0x02, 0x03, 0x1f, 0x11, 0x01, 0x01, 0x10, 0x00 }; + + unsigned char info[120]; + int i,j; + + /* Initialise the code for the GSM interface. */ + fbusinit(NULL); + if (strstr(GSM_Info->FBUSModels, "3310") == NULL) + { + fprintf(stderr,("Not supported\n")); + GSM->Terminate(); + return -1; + } + N6110_EnableExtendedCommands(0x02); + /* Initial info */ + if (GSM->SimlockInfo(&siml)!=GE_NONE) { + fprintf(stderr,_("Error getting simlock info\n"));GSM->Terminate();return -1; + } + /* Opening all locks (we must check, if we can open them) */ + NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer0); + openbuffer[4]=1;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer); + openbuffer[4]=2;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer); + openbuffer[4]=4;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer); + openbuffer[4]=8;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer); + if (GSM->SimlockInfo(&siml)!=GE_NONE) { + fprintf(stderr,_("Error getting simlock info\n"));GSM->Terminate();return -1; + } + for (i=0;i<4;i++) { + if (siml.simlocks[i].enabled) { + fprintf(stderr,_("Can not open simlock %i\n"),i+1);GSM->Terminate();return -1; + } + } + /* Making frame for closing simlocks */ + strcpy(info,"00101"); + j=0;i=7; + while (j!=strlen(info)) { + if (j+2<=strlen(info)) { + closebuffer[i]=((info[j] & 0x0f)<<4) | (info[j+1] & 0x0f);j=j+2; + } else { + closebuffer[i]=(info[j] & 0x0f) << 4;j++; + }i++; + } + strcpy(info,"0000");j=0;i=15; + while (j!=strlen(info)) { + if (j+2<=strlen(info)) { + closebuffer[i]=((info[j] & 0x0f)<<4) | (info[j+1] & 0x0f);j=j+2; + } else { + closebuffer[i]=(info[j] & 0x0f) << 4;j++; + }i++; + } + strcpy(info,"0000");j=0;i=17; + while (j!=strlen(info)) { + if (j+2<=strlen(info)) { + closebuffer[i]=((info[j] & 0x0f)<<4) | (info[j+1] & 0x0f);j=j+2; + } else { + closebuffer[i]=(info[j] & 0x0f) << 4;j++; + }i++; + } + strcpy(info,"0000000001");j=0;i=9; + while (j!=strlen(info)) { + if (j+2<=strlen(info)) { + if (j==0) { + closebuffer[i]=closebuffer[i] | (info[j] & 0x0f);j++; + } else { + closebuffer[i]=((info[j] & 0x0f)<<4) | (info[j+1] & 0x0f);j=j+2; + } + } else { + closebuffer[i]=(info[j] & 0x0f) << 4;j++; + }i++; + } + /* Closing simlock with given values */ + closebuffer[4]=1+2+4+8; + NULL_SendMessageSequence(50, &CurrentMagicError, 20, 0x40,closebuffer); + /* Opening all locks */ + NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer0); + openbuffer[4]=1;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer); + openbuffer[4]=2;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer); + openbuffer[4]=4;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer); + openbuffer[4]=8;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer); + GSM->Reset(0x03); + GSM->Terminate(); + return 0; +} + +int simlockinfo() +{ + GSM_AllSimlocks siml; + char s[7]; + + /* Initialise the code for the GSM interface. */ + fbusinit(NULL); + + if (GSM->SimlockInfo(&siml)!=GE_NONE) fprintf(stderr,_("Error\n")); + + fprintf(stdout,_("MCC + MNC : %s ("),siml.simlocks[0].data); + if (siml.simlocks[0].enabled) fprintf(stdout,_("CLOSED")); + else fprintf(stdout,_("opened")); + if (siml.simlocks[0].factory) fprintf(stdout,_(") (factory")); + else fprintf(stdout,_(") (user")); + fprintf(stdout,_(") (counter %i"),siml.simlocks[0].counter); + + s[0]=siml.simlocks[0].data[0]; + s[1]=siml.simlocks[0].data[1]; + s[2]=siml.simlocks[0].data[2]; + s[3]=' '; + s[4]=siml.simlocks[0].data[3]; + s[5]=siml.simlocks[0].data[4]; + s[6]=0; + + if (strcmp(GSM_GetNetworkName(s),"unknown")) + fprintf(stdout,_(") (network \"%s\""),GSM_GetNetworkName(s)); + + fprintf(stdout,_(")\n")); + + fprintf(stdout,_("GID1 : %s ("),siml.simlocks[1].data); + if (siml.simlocks[1].enabled) fprintf(stdout,_("CLOSED")); + else fprintf(stdout,_("opened")); + if (siml.simlocks[1].factory) fprintf(stdout,_(") (factory")); + else fprintf(stdout,_(") (user")); + fprintf(stdout,_(") (counter %i"),siml.simlocks[1].counter); + fprintf(stdout,_(")\n")); + + fprintf(stdout,_("GID2 : %s ("),siml.simlocks[2].data); + if (siml.simlocks[2].enabled) fprintf(stdout,_("CLOSED")); + else fprintf(stdout,_("opened")); + if (siml.simlocks[2].factory) fprintf(stdout,_(") (factory")); + else fprintf(stdout,_(") (user")); + fprintf(stdout,_(") (counter %i"),siml.simlocks[2].counter); + fprintf(stdout,_(")\n")); + + fprintf(stdout,_("MSIN : %s ("),siml.simlocks[3].data); + if (siml.simlocks[3].enabled) fprintf(stdout,_("CLOSED")); + else fprintf(stdout,_("opened")); + if (siml.simlocks[3].factory) fprintf(stdout,_(") (factory")); + else fprintf(stdout,_(") (user")); + fprintf(stdout,_(") (counter %i"),siml.simlocks[3].counter); + fprintf(stdout,_(")\n")); + + GSM->Terminate(); + + return 0; +} + +/* Getting EEPROM from older phones */ +/* Tested with N5110 5.07, 6150 5.22 */ +int geteeprom() +{ + int i=0x40; + + unsigned char buffer[1000]={ 0x00, 0x01, 0xd4, 0x02, 0x00, 0xa0, + 0x00, 0x00, /* location Lo and Hi */ + 0x10 }; /* how many bytes */ + + strcpy(Connection,"mbus"); + fprintf(stderr,_("Switching connection type to MBUS\n")); + + strcpy(model,"5110"); + + /* Initialise the code for the GSM interface. */ + fbusinit(NULL); + + if (strstr(GSM_Info->FBUSModels, "3310") == NULL) + { + fprintf(stderr,("Not supported\n")); + GSM->Terminate(); + return -1; + } + + for (i=0;i<64;i++) { + fprintf(stdout,_("%c"),0xff); + } + + while (i<300000) { + buffer[6] = i/256; + buffer[7] = i%256; + + if ((i/256)!=((i-1)/256)) fprintf(stderr,_(".")); + + if (NULL_SendMessageSequence(50, &CurrentMagicError, 9, 0x40,buffer)!=GE_NONE) break; + + i=i+0x10; + } + + fprintf(stderr,_("\n")); + + GSM->Terminate(); + + return 0; +} + +int getsmsfolders() +{ + GSM_SMSFolders folders; + GSM_Error error; + + int i; + + /* Initialise the code for the GSM interface. */ + fbusinit(NULL); + + folders.number = 0; + + error=GSM->GetSMSFolders(&folders); + + GSM->Terminate(); + + if (error!=GE_NONE && !folders.number) { + fprintf(stdout,_("Error!\n")); + return -1; + } + + for (i=0;iResetPhoneSettings(); + + GSM->Reset(0x03); + + GSM->Terminate(); + + return 0; +} + +/* Checked on 3310 4.02 and doesn't work. + Possible reasons: SMSC has problems (possible), bug in phone firmware + (very possible) or here in code. + I quess, that the second is the most possible - 3310 treat only 3 SMS + as linked (the most often profile needs 4 - 2 and few bytes in 3'th + for screen saver, few bytes for profile name and 1 or 2 sms for ringtone). + When send separate ringtone (see --sendringtone with --profilestyle) + and screen saver (--sendlogo screensaver...), it's received OK. + It's for checking in higher firmware. */ +int sendprofile(int argc, char *argv[]) +{ + GSM_Ringtone ringtone; + GSM_Bitmap bitmap; + GSM_MultiSMSMessage MultiSMS; + + int current=0,i,j; + + u8 MessageBuffer[140*4]; + u16 MessageLength=0; + + char profilename[10+1]; + + if (GSM_ReadRingtoneFileOnConsole(argv[2], &ringtone)!=GE_NONE) return(-1); + + ringtone.allnotesscale=false; + for (i=0;iFB61_MAX_RINGTONE_NOTES) { + fprintf(stderr,_("Warning: due to phone limitation")); + } else { + fprintf(stderr,_("Warning: ringtone was too long to be saved into SMS,")); + } + fprintf(stderr, _(" only %i first notes were packed (%i cut)\n"),current,ringtone.NrNotes-current); + } + + MessageBuffer[i]=(j)/256; + MessageBuffer[i+1]=(j)%256; + + MessageBuffer[MessageLength++]=SM30_SCREENSAVER; //ID for OTA screen saver + MessageBuffer[MessageLength++]=0x01; //length hi + MessageBuffer[MessageLength++]=0x00; //length lo + MessageBuffer[MessageLength++]=0x00; + MessageBuffer[MessageLength++]=bitmap.width; + MessageBuffer[MessageLength++]=bitmap.height; + MessageBuffer[MessageLength++]=0x01; + + memcpy(MessageBuffer+MessageLength,bitmap.bitmap,bitmap.size); + MessageLength=MessageLength+bitmap.size; + + GSM_MakeMultiPartSMS2(&MultiSMS,MessageBuffer,MessageLength, GSM_ProfileUDH, GSM_Coding_Default); + + optind = 4; + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + for (i=0;iGetWAPSettings(&settings); + + switch (error) { + case GE_NONE: + fprintf(stdout,_("%s."),argv[0]); + if (!(strcmp(settings.title,""))) fprintf(stdout,_("Set %s\n"),argv[0]); + else fprintf(stdout,_("%s\n"),settings.title); + fprintf(stdout,_("Homepage: %s\n"),settings.homepage); + if (settings.iscontinuous) fprintf(stdout,_("Connection type: continuous\n")); + else fprintf(stdout,_("Connection type: temporary\n")); + if (settings.issecurity) fprintf(stdout,_("Connection security: on\n")); + else fprintf(stdout,_("Connection security: off\n")); + switch (settings.bearer) { + case WAPSETTINGS_BEARER_SMS: + fprintf(stdout,_("Bearer: SMS\n")); + fprintf(stdout,_("Server number: %s\n"),settings.server); + fprintf(stdout,_("Service number: %s\n"),settings.service); + break; + case WAPSETTINGS_BEARER_DATA: + fprintf(stdout,_("Bearer: Data (CSD)\n")); + fprintf(stdout,_("Dial-up number: %s\n"),settings.dialup); + fprintf(stdout,_("IP address: %s\n"),settings.ipaddress); + if (settings.isnormalauthentication) fprintf(stdout,_("Authentication type: normal\n")); + else fprintf(stdout,_("Authentication type: secure\n")); + if (settings.isISDNcall) fprintf(stdout,_("Data call type: ISDN\n")); + else fprintf(stdout,_("Data call type: analogue\n")); + if (settings.isspeed14400) fprintf(stdout,_("Data call speed: 14400\n")); + else fprintf(stdout,_("Data call speed: 9600\n")); + fprintf(stdout,_("User name: %s\n"),settings.user); + fprintf(stdout,_("Password: %s\n"),settings.password); + break; + case WAPSETTINGS_BEARER_USSD: + fprintf(stdout,_("Bearer: USSD\n")); + fprintf(stdout,_("Service code: %s\n"),settings.code); + if (settings.isIP) fprintf(stdout,_("Address type: IP address\nIPaddress: %s\n"),settings.service); + else fprintf(stdout,_("Address type: service number\nService number: %s\n"),settings.service); + break; + } + break; + default: + fprintf(stderr,_("%s\n"),print_error(error)); + } + + GSM->Terminate(); + + return 0; + +} + +/* Not full done now */ +int savewapsettings(int argc, char *argv[]) +{ + GSM_WAPSettings settings; + GSM_MultiSMSMessage MultiSMS; + GSM_Error error; + int w; + + settings.location=atoi(argv[0]); + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + error=GSM->GetWAPSettings(&settings); +// strcpy(settings.homepage,"http://OtherSites/"); +// strcpy(settings.title,"Orange"); + + error=GE_NONE; + + switch (error) { + case GE_NONE: + /* Put settings into SMS structure */ + GSM_SaveWAPSettingsToSMS(&MultiSMS,&settings); + + for (w=0;wTerminate(); + + return 0; +} + +int sendwapsettings(int argc, char *argv[]) +{ + GSM_WAPSettings settings; + GSM_MultiSMSMessage MultiSMS; + GSM_Error error; + int w; + + settings.location=atoi(argv[0]); + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + error=GSM->GetWAPSettings(&settings); +// strcpy(settings.homepage,"http://OtherSites/"); +// strcpy(settings.title,"Orange"); + + error=GE_NONE; + + switch (error) { + case GE_NONE: + /* Put settings into SMS structure */ + GSM_SaveWAPSettingsToSMS(&MultiSMS,&settings); + + for (w=0;wTerminate(); + + return 0; +} + +int getwapbookmark(int argc, char *argv[]) +{ + GSM_WAPBookmark bookmark; + GSM_Error error; + + bookmark.location=atoi(argv[0]); + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + error=GSM->GetWAPBookmark(&bookmark); + + switch (error) { + case GE_NONE: + if (bookmark.address[0]==0) { + fprintf(stdout,_("Empty bookmark location\n")); + } else { + fprintf(stdout,_("Address: \"%s\"\n"),bookmark.address); + if (bookmark.title[0]==0) + fprintf(stdout,_("Title: \"%s\"\n"),bookmark.address); + else + fprintf(stdout,_("Title: \"%s\"\n"),bookmark.title); + } + break; + default: + fprintf(stderr,_("%s\n"),print_error(error)); + } + + GSM->Terminate(); + + return 0; + +} + +int setwapbookmark(int argc, char *argv[]) +{ + GSM_WAPBookmark bookmark; + GSM_Error error; + + if (argc == 3) /* if location given, use it */ + bookmark.location=atoi(argv[2]); + else /* else use first empty location */ + bookmark.location=0xffff; + + strcpy(bookmark.title, argv[0]); + strcpy(bookmark.address, argv[1]); + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + error=GSM->SetWAPBookmark(&bookmark); + + switch (error) { + case GE_NONE: + fprintf(stdout,_("No errors\n")); + break; + default: + fprintf(stderr,_("%s\n"),print_error(error)); + } + + GSM->Terminate(); + + return 0; + +} + +int savewapbookmark(int argc, char *argv[]) +{ + GSM_WAPBookmark bookmark; + GSM_MultiSMSMessage MultiSMS; + GSM_Error error; + int w; + + bookmark.location=atoi(argv[0]); + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + error=GSM->GetWAPBookmark(&bookmark); + +// strcpy(bookmark.title,"tytulagagagagagagagagagagagagagagagagagagagagagend"); +// strcpy(bookmark.address,"http://jajajajajajajajajajajajagagagagagagagagagagagagagagagagagagagagagpapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapap¥papapapapapapapapagagagagagagagagagagagagagagagagagagagagagagagagagadadadadadadadajdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdstp"); + error=GE_NONE; + + switch (error) { + case GE_NONE: + + if (bookmark.address[0]==0) { + fprintf(stdout,_("Empty bookmark location\n")); + GSM->Terminate(); + return 1; + } + + /* Put bookmark into SMS structure */ + GSM_SaveWAPBookmarkToSMS(&MultiSMS,&bookmark); + + for (w=0;wTerminate(); + + return 0; + +} + +int sendwapbookmark(int argc, char *argv[]) +{ + GSM_WAPBookmark bookmark; + GSM_MultiSMSMessage MultiSMS; + GSM_Error error; + int w; + + bookmark.location=atoi(argv[0]); + + /* Initialise the GSM interface. */ + fbusinit(NULL); + + error=GSM->GetWAPBookmark(&bookmark); + + switch (error) { + case GE_NONE: + + if (bookmark.address[0]==0) { + fprintf(stdout,_("Empty bookmark location\n")); + GSM->Terminate(); + return 1; + } + + /* Put bookmark into SMS structure */ + GSM_SaveWAPBookmarkToSMS(&MultiSMS,&bookmark); + + for (w=0;wTerminate(); + + return 0; + +} + +int savecalendarnote(int argc, char *argv[]) +{ + GSM_MultiSMSMessage MultiSMS; + int w; + GSM_CalendarNote CalendarNote; + int number; + + number=atoi(argv[1]); + + if (number<1) { + fprintf(stdout, _("Number of calendar note must be 1 or higher\n")); + return -1; + } + + switch ( GSM_ReadVCalendarFile(argv[0], &CalendarNote, &number) ) { + case GE_NONE: + break; + case GE_CANTOPENFILE: + fprintf(stdout, _("Failed to open vCalendar file \"%s\"\n"),argv[0]); + return -1; + case GE_TOOSHORT: + fprintf(stdout, _("Number of given calendar note is too high (max=%i)\n"),number); + return(-1); + default: + fprintf(stdout, _("Failed to parse vCalendar file \"%s\"\n"),argv[0]); + return -1; + } + + fbusinit(NULL); + + /* Put note into SMS structure */ + GSM_SaveCalendarNoteToSMS(&MultiSMS,&CalendarNote); + + for (w=0;wGetSMSStatus(&SMSStatus) == GE_NONE) { + if (SMSStatus.Number!=0) { + + GetMachineDateTime(nowdate, nowtime ); + logfile = fopen("log", "a"); + if (logfile) { + fprintf(logfile, _("%s %s SMS Messages: UnRead %d, Number %d\n"), + nowdate, nowtime, SMSStatus.UnRead, SMSStatus.Number); + fclose(logfile); + } + + read=0; + location=1; + + while (!bshutdown) { + + SMS.Location=location; + if (GSM->GetSMSMessage(&SMS)==GE_NONE) { + if (SMS.folder==0 || SMS.folder==0x08) { //GST_7110_INBOX + + GetMachineDateTime(nowdate, nowtime ); + logfile = fopen("log", "a"); + if (logfile) { + fprintf(logfile,_("%s %s SMS on location %i\n"), + nowdate,nowtime,SMS.MessageNumber); + fclose(logfile); + } + + number= 16*(SMS.MessageText[2] >> 4)+ (SMS.MessageText[2] & 0x0f); + number=number+ 256*16*(SMS.MessageText[1] >> 4)+ 256*(SMS.MessageText[1] & 0x0f); + number=number+65536*16*(SMS.MessageText[0] >> 4)+65536*(SMS.MessageText[0] & 0x0f); + + sprintf( name, "%07i_%02d%02d%02d_%02d%02d%02d.sms", number, + SMS.Time.Year, SMS.Time.Month, SMS.Time.Day, + SMS.Time.Hour, SMS.Time.Minute, SMS.Time.Second); + + strcpy(filename,Dir); + strcat(filename,name); + + logfile = fopen("log", "a"); + if (logfile) { + fprintf(logfile,_("%s %s Name is \"%s\"\n"),nowdate,nowtime,filename); + fclose(logfile); + } + + file = fopen(filename, "rb"); + if (!file) { + file = fopen(filename, "wb"); + if (!file) { + GetMachineDateTime(nowdate, nowtime ); + fprintf(stderr,_("%s %s ERROR: opening file \"%s\" failed !\n"),nowdate,nowtime,filename); + logfile = fopen("log", "a"); + if (logfile) { + fprintf(logfile,_("%s %s ERROR: opening file \"%s\" failed !\n"),nowdate,nowtime,filename); + fclose(logfile); + } + } else { + fwrite(SMS.MessageText,1,SMS.Length,file); + fclose(file); + } + } else { + fclose(file); + + GetMachineDateTime(nowdate, nowtime ); + fprintf(stderr,_("%s %s ERROR: file \"%s\" already exist !\n"),nowdate,nowtime,filename); + logfile = fopen("log", "a"); + if (logfile) { + fprintf(logfile,_("%s %s ERROR: file \"%s\" already exist !\n"),nowdate,nowtime,filename); + fclose(logfile); + } + } + + SMS.Location=SMS.MessageNumber; + if (GSM->DeleteSMSMessage(&SMS)!=GE_NONE) { + GetMachineDateTime(nowdate, nowtime ); + fprintf(stderr,_("%s %s ERROR: Deleting SMS location %i failed !\n"),nowdate,nowtime,SMS.MessageNumber); + logfile = fopen("log", "a"); + if (logfile) { + fprintf(logfile,_("%s %s ERROR: Deleting SMS location %i failed !\n"),nowdate,nowtime,SMS.MessageNumber); + fclose(logfile); + } + } + } + read++; + } + location++; + if (read==SMSStatus.Number) break; + } + } + } else { + GetMachineDateTime(nowdate, nowtime ); + fprintf(stderr,_("%s %s ERROR: Can't get SMS status !\n"),nowdate,nowtime); + logfile = fopen("log", "a"); + if (logfile) { + fprintf(logfile,_("%s %s ERROR: Can't get SMS status !\n"),nowdate,nowtime); + fclose(logfile); + } + } + + sleep(1); + } + + fprintf (stderr, _("Leaving monitor mode...\n")); + + GSM->Terminate(); + + return 0; +} + +int divert(int argc, char *argv[]) +{ + GSM_CallDivert cd; + GSM_Error error; + + memset(&cd, 0, sizeof(GSM_CallDivert)); + + if (!strcmp("register", argv[0])){cd.Operation = GSM_CDV_Register ;} + else if (!strcmp("enable" , argv[0])){cd.Operation = GSM_CDV_Enable ;} + else if (!strcmp("disable" , argv[0])){cd.Operation = GSM_CDV_Disable ;} + else if (!strcmp("erasure" , argv[0])){cd.Operation = GSM_CDV_Erasure ;} + else if (!strcmp("query" , argv[0])){cd.Operation = GSM_CDV_Query ;} + else { + usage(); + exit(-1); + } + + if (!strcmp("all" , argv[1])) {cd.DType = GSM_CDV_AllTypes ;} + else if (!strcmp("busy" , argv[1])) {cd.DType = GSM_CDV_Busy ;} + else if (!strcmp("noans" , argv[1])) {cd.DType = GSM_CDV_NoAnswer ;} + else if (!strcmp("outofreach", argv[1])) {cd.DType = GSM_CDV_OutOfReach;} + else { + usage(); + exit(-1); + } + + if (!strcmp("all" , argv[2])) {cd.CType = GSM_CDV_AllCalls ;} + else if (!strcmp("voice", argv[2])) {cd.CType = GSM_CDV_VoiceCalls;} + else if (!strcmp("fax" , argv[2])) {cd.CType = GSM_CDV_FaxCalls ;} + else if (!strcmp("data" , argv[2])) {cd.CType = GSM_CDV_DataCalls ;} + else { + usage(); + exit(-1); + } + + if (argc>3) strcpy(cd.Number, argv[3]); + + if (argc>4) cd.Timeout = atoi(argv[4]); + + /* Initialise the code for the GSM interface. */ + fbusinit(NULL); + + error=GSM->CallDivert(&cd); + + if (error == GE_NONE) { + switch (cd.Operation) + { + case GSM_CDV_Query: + fprintf(stdout, _("Divert type: ")); + switch (cd.DType) { + case GSM_CDV_Busy :fprintf(stdout, _("when busy"));break; + case GSM_CDV_NoAnswer :fprintf(stdout, _("when not answered"));break; + case GSM_CDV_OutOfReach:fprintf(stdout, _("when phone off or no coverage"));break; + case GSM_CDV_AllTypes :fprintf(stdout, _("all call diverts"));break; //? + default: fprintf(stdout, _("unknown %i"),cd.DType);break; + } + + fprintf(stdout, _("\nCalls type : ")); + switch (cd.CType) { + case GSM_CDV_VoiceCalls: fprintf(stdout, _("voice"));break; + case GSM_CDV_FaxCalls : fprintf(stdout, _("fax"));break; + case GSM_CDV_DataCalls : fprintf(stdout, _("data"));break; + case GSM_CDV_AllCalls : fprintf(stdout, _("voice, fax & data"));break; + default: fprintf(stdout, _("unknown %i"),cd.CType);break; + } + fprintf(stdout, _("\n")); + + if (cd.Enabled) { + fprintf(stdout, _("Status : active\n")); + fprintf(stdout, _("Timeout : %i seconds\n"),cd.Timeout); + fprintf(stdout, _("Number : %s\n"),cd.Number); + } else { + fprintf(stdout, _("Status : deactivated\n")); + } + + break; + default: + fprintf(stdout,_("Divert done\n")); + } + } else + fprintf(stderr,_("%s\n"),print_error(error)); + + GSM->Terminate(); + + return 0; +} + +int savephonebookentry(int argc, char *argv[]) +{ + GSM_MultiSMSMessage MultiSMS; + GSM_PhonebookEntry entry; + GSM_Error error; + int w; + + fbusinit(NULL); + + /* Handle command line args that set type, start and end locations. */ + if (!GetMemoryTypeID(argv[0], &entry.MemoryType)) + { + fprintf(stderr, _("Unknown memory type %s!\n"), argv[0]); + return (-1); + } + + entry.Location=atoi(argv[1]); + + fbusinit(NULL); + + error=GSM->GetMemoryLocation(&entry); + + switch (error) { + case GE_NONE: + + /* Put entry into SMS structure */ + if (GetModelFeature(FN_PHONEBOOK)==F_PBK71INT) { + GSM_SavePhonebookEntryToSMS(&MultiSMS,&entry,21); + } else { + GSM_SavePhonebookEntryToSMS(&MultiSMS,&entry,10); + } + + for (w=0;wGetMemoryLocation(&entry); + + switch (error) { + case GE_NONE: + + /* Put entry into SMS structure */ + if (GetModelFeature(FN_PHONEBOOK)==F_PBK71INT) { + GSM_SavePhonebookEntryToSMS(&MultiSMS,&entry,21); + } else { + GSM_SavePhonebookEntryToSMS(&MultiSMS,&entry,10); + } + + for (w=0;w