http://marcin-wiacek.fkn.pl/english/zips/mygnokii.tar.gz
authorshort <>
Mon, 18 Feb 2002 02:06:50 +0000 (02:06 +0000)
committershort <>
Mon, 18 Feb 2002 02:06:50 +0000 (02:06 +0000)
md5sum: b14eeefdf274009e844ac6424b45d9ef
length: 1078794

90 files changed:
COPYING
Docs/CREDITS
Docs/Makefile
Docs/man/gnokii.1
Docs/man/todologo.1
Docs/man/xgnokii.1x
Makefile
Makefile.global.in
VERSION
common/Makefile
common/data/at-emulator.c
common/data/datapump.c
common/data/rlp-common.c
common/data/rlp-crc24.c
common/data/virtmodem.c
common/devices/tekram.c
common/devices/unixirda.c
common/devices/unixserial.c
common/gsm-api.c
common/gsm-bitmaps.c
common/gsm-networks.c
common/gsm-ringtones.c
common/gsm-sms.c
common/misc.c
configure.in
getopt/Makefile
gnokii/Makefile
gnokii/gnokii.c
gnokiid/Makefile
gnokiid/gnokiid.c
include/config.h.in.in
include/data/at-emulator.h
include/data/datapump.h
include/data/rlp-common.h
include/data/rlp-crc24.h
include/data/virtmodem.h
include/devices/tekram.h
include/devices/unixirda.h
include/devices/unixserial.h
include/gsm-api.h
include/gsm-bitmaps.h
include/gsm-common.h
include/gsm-networks.h
include/gsm-ringtones.h
include/gsm-sms.h
include/misc.h
packaging/Debian/README.debian
packaging/Debian/control
packaging/Debian/copyright
packaging/Debian/docs
packaging/Debian/menu
packaging/Debian/postinst
packaging/Debian/preinst
packaging/Debian/rules
packaging/RedHat/gnokii.spec.in
packaging/Slackware/SlackBuild.in
packaging/make_dist
po/Makefile.in.in
po/POTFILES.in
po/et.po
po/pl.po
utils/Makefile
utils/mgnokiidev.c
xgnokii/Makefile
xgnokii/VERSION
xgnokii/xgnokii.c
xgnokii/xgnokii.h
xgnokii/xgnokii_calendar.c
xgnokii/xgnokii_calendar.h
xgnokii/xgnokii_cfg.c
xgnokii/xgnokii_cfg.h
xgnokii/xgnokii_common.c
xgnokii/xgnokii_common.h
xgnokii/xgnokii_contacts.c
xgnokii/xgnokii_contacts.h
xgnokii/xgnokii_data.c
xgnokii/xgnokii_data.h
xgnokii/xgnokii_dtmf.c
xgnokii/xgnokii_dtmf.h
xgnokii/xgnokii_logos.c
xgnokii/xgnokii_lowlevel.c
xgnokii/xgnokii_lowlevel.h
xgnokii/xgnokii_netmon.c
xgnokii/xgnokii_netmon.h
xgnokii/xgnokii_sms.c
xgnokii/xgnokii_sms.h
xgnokii/xgnokii_speed.c
xgnokii/xgnokii_speed.h
xgnokii/xgnokii_xkeyb.c
xgnokii/xgnokii_xkeyb.h

diff --git a/COPYING b/COPYING
index 99a8ab6..049061c 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -17,7 +17,7 @@ Place - Suite 330, Boston, MA 02111-1307, USA.
 
 You can contact authors by mail at
 
-hugh@blemings.org                     Pavel.Janik@suse.cz
+hugh@linuxcare.com                    Pavel.Janik@suse.cz
 Hugh Blemings                         Mgr. Pavel Janík, SuSE CR, s.r.o.
 PO Box 234                            Pod Pekárnami 338/12
 Belconnen ACT 2616                    190 00 Praha 9
index 820c4af..8232bd3 100644 (file)
@@ -56,7 +56,7 @@ Thank you to, in no particular order...
 *  Goran Dokic, Samuli Sorvakko and anonymous for gettext files for
    Dutch, Finnish and German translations.
    
-*  Marcel Holtmann for RLP FCS code, the irda code and other misc stuff.
+*  Marcel Holtmann for RLP FCS code and misc stuff.
 
 *  Chris Kemp for logo stuff and a big part of the RLP code.
   
@@ -73,54 +73,38 @@ Thank you to, in no particular order...
    
 *  Alessandro Zummo for reset and getopts code.
 
-*  Manfred Jonsson for his manufacturer and windows patch, and AT command
-   support.
-
 *  Mark Looi for Cell Broadcast code - based on protocol decoded by
-   Colin Paton.
-
-*  Sebastian Zagrodzki and Jacek Fiok for Polish .po file.
-
-*  Marcin Wi±cek for all his work and tons of patches.
-
-*  Gabriele Zappi for testing, general help and bug fixes.
-
-*  Erik Rossen for help with documentation and debian packaging support.
+   Colin Paton
 
-*  Marian Jancar for patches on 7110 series.
+*  Sebastian Zagrodzki and Jacek Fiok for Polish .po file
 
-*  Tamar Bondar for updates on SMS handling on 3810 series.
-
-*  Marek Rogoziñski for help in tracing some nasty bugs.
-
-*  Pavel Machek for developing 2110 and Duncall support and many clever
-   hints.
-
-*  Bo¹tjan Müller for Slovenian translation and other things.
-
-*  Hans Motshärg for Estonian translation.
+*  Lucy for making pizza and putting up with Hugh disappearing to
+   work on this.  Rachael for new parent induced insomnia...
 
-*  Marcin P³awiñski for preview logos.
+*  Last not least: Mirka for allowing Pavel to work on gnokii
+   and for _great_ gnokii operator logos...
 
-*  Martin Lucina for any kind of help he is providing ;-)
+*  Hendrik Spohr for getting 7110 functions and DLR-3 to work (one small step
+   for Hendrik, big step for (my)gnokii :-))
+   
+*  Balazs Nagy for frames list and long hacker's work...
 
-*  Gabriele Stella for Italian translation.
+*  Ladislav Michl & Manfred Jonsson\r for support for various AT phones...
 
-*  Andrea Scopece for bug reports and other help.
-*  Panagiotis Astithas, Daniel O'Connor, Sheldon Hearn for help with FreeBSD.
+*  Manfred Jonsson for idea of programming, which looks for me good
 
-*  Artur Kubiak for help with Solaris.
+*  Michael Hund for many improvements and progress in 7110/6210 source...
 
-*  Markus Plail for work on 7110 support.
+*  Ralf Thelen for very required by many, many people patch and getting
+   infrared sockets to work -> small changes, few days of hard searching :-).
+   Also sms stuff is OK now
 
-*  Simon Huggins for help with 6210 and IrDA.
+*  Gabriele Zappi for many 6210 improvements and big calendar source
 
-*  Lucy for making pizza and putting up with Hugh disappearing to
-   work on this.  Rachael for new parent induced insomnia...
+*  Andrea Scopece for 61xx source for netmonitor and other improvements
 
-*  Last not least: Mirka for allowing Pavel to work on gnokii
-   and for _great_ gnokii operator logos...
+*  ....and other people, who reported me bugs or want(ed) to use mygnokii
+   and help me in making it the best !
 
 We tried to mentioned everyone who contributed to gnokii project but we
 might to forgot someone. If anyone does feel that we missed him and his
index d5666ac..8dd1724 100644 (file)
@@ -1,47 +1,63 @@
 #
-# Makefile for the GNOKII tool suite's documentation directory
-#
-# Copyright (C) 1999 Hugh Blemings & Pavel Janík ml.
-#               2000 Karel Zak
+# Makefile for the xGNOKII tool suite.
 #
 
-TOPDIR=../
-include ${TOPDIR}/Makefile.global
+TOPDIR=..
+include $(TOPDIR)/Makefile.global
 
-#
-# Documentation for gnokii (xgnokii install documentation files itself).
-#
+HELP1_DIR = en_US
+HELP11_DIR = pl_PL
+HELP2_DIR = examples
+HELP3_DIR = default
+
+GNOKII1_MAN1 = "man/gnokii.1"
+GNOKII1_MAN2 = "man/todologo.1"
+GNOKII8_MAN1 = "man/gnokiid.8"
+GNOKII8_MAN2 = "man/mgnokiidev.8"
+XGNOKII_MAN = "man/xgnokii.1x"
 
-INSTALL_DOCS =         README \
-               README-3810 \
-               README-6110 \
-               CREDITS \
-               DataCalls-QuickStart \
-               README-WIN32 \
-               gettext-howto \
-               gnokii.nol \
-               gnokii-ir-howto \
-               packaging-howto \
-               sample.gnokiirc
-
-GNOKII1_MAN = "man/gnokii.1 man/todologo.1"
-GNOKII8_MAN = "man/gnokiid.8 man/mgnokiidev.8"
-XGNOKII_MAN = man/xgnokii.1x
-
-all:
+all: 
        @echo
 
+makelib:
+       @echo
+       
 install:
        $(INSTALL) -d $(docdir)
-       @for xxx in $(INSTALL_DOCS); do \
-           if [ -e $$xxx ]; then \
-               $(INSTALL) -m 0444 $$xxx $(docdir)/$$xxx; \
-           fi; \
-       done
-       $(INSTALL) $(GNOKII1_MAN) $(man1dir)
-       $(INSTALL) $(GNOKII8_MAN) $(man8dir)
-       if [ "x$HAVE_XGNOKII" = xyes ]; then \
-               $(INSTALL) $(XGNOKII_MAN) $(xmandir) \
+
+       ( cd $(HELP1_DIR); \
+         $(FIND) . -type d \! -path "*CVS*" \
+              -exec $(INSTALL) -d $(docdir)/en_US/{} \; ; \
+         $(FIND) . -type f \! -path "*CVS*" \
+              -exec $(INSTALL) -m 0444 {} $(docdir)/en_US/{} \; \
+       )
+       ( cd $(HELP11_DIR); \
+         $(FIND) . -type d \! -path "*CVS*" \
+              -exec $(INSTALL) -d $(docdir)/pl_PL/{} \; ; \
+         $(FIND) . -type f \! -path "*CVS*" \
+              -exec $(INSTALL) -m 0444 {} $(docdir)/pl_PL/{} \; \
+       )
+
+       ( cd $(HELP2_DIR); \
+         $(FIND) . -type d \! -path "*CVS*" \
+              -exec $(INSTALL) -d $(docdir)/examples/{} \; ; \
+         $(FIND) . -type f \! -path "*CVS*" \
+              -exec $(INSTALL) -m 0444 {} $(docdir)/examples/{} \; \
+       )
+       ( cd $(HELP3_DIR); \
+         $(FIND) . -type d \! -path "*CVS*" \
+              -exec $(INSTALL) -d $(docdir)/default/{} \; ; \
+         $(FIND) . -type f \! -path "*CVS*" \
+              -exec $(INSTALL) -m 0444 {} $(docdir)/default/{} \; \
+       )
+       $(INSTALL) -m 0444 CREDITS $(docdir)
+       $(INSTALL) -m 0444 ../COPYING $(docdir)
+       $(INSTALL) $(GNOKII1_MAN1) $(man1dir)
+       $(INSTALL) $(GNOKII1_MAN2) $(man1dir)
+       $(INSTALL) $(GNOKII8_MAN1) $(man8dir)
+       $(INSTALL) $(GNOKII8_MAN2) $(man8dir)
+       if [ "x$(HAVE_XGNOKII)" = xyes ]; then \
+               ($(INSTALL) $(XGNOKII_MAN) $(xmandir)) \
        fi
        @echo "done"
 
index 1c9e4a2..214d696 100644 (file)
@@ -61,16 +61,16 @@ resets the phone.
 
 .SS CALENDAR
 .TP 
-.BR "\-\-getcalendarnote \fIstart\fP [\fIsend\fP] [\-v]"
-get the note with numbers from \fIstart\fR to \fIend\fR from calendar.
+.BR "\-\-getcalendarnote \fIindex\fP [\-v]"
+get the note with number \fIindex\fR from calendar.
 .PP 
 [\-v] \- output in vCalendar 1.0 format
 .TP 
 .BR "\-\-writecalendarnote"
 write the note to calendar.
 .TP 
-.BR "\-\-deletecalendarnote \fIstart\fP [\fIend\fP]"
-delete the note with numbers from \fIstart\fR to \fIend\fR from calendar.
+.BR "\-\-deletecalendarnote \fIindex\fP"
+delete the note with number [\fIindex\fR] from calendar.
 
 .SS SMS
 .TP 
@@ -193,4 +193,4 @@ See also Docs/CREDITS from Gnokii sources.
 This program is distributed under the GNU Public License.
 
 .SH "SEE ALSO"
-gnokiid, xgnokii
+gnokiid, xgnokii, xlogos
index db9b969..c66955b 100644 (file)
@@ -33,7 +33,7 @@ from \fIgnokii.nol\fR that is distributed with
 mobile phone. Use 
 .B gnokii
 or
-.B xgnokii
+.B xlogos
 to do the uploading.
 
 .SH EXAMPLES
@@ -52,5 +52,6 @@ Tomi Ollila <Tomi.Ollila@iki.fi>
 This program is distributed under the GNU Public License.
 
 .SH SEE ALSO
-.BR gnokii(1), xgnokii(1x)
+.BR gnokii(1),
+xlogos
 
index 16f1037..5fad541 100644 (file)
@@ -36,4 +36,4 @@ See also Docs/CREDITS from the Gnokii sources.
 This program is distributed under the GNU Public License.
 
 .SH "SEE ALSO"
-gnokii, gnokiid
+gnokii, gnokiid, xlogos
index cfef684..1feaf9c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -18,17 +18,26 @@ include ${TOPDIR}/Makefile.global
 BIN_DIRS = gnokii
 
 ifndef WIN32
-BIN_DIRS += gnokiid utils
+BIN_DIRS += gnokiid
+BIN_DIRS += mgnetd
+BIN_DIRS += mgnetd/mg_demo_client
 endif
 
-DIRS =  common/phones \
-       common/links \
-       common/devices \
-       common/data \
-        common \
+DIRS =  common \
+        Docs \
        $(BIN_DIRS)
 
-GTK_DIRS =  xgnokii
+#
+# For now gnokiid and utils only make sense on Unix like systems.
+# Some other stuff that makes only sense on Win32 platform.
+#
+
+ifndef WIN32
+DIRS +=        utils
+endif
+
+GTK_DIRS =  xgnokii \
+            xlogos
 
 PO_DIR   =     po
 DOCS_DIR =     Docs
@@ -47,6 +56,25 @@ all: $(DIRS)
        fi
        @echo "done"
 
+makelib:
+       @for dir in $(DIRS); do \
+           if [ -e $$dir/Makefile ]; then \
+               $(MAKE) -C $$dir makelib; \
+           fi; \
+       done
+       @if [ "x$(USE_NLS)" = xyes ]; then \
+               $(MAKE) -C $(PO_DIR) makelib; \
+       fi
+
+       @if [ "$(GTK_LIBS)" ]; then \
+               for dir in $(GTK_DIRS); do \
+                   if [ -e $$dir/Makefile ]; then \
+                       $(MAKE) -C $$dir makelib; \
+                   fi; \
+               done \
+       fi
+       @echo "done"
+
 dummy:
 
 $(DIRS): dummy
@@ -90,8 +118,6 @@ distclean:   clean
                packaging/Slackware/SlackBuild \
                po/Makefile.in \
                debian
-       $(RM) `$(FIND) . -name "*~"`
-       @echo "done"
 
 dep:
        @for dir in $(DIRS); do \
@@ -109,7 +135,7 @@ dep:
        fi
        @echo "done"
 
-install: all
+install:
        @for dir in $(DIRS); do \
            if [ -e $$dir/Makefile ]; then \
                $(MAKE) -C $$dir install; \
index 05f4a5a..23fa672 100644 (file)
@@ -27,7 +27,7 @@ libdir         = @libdir@
 xgnokii_libdir = @XGNOKIIDIR@/@XPACKAGE@
 man1dir        = @mandir@/man1/
 man8dir        = @mandir@/man8/
-xmandir        = ${prefix}/X11R6/man/man1/
+xmandir        = @mandir@/man1/
 docdir         = ${prefix}/doc/${PACKAGE}
 locdir         = @datadir@/locale
 
diff --git a/VERSION b/VERSION
index 15a1a14..4735d92 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.4.0pre5
+0.3.3_pre8-gold_2002_02_16
index 9b44ad1..e396803 100644 (file)
@@ -1,12 +1,7 @@
 
 #
-# $Id$
-#
 # Makefile for the GNOKII tool suite.
 #
-# Copyright (C) 1999 Hugh Blemings & Pavel Janík ml.
-#               2000 Karel Zak
-#
 
 #
 # For this common directory is used "subsystem.o" .o files concept.
 TOPDIR=..
 include $(TOPDIR)/Makefile.global
 
-OBJS = cfgreader.o \
-       device.o \
+CFLAGS += $(PTHREAD_CFLAGS)
+
+DIRS =         protocol \
+               oldmodules \
+               newmodules
+
+OBJS = devices/device.o \
+       data/rlp-common.o \
+       data/rlp-crc24.o \
+       files/midifile.o \
        gsm-ringtones.o \
+       gsm-coding.o \
+       gsm-datetime.o \
+       gsm-wap.o \
        gsm-api.o \
+       gsm-phonebook.o \
+       gsm-calendar.o \
        gsm-networks.o \
-       vcal.o \
-       misc.o \
-        gsm-sms.o \
        gsm-bitmaps.o \
-       gsm-common.o \
-       gsm-encoding.o \
-       gsm-error.o \
-       gsm-statemachine.o
-
-all: libgnokii.so gsm-filetypes.o
+       gsm-sms.o \
+       files/cfgreader.o \
+       misc.o \
+       protocol/fbus.o \
+       protocol/fbusirda.o \
+       protocol/mbus.o \
+       protocol/at.o \
+       newmodules/sniff/sniff.o \
+       newmodules/newat.o \
+       newmodules/n6110.o \
+       newmodules/n7110.o
+
+DATA_OBJS = data/virtmodem.o \
+       data/at-emulator.o \
+       data/datapump.o
+
+ifdef WIN32
+       OBJS += $(TOPDIR)/win32/winserial.o
+else
+       OBJS += devices/unixserial.o \
+               devices/unixirda.o \
+               devices/tekram.o
+endif
 
-phones/PHONES.o:
-       $(MAKE) -C phones PHONES.o
+ifdef XPM_CFLAGS
+    CFLAGS += $(XPM_CFLAGS)
+endif
 
-links/LINKS.o:
-       $(MAKE) -C links LINKS.o
+all: COMMON.o DATA.o gsm-filetypes.o
 
-devices/DEVICES.o:
-       $(MAKE) -C devices DEVICES.o
+COMMON.o: $(OBJS)
+       $(LD) $(LDREL) $(LDOUT) COMMON.o $(OBJS)
 
-libgnokii.so: $(OBJS) phones/PHONES.o links/LINKS.o devices/DEVICES.o
-       $(CC) -shared -o libgnokii.so $(OBJS) phones/PHONES.o links/LINKS.o devices/DEVICES.o
+DATA.o: $(DATA_OBJS)
+       $(LD) $(LDREL) $(LDOUT) DATA.o $(DATA_OBJS)
 
-gsm-filetypes.o: gsm-filetypes.c
-       $(CC) $(CFLAGS) $(CPPFLAGS) $(XPM_CFLAGS) -c gsm-filetypes.c
+gsm-filetypes.o: files/gsm-filetypes.c 
+       $(CC) $(CFLAGS) -c files/gsm-filetypes.c
 
-vcal.c: vcal.lx
-       $(LEX) -ovcal.c vcal.lx
+makelib: $(OBJS) DATA.o gsm-filetypes.o
+       $(CC) -shared -o libmygnokii.so $(OBJS) DATA.o gsm-filetypes.o
 
 clean:
-       $(RM) $(OBJS) *~ depend libgnokii.so gsm-filetypes.o vcal.c phones/PHONES.o links/LINKS.o devices/DEVICES.o
-
+       $(RM) $(OBJS) $(DATA_OBJS) *~ depend libmygnokii.so COMMON.o gsm-filetypes.o DATA.o
+       
 install:
        $(INSTALL) -d $(libdir)
-       $(INSTALL) libgnokii.so $(libdir)
+       $(INSTALL) libmygnokii.so $(libdir)
        @echo
 
 depend dep:
@@ -68,4 +90,3 @@ endif
 
 
 .PHONY: all install clean dep depend
-
index e952df2..41445c8 100644 (file)
@@ -6,8 +6,6 @@
 
   A Linux/Unix toolset and driver for Nokia mobile phones.
 
-  Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
-
   Released under the terms of the GNU GPL, see file COPYING for more details.
 
   This file provides a virtual modem or "AT" interface to the GSM phone by
@@ -33,7 +31,7 @@
 
 #ifndef WIN32
 
-#  include <termios.h>
+  #include <termios.h>
 
 #endif
 
@@ -307,7 +305,7 @@ static GSM_Error ATEM_ReadSMS(int number, GSM_MemoryType type, GSM_SMSMessage *m
        GSM_Error error;
 
        message->MemoryType = type;
-       message->Number = number;
+       message->Location = number;
        error = GSM->GetSMSMessage(message);
 
        return error;
@@ -317,14 +315,13 @@ static void ATEM_PrintSMS(char *line, GSM_SMSMessage *message, int mode)
 {
        switch (mode) {
        case INTERACT_MODE:
-               gsprintf(line, MAX_LINE_LENGTH, _("\n\rDate/time: %d/%d/%d %d:%02d:%02d Sender: %s Msg Center: %s\n\rText: %s\n\r"), message->Time.Day, message->Time.Month, message->Time.Year, message->Time.Hour, message->Time.Minute, message->Time.Second, message->RemoteNumber.number, message->MessageCenter.Number, message->MessageText);
+               gsprintf(line, MAX_LINE_LENGTH, _("\n\rDate/time: %d/%d/%d %d:%02d:%02d Sender: %s Msg Center: %s\n\rText: %s\n\r"), message->Time.Day, message->Time.Month, message->Time.Year, message->Time.Hour, message->Time.Minute, message->Time.Second, message->Sender, message->MessageCenter.Number, message->MessageText);
                break;
        case TEXT_MODE:
-               if ((message->DCS.Type == SMS_GeneralDataCoding) &&
-                   (message->DCS.u.General.Alphabet == SMS_8bit))
-                       gsprintf(line, MAX_LINE_LENGTH, _("\"%s\",\"%s\",,\"%02d/%02d/%02d,%02d:%02d:%02d+%02d\"\n\r%s"), (message->Status ? _("REC READ") : _("REC UNREAD")), message->RemoteNumber.number, message->Time.Year, message->Time.Month, message->Time.Day, message->Time.Hour, message->Time.Minute, message->Time.Second, message->Time.Timezone, _("<Not implemented>"));
+               if (message->Coding==GSM_Coding_8bit)
+                       gsprintf(line, MAX_LINE_LENGTH, _("\"%s\",\"%s\",,\"%02d/%02d/%02d,%02d:%02d:%02d+%02d\"\n\r%s"), (message->Status ? _("REC READ") : _("REC UNREAD")), message->Sender, message->Time.Year, message->Time.Month, message->Time.Day, message->Time.Hour, message->Time.Minute, message->Time.Second, message->Time.Timezone, _("<Not implemented>"));
                else
-                       gsprintf(line, MAX_LINE_LENGTH, _("\"%s\",\"%s\",,\"%02d/%02d/%02d,%02d:%02d:%02d+%02d\"\n\r%s"), (message->Status ? _("REC READ") : _("REC UNREAD")), message->RemoteNumber.number, message->Time.Year, message->Time.Month, message->Time.Day, message->Time.Hour, message->Time.Minute, message->Time.Second, message->Time.Timezone, message->MessageText);
+                       gsprintf(line, MAX_LINE_LENGTH, _("\"%s\",\"%s\",,\"%02d/%02d/%02d,%02d:%02d:%02d+%02d\"\n\r%s"), (message->Status ? _("REC READ") : _("REC UNREAD")), message->Sender, message->Time.Year, message->Time.Month, message->Time.Day, message->Time.Hour, message->Time.Minute, message->Time.Second, message->Time.Timezone, message->MessageText);
                break;
        case PDU_MODE:
                gsprintf(line, MAX_LINE_LENGTH, _("<Not implemented>"));
@@ -339,7 +336,7 @@ static void ATEM_EraseSMS(int number, GSM_MemoryType type)
 {
        GSM_SMSMessage message;
        message.MemoryType = type;
-       message.Number = number;
+       message.Location = number;
        if (GSM->DeleteSMSMessage(&message) == GE_NONE) {
                ATEM_ModemResult(MR_OK);
        } else {
@@ -555,12 +552,12 @@ bool      ATEM_CommandPlusC(char **buf)
                                strcasecmp(*buf, "3") == 0 ||
                                strcasecmp(*buf, "\"REC READ\"") == 0 ||
                                strcasecmp(*buf, "\"STO SENT\"") == 0) {
-                               status = SMS_Sent;
+                               status = GSS_SENTREAD;
                        } else if (strcasecmp(*buf, "0") == 0 ||
                                strcasecmp(*buf, "2") == 0 ||
                                strcasecmp(*buf, "\"REC UNREAD\"") == 0 ||
                                strcasecmp(*buf, "\"STO UNSENT\"") == 0) {
-                               status = SMS_Unsent;
+                               status = GSS_NOTSENTREAD;
                        } else if (strcasecmp(*buf, "4") == 0 ||
                                strcasecmp(*buf, "\"ALL\"") == 0) {
                                status = 4; /* ALL */
index 969091a..4eede53 100644 (file)
@@ -6,28 +6,12 @@
 
   A Linux/Unix toolset and driver for Nokia mobile phones.
 
-  Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
-
   Released under the terms of the GNU GPL, see file COPYING for more details.
 
   This file provides routines to handle processing of data when connected in
   fax or data mode. Converts data from/to GSM phone to virtual modem
   interface.
 
-  $Log$
-  Revision 1.1.1.1  2001/11/25 21:59:07  short
-  :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
-
-  Revision 1.4  2001/11/17 16:41:35  pkot
-  Cleanup
-
-  Revision 1.3  2001/02/21 19:57:00  chris
-  More fiddling with the directory layout
-
-  Revision 1.2  2001/02/17 22:40:51  chris
-  ATA support
-
-
 */
 
 #define                __data_datapump_c
@@ -69,12 +53,12 @@ bool DP_Initialise(int read_fd, int write_fd)
 {
        PtyRDFD = read_fd;
        PtyWRFD = write_fd;
-       ufds.fd = PtyRDFD;
-       ufds.events = POLLIN;
+       ufds.fd=PtyRDFD;
+       ufds.events=POLLIN;
        RLP_Initialise(GSM->SendRLPFrame, DP_CallBack);
-       RLP_SetUserRequest(Attach_Req, true);
-       pluscount = 0;
-       connected = false;
+       RLP_SetUserRequest(Attach_Req,true);
+       pluscount=0;
+       connected=false;
        return true;
 }
 
@@ -85,76 +69,78 @@ int DP_CallBack(RLP_UserInds ind, u8 *buffer, int length)
 
        switch(ind) {
        case Data:
-               if (CommandMode == false) write(PtyWRFD, buffer, length);
+               if (CommandMode==false) write(PtyWRFD, buffer, length);
                break;
        case Conn_Ind:
-               if (CommandMode == false) ATEM_ModemResult(MR_CARRIER);
-               RLP_SetUserRequest(Conn_Req, true);
+               if (CommandMode==false) ATEM_ModemResult(MR_CARRIER);
+               RLP_SetUserRequest(Conn_Req,true);
                break;
        case StatusChange:
-               if (buffer[0] == 0) {
-                       connected = true;
-                       if (CommandMode == false) ATEM_ModemResult(MR_CONNECT);
+               if (buffer[0]==0) {
+                       connected=true;
+                       if (CommandMode==false) ATEM_ModemResult(MR_CONNECT);
                }
                break;
        case Disc_Ind:
-               if (CommandMode == false) ATEM_ModemResult(MR_NOCARRIER);
-               connected = false;
+               if (CommandMode==false) ATEM_ModemResult(MR_NOCARRIER);
+               connected=false;
                /* Set the call passup back to the at emulator */
-               GSM->DialData(NULL, -1, &ATEM_CallPassup);
-               CommandMode = true;
+               GSM->DialData(NULL,-1,&ATEM_CallPassup);
+               CommandMode=true;
                break;
        case Reset_Ind:
-               RLP_SetUserRequest(Reset_Resp, true);
+               RLP_SetUserRequest(Reset_Resp,true);
                break;
        case GetData:
-               if (poll(&ufds, 1, 0)) {
+               if (poll(&ufds,1,0)) {
 
                        /* Check if the program has closed */
                        /* Return to command mode */
                        /* Note that the call will still be in progress, */
                        /* as with a normal modem (I think) */
 
-                       if (ufds.revents != POLLIN) { 
-                               CommandMode = true;
+                       if (ufds.revents!=POLLIN) { 
+                               CommandMode=true;
                                /* Set the call passup back to the at emulator */
-                               GSM->DialData(NULL, -1, &ATEM_CallPassup);
+                               GSM->DialData(NULL,-1,&ATEM_CallPassup);
                                return 0;
                        }
 
                        temp = read(PtyRDFD, buffer, length);
 
-                       if (temp < 0) return 0; /* FIXME - what do we do now? */
+                       if (temp<0) return 0; /* FIXME - what do we do now? */
 
                        /* This will only check +++ and the beginning of a read */
                        /* But there should be a pause before it anyway */
       
-                       if (buffer[0] == '+') {
+                       if (buffer[0]=='+') {
                                pluscount++;
-                               if (temp > 1) {
-                                       if (buffer[1] == '+') pluscount++;
-                                       else pluscount = 0;
-                                       if (temp > 2) {
-                                               if (buffer[2] == '+') pluscount++;
-                                               else pluscount = 0;
-                                               if (temp > 3) pluscount = 0;
+                               if (temp>1) {
+                                       if (buffer[1]=='+') pluscount++;
+                                       else pluscount=0;
+                                       if (temp>2) {
+                                               if (buffer[2]=='+') pluscount++;
+                                               else pluscount=0;
+                                               if (temp>3) pluscount=0;
                                        }
                                }
-                       } else pluscount = 0;
+                       } else pluscount=0;
       
-                       if (pluscount == 3) {
-                               CommandMode = true;
+                       if (pluscount==3) {
+                               CommandMode=true;
                                /* Set the call passup back to the at emulator */
-                               GSM->DialData(NULL, -1, &ATEM_CallPassup);
+                               GSM->DialData(NULL,-1,&ATEM_CallPassup);
                                ATEM_ModemResult(MR_OK);
                                break;
                        }
       
                        return temp;
                }
+               return 0;
                break;
+
        default:
-               break;
+
        }
        return 0;
 }
@@ -163,17 +149,17 @@ void DP_CallPassup(char c)
 {
        switch (c) {
        case 'D':
-               if (CommandMode == false) ATEM_ModemResult(MR_CARRIER);
-               RLP_SetUserRequest(Conn_Req, true);
-               connected = true;
+               if (CommandMode==false) ATEM_ModemResult(MR_CARRIER);
+               RLP_SetUserRequest(Conn_Req,true);
+               connected=true;
                break;
        case ' ':
-               CommandMode = true;
+               CommandMode=true;
                /* Set the call passup back to the at emulator */
-               GSM->DialData(NULL, -1, &ATEM_CallPassup);
+               GSM->DialData(NULL,-1,&ATEM_CallPassup);
                ATEM_ModemResult(MR_NOCARRIER);
                RLP_SetUserRequest(Disc_Req, true);
-               connected = false;
+               connected=false;
                break;
        default:
                break;
index 599ab6a..9c46e0d 100644 (file)
@@ -6,8 +6,6 @@
 
   A Linux/Unix toolset and driver for Nokia mobile phones.
 
-  Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
-  
   Released under the terms of the GNU GPL, see file COPYING for more details.
 
   The development of RLP protocol is sponsored by SuSE CR, s.r.o. (Pavel use
   Actual implementation of RLP protocol. Based on GSM 04.22 version 7.1.0,
   downloadable from www.etsi.org (if you register with them)
 
-  $Log$
-  Revision 1.1.1.1  2001/11/25 21:59:08  short
-  :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
-
-  Revision 1.5  2001/03/26 23:39:36  pkot
-  Minor updates:
-   - Windows INLINE patch (Manfred Jonsson)
-   - patch to configure.in to compile under FreeBSD (Panagiotis Astithas)
-   - other cleanups (me)
-
-  Revision 1.4  2001/03/13 01:23:18  pkot
-  Windows updates (Manfred Jonsson)
-
-  Revision 1.3  2001/02/21 19:57:00  chris
-  More fiddling with the directory layout
-
-  Revision 1.2  2001/02/17 22:40:51  chris
-  ATA support
-
-
 */
 
 #include <stdio.h>
index 3b7108e..cc8af90 100644 (file)
@@ -6,20 +6,10 @@
 
   A Linux/Unix toolset and driver for Nokia mobile phones.
 
-  Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
-
   Released under the terms of the GNU GPL, see file COPYING for more details.
 
   CRC24 (aka FCS) implementation in RLP.
 
-  $Log$
-  Revision 1.1.1.1  2001/11/25 21:59:08  short
-  :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
-
-  Revision 1.2  2001/02/21 19:57:02  chris
-  More fiddling with the directory layout
-
-
 */
 
 #include "data/rlp-crc24.h"
index fe18f6b..7c7f4e2 100644 (file)
@@ -5,8 +5,6 @@
 
   A Linux/Unix toolset and driver for Nokia mobile phones.
 
-  Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
-
   Released under the terms of the GNU GPL, see file COPYING for more details.
 
   This file provides a virtual modem interface to the GSM phone by calling
   (AT-emulator) and "online" mode where the data pump code translates data
   from/to the GSM handset and the modem data/fax stream.
 
-  $Log$
-  Revision 1.1.1.1  2001/11/25 21:59:08  short
-  :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
-
-  Revision 1.4  2001/04/14 23:23:43  pkot
-  Fixed problems with grantpt
-
-  Revision 1.3  2001/03/21 23:36:04  chris
-  Added the statemachine
-  This will break gnokii --identify and --monitor except for 6210/7110
-
-  Revision 1.2  2001/02/21 19:57:02  chris
-  More fiddling with the directory layout
-
-  Revision 1.1  2001/02/16 14:29:51  chris
-  Restructure of common/.  Fixed a problem in fbus-phonet.c
-  Lots of dprintfs for Marcin
-  Any size xpm can now be loaded (eg for 7110 startup logos)
-  nk7110 code detects 7110/6210 and alters startup logo size to suit
-  Moved Marcin's extended phonebook code into gnokii.c
-
-  Revision 1.5  2001/01/08 15:11:37  pkot
-  Documentation updates.
-  Fixed some bugs and removed FIXMEs.
-  We need to move some stuff from configure.in to aclocal.m4
-
-  Revision 1.4  2001/01/02 09:09:09  pkot
-  Misc fixes and updates.
-
-  Revision 1.3  2000/12/27 10:54:14  pkot
-  Added Unix98 PTYs support (Michael Mráka).
-
-  
 */
 
 #define                __virtmodem_c
@@ -84,7 +49,7 @@
 
        /* Global variables */
 
-extern bool TerminateThread;
+//extern bool TerminateThread;
 int ConnectCount;
 
        /* Local variables */
@@ -101,7 +66,7 @@ bool                 RequestTerminate;
 
        /* If initialised in debug mode, stdin/out is used instead
           of ptys for interface. */
-bool   VM_Initialise(char *model,char *port, char *initlength, GSM_ConnectionType connection, char *bindir, bool debug_mode, bool GSMInit)
+bool   VM_Initialise(char *model,char *port, char *initlength, GSM_ConnectionType connection, char *bindir, bool debug_mode, bool GSMInit,char *synchronizetime)
 {
        int             rtn;
 
@@ -120,9 +85,10 @@ bool        VM_Initialise(char *model,char *port, char *initlength, GSM_ConnectionType
 #ifdef DEBUG
          fprintf (stderr , "Initialising GSM\n");
 #endif /* DEBUG */
-         if ((VM_GSMInitialise(model, port, initlength, connection) != GE_NONE)) {
+         if ((VM_GSMInitialise(model, port, initlength, connection, synchronizetime) != GE_NONE)) {
                fprintf (stderr, _("VM_Initialise - VM_GSMInitialise failed!\n"));
                return (false);
+               
          }
        }
        GSMInit=false;
@@ -275,7 +241,7 @@ void    VM_CharHandler(void)
       /* Note that file closure etc. should have been dealt with in ThreadLoop */
       
       if (res < 0) {   
-           TerminateThread=true;
+//         TerminateThread=true;
            return;
       }
        
@@ -284,15 +250,14 @@ void    VM_CharHandler(void)
 }     
 
        /* Initialise GSM interface, returning GSM_Error as appropriate  */
-GSM_Error      VM_GSMInitialise(char *model, char *port, char *initlength, GSM_ConnectionType connection)
+GSM_Error      VM_GSMInitialise(char *model, char *port, char *initlength, GSM_ConnectionType connection, char *synchronizetime)
 {
        int             count=0;
        GSM_Error       error;
-       static GSM_Statemachine sm;
 
                /* Initialise the code for the GSM interface. */     
 
-       error = GSM_Initialise(model,port, initlength, connection, RLP_DisplayF96Frame, &sm);
+       error = GSM_Initialise(model,port, initlength, connection, RLP_DisplayF96Frame, synchronizetime);
 
        if (error != GE_NONE) {
                fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
index 21b5b6f..5da6097 100644 (file)
@@ -6,9 +6,6 @@
  *
  * A Linux/Unix toolset and driver for Nokia mobile phones.
  *
- * Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
- * Copyright (C) 2000-2001  Marcel Holtmann <marcel@holtmann.org>
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * License as published by the Free Software Foundation; either
  * License along with this library; if not, write to the Free
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Log$
- * Revision 1.1.1.1  2001/11/25 21:59:08  short
- * :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
- *
- * Revision 1.2  2001/02/21 19:57:03  chris
- * More fiddling with the directory layout
- *
- * Revision 1.1  2001/02/16 14:29:51  chris
- * Restructure of common/.  Fixed a problem in fbus-phonet.c
- * Lots of dprintfs for Marcin
- * Any size xpm can now be loaded (eg for 7110 startup logos)
- * nk7110 code detects 7110/6210 and alters startup logo size to suit
- * Moved Marcin's extended phonebook code into gnokii.c
- *
- * Revision 1.2  2001/02/12 15:13:46  chris
- * Fixed my bug in xgnokii_contacts.c and added <string.h> to tekram.c
- *
- * Revision 1.1  2001/02/09 18:12:53  chris
- * Marcel's tekram support
- *
  */
 
 #include <stdio.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <termios.h>
 #include <string.h>
 
 #ifndef WIN32
-#include "devices/unixserial.h"
+  #include <fcntl.h>
+  #include <sys/ioctl.h>
+  #include <termios.h>
+  #include "devices/unixserial.h"
 #else
-#include "winserial.h"
+  #include <windows.h>
+  #include "devices/winserial.h"
 #endif
 
 #include "devices/tekram.h"
 
-
-
-
 int tekram_open(__const char *__file) {
 
   return (serial_open(__file, O_RDWR | O_NOCTTY | O_NONBLOCK));
@@ -76,18 +51,9 @@ void tekram_close(int __fd) {
 
 void tekram_reset(int __fd) {
 
-  serial_setdtrrts(__fd, 0, 0);
-
-  usleep(50000);
-
-  serial_setdtrrts(__fd, 1, 0);
-
-  usleep(1000);
-
-  serial_setdtrrts(__fd, 1, 1);
-
-  usleep(50);
-
+  serial_setdtrrts(__fd, 0, 0); usleep(50000);
+  serial_setdtrrts(__fd, 1, 0); usleep(1000);
+  serial_setdtrrts(__fd, 1, 1); usleep(50);
 
   serial_changespeed(__fd, 9600);
 }
index 2931d11..cfbf39a 100644 (file)
@@ -1,14 +1,10 @@
 /*
  * $Id$
  *
- *
  * G N O K I I
  *
  * A Linux/Unix toolset and driver for Nokia mobile phones.
  *
- * Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
- * Copyright (C) 2000-2001  Marcel Holtmann <marcel@holtmann.org>
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * License as published by the Free Software Foundation; either
  * License along with this library; if not, write to the Free
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Log$
- * Revision 1.1.1.1  2001/11/25 21:59:09  short
- * :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
- *
- * Revision 1.7  2001/11/08 16:49:19  pkot
- * Cleanups
- *
- * Revision 1.6  2001/08/17 00:18:12  pkot
- * Removed recv() from IrDA initializing procedure (many people)
- *
- * Revision 1.5  2001/06/27 23:52:48  pkot
- * 7110/6210 updates (Marian Jancar)
- *
- * Revision 1.4  2001/06/20 21:27:34  pkot
- * IrDA patch (Marian Jancar)
- *
- * Revision 1.3  2001/02/21 19:57:04  chris
- * More fiddling with the directory layout
- *
- * Revision 1.2  2001/02/20 21:55:10  pkot
- * Small #include updates
- *
- * Revision 1.1  2001/02/16 14:29:52  chris
- * Restructure of common/.  Fixed a problem in fbus-phonet.c
- * Lots of dprintfs for Marcin
- * Any size xpm can now be loaded (eg for 7110 startup logos)
- * nk7110 code detects 7110/6210 and alters startup logo size to suit
- * Moved Marcin's extended phonebook code into gnokii.c
- *
- * Revision 1.2  2001/02/06 21:15:35  chris
- * Preliminary irda support for 7110 etc.  Not well tested!
- *
- * Revision 1.1  2001/02/03 23:56:17  chris
- * Start of work on irda support (now we just need fbus-irda.c!)
- * Proper unicode support in 7110 code (from pkot)
- *
  */
 
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
 #include "devices/unixirda.h"
+#include "devices/linuxirda.h"
+
 
 #ifndef AF_IRDA
 #define AF_IRDA 23
 #define DISCOVERY_SLEEP                0.4
 
 static char *phone[] = {
-       "Nokia 7110", "Nokia 6210"
+        "Nokia 5210",
+       "Nokia 6210", "Nokia 6250", "Nokia 6310",
+       "Nokia 7110",
+       "Nokia 8210", "Nokia 8310", "Nokia 8850"
 };
 
 double d_time(void)
@@ -101,18 +77,17 @@ double d_sleep(double s)
        return time;
 }
 
-static int irda_discover_device(void)
+static int irda_discover_device(int fd)
 {
 
        struct irda_device_list *list;
        struct irda_device_info *dev;
        unsigned char           *buf;
-       int                     s, len, i, j, daddr = -1, fd;
+       int                     s, len, i, j;
+       int                     daddr = -1;
        double                  t1, t2;
        int phones = sizeof(phone) / sizeof(*phone);
        
-       fd = socket(AF_IRDA, SOCK_STREAM, 0);
-       
        len = sizeof(*list) + sizeof(*dev) * 10;        // 10 = max devices in discover
        buf = malloc(len);
        list = (struct irda_device_list *)buf;
@@ -129,11 +104,15 @@ static int irda_discover_device(void)
                                for (j = 0; (j < phones) && (daddr == -1); j++) {
                                        if (strncmp(dev[i].info, phone[j], INFO_LEN) == 0) {
                                                daddr = dev[i].daddr;
-                                               dprintf("%s\t%x\n", dev[i].info, dev[i].daddr);
+#ifdef DEBUG
+                                               fprintf(stdout,_("%s\t%x\n"), dev[i].info, dev[i].daddr);
+#endif
                                        }
                                }
                                if (daddr == -1) {
-                                       dprintf("unknown: %s\t%x\n", dev[i].info, dev[i].daddr);
+#ifdef DEBUG
+                                       fprintf(stdout,_("unknown: %s\t%x\n"), dev[i].info, dev[i].daddr);
+#endif
                                }
                        }
                }
@@ -147,7 +126,6 @@ static int irda_discover_device(void)
        } while ((t2 - t1 < DISCOVERY_TIMEOUT) && (daddr == -1));
        
        free(buf);
-       close(fd);
        
        return daddr;
 }
@@ -156,24 +134,44 @@ int irda_open(void)
 {
        struct sockaddr_irda    peer;
        int                     fd = -1, daddr;
+       int                     pgrp;         
        
-       daddr = irda_discover_device();                 /* discover the devices */
        
-       if (daddr != -1)  {
-               fd = socket(AF_IRDA, SOCK_STREAM, 0);   /* Create socket */
-               peer.sir_family = AF_IRDA;
-               peer.sir_lsap_sel = LSAP_ANY;
-               peer.sir_addr = daddr;
-               strcpy(peer.sir_name, "Nokia:PhoNet");
+       fd = socket(AF_IRDA, SOCK_STREAM, 0);   /* Create socket */
+       if (fd == -1) {
+               perror("socket");
+                       exit(1);
+                    }
+
+       /* discover the devices */ 
+       daddr = irda_discover_device(fd);
+       if (daddr == -1)  {
+                       printf("irda_discover: no nokia devices found");
+                       exit(1);
+                    }
+
+       /* Arrange for the current process to receive
+           SIGIO when the state of the socket changes. */
+       pgrp = getpid();
+       if (fcntl (fd, F_SETOWN, pgrp) < 0)
+       perror("F_SETOWN");
+
+       /*  Set the socket state for Asynchronous  */
+       if (fcntl (fd, F_SETFL, FASYNC) < 0) {
+               perror("fcntl");
+                       exit(1);
+                    }
+
+       peer.sir_family = AF_IRDA;
+       peer.sir_lsap_sel = LSAP_ANY;
+       peer.sir_addr = daddr;
+       strcpy(peer.sir_name, "Nokia:PhoNet");
                
-               if (connect(fd, (struct sockaddr *)&peer, sizeof(peer))) {      /* Connect to service "Nokia:PhoNet" */
-                       perror("connect");
-                       close(fd);
-                       fd = -1;
-/*             } else { FIXME: It does not work in most cases. Why? Or why it should work?
-                       recv(fd, NULL, 0, 0);            call recv first to make select work correctly */
+       if (connect(fd, (struct sockaddr *)&peer, sizeof(peer))) {      /* Connect to service "Nokia:PhoNet" */
+               perror("connect");
+               close(fd);
+               fd = -1;
                }
-       }
        
        return fd;
 }
@@ -186,7 +184,20 @@ int irda_close(int fd)
 
 int irda_write(int __fd, __const __ptr_t __bytes, int __size)
 {
-       return (send(__fd, __bytes, __size, 0));
+  int actual,ret;
+
+   actual = 0;
+   
+   do {
+    if ((ret = send(__fd, __bytes, __size - actual, 0)) < 0)
+       return(actual);
+
+       actual += ret;
+       __bytes += ret;
+
+    } while (actual < __size);
+
+    return (actual);
 }
 
 int irda_read(int __fd, __ptr_t __bytes, int __size)
index 916ba4a..bc7e37e 100644 (file)
@@ -6,48 +6,8 @@
 
   A Linux/Unix toolset and driver for Nokia mobile phones.
 
-  Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
-
   Released under the terms of the GNU GPL, see file COPYING for more details.
 
-  $Log$
-  Revision 1.1.1.3  2001/12/05 03:16:40  short
-  :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Dec  4 22:45 CET 2001
-
-  Revision 1.12  2001/11/29 17:54:56  pkot
-  Cleanup. Removed cvs logs.
-
-  Revision 1.11  2001/11/27 12:19:01  pkot
-  Cleanup, indentation, ANSI complaint preprocesor symbols (Jan Kratochvil, me)
-
-  Revision 1.10  2001/11/14 10:46:12  pkot
-  Small cleanup with __unices__
-
-  Revision 1.9  2001/09/14 12:15:28  pkot
-  Cleanups from 0.3.3 (part1)
-
-  Revision 1.8  2001/08/20 23:27:37  pkot
-  Add hardware shakehand to the link layer (Manfred Jonsson)
-
-  Revision 1.7  2001/07/03 00:03:36  pkot
-  Small fixes to let gnokii compile and work under solaris (thanks to Artur Kubiak)
-
-  Revision 1.6  2001/03/21 23:36:04  chris
-  Added the statemachine
-  This will break gnokii --identify and --monitor except for 6210/7110
-
-  Revision 1.5  2001/03/19 23:43:46  pkot
-  Solaris/ *BSD '#if defined' cleanup
-
-  Revision 1.4  2001/03/13 01:21:38  pkot
-  *BSD updates (Bert Driehuis)
-
-  Revision 1.3  2001/03/06 22:27:46  pkot
-  Misc docs and Makefiles updates and cleanups
-
-  Revision 1.2  2001/02/21 19:57:05  chris
-  More fiddling with the directory layout
-
 */
 
 #include "misc.h"
 #include <sys/ioctl.h>
 #include <string.h>
 
+#if __unices__
+#  include <sys/file.h>
+#endif
+
 #include <termios.h>
 #include "devices/unixserial.h"
 
 #ifdef HAVE_SYS_IOCTL_COMPAT_H
-#  include <sys/ioctl_compat.h>
+  #include <sys/ioctl_compat.h>
 #endif
 
 #ifdef HAVE_SYS_SELECT_H
-#  include <sys/select.h>
+#include <sys/select.h>
 #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                     /* HAVE_TERMIOS_CSPEED */
-       return 0;
-}
-#  endif                       /* HAVE_CFSETISPEED && HAVE_CFSETOSPEED */
-#endif                         /* 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
+  #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;
+
+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));
+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);
+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;
 
-       if (fd < 0) return fd;
+  /* Allow process/thread to receive SIGIO */
 
-       /* 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);
-       }
+  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;
+  /* 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;
+void serial_setdtrrts(int __fd, int __dtr, int __rts) {
+
+  unsigned int flags;
 
-       if (__dtr)
-               ioctl(__fd, TIOCMBIS, &flags);
-       else
-               ioctl(__fd, TIOCMBIC, &flags);
+  flags = TIOCM_DTR;
 
-       flags = TIOCM_RTS;
+  if (__dtr) ioctl(__fd, TIOCMBIS, &flags);
+        else ioctl(__fd, TIOCMBIC, &flags);
 
-       if (__rts)
-               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;
+int serial_select(int fd, struct timeval *timeout) {
+
+  fd_set readfds;
 
-       FD_ZERO(&readfds);
-       FD_SET(fd, &readfds);
+  FD_ZERO(&readfds);
+  FD_SET(fd, &readfds);
+
+  return (select(fd + 1, &readfds, NULL, NULL, timeout));
 
-       return (select(fd + 1, &readfds, NULL, NULL, timeout));
 }
 
 
 /* Change the speed of the serial device. */
-void serial_changespeed(int __fd, int __speed)
-{
+
+void serial_changespeed(int __fd, int __speed) {
+
 #ifndef SGTTY
-       struct termios t;
+  struct termios t;
 #else
-       struct sgttyb t;
+  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);
+  int speed=B9600;
 
-       if (cfsetspeed(&t, speed) == -1)
-               dprintf("Serial port speed setting failed\n");
+  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;
+  }
 
-       tcsetattr(__fd, TCSADRAIN, &t);
+#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
-       ioctl(__fd, TIOCGETP, &t);
+  cfsetspeed(&t, speed);
+#endif
 
-       t.sg_ispeed = speed;
-       t.sg_ospeed = speed;
+  tcsetattr(__fd, TCSADRAIN, &t);
+#else
+  ioctl(__fd, TIOCGETP, &t);
+
+  t.sg_ispeed = speed;
+  t.sg_ospeed = speed;
 
-       ioctl(__fd, TIOCSETN, &t);
+  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));
+
+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)
-{
+
+size_t serial_write(int __fd, __const __ptr_t __buf, size_t __n) {
+       
        return (write(__fd, __buf, __n));
 }
 
-#endif /* WIN32 */
+#endif  /* WIN32 */
index e967946..99b73d7 100644 (file)
@@ -1,13 +1,9 @@
 /*
 
-  $Id$
-  
   G N O K I I
 
   A Linux/Unix toolset and driver for Nokia mobile phones.
 
-  Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
-
   Released under the terms of the GNU GPL, see file COPYING for more details.
        
   Provides a generic API for accessing functions on the phone, wherever
   Unless otherwise noted, all functions herein block until they complete.  The
   functions themselves are defined in a structure in gsm-common.h.
 
-  $Log$
-  Revision 1.1.1.1  2001/11/25 21:59:04  short
-  :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
-
-  Revision 1.32  2001/11/14 11:26:18  pkot
-  Getting SMS in 6210/7110 does finally work in some cases :)
-
-  Revision 1.31  2001/11/08 16:45:58  pkot
-  Obsolete old structure, kill treads where possible and make shared library
-
-  Revision 1.30  2001/08/09 11:51:38  pkot
-  Generic AT support updates and cleanup (Manfred Jonsson)
-
-  Revision 1.29  2001/07/27 00:02:20  pkot
-  Generic AT support for the new structure (Manfred Jonsson)
-
-  Revision 1.28  2001/06/06 09:05:56  machek
-  Convert Grab/Release display to new structure.
-
-  Revision 1.27  2001/05/07 14:13:06  machek
-  nokia-2110 module converted to suit new API better. --identify now works.
-
-  Revision 1.26  2001/04/25 12:54:47  machek
-  Partly converted nokia 2110 to "new" form, and moved it to phone
-  directory.
-
-  Revision 1.25  2001/03/26 23:39:21  pkot
-  Minor updates:
-   - Windows INLINE patch (Manfred Jonsson)
-   - patch to configure.in to compile under FreeBSD (Panagiotis Astithas)
-   - other cleanups (me)
-
-  
 */
 
 #include <stdio.h>
 #include <string.h>
-
-#include "misc.h"
-#include "gsm-common.h"
-#include "data/rlp-common.h"
-#include "gsm-statemachine.h"
-#include "phones/nk7110.h"
-#include "phones/nk6100.h"
-#include "phones/nk3110.h"
-#include "phones/nk2110.h"
-
-GSM_Statemachine GSM_SM;
-GSM_Error (*GSM_F)(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state);
-
+#include <stdlib.h>
+#include <time.h>
+
+#ifdef WIN32
+  #include <windows.h>
+  #include "misc_win32.h"
+#endif
+
+#include "gsm-api.h"
+
+#include "newmodules/n6110.h"
+#include "newmodules/n7110.h"
+#include "newmodules/newat.h"
+#ifdef DEBUG
+  #include "newmodules/sniff/sniff.h"
+#endif
+#include "protocol/fbusirda.h"
+#include "protocol/fbus.h"
+#include "protocol/mbus.h"
+#include "protocol/at.h"
+#include "files/cfgreader.h"
+
+#ifndef WIN32
+  #include "devices/device.h"
+#endif
+
+#ifdef VC6
+  /* for VC6 make scripts save VERSION constant in mversion.h file */
+  #include "mversion.h"
+#endif
 
 /* GSM_LinkOK is set to true once normal communications with the phone have
    been established. */
 
 bool *GSM_LinkOK;
-bool LinkAlwaysOK = true;
 
 /* Define pointer to the GSM_Functions structure used by external code to call
    relevant API functions. This structure is defined in gsm-common.h. */
@@ -92,62 +71,722 @@ GSM_Information            *GSM_Info;
    3810, 5110, 6110 etc. Device is the serial port to use e.g. /dev/ttyS0, the
    user must have write permission to the device. */
 
-static GSM_Error register_phone(GSM_Phone *phone, char *model, char *setupmodel, GSM_Statemachine *sm)
+GSM_Protocol *Protocol;
+
+/* Local variables used by get/set phonebook entry code. Buffer is used as a
+   source or destination for phonebook data and other functions... Error is
+   set to GE_NONE by calling function, set to GE_COMPLETE or an error code by
+   handler routines as appropriate. */
+                                  
+GSM_PhonebookEntry *CurrentPhonebookEntry;
+GSM_Error          CurrentPhonebookError;
+
+GSM_SpeedDial      *CurrentSpeedDialEntry;
+GSM_Error          CurrentSpeedDialError;
+
+unsigned char      Current_IMEI[GSM_MAX_IMEI_LENGTH];
+unsigned char      Current_Revision[GSM_MAX_REVISION_LENGTH];
+unsigned char      Current_Model[GSM_MAX_MODEL_LENGTH];
+
+GSM_SMSMessage     *CurrentSMSMessage;
+GSM_Error          CurrentSMSMessageError;
+int                CurrentSMSPointer;
+
+GSM_SMSFolders      *CurrentSMSFolders;
+GSM_Error          CurrentSMSFoldersError;
+int                CurrentSMSFoldersCount;
+
+GSM_OneSMSFolder   CurrentSMSFolder;
+GSM_Error          CurrentSMSFolderError;
+int                CurrentSMSFolderID;
+
+GSM_MemoryStatus   *CurrentMemoryStatus;
+GSM_Error          CurrentMemoryStatusError;
+
+GSM_NetworkInfo    *CurrentNetworkInfo;
+GSM_Error          CurrentNetworkInfoError;
+
+GSM_SMSStatus      *CurrentSMSStatus;
+GSM_Error          CurrentSMSStatusError;
+
+GSM_MessageCenter  *CurrentMessageCenter;
+GSM_Error          CurrentMessageCenterError;
+
+int                *CurrentSecurityCodeStatus;
+GSM_Error          CurrentSecurityCodeError;
+GSM_SecurityCode   *CurrentSecurityCode;
+
+GSM_DateTime       *CurrentDateTime;
+GSM_Error          CurrentDateTimeError;
+
+GSM_DateTime       *CurrentAlarm;
+GSM_Error          CurrentAlarmError;
+
+GSM_CalendarNote   *CurrentCalendarNote;
+GSM_Error          CurrentCalendarNoteError;
+
+GSM_NotesInfo      CurrentCalendarNotesInfo,*CurrentCalendarNotesInfo2;
+GSM_Error          CurrentCalendarNotesInfoError;
+
+GSM_Error          CurrentSetDateTimeError;
+GSM_Error          CurrentSetAlarmError;
+
+GSM_Error          CurrentEnableExtendedCommandsError;
+
+int                CurrentRFLevel,
+                   CurrentBatteryLevel,
+                   CurrentPowerSource;
+
+int                CurrentDisplayStatus;
+GSM_Error          CurrentDisplayStatusError;
+
+GSM_Error          CurrentResetPhoneSettingsError;
+
+char               *CurrentNetmonitor;
+GSM_Error          CurrentNetmonitorError;
+
+GSM_Bitmap         *CurrentGetBitmap=NULL;
+GSM_Error          CurrentGetBitmapError;
+
+GSM_Error          CurrentSetBitmapError;
+
+GSM_Error          CurrentSendDTMFError;
+
+GSM_Profile        *CurrentProfile;
+GSM_Error          CurrentProfileError;
+
+GSM_Error          CurrentDisplayOutputError;
+
+GSM_CBMessage      *CurrentCBMessage;
+GSM_Error          CurrentCBError;
+
+int                CurrentPressKeyEvent;
+GSM_Error          CurrentPressKeyError;
+
+GSM_Error          CurrentPlayToneError=GE_UNKNOWN;
+
+GSM_Error          CurrentDialVoiceError;
+
+GSM_Error          CurrentGetOperatorNameError;
+GSM_Network        *CurrentGetOperatorNameNetwork;
+GSM_Error          CurrentSetOperatorNameError;
+
+GSM_Error          CurrentGetIMEIError;
+
+GSM_Error          CurrentGetHWError;
+
+unsigned char      CurrentPPS[4];
+GSM_Error          CurrentProductProfileSettingsError;
+
+char               CurrentIncomingCall[20];
+
+GSM_Error          CurrentBinRingtoneError;
+GSM_BinRingtone    *CurrentGetBinRingtone=NULL;
+
+GSM_Error          CurrentRingtoneError;
+
+GSM_Error          CurrentMagicError;
+
+GSM_Error          CurrentSimlockInfoError;
+GSM_AllSimlocks    *CurrentSimLock;
+
+GSM_Error          CurrentGetWAPBookmarkError;
+GSM_Error          CurrentSetWAPBookmarkError;
+GSM_WAPBookmark    *WAPBookmark;
+
+GSM_Error          CurrentGetWAPSettingsError;
+GSM_WAPSettings    *WAPSettings;
+
+GSM_Error          CurrentCallDivertError;
+GSM_CallDivert    *CurrentCallDivert;
+
+char              *CurrentManufacturer;
+
+/* This is the connection type used in gnokii. */
+GSM_ConnectionType CurrentConnectionType;
+
+/* Pointer to a callback function used to return changes to a calls status */
+/* This saves unreliable polling */
+void (*CurrentCallPassup)(char c);
+
+/* Pointer to callback function in user code to be called when RLP frames
+   are received. */
+void (*CurrentRLP_RXCallback)(RLP_F96Frame *frame);
+
+/* Used to disconnect the call */
+u8 CurrentCallSequenceNumber;
+
+bool CurrentLinkOK;
+
+bool CurrentRequestTerminate;
+
+bool CurrentDisableKeepAlive;
+
+bool CheckModel (GSM_Information InfoToCheck, char *model, GSM_ConnectionType connection) {
+
+  bool found_match=false;
+
+  if (strstr(InfoToCheck.FBUSModels, model) != NULL) {
+    if (connection==GCT_FBUS) found_match=true;
+  }
+  if (strstr(InfoToCheck.MBUSModels, model) != NULL) {
+    if (connection==GCT_MBUS) found_match=true;
+  }
+  if (strstr(InfoToCheck.InfraredModels, model) != NULL) {
+    if (connection==GCT_Infrared) found_match=true;
+  }
+  if (strstr(InfoToCheck.DLR3Models, model) != NULL) {
+    if (connection==GCT_DLR3) found_match=true;
+  }
+  if (strstr(InfoToCheck.IrdaModels, model) != NULL) {
+    if (connection==GCT_Irda) found_match=true;
+  }
+  if (strstr(InfoToCheck.ATModels, model) != NULL) {
+    if (connection==GCT_AT) found_match=true;
+  }
+  if (strstr(InfoToCheck.TekramModels, model) != NULL) {
+    if (connection==GCT_Tekram) found_match=true;
+  }
+
+  return found_match;
+}
+GSM_Error TryNewNokia(char *model, char *device, char *initlength, GSM_ConnectionType connection, void (*rlp_callback)(RLP_F96Frame *frame)) {
+  int InitLength;
+  int count;
+  unsigned char init_char = N6110_SYNC_BYTE;
+
+  /* Hopefully is 64 larger as FB38_MAX* / N6110_MAX* */
+  char phonemodel[64];
+
+  if (Protocol->Initialise(device,initlength,connection,rlp_callback)!=GE_NONE)
+  {
+    return GE_NOTSUPPORTED; 
+  }
+
+  if (connection!=GCT_MBUS) {
+    InitLength = atoi(initlength);
+
+    if ((strcmp(initlength, "default") == 0) || (InitLength == 0)) {
+      InitLength = 250;        /* This is the usual value, lower may work. */
+    }
+
+#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 ++) {
+      usleep(100);
+      Protocol->WritePhone(1,&init_char);
+    }
+
+#ifdef DEBUG
+    fprintf(stdout,_("Done\n"));  
+#endif
+
+    N6110_SendStatusRequest();
+  }
+
+  usleep(100);
+
+  if (N6110_SendIDFrame()!=GE_NONE)
+    return GE_TIMEOUT;
+  while (N6110_GetModel(phonemodel) != GE_NONE)
+    sleep(1);
+
+  if (!strcmp(phonemodel,"NPE-3") || !strcmp(phonemodel,"NSE-5"))
+  {
+    GSM->Terminate();      
+    
+    /* Set pointers to relevant addresses */
+    GSM = &N7110_Functions;
+    GSM_Info = &N7110_Information;
+    GSM_LinkOK = &CurrentLinkOK;
+    return GE_NONE;
+  }
+
+  return GE_NONE;
+}
+
+GSM_Error GSM_Initialise(char *model, char *device, char *initlength, GSM_ConnectionType connection, void (*rlp_callback)(RLP_F96Frame *frame), char* SynchronizeTime)
 {
-       GSM_Data data;
-       GSM_Data *p_data;
-       if (setupmodel) {
-               GSM_DataClear(&data);
-               data.Model = setupmodel;
-               p_data = &data;
-       } else {
-               p_data = NULL;
-       }
-       if (strstr(phone->Info.Models, model) != NULL)
-               return phone->Functions(GOP_Init, p_data, sm);
-       return GE_UNKNOWNMODEL;
+  bool found_match=false;
+  
+  GSM_ConnectionType connection2;
+
+  struct tm *now;
+  time_t nowh;
+  GSM_DateTime Date;
+  GSM_Error error;
+  
+  connection2=connection;
+
+  CurrentRLP_RXCallback = rlp_callback;
+  CurrentCallPassup=NULL;
+  CurrentPhonebookEntry=NULL;
+  CurrentNetworkInfo = NULL;
+  CurrentGetBitmap=NULL;
+  CurrentPlayToneError=GE_UNKNOWN;
+  strcpy(CurrentIncomingCall," ");
+  CurrentGetBinRingtone=NULL;
+  CurrentNetworkInfo=NULL;
+  CurrentRequestTerminate=false;
+  CurrentDisableKeepAlive=false;
+  CurrentCalendarNotesInfo.HowMany=2000;
+  CurrentMagicError = GE_BUSY;  
+  
+  if (!strcmp(model,"auto")) {
+
+    /* For now */
+    GSM = &N6110_Functions;
+    GSM_Info = &N6110_Information;
+    GSM_LinkOK = &CurrentLinkOK;
+#ifdef DEBUG
+    fprintf(stdout,_("Trying FBUS for new Nokia phones...\n"));
+#endif
+    /* Trying FBUS */
+    Protocol = &FBUS_Functions;
+    CurrentConnectionType=GCT_FBUS;    
+    connection2=GCT_FBUS;
+    if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE)
+    {
+      found_match=true;
+    } else {
+      GSM->Terminate();      
+    }
+
+    if (!found_match) {
+      usleep(100);          
+      
+      /* For now */
+      GSM = &N6110_Functions;
+      GSM_Info = &N6110_Information;
+      GSM_LinkOK = &CurrentLinkOK;
+#ifdef DEBUG
+      fprintf(stdout,_("Trying DLR3 for new Nokia phones...\n"));
+#endif
+      /* Trying DLR3 */
+      Protocol = &FBUS_Functions;
+      CurrentConnectionType=GCT_DLR3;    
+      connection2=GCT_DLR3;
+      if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE)
+      {
+        found_match=true;
+      } else {
+        GSM->Terminate();      
+      }
+    }
+    
+    if (!found_match) {
+      usleep(100);          
+      
+      /* For now */
+      GSM = &N6110_Functions;
+      GSM_Info = &N6110_Information;
+      GSM_LinkOK = &CurrentLinkOK;
+#ifdef DEBUG
+      fprintf(stdout,_("Trying MBUS for new Nokia phones...\n"));
+#endif
+      /* Trying MBUS */
+      Protocol = &MBUS_Functions;
+      CurrentConnectionType=GCT_MBUS;    
+      connection2=GCT_MBUS;
+      if (TryNewNokia(model,device,initlength,CurrentConnectionType,rlp_callback)==GE_NONE)
+      {
+        found_match=true;
+      } else {
+        GSM->Terminate();      
+      }
+    }
+
+    if (!found_match) return GE_NOTSUPPORTED;
+
+    usleep(50);
+        
+  } else {
+#ifdef DEBUG
+    if (CheckModel (Nsniff_Information, model, connection)) {
+      /* Set pointers to relevant addresses */
+      GSM = &Nsniff_Functions;
+      GSM_Info = &Nsniff_Information;
+      GSM_LinkOK = &CurrentLinkOK;
+      found_match=true;
+    }
+#endif
+
+    if (CheckModel (N6110_Information, model, connection)) {
+      /* Set pointers to relevant addresses */
+      GSM = &N6110_Functions;
+      GSM_Info = &N6110_Information;
+      GSM_LinkOK = &CurrentLinkOK;
+      found_match=true;
+    }
+    if (CheckModel (N7110_Information, model, connection)) {
+      /* Set pointers to relevant addresses */
+      GSM = &N7110_Functions;
+      GSM_Info = &N7110_Information;
+      GSM_LinkOK = &CurrentLinkOK;
+      found_match=true;
+    }
+    if (CheckModel (Nat_Information, model, connection)) {
+      /* Set pointers to relevant addresses */
+      GSM = &Nat_Functions;
+      GSM_Info = &Nat_Information;
+      GSM_LinkOK = &CurrentLinkOK;
+      found_match=true;
+    }
+
+    if (found_match) {
+      switch (connection) {
+        case GCT_FBUS    : Protocol = &FBUS_Functions;    break;
+        case GCT_Infrared: Protocol = &FBUS_Functions;    break;
+        case GCT_Tekram  : Protocol = &FBUS_Functions;    break;
+        case GCT_DLR3    : Protocol = &FBUS_Functions;    break;
+        case GCT_MBUS    : Protocol = &MBUS_Functions;    break;
+        case GCT_Irda    : Protocol = &FBUSIRDA_Functions;break;
+        case GCT_AT      : Protocol = &AT_Functions;      break;
+        case GCT_Default : Protocol = NULL;               break;
+      }
+    } else
+      return GE_NOTSUPPORTED;
+  }
+
+    
+  /* Now call model specific initialisation code. */
+  error=(GSM->Initialise(device, initlength, connection2, rlp_callback));
+
+  /* RTH: FIXME: second try for Irda (6210 only?)*/
+  if ( error!=GE_NONE && connection == GCT_Irda)
+  {
+   #ifdef DEBUG
+     fprintf(stdout,"Irda connection: second try!\n");
+   #endif
+   device_close();
+   error=(GSM->Initialise(device, initlength, connection2, rlp_callback));
+  }
+
+  if (error==GE_NONE && !strcmp(SynchronizeTime,"yes"))
+  {
+    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 (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);
+  }
+
+  return error;
 }
 
-#define MODULE(x) { \
-       extern GSM_Functions x##_Functions; \
-       extern GSM_Information x##_Information; \
-       extern bool x##_LinkOK; \
-       if (strstr(x##_Information.Models, model) != NULL) { \
-               GSM = & x##_Functions; \
-               GSM_Info = & x##_Information; \
-               GSM_LinkOK = & x##_LinkOK; \
-               return (GSM->Initialise(device, initlength, connection, rlp_callback)); \
-       } \
+GSM_Error Unimplemented(void)
+{
+       return GE_NOTIMPLEMENTED;
 }
 
-#define REGISTER_PHONE(x, y) { \
-        extern GSM_Phone phone_##x; \
-        if ((ret = register_phone(&phone_##x, model, y, sm)) != GE_UNKNOWNMODEL) \
-                return ret; \
- } 
+GSM_Error NotSupported(void)
+{
+       return GE_NOTSUPPORTED;
+}
 
-GSM_Error GSM_Initialise(char *model, char *device, char *initlength, GSM_ConnectionType connection, void (*rlp_callback)(RLP_F96Frame *frame), GSM_Statemachine *sm)
-{
-        GSM_Error ret;
-#ifndef WIN32  /* MB21 not supported in win32 */
-       if (strstr("2110", model)) {
-               extern GSM_Phone phone_nokia_2110;
-               memcpy(&(sm->Phone), &phone_nokia_2110, sizeof(GSM_Phone));
-               sm->Phone.Functions(GOP_Init, NULL, sm);
+/* Applications should call N6110_Terminate to shut down the N6110 thread and
+   close the serial port. */
+void NULL_Terminate(void)
+{
+  Protocol->Terminate();
+}
+
+#ifdef WIN32
+/* Here are things made for keeping connecting */
+void NULL_KeepAlive()
+{
+}
+#else
+/* Here are things made for keeping connecting */
+void NULL_KeepAlive()
+{
+}
+#endif
+
+#ifdef DEBUG
+void NULL_TX_DisplayMessage(u16 MessageLength, u8 *MessageBuffer)
+{
+  fprintf(stdout, _("PC: "));
+
+  txhexdump(MessageLength,MessageBuffer);
+}
+#endif
+
+bool NULL_WritePhone (u16 length, u8 *buffer) {
+  if (device_write(buffer,length)!=length) return false;
+                                      else return true;
+}
+
+GSM_Error NULL_WaitUntil (int time, GSM_Error *value)
+{
+  int timeout;
+
+  timeout=time;
+  
+  /* Wait for timeout or other error. */
+  while (timeout != 0 && *value == GE_BUSY ) {
+          
+    if (--timeout == 0)
+      return (GE_TIMEOUT);
+                    
+    usleep (100000);
+  }
+
+  return *value;
+}
+
+GSM_Error NULL_SendMessageSequence (int time, GSM_Error *value,
+                 u16 message_length, u8 message_type, u8 *buffer)
+{
+  *value=GE_BUSY;
+  
+  Protocol->SendMessage(message_length, message_type, buffer);  
+
+  return NULL_WaitUntil (time, value);
+}
+
+GSM_ConnectionType GetConnectionTypeFromString(char *Connection) {
+
+  GSM_ConnectionType connection=GCT_FBUS;
+
+  if (!strcmp(Connection, "irda"))     connection=GCT_Irda;
+  if (!strcmp(Connection, "infrared")) connection=GCT_Infrared;
+  if (!strcmp(Connection, "mbus"))     connection=GCT_MBUS;
+  if (!strcmp(Connection, "dlr3"))     connection=GCT_DLR3;
+  if (!strcmp(Connection, "at"))       connection=GCT_AT;
+  if (!strcmp(Connection, "tekram210"))connection=GCT_Tekram;
+  
+  return connection;
+}
+
+bool GetMemoryTypeString(char *memorytext, GSM_MemoryType *type)
+{
+  int i=0;
+
+  typedef struct {
+    GSM_MemoryType type;
+    char *name;
+  } GSM_MTStrings;
+
+  GSM_MTStrings mystring[] = {
+    {GMT_ME,"ME"},
+    {GMT_SM,"SM"},
+    {GMT_FD,"FD"},
+    {GMT_ON,"ON"},
+    {GMT_EN,"EN"},
+    {GMT_DC,"DC"},
+    {GMT_RC,"RC"},  
+    {GMT_MC,"MC"},
+    {GMT_LD,"LD"},
+    {GMT_MT,"MT"},
+    {GMT_ME,"undefined"}
+  };
+
+  while (strcmp(mystring[i].name,"undefined")) {
+    if (*type==mystring[i].type) {
+      strcpy(memorytext,mystring[i].name);
+      return true;
+    }
+    i++;
+  }
+  return false;
+}
+
+bool GetMemoryTypeID(char *memorytext, GSM_MemoryType *type)
+{
+  int i=0;
+
+  typedef struct {
+    GSM_MemoryType type;
+    char *name;
+  } GSM_MTStrings;
+
+  GSM_MTStrings mystring[] = {
+    {GMT_ME,"ME"},
+    {GMT_SM,"SM"},
+    {GMT_FD,"FD"},
+    {GMT_ON,"ON"},
+    {GMT_EN,"EN"},
+    {GMT_DC,"DC"},
+    {GMT_RC,"RC"},  
+    {GMT_MC,"MC"},
+    {GMT_LD,"LD"},
+    {GMT_MT,"MT"},
+    {GMT_ME,"undefined"}
+  };
+
+  while (strcmp(mystring[i].name,"undefined")) {
+    if (strcmp(mystring[i].name,memorytext)==0) {
+      *type=mystring[i].type;
+      return true;
+    }
+    i++;
+  }
+
+  return false;
+}
+
+char *GetMygnokiiVersion() {
+
+  static char Buffer[1000]="";
+
+  sprintf(Buffer, "%s",VERSION);
+
+  return Buffer;
+}
+
+/*
+1.Name,2.CodeName,3.Calendar,4.Netmonitor,5.Caller groups,6.Phonebook,
+7.Authentication 8.Datacalls 9.KeysPressing 10.SMSC Default Recipient
+11.SpeedDials 12.ScreenSavers 13.DTMF 14.SMS 15.NoPowerFrame 16.StartUpLogo
+17.Profiles 18.Ringtones 19.WAP
+*/
+
+static OnePhoneModel allmodels[] = {
+
+/*1,    2,       3,      4,       5,        6       7      8        9      10        11      12       13     14      15        16       17       18        19 */
+{"3210","NSE-8",{      0,F_NETMON,        0,      0,     0,       0,     0,F_SMSCDEF,F_SPEED,       0,     0,F_SMS  ,F_NOPOWER,F_STANIM,F_PROF51,F_RINGBIN,    0}},
+{"3210","NSE-9",{      0,F_NETMON,        0,      0,     0,       0,     0,F_SMSCDEF,F_SPEED,       0,     0,F_SMS  ,F_NOPOWER,F_STANIM,F_PROF51,F_RINGBIN,    0}},
+{"3310","NHM-5",{F_CAL33,F_NETMON,        0,F_PBK33,     0,       0,     0,F_SMSCDEF,F_SPEED,F_SCRSAV,     0,F_SMS  ,F_NOPOWER,F_STANIM,F_PROF33,F_RING_SM,    0}},
+{"3330","NHM-6",{F_CAL33,F_NETMON,        0,F_PBK33,     0,       0,F_KEYB,F_SMSCDEF,F_SPEED,F_SCRSAV,     0,F_SMS  ,        0,F_STANIM,F_PROF33,F_RING_SM,F_WAP}},
+{"5110","NSE-1",{      0,F_NETMON,        0,      0,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,       0,F_PROF51,        0,    0}},
+{"5130","NSK-1",{      0,F_NETMON,        0,      0,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,       0,F_PROF51,        0,    0}},
+{"5190","NSB-1",{      0,F_NETMON,        0,      0,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,       0,F_PROF51,        0,    0}},
+{"6110","NSE-3",{F_CAL61,F_NETMON,F_CALER61,      0,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0}},
+{"6130","NSK-3",{F_CAL61,F_NETMON,F_CALER61,      0,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0}},
+{"6150","NSM-1",{F_CAL61,F_NETMON,F_CALER61,      0,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0}},
+{"6190","NSB-3",{F_CAL61,F_NETMON,F_CALER61,      0,F_AUTH,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0}},
+{"6210","NPE-3",{F_CAL71,F_NETMON,F_CALER61,F_PBK71,     0,F_DATA71,     0,F_SMSCDEF,F_SPEED,       0,     0,F_SMS71,        0,F_STA62 ,F_PROF61,F_RINGBIN,F_WAP}},
+{"6250","NHM-3",{F_CAL71,F_NETMON,F_CALER61,F_PBK71,     0,F_DATA71,     0,F_SMSCDEF,F_SPEED,       0,     0,F_SMS71,        0,F_STA62 ,F_PROF61,F_RINGBIN,F_WAP}},    
+{"7110","NSE-5",{F_CAL71,F_NETMON,F_CALER61,F_PBK71,     0,F_DATA71,     0,F_SMSCDEF,F_SPEED,       0,     0,F_SMS71,        0,F_STA71 ,F_PROF61,F_RINGBIN,F_WAP}},
+{"8210","NSM-3",{      0,F_NETMON,F_CALER61,      0,     0,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0}},
+{"8850","NSM-2",{      0,F_NETMON,F_CALER61,      0,     0,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0}},
+{"9210","RAE-3",{      0,F_NETMON,F_CALER61,      0,     0,F_DATA61,F_KEYB,F_SMSCDEF,F_SPEED,       0,F_DTMF,F_SMS  ,        0,F_STA   ,F_PROF61,F_RINGBIN,    0}},//quesses only !
+{""    ,""     ,{      0,       0,        0,      0,     0,       0,     0,        0,      0,       0,     0,      0,        0,       0,       0,        0,    0}}
+};
+
+OnePhoneModel *GetPhoneModelData (const char *num)
+{
+       register int i = 0;
+
+       while (allmodels[i].number != "") {
+               if (strcmp (num, allmodels[i].number) == 0) {
+                       return (&allmodels[i]);
+               }
+               i++;
        }
-       MODULE(N2110);
-        GSM_LinkOK = &LinkAlwaysOK;
-        sm->Link.ConnectionType=connection;
-        sm->Link.InitLength=atoi(initlength);
-        strcpy(sm->Link.PortDevice,device);
-        REGISTER_PHONE(nokia_7110, NULL);
-       REGISTER_PHONE(nokia_6100, NULL);
-       REGISTER_PHONE(nokia_3110, NULL);
-       REGISTER_PHONE(at, model);
 
-#endif /* WIN32 */ 
-        return (GE_UNKNOWNMODEL);
+       return (&allmodels[i]);
+}
+
+char *GetModelName ()
+{
+  static char model[64];
+
+  while (GSM->GetModel(model)  != GE_NONE) sleep(1);
+
+  return (GetPhoneModelData(model)->model);
+}
+
+int GetModelFeature (featnum_index num)
+{
+  static char model[64];
+
+  while (GSM->GetModel(model)  != GE_NONE) sleep(1);
+
+  return (GetPhoneModelData(model)->features[num]);
+}
+
+int LogAvailable=-1; //-1 not checked earlier, 0 not, 1 yes
+char *logfilename;
+
+bool AppendLog(u8 *buffer, int length,bool format)
+{
+  FILE *file=NULL;
+  char buffer2[50001];
+  int i;
+
+  struct CFG_Header *cfg_info;
+  char *LogFile;       
+
+  if (LogAvailable==-1) {
+
+    LogAvailable=0;
+
+    cfg_info=CFG_FindGnokiirc();
+    if (cfg_info==NULL) return false;
+
+    LogFile = CFG_Get(cfg_info, "global", "logfile");
+    if (LogFile) {
+      LogAvailable=1;
+      logfilename=LogFile;
+
+      file=fopen(logfilename, "a+");
+
+      /* We have first entry in this session and too large file */
+      if (fread( buffer2, 1, 50000,file )==50000) {
+        fclose(file);
+        file=fopen(logfilename, "w");
+      }
+    }
+  } else {
+    if (LogAvailable==1) {
+      file=fopen(logfilename, "a");
+    }
+  }
+  
+  if (LogAvailable==1) {
+    for (i=0;i<length;i++) {
+      if (format) {
+        fprintf(file, "%02x",buffer[i]);
+        switch (buffer[i]) {
+          case 0x09:fprintf(file,_(" |"));break;
+          default:
+            if (isprint(buffer[i])) fprintf(file, _("%c|"),buffer[i]);
+                               else fprintf(file, _(" |"));
+            break;
+        } 
+      } else {
+        fprintf(file, "%c",buffer[i]);
+      }
+    }
+    if (format) fprintf(file, "\n");
+    fclose(file);
+  }
+
+  return (LogAvailable==1);
+}
+
+bool AppendLogText(u8 *buffer,bool format)
+{
+  return AppendLog(buffer,strlen(buffer),format);
 }
index 9361921..1e96f8b 100644 (file)
@@ -4,14 +4,10 @@
 
   A Linux/Unix toolset and driver for Nokia mobile phones.
 
-  Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml. 
-
   Released under the terms of the GNU GPL, see file COPYING for more details.
        
-  Functions for common bitmap operations.
-  Last modified: Sat 18 Nov 2000 by Chris Kemp
-
+  Functions for manipulating bitmaps
+  
 */
 
 #include <stdio.h>
 
 #include "gsm-common.h"
 #include "gsm-bitmaps.h"
-#include "gsm-api.h"
-
-/* A few useful functions for bitmaps */
+#include "gsm-sms.h"
+#include "gsm-coding.h"
+#include "gsm-networks.h"
 
 void GSM_SetPointBitmap(GSM_Bitmap *bmp, int x, int y)
 {
-       if (bmp->type == GSM_StartupLogo) bmp->bitmap[((y/8)*bmp->width)+x] |= 1 << (y%8);
-       if (bmp->type == GSM_OperatorLogo || bmp->type == GSM_CallerLogo) bmp->bitmap[(y*bmp->width+x)/8] |= 1 << (7-((y*bmp->width+x)%8));
-
-       /* Testing only! */
-       if (bmp->type == GSM_PictureImage) bmp->bitmap[9*y + (x/8)] |= 1 << (7-(x%8));
+  int pixel;
+  if (bmp->type == GSM_StartupLogo || bmp->type == GSM_6210StartupLogo || bmp->type == GSM_7110StartupLogo)
+    bmp->bitmap[((y/8)*bmp->width)+x] |= 1 << (y%8);
+  if (bmp->type == GSM_OperatorLogo || bmp->type == GSM_7110OperatorLogo || bmp->type == GSM_CallerLogo) {
+    pixel=bmp->width*y + x;
+    bmp->bitmap[pixel/8] |= 1 << (7-(pixel%8));
+  }
+  if (bmp->type == GSM_PictureImage) bmp->bitmap[9*y + (x/8)] |= 1 << (7-(x%8));
 }
-
+  
 void GSM_ClearPointBitmap(GSM_Bitmap *bmp, int x, int y)
 {
-       if (bmp->type == GSM_StartupLogo) bmp->bitmap[((y/8)*bmp->width)+x] &= 255 - (1 << (y%8));
-       if (bmp->type == GSM_OperatorLogo || bmp->type == GSM_CallerLogo) bmp->bitmap[(y*bmp->width+x)/8] &= 255 - (1 << (7-((y*bmp->width+x)%8)));
-
-       /* Testing only ! */
-       if (bmp->type == GSM_PictureImage) bmp->bitmap[9*y + (x/8)] &= 255 - (1 << (7-(x%8)));
+  int pixel;
+  if (bmp->type == GSM_StartupLogo || bmp->type == GSM_6210StartupLogo || bmp->type == GSM_7110StartupLogo)
+    bmp->bitmap[((y/8)*bmp->width)+x] &= 255 - (1 << (y%8));
+  if (bmp->type == GSM_OperatorLogo || bmp->type == GSM_7110OperatorLogo || bmp->type == GSM_CallerLogo) {
+    pixel=bmp->width*y + x;
+    bmp->bitmap[pixel/8] &= ~(1 << (7-(pixel%8)));
+  }
+  if (bmp->type == GSM_PictureImage) bmp->bitmap[9*y + (x/8)] &= 255 - (1 << (7-(x%8)));
 }
 
 bool GSM_IsPointBitmap(GSM_Bitmap *bmp, int x, int y)
 {
-       int i = 0;
-
-       if (bmp->type == GSM_StartupLogo) i = (bmp->bitmap[((y/8)*bmp->width) + x] & 1<<((y%8)));
-       if (bmp->type == GSM_OperatorLogo || bmp->type == GSM_CallerLogo)
-               i = (bmp->bitmap[(y*bmp->width+x)/8] & 1 << (7-((y*bmp->width+x)%8)));
-       /* Testing only ! */
-       if (bmp->type == GSM_PictureImage) i = (bmp->bitmap[9*y + (x/8)] & 1<<(7-(x%8)));
-       if (i) return true;
-       else return false;
+  int i=0;
+  int pixel;
+
+  if (bmp->type == GSM_StartupLogo || bmp->type == GSM_6210StartupLogo || bmp->type == GSM_7110StartupLogo)
+    i=(bmp->bitmap[((y/8)*bmp->width) + x] & 1<<((y%8)));
+  if (bmp->type == GSM_OperatorLogo || bmp->type == GSM_7110OperatorLogo || bmp->type == GSM_CallerLogo) {
+    pixel=bmp->width*y + x;
+    i=(bmp->bitmap[pixel/8] & 1<<(7-(pixel%8)));
+  }
+  if (bmp->type == GSM_PictureImage) i=(bmp->bitmap[9*y + (x/8)] & 1<<(7-(x%8)));
+
+  if (i) return true; else return false;
 }
-
+  
 void GSM_ClearBitmap(GSM_Bitmap *bmp)
 {
-       int i;
-
-       for (i = 0; i < bmp->size; i++) bmp->bitmap[i] = 0;
+  int i;
+  for (i=0;i<bmp->size;i++) bmp->bitmap[i]=0;
 }
 
-
-void GSM_ResizeBitmap(GSM_Bitmap *bitmap, GSM_Bitmap_Types target, GSM_Information *info)
+GSM_Error GSM_ReadBitmap(GSM_SMSMessage *message, GSM_Bitmap *bitmap)
 {
-       GSM_Bitmap backup;
-       int x,y,copywidth,copyheight;
+  int offset = 1;
+  unsigned char buffer[20];
+
+  switch (message->UDHType) {
+  case GSM_OpLogo:
+    EncodeUDHHeader(buffer, GSM_OperatorLogo);
+    if (message->Length!=133) return GE_UNKNOWN;
+    
+    bitmap->type = GSM_OperatorLogo;
+
+    DecodeNetworkCode(message->MessageText, bitmap->netcode);
+
+    offset = 4;
+    break;
+
+  case GSM_CallerIDLogo:
+    EncodeUDHHeader(buffer, GSM_CallerLogo);
+    if (message->Length!=130) return GE_UNKNOWN;
+    
+    bitmap->type=GSM_CallerLogo;
+
+    break;
+  default: /* error */
+    return GE_UNKNOWN;
+    break;
+  }
+  bitmap->width = message->MessageText[offset];
+  bitmap->height = message->MessageText[offset + 1];
+  
+  if (bitmap->width!=72 || bitmap->height!=14) return GE_INVALIDIMAGESIZE;
+  
+  bitmap->size = (bitmap->width * bitmap->height) / 8;
+  memcpy(bitmap->bitmap, message->MessageText + offset + 3, bitmap->size);
 
-       /* Copy into the backup */
-       memcpy(&backup,bitmap,sizeof(GSM_Bitmap));
+#ifdef DEBUG
+  fprintf(stdout, _("Bitmap from SMS: width %i, height %i\n"),bitmap->width,bitmap->height);
+#endif
+
+  return GE_NONE;
+}
+
+void GSM_ResizeBitmap(GSM_Bitmap *bitmap, GSM_Bitmap_Types target)
+{
+  GSM_Bitmap backup;
+  int x,y,width,height;
+  
+  backup=*bitmap;
       
-       if (target==GSM_StartupLogo) {
-               bitmap->width=info->StartupLogoW;
-               bitmap->height=info->StartupLogoH;
-               bitmap->size=((bitmap->height/8)+(bitmap->height%8>0))*bitmap->width;
-       }
-       if (target==GSM_OperatorLogo) {
-               bitmap->width=info->OpLogoW;
-               bitmap->height=info->OpLogoH;
-               x=bitmap->width*bitmap->height;
-               bitmap->size=(x/8)+(x%8>0);
-       }
-       if (target==GSM_CallerLogo) {
-               bitmap->width=info->CallerLogoW;
-               bitmap->height=info->CallerLogoH;
-               x=bitmap->width*bitmap->height;
-               bitmap->size=(x/8)+(x%8>0);
-       }
-       if (target==GSM_PictureImage) {
-               bitmap->width=72;
-               bitmap->height=28;
-               bitmap->size=bitmap->width*bitmap->height/8;
-       }
-       bitmap->type=target;
-
-       if (backup.width>bitmap->width) {
-               copywidth=bitmap->width;
+  if (target==GSM_StartupLogo) {
+    bitmap->width=84;
+    bitmap->height=48;
+  }
+  if (target==GSM_7110StartupLogo) {
+    bitmap->width=96;
+    bitmap->height=65;
+  }
+  if (target==GSM_6210StartupLogo) {
+    bitmap->width=96;
+    bitmap->height=60;
+  }
+  if (target==GSM_OperatorLogo || target==GSM_CallerLogo) {
+    bitmap->width=72;
+    bitmap->height=14;
+  }
+  if (target==GSM_PictureImage ) {
+    bitmap->width=72;
+    bitmap->height=28;
+  }
+  if (target==GSM_7110OperatorLogo) {
+    bitmap->width=78;
+    bitmap->height=21;
+  }
+  bitmap->type=target;
+  bitmap->size=(bitmap->width*bitmap->height + 7)/8;
+  
+  width=backup.width;
+  if (bitmap->width<width) {
+    width=bitmap->width;
 #ifdef DEBUG
-               fprintf(stdout,_("We lost some part of image - it's cut (width from %i to %i) !\n"),backup.width,bitmap->width);
+    fprintf(stdout,_("We lost some part of image - it's cut (width from %i to %i) !\n"),backup.width,width);
 #endif /* DEBUG */
-       } else copywidth=backup.width;
-
-       if (backup.height>bitmap->height) {
-               copyheight=bitmap->height;
+  }
+  
+  height=backup.height;
+  if (bitmap->height<height) {
+    height=bitmap->height; 
 #ifdef DEBUG
-               fprintf(stdout,_("We lost some part of image - it's cut (height from %i to %i) !\n"),backup.height,bitmap->height);
+    fprintf(stdout,_("We lost some part of image - it's cut (height from %i to %i) !\n"),backup.height,height);
 #endif /* DEBUG */
-       } else copyheight=backup.height;
+  }
   
-
-       GSM_ClearBitmap(bitmap);
+  GSM_ClearBitmap(bitmap);
   
-       for (y=0;y<copyheight;y++) {
-               for (x=0;x<copywidth;x++)
-                       if (GSM_IsPointBitmap(&backup,x,y)) GSM_SetPointBitmap(bitmap,x,y);
-       }
+  for (y=0;y<height;y++) {
+    for (x=0;x<width;x++)
+      if (GSM_IsPointBitmap(&backup,x,y)) GSM_SetPointBitmap(bitmap,x,y);
+  }
+  
+//GSM_PrintBitmap(&backup);
+//GSM_PrintBitmap(bitmap);
 }
 
 void GSM_PrintBitmap(GSM_Bitmap *bitmap)
 {
-       int x, y;
-
-       for (y = 0; y < bitmap->height; y++) {
-               for (x = 0; x < bitmap->width; x++) {
-                       if (GSM_IsPointBitmap(bitmap, x, y)) {
-                               fprintf(stdout, "#");
-                       } else {
-                               fprintf(stdout, " ");
-                       }
-               }
-               fprintf(stdout, "\n");
-       }
+  int x,y;
+
+  for (y=0;y<bitmap->height;y++) {
+    for (x=0;x<bitmap->width;x++) {
+      if (GSM_IsPointBitmap(bitmap,x,y)) {
+        fprintf(stdout, _("#"));
+      } else {
+        fprintf(stdout, _(" "));
+      }
+    }
+    fprintf(stdout, _("\n"));
+  }
 }
 
-
-GSM_Error GSM_ReadSMSBitmap(int type, char *message, char *code, GSM_Bitmap *bitmap)
+int GSM_SaveBitmapToSMS(GSM_MultiSMSMessage *SMS, GSM_Bitmap *bitmap,
+                        bool ScreenSaver, bool UnicodeText)
 {
-       int offset = 0;
-
-       switch (type) {
-       case SMS_OpLogo:
-               if (!code) return GE_UNKNOWN;
-
-               bitmap->type = SMS_OpLogo;
-
-               bitmap->netcode[0] = '0' + (message[0] & 0x0f);
-               bitmap->netcode[1] = '0' + (message[0] >> 4);
-               bitmap->netcode[2] = '0' + (message[1] & 0x0f);
-               bitmap->netcode[3] = ' ';
-               bitmap->netcode[4] = '0' + (message[2] & 0x0f);
-               bitmap->netcode[5] = '0' + (message[2] >> 4);
-               bitmap->netcode[6] = 0;
-
-               break;
-       case SMS_CallerIDLogo:
-               bitmap->type = SMS_CallerIDLogo;
-               break;
-       case SMS_Picture:
-               offset = 2;
-               bitmap->type = GSM_PictureImage;
-               break;
-       default: /* error */
-               return GE_UNKNOWN;
-               break;
-       }
-       bitmap->width = message[0];
-       bitmap->height = message[1];
+  char MessageBuffer[GSM_MAX_SMS_8_BIT_LENGTH*4];
+  int MessageLength=0;
+  GSM_UDH UDHType=GSM_NoUDH;
   
-       bitmap->size = (bitmap->width * bitmap->height) / 8;
-       memcpy(bitmap->bitmap, message + offset + 2, bitmap->size);
-
-       dprintf("Bitmap from SMS: width %i, height %i\n", bitmap->width, bitmap->height);
-
-       return GE_NONE;
-}
-
-
-/* Returns message length */
-
-int GSM_SaveSMSBitmap(GSM_SMSMessage *message, GSM_Bitmap *bitmap)
-{
-       int current=0;
-  
-       char UserDataHeader[7] = {      0x06, /* UDH Length */
-                                       0x05, /* IEI: application port addressing scheme, 16 bit address */
-                                       0x04, /* IEI length */
-                                       0x15, /* destination address: high byte */
-                                       0x00, /* destination address: low byte */
-                                       0x00, /* originator address */
-                                       0x00};
-
-       char Data[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-  
-       /* Default settings for SMS message:
-          - no delivery report
-          - Class Message 1
-          - no compression
-          - 8 bit data
-          - SMSC no. 1
-          - validity 3 days
-          - set UserDataHeaderIndicator
-       */
-
-       message->Status = SMS_Sent;
-       /* Data Coding Scheme */
-       message->DCS.Type = SMS_GeneralDataCoding;
-       message->DCS.u.General.Class = 2;
-       message->DCS.u.General.Compressed = false;
-       message->DCS.u.General.Alphabet = SMS_8bit;
-
-
-       message->MessageCenter.No = 1;
-       message->Validity.VPF = SMS_RelativeFormat;
-       message->Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
-       message->ReplyViaSameSMSC = false;
-
-       switch (bitmap->type) {
-       case GSM_OperatorLogo:
-               message->UDH[0].Type = SMS_OpLogo;
-               UserDataHeader[4] = 0x82; /* NBS port 0x1582 */
-      
-               /* Set the network code */
-               Data[current++] = ((bitmap->netcode[1] & 0x0f) << 4) | (bitmap->netcode[0] & 0xf);
-               Data[current++] = 0xf0 | (bitmap->netcode[2] & 0x0f);
-               Data[current++] = ((bitmap->netcode[5] & 0x0f) << 4) | (bitmap->netcode[4] & 0xf);
-
-               break;
-       case GSM_CallerLogo:
-               message->UDH[0].Type = SMS_CallerIDLogo;
-               UserDataHeader[4] = 0x83; /* NBS port 0x1583 */
-               break;
-       default: /* error */
-               break;
-       }
+  switch (bitmap->type) {
+    case GSM_OperatorLogo:
+      UDHType=GSM_OpLogo;
+
+      EncodeNetworkCode(MessageBuffer, bitmap->netcode);
+      MessageLength=3;
+
+      /* Set the logo size */
+      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;
+
+      break;
+    case GSM_CallerLogo:
+      UDHType=GSM_CallerIDLogo;
+
+      /* Set the logo size */
+      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;
+
+      break;
+    case GSM_PictureImage:
+      UDHType=GSM_ProfileUDH;
+
+      MessageBuffer[MessageLength++]=0x30;     //SM version. Here 3.0
+
+      if (!ScreenSaver)
+        MessageBuffer[MessageLength++]=SM30_OTA; //ID for OTA bitmap
+      else
+        MessageBuffer[MessageLength++]=SM30_SCREENSAVER; //ID for screen saver
+
+      /* Length for picture part */
+      MessageBuffer[MessageLength++]=0x01;     //length hi
+      MessageBuffer[MessageLength++]=0x00;     //length lo
+
+      /* Set the logo size */
+      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;
+
+      if (strlen(bitmap->text)!=0) {
+        if (UnicodeText) {
+          MessageBuffer[MessageLength++]=SM30_UNICODETEXT; //ID for Unicode text
+
+          /* Length for text part */
+          MessageBuffer[MessageLength++]=0x00;             //length of text1
+          MessageBuffer[MessageLength++]=strlen(bitmap->text)*2;//length of text2
+
+          EncodeUnicode (MessageBuffer+MessageLength,bitmap->text,strlen(bitmap->text));
+          MessageLength=MessageLength+2*strlen(bitmap->text);
+        } else {
+          MessageBuffer[MessageLength++]=SM30_ISOTEXT;    //ID for ISO-8859-1 text
+
+          /* Length for text part */
+          MessageBuffer[MessageLength++]=0x00;            //length of text1
+          MessageBuffer[MessageLength++]=strlen(bitmap->text); //length of text2
+
+          memcpy(MessageBuffer+MessageLength,bitmap->text,strlen(bitmap->text));
+          MessageLength=MessageLength+strlen(bitmap->text);
+       }
+      }
+      break;
+    
+    default: /* error */
+      break;
+  }
         
-       /* Set the logo size */
-       current++;
-       Data[current++] = bitmap->width;
-       Data[current++] = bitmap->height;
-
-       Data[current++] = 0x01;
-
-       memcpy(message->MessageText, UserDataHeader, 7);
-       memcpy(message->MessageText, Data, current);
-       memcpy(message->MessageText+current, bitmap->bitmap, bitmap->size);
+  GSM_MakeMultiPartSMS2(SMS,MessageBuffer,MessageLength, UDHType, GSM_Coding_Default);
 
-       return current;
+  return 0;
 }
index 2ef285f..b36bcf5 100644 (file)
@@ -1,29 +1,20 @@
 /*
 
-  $Id$
-
   G N O K I I
 
   A Linux/Unix toolset and driver for Nokia mobile phones.
 
-  Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
-
   Released under the terms of the GNU GPL, see file COPYING for more details.
        
   This file implements GSM networks searching.
 
-  $Log$
-  Revision 1.1.1.1  2001/11/25 21:59:00  short
-  :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
-
-  Revision 1.14  2001/06/28 00:28:45  pkot
-  Small docs updates (Pawel Kot)
-
-
 */
 
 #include <string.h>
+
+#include "gsm-common.h"
 #include "gsm-networks.h"
+#include "gsm-coding.h"
 
 GSM_Country GSM_Countries[] =
 {
@@ -277,19 +268,50 @@ GSM_Network GSM_Networks[] =
   { "340 01", "AMERIS" },
   { "400 01", "AZERCELL GSM" },
   { "400 02", "Bakcell GSM 2000" },
-  { "404 07", "TATA Cellular" },
-  { "404 10", "AirTel" },
-  { "404 11", "Essar Cellphone" },
-  { "404 12", "Escotel" },
-  { "404 14", "Modicom" },
-  { "404 15", "Essar Cellphone" },
-  { "404 20", "Max Touch" },
-  { "404 21", "BPL - Mobile" },
-  { "404 27", "BPL USWEST Cellular" },
-  { "404 30", "Command" },
-  { "404 40", "SkyCell" },
-  { "404 41", "RPG Cellular" },
-  { "404 42", "AIRCEL" },
+
+  { "404 01", "AIRCELL"},\r
+  { "404 02", "Evergrowth"},\r
+  { "404 03", "Bharthi Telenet"},\r
+  { "404 05", "Fascel"},\r
+  { "404 07", "Tata Cell"},\r //TATA Cellular
+  { "404 08", "Koshika"},
+  { "404 09", "Reliance"},\r
+  { "404 10", "AIRTEL"},\r //AirTel
+  { "404 11", "Essar"},\r //Essar Cellphone
+  { "404 12", "Escotel"},\r
+  { "404 14", "Spice"},\r //Modicom
+  { "404 15", "AIRCELL"},\r //Essar Cellphone
+  { "404 18", "Reliance"},\r
+  { "404 19", "Escotel"},\r
+  { "404 20", "Orange"},\r //Max Touch
+  { "404 21", "BPL Mobile"},\r //BPL - Mobile
+  { "404 22", "Birla AT&T"},\r
+  { "404 24", "Birla AT&T"},\r
+  { "404 26", "Koshika"},\r
+  { "404 27", "BPL Mobile"},\r //BPL USWEST Cellular
+  { "404 30", "Usha"},\r //Command
+  { "404 31", "AIRCELL"},\r //?
+  { "404 31", "Command"},\r //?
+  { "404 32", "Koshika"},\r
+  { "404 34", "Koshika"},\r
+  { "404 36", "Reliance"},\r
+  { "404 40", "SkyCell"},\r
+  { "404 41", "RPG"}, //RPG Cellular
+  { "404 42", "AIRCELL"},\r //AIRCEL
+  { "404 43", "BPL Mobile"},\r
+  { "404 44", "Spice"},\r
+  { "404 45", "AIRTEL-blr"},\r
+  { "404 46", "BPL Moibile"},\r
+  { "404 49", "AIRTEL"},
+  { "404 50", "Reliance"},\r
+  { "404 52", "Reliance"},
+  { "404 56", "Escotel"},
+  { "404 60", "AIRCELL"},\r
+  { "404 67", "Reliance"},
+  { "404 70", "Hexacom"},\r
+  { "404 78", "RPG"},\r
+  { "404 85", "Reliance"},\r
+\r
   { "410 01", "Mobilink" },
   { "413 02", "DIALOG GSM" },
   { "415 01", "CELLIS" },
@@ -443,3 +465,18 @@ char *GSM_GetCountryCode(char *CountryName)
 
   return GSM_Countries[index].Code;
 }
+
+void EncodeNetworkCode(unsigned char* buffer, unsigned char* output)
+{
+    EncodeBCD (buffer, output, 6, false);
+    buffer[1]=buffer[1] | 0xf0;
+}
+
+void DecodeNetworkCode(unsigned char* buffer, unsigned char* output)
+{
+    DecodeBCD (output, buffer, 3);
+    output[6]=output[5];
+    output[5]=output[4];
+    output[4]=output[3];
+    output[3]=' ';
+}
index f99883e..aa68378 100644 (file)
 /*
 
-  $Id$
-
   G N O K I I
 
   A Linux/Unix toolset and driver for Nokia mobile phones.
 
-  Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
-
   Released under the terms of the GNU GPL, see file COPYING for more details.
 
   This file provides support for ringtones.
 
-  $Log$
-  Revision 1.1.1.1  2001/11/25 21:59:00  short
-  :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
-
-  Revision 1.3  2001/11/08 16:34:19  pkot
-  Updates to work with new libsms
-
-  Revision 1.2  2001/09/20 21:46:21  pkot
-  Locale cleanups (Pawel Kot)
+*/
 
+#ifdef WIN32
+  #include <windows.h>
+  #include "misc_win32.h"
+#else
+  #include <unistd.h>
+#endif
 
-*/
+#include "gsm-api.h"
 
-#include "gsm-ringtones.h"
-#include "misc.h"
+GSM_Ringtone SMringtone;
+GSM_BinRingtone ringtone;
 
 /* Beats-per-Minute Encoding */
 
 int BeatsPerMinute[] = {
-       25,
-       28,
-       31,
-       35,
-       40,
-       45,
-       50,
-       56,
-       63,
-       70,
-       80,
-       90,
-       100,
-       112,
-       125,
-       140,
-       160,
-       180,
-       200,
-       225,
-       250,
-       285,
-       320,
-       355,
-       400,
-       450,
-       500,
-       565,
-       635,
-       715,
-       800,
-       900
+   25,  28,  31,  35,  40,  45,  50,  56,  63,  70,
+   80,  90, 100, 112, 125, 140, 160, 180, 200, 225,
+  250, 285, 320, 355, 400, 450, 500, 565, 635, 715,
+  800, 900
+};
+
+struct OneRingtone RingingTones[] = {
+         {"",0,0},
+/*  1 */ {"Uploaded #1",0,0},   /*  2 */ {"Ring ring",0,0},
+/*  3 */ {"Low",0,0},           /*  4 */ {"Fly",0,0},
+/*  5 */ {"Mosquito",0,0},      /*  6 */ {"Bee",0,0},
+/*  7 */ {"Intro",0,0},         /*  8 */ {"Etude",0,0},
+/*  9 */ {"Hunt",0,0},          /* 10 */ {"Going up",0,0},
+/* 11 */ {"City bird",0,0},     /* 12 */ {"Chase",0,0},
+/* 13 */ {"Scifi",0,0},         /* 14 */ {"Kick",0,0},
+/* 15 */ {"Do-mi-so",0,0},      /* 16 */ {"Robo N1X",0,0},
+/* 17 */ {"Dizzy",0,0},         /* 18 */ {"Playground",0,0},
+/* 19 */ {"That's it!",0,0},    /* 20 */ {"Grande valse",0,0},
+/* 21 */ {"Knock knock",0,0},   /* 22 */ {"Knock again",0,0},
+/* 23 */ {"Helan",0,0},         /* 24 */ {"Fuga",0,0},          
+/* 25 */ {"Menuet",0,0},        /* 26 */ {"Ode to Joy",0,0},
+/* 27 */ {"Elise",0,0},         /* 28 */ {"Mozart 40",0,0},
+/* 29 */ {"Piano Concerto",0,0},/* 30 */ {"William Tell",0,0},
+/* 31 */ {"Badinerie",0,0},     /* 32 */ {"Polka",0,0},
+/* 33 */ {"Attraction",0,0},    /* 34 */ {"Polite",0,0},
+/* 35 */ {"Persuasion",0,0},    /* 36 */ {"Tick tick",0,0},
+/* 37 */ {"Samba",0,0},         /* 38 */ {"Orient",0,0},
+/* 39 */ {"Charleston",0,0},    /* 40 */ {"Songette",0,0},    
+/* 41 */ {"Jumping",0,0},       /* 42 */ {"Lamb",0,0},
+/* 43 */ {"Marry",0,0},         /* 44 */ {"Tango",0,0},
+/* 45 */ {"Tangoed",0,0},       /* 46 */ {"Down",0,0},
+/* 47 */ {"Polska",0,0},        /* 48 */ {"WalzeBrilliant",0,0},
+/* 49 */ {"Cicada",0,0},        /* 50 */ {"Trio",0,0},
+/* 51 */ {"Circles",0,0},       /* 52 */ {"Nokia tune",0,0},
+/* 53 */ {"Sunny walks",0,0},   /* 54 */ {"Basic rock",0,0},
+/* 55 */ {"Reveille",0,0},      /* 56 */ {"Groovy Blue",0,0},
+/* 57 */ {"Brave Scotland",0,0},/* 58 */ {"Matilda",0,0},
+/* 59 */ {"Bumblebee",0,0},     /* 60 */ {"Hungarian",0,0},
+/* 61 */ {"Valkyrie",0,0},      /* 62 */ {"Bach #3",0,0},
+/* 63 */ {"Toreador",0,0},      /* 64 */ {"9th Symphony",0,0},
+/* 65 */ {"Uploaded #2",0,0},   /* 66 */ {"Uploaded #3",0,0},
+/* 67 */ {"Uploaded #4",0,0},   /* 68 */ {"Uploaded #5",0,0},
+         {"",0,0}
 };
 
 int OctetAlign(unsigned char *Dest, int CurrentBit)
 {
-       int i=0;
+  int i=0;
 
-       while((CurrentBit+i)%8) {
-               ClearBit(Dest, CurrentBit+i);
-               i++;
-       }
+  while((CurrentBit+i)%8) {
+    ClearBit(Dest, CurrentBit+i);
+    i++;
+  }
 
-       return CurrentBit+i;
+  return CurrentBit+i;
 }
 
 int OctetAlignNumber(int CurrentBit)
 {
-       int i=0;
+  int i=0;
 
-       while((CurrentBit+i)%8) {
-               i++;
-       }
+  while((CurrentBit+i)%8) { i++; }
 
-       return CurrentBit+i;
+  return CurrentBit+i;
 }
 
 int BitPack(unsigned char *Dest, int CurrentBit, unsigned char *Source, int Bits)
 {
-       int i;
 
-       for (i=0; i<Bits; i++)
-               if (GetBit(Source, i))
-                       SetBit(Dest, CurrentBit+i);
-               else
-                       ClearBit(Dest, CurrentBit+i);
+  int i;
 
-       return CurrentBit+Bits;
+  for (i=0; i<Bits; i++)
+    if (GetBit(Source, i))   SetBit(Dest, CurrentBit+i);
+                      else ClearBit(Dest, CurrentBit+i);
+
+  return CurrentBit+Bits;
 }
 
-int GetTempo(int Beats)
-{
-       int i=0;
+int GSM_GetTempo(int Beats) {
 
-       while ( i < sizeof(BeatsPerMinute)/sizeof(BeatsPerMinute[0])) {
+  int i=0;
 
-               if (Beats<=BeatsPerMinute[i])
-                       break;
-               i++;
-       }
+  while ( i < sizeof(BeatsPerMinute)/sizeof(BeatsPerMinute[0])) {
 
-       return i<<3;
+    if (Beats<=BeatsPerMinute[i]) break;
+    i++;
+  }
+
+  return i<<3;
 }    
 
-int BitPackByte(unsigned char *Dest, int CurrentBit, unsigned char Command, int Bits)
-{
-       unsigned char Byte[]={Command};
+int BitPackByte(unsigned char *Dest, int CurrentBit, unsigned char Command, int Bits) {
 
-       return BitPack(Dest, CurrentBit, Byte, Bits);
-}
+  unsigned char Byte[]={Command};
 
+  return BitPack(Dest, CurrentBit, Byte, Bits);
+}
 
 
 /* This is messy but saves using the math library! */
 
-int GSM_GetDuration(int number, unsigned char *spec)
-{
-       int duration=0;
-
-       switch (number) {
-
-       case 128*3/2:
-               duration=Duration_Full; *spec=DottedNote; break;  
-       case 128*2/3:
-               duration=Duration_Full; *spec=Length_2_3; break;  
-       case 128:
-               duration=Duration_Full; *spec=NoSpecialDuration; break;  
-       case 64*9/4:
-               duration=Duration_1_2; *spec=DoubleDottedNote; break;    
-       case 64*3/2:
-               duration=Duration_1_2; *spec=DottedNote; break;  
-       case 64*2/3:
-               duration=Duration_1_2; *spec=Length_2_3; break;  
-       case 64:
-               duration=Duration_1_2; *spec=NoSpecialDuration; break;  
-       case 32*9/4:
-               duration=Duration_1_4; *spec=DoubleDottedNote; break;    
-       case 32*3/2:
-               duration=Duration_1_4; *spec=DottedNote; break;  
-       case 32*2/3:
-               duration=Duration_1_4; *spec=Length_2_3; break;  
-       case 32:
-               duration=Duration_1_4; *spec=NoSpecialDuration; break;  
-       case 16*9/4:
-               duration=Duration_1_8; *spec=DoubleDottedNote; break;    
-       case 16*3/2:
-               duration=Duration_1_8; *spec=DottedNote; break;  
-       case 16*2/3:
-               duration=Duration_1_8; *spec=Length_2_3; break;  
-       case 16:
-               duration=Duration_1_8; *spec=NoSpecialDuration; break;  
-       case 8*9/4:
-               duration=Duration_1_16; *spec=DoubleDottedNote; break;    
-       case 8*3/2:
-               duration=Duration_1_16; *spec=DottedNote; break;  
-       case 8*2/3:
-               duration=Duration_1_16; *spec=Length_2_3; break;  
-       case 8:
-               duration=Duration_1_16; *spec=NoSpecialDuration; break;  
-       case 4*9/4:
-               duration=Duration_1_32; *spec=DoubleDottedNote; break;    
-       case 4*3/2:
-               duration=Duration_1_32; *spec=DottedNote; break;  
-       case 4*2/3:
-               duration=Duration_1_32; *spec=Length_2_3; break;  
-       case 4:
-               duration=Duration_1_32; *spec=NoSpecialDuration; break;  
-       }
-
-       return duration;
+int GSM_GetDuration(int number, unsigned char *spec) {
+
+  int duration=0;
+
+  switch (number) {
+
+  case 128*3/2: duration=Duration_Full; *spec=DottedNote;        break;  
+  case 128*2/3: duration=Duration_Full; *spec=Length_2_3;        break;  
+  case 128    : duration=Duration_Full; *spec=NoSpecialDuration; break;  
+  case 64*9/4 : duration=Duration_1_2;  *spec=DoubleDottedNote;  break;    
+  case 64*3/2 : duration=Duration_1_2;  *spec=DottedNote;        break;  
+  case 64*2/3 : duration=Duration_1_2;  *spec=Length_2_3;        break;  
+  case 64     : duration=Duration_1_2;  *spec=NoSpecialDuration; break;  
+  case 32*9/4 : duration=Duration_1_4;  *spec=DoubleDottedNote;  break;    
+  case 32*3/2 : duration=Duration_1_4;  *spec=DottedNote;        break;  
+  case 32*2/3 : duration=Duration_1_4;  *spec=Length_2_3;        break;  
+  case 32     : duration=Duration_1_4;  *spec=NoSpecialDuration; break;  
+  case 16*9/4 : duration=Duration_1_8;  *spec=DoubleDottedNote;  break;    
+  case 16*3/2 : duration=Duration_1_8;  *spec=DottedNote;        break;  
+  case 16*2/3 : duration=Duration_1_8;  *spec=Length_2_3;        break;  
+  case 16     : duration=Duration_1_8;  *spec=NoSpecialDuration; break;  
+  case 8*9/4  : duration=Duration_1_16; *spec=DoubleDottedNote;  break;    
+  case 8*3/2  : duration=Duration_1_16; *spec=DottedNote;        break;  
+  case 8*2/3  : duration=Duration_1_16; *spec=Length_2_3;        break;  
+  case 8      : duration=Duration_1_16; *spec=NoSpecialDuration; break;  
+  case 4*9/4  : duration=Duration_1_32; *spec=DoubleDottedNote;  break;    
+  case 4*3/2  : duration=Duration_1_32; *spec=DottedNote;        break;  
+  case 4*2/3  : duration=Duration_1_32; *spec=Length_2_3;        break;  
+  case 4      : duration=Duration_1_32; *spec=NoSpecialDuration; break;  
+  }
+
+  return duration;
 }
 
 
-int GSM_GetNote(int number)
-{
-       int note=0;
+int GSM_GetNote(int number) {
+  
+  int note=0;
  
-       if (number!=255) {
-               note=number%14;
-               switch (note) {
-
-               case 0:
-                       note=Note_C; break;
-               case 1:
-                       note=Note_Cis; break;
-               case 2:
-                       note=Note_D; break;
-               case 3:
-                       note=Note_Dis; break;
-               case 4:
-                       note=Note_E; break;
-               case 6:
-                       note=Note_F; break;
-               case 7:
-                       note=Note_Fis; break;
-               case 8:
-                       note=Note_G; break;
-               case 9:
-                       note=Note_Gis; break;
-               case 10:
-                       note=Note_A; break;
-               case 11:
-                       note=Note_Ais; break;
-               case 12:
-                       note=Note_H; break;
-               }
-       }
-       else note = Note_Pause;
-
-       return note;
+  if (number!=255) {
+    note=number%14;
+    switch (note) {
+
+    case  0: note=Note_C;   break;
+    case  1: note=Note_Cis; break;
+    case  2: note=Note_D;   break;
+    case  3: note=Note_Dis; break;
+    case  4: note=Note_E;   break;
+    case  6: note=Note_F;   break;
+    case  7: note=Note_Fis; break;
+    case  8: note=Note_G;   break;
+    case  9: note=Note_Gis; break;
+    case 10: note=Note_A;   break;
+    case 11: note=Note_Ais; break;
+    case 12: note=Note_H;   break;
+    }
+  }
+  else note = Note_Pause;
+
+  return note;
 
 }
 
-int GSM_GetScale(int number)
-{
-       int scale=-1;
+int GSM_GetScale(int number) {
 
-       if (number!=255) {
-               scale=number/14;
+  int scale=-1;
 
-               /* Ensure the scale is valid */
-               scale%=4;
+  if (number!=255) {
+    scale=number/14;
 
-               scale=scale<<6;
-       }
-       return scale;
-}
+    /* Ensure the scale is valid */
+    scale%=4;
 
+    scale=scale<<6;
+  }
+  return scale;
+}
 
-/* This function packs the ringtone from the structure, so it can be set
-   or sent via sms to another phone.
-   Function returns number of packed notes and changes maxlength to
+/* This function packs the ringtone from the structure "ringtone" to
+   "package", where maxlength means length of package.
+   Function returns number of packed notes and change maxlength to
    number of used chars in "package" */
-
-u8 GSM_PackRingtone(GSM_Ringtone *ringtone, char *package, int *maxlength)
+u8 GSM_PackRingtone(GSM_Ringtone *ringtone, unsigned char *package, int *maxlength)
 {
-       int StartBit=0;
-       int i;
-       unsigned char CommandLength = 0x02;
-       unsigned char spec;
-       int oldscale=10, newscale;
-       int HowMany=0, HowLong=0, StartNote=0, EndNote=0;
-
-       StartBit=BitPackByte(package, StartBit, CommandLength, 8);
-       StartBit=BitPackByte(package, StartBit, RingingToneProgramming, 7);
-
-       /* The page 3-23 of the specs says that <command-part> is always
-          octet-aligned. */
-       StartBit=OctetAlign(package, StartBit);
-
-       StartBit=BitPackByte(package, StartBit, Sound, 7);
-       StartBit=BitPackByte(package, StartBit, BasicSongType, 3);
-
-       /* Packing the name of the tune. */
-       StartBit=BitPackByte(package, StartBit, strlen(ringtone->name)<<4, 4);
-       StartBit=BitPack(package, StartBit, ringtone->name, 8*strlen(ringtone->name));
-
-       /* Info about song pattern */
-       StartBit=BitPackByte(package, StartBit, 0x01, 8); /* One song pattern */
-       StartBit=BitPackByte(package, StartBit, PatternHeaderId, 3);
-       StartBit=BitPackByte(package, StartBit, A_part, 2);
-       StartBit=BitPackByte(package, StartBit, 0, 4); /* No loop value */
-
-       /* Info, how long is contents for SMS */
-       HowLong=30+8*strlen(ringtone->name)+17+8+8+13;
+  int StartBit=0;
+  unsigned char CommandLength = 0x02;
+  unsigned char spec;
+  int oldscale=10, newscale=0, oldstyle=0, oldtempo=0;
+  int HowMany=0;              /* How many instructions packed */
+  int HowLong=0;              /* How many bits packed */
+  int StartNote=0, EndNote=0; /* First and last packed note from ringtone */
+
+  /* Default ringtone parameters */
+  u8 DefNoteScale=2, DefNoteDuration=4;
+  int DefNoteTempo=63;
+  u8 DefNoteStyle=NaturalStyle;
+  
+  int buffer[6];\r              /* Used to find default ringtone parameters */
+  int i,j,k=0,thisnote,thisnotelong;\r
   
-       /* Calculate the number of instructions in the tune.
-          Each Note contains Note and (sometimes) Scale.
-          Default Tempo and Style are instructions too. */
-       HowMany=2; /* Default Tempo and Style */
-
-       for(i=0; i<ringtone->NrNotes; i++) {
-
-               /* PC Composer 2.0.010 doesn't like, when we start ringtone from pause:
-                  it displays that the format is invalid and
-                  hangs, when you move mouse over place, where pause is */       
-               if (GSM_GetNote(ringtone->notes[i].note)==Note_Pause && oldscale==10) {
-                       StartNote++;
-               } else {
+  /* Find the most frequently used duration and use this for the default */\r
\r for (i=0;i<6;i++) buffer[i]=0;\r
+  for (i=0;i<ringtone->NrNotes;i++) {\r
+    switch (ringtone->notes[i].duration) {\r
+      case 192: buffer[0]++; break;\r
+      case 128: buffer[0]++; break;\r
+      case  96:        buffer[1]++; break;\r
+      case  64: buffer[1]++; break;\r
+      case  48: buffer[2]++; break;\r
+      case  32: buffer[2]++; break;\r
+      case  24: buffer[3]++; break;\r
+      case  16: buffer[3]++; break;\r
+      case  12: buffer[4]++; break;\r
+      case   8: buffer[4]++; break;\r
+      case   6: buffer[5]++; break;\r
+      case   4: buffer[5]++; break;\r
+    }\r
+  }\r
+\r
+  /* Now find the most frequently used */\r
+  j=0;\r
+  for (i=0;i<6;i++) {\r
+    if (buffer[i]>j) {\r
+      k=i; \r
+      j=buffer[i];\r
+    }\r
+  }\r
+\r
+  /* Finally convert the default duration */\r
+  switch (k) {\r
+      case 0: DefNoteDuration=128; break;      \r
+      case 1: DefNoteDuration= 64; break;      \r
+      case 2: DefNoteDuration= 32; break;      \r
+      case 3: DefNoteDuration= 16; break;      \r
+      case 4: DefNoteDuration=  8; break;      \r
+      case 5: DefNoteDuration=  4; break;      \r
+     default: DefNoteDuration= 16; break;      \r
+  }  \r
+\r
+  /* Find the most frequently used scale and use this for the default */\r\r
+  for (i=0;i<6;i++) buffer[i]=0;\r
+  for (i=0;i<ringtone->NrNotes;i++) {\r
+    if (ringtone->notes[i].note!=255) {\r
+      buffer[ringtone->notes[i].note/14]++;\r
+    }\r
+  }\r
+  j=0;\r
+  for (i=0;i<6;i++) {\r
+    if (buffer[i]>j) {\r
+      DefNoteScale=i;\r
+      j=buffer[i];\r
+    }\r
+  }\r
+
+  StartBit=BitPackByte(package, StartBit, CommandLength, 8);
+  StartBit=BitPackByte(package, StartBit, RingingToneProgramming, 7);
+
+  /* The page 3-23 of the specs says that <command-part> is always
+     octet-aligned. */
+  StartBit=OctetAlign(package, StartBit);
+
+  StartBit=BitPackByte(package, StartBit, Sound, 7);
+  StartBit=BitPackByte(package, StartBit, BasicSongType, 3);
+
+  /* Set special chars in ringtone name */
+  for (i=0;i<strlen(ringtone->name);i++) {
+    if (ringtone->name[i]=='~') ringtone->name[i]=1; //enables/disables blinking
+    if (ringtone->name[i]=='`') ringtone->name[i]=0; //hides rest ot contents
+  }
+
+  /* Packing the name of the tune. */
+  StartBit=BitPackByte(package, StartBit, strlen(ringtone->name)<<4, 4);
+  StartBit=BitPack(package, StartBit, ringtone->name, 8*strlen(ringtone->name));
+
+  /* Set special chars in ringtone name */
+  for (i=0;i<strlen(ringtone->name);i++) {
+    if (ringtone->name[i]==1) ringtone->name[i]='~'; //enables/disables blinking
+    if (ringtone->name[i]==0) ringtone->name[i]='`'; //hides rest ot contents
+  }
+
+  /* Info about song pattern */
+  StartBit=BitPackByte(package, StartBit, 0x01, 8); /* One song pattern */
+  StartBit=BitPackByte(package, StartBit, PatternHeaderId, 3);
+  StartBit=BitPackByte(package, StartBit, A_part, 2);
+  StartBit=BitPackByte(package, StartBit, ringtone->Loop<<4, 4);
+
+  /* Info, how long is contents for SMS */
+  HowLong=8+8+7+3+4+8*strlen(ringtone->name)+8+3+2+4+8+3+2+3+5;
+  
+  /* Calculating number of instructions in the tune.
+     Each Note contains Note and (sometimes) Scale.
+     Default Tempo and Style are instructions too. */
+  HowMany=2; /* Default Tempo and Style */
+
+  /* Default style and tempo */
+  DefNoteStyle=ringtone->notes[0].style;
+  DefNoteTempo=ringtone->notes[0].tempo;
+  oldstyle=DefNoteStyle;
+  oldtempo=DefNoteTempo;
+
+  for(i=0; i<ringtone->NrNotes; i++) {
+
+    /* PC Composer 2.0.010 doesn't like, when we start ringtone from pause:
+       displays, that format is invalid and
+       hangs, when you move mouse over place, where pause is */       
+    if (GSM_GetNote(ringtone->notes[i].note)==Note_Pause && oldscale==10) {
+      StartNote++;
+    } else {
+
+      thisnote=0;
+      thisnotelong=0;
+     
+      /* we don't write Scale/Style info before "Pause" note - it saves place */
+      if (GSM_GetNote(ringtone->notes[i].note)!=Note_Pause) {
+
+        if (ringtone->allnotesscale ||
+            oldscale!=(newscale=GSM_GetScale(ringtone->notes[i].note))) {
+
+          /* We calculate, if we have space to add next scale instruction */
+          if (((OctetAlignNumber(HowLong+5)+8)/8)<=(*maxlength)) {
+            oldscale=newscale;
+            HowLong+=5;
+            HowMany++;
+            thisnote++;
+            thisnotelong+=5;
+         } else {
+           break;
+         }
+       }
+       if (ringtone->notes[i].style!=oldstyle) {
+          /* We calculate, if we have space to add next style instruction */
+          if (((OctetAlignNumber(HowLong+5)+8)/8)<=(*maxlength)) {
+           oldstyle=ringtone->notes[i].style;
+            HowLong+=5;
+            HowMany++;
+            thisnote++;
+            thisnotelong+=5;
+         } else {
+            HowLong=HowLong-thisnotelong;
+            HowMany=HowMany-thisnote;
+            break;
+         }
+       }
+      }
       
-                       /* we don't write Scale info before "Pause" note - it saves space */
-                       if (GSM_GetNote(ringtone->notes[i].note)!=Note_Pause &&
-                           oldscale!=(newscale=GSM_GetScale(ringtone->notes[i].note))) {
-
-                               /* We calculate, if we have space to add next scale instruction */
-                               if (((HowLong+5)/8)<=(*maxlength-1)) {
-                                       oldscale=newscale;
-                                       HowMany++;
-                                       HowLong+=5;
-                               } else {
-                                       break;
-                               }
-                       }
+      if (ringtone->notes[i].tempo!=oldtempo) {
+        /* We calculate, if we have space to add next tempo instruction */
+        if (((OctetAlignNumber(HowLong+8)+8)/8)<=(*maxlength)) {
+          oldtempo=ringtone->notes[i].tempo;
+          HowLong+=8;
+          HowMany++;
+          thisnote++;
+          thisnotelong+=8;
+       } else {
+          HowLong=HowLong-thisnotelong;
+          HowMany=HowMany-thisnote;
+          break;
+        }
+      }
     
-                       /* We calculate, if we have space to add next note instruction */
-                       if (((HowLong+12)/8)<=(*maxlength-1)) {
-                               HowMany++;
-                               EndNote++;
-                               HowLong+=12;
-                       } else {
-                               break;
-                       }
-               }
-
-               /* If we are sure, we pack it for SMS or setting to phone, not for OTT file */    
-               if (*maxlength<1000) {
-                       /* Pc Composer gives this as the phone limitation */
-                       if ((EndNote-StartNote)==GSM_MAX_RINGTONE_NOTES-1) break;
-               }
-       }
-
-       StartBit=BitPackByte(package, StartBit, HowMany, 8);
-
-       /* Style */
-       StartBit=BitPackByte(package, StartBit, StyleInstructionId, 3);
-       StartBit=BitPackByte(package, StartBit, ContinuousStyle, 2);
-
-       /* Beats per minute/tempo of the tune */
-       StartBit=BitPackByte(package, StartBit, TempoInstructionId, 3);
-       StartBit=BitPackByte(package, StartBit, GetTempo(ringtone->tempo), 5);
+      /* We calculate, if we have space to add next note instruction */
+      if (((OctetAlignNumber(HowLong+12)+8)/8)<=(*maxlength)) {
+        HowMany++;
+        EndNote++;
+        HowLong+=12;
+      } else {
+        HowLong=HowLong-thisnotelong;
+        HowMany=HowMany-thisnote;
+        break;
+      }
+    }
+
+    /* We are sure, we pack it for SMS or setting to phone, not for OTT file */    
+    if (*maxlength<1000) {
+       /* Like Pc Composer say - before of phone limitations...*/
+      if ((EndNote-StartNote)==FB61_MAX_RINGTONE_NOTES-1) break;
+    }
+  }
+
+  StartBit=BitPackByte(package, StartBit, HowMany, 8);
+#ifdef DEBUG
+//  fprintf(stdout,_("length of new pattern: %i %i\n"),HowMany,StartBit);
+#endif
+
+  /* Style */
+  StartBit=BitPackByte(package, StartBit, StyleInstructionId, 3);
+  StartBit=BitPackByte(package, StartBit, DefNoteStyle, 2);
+    
+  /* Beats per minute/tempo of the tune */
+  StartBit=BitPackByte(package, StartBit, TempoInstructionId, 3);
+  StartBit=BitPackByte(package, StartBit, GSM_GetTempo(DefNoteTempo), 5);
+#ifdef DEBUG
+//  fprintf(stdout,_("def temp: %i %i\n"),GSM_GetTempo(DefNoteTempo),StartBit);
+#endif
+
+  /* Default scale */
+  oldscale=10;
+  
+  /* Default style */
+  oldstyle=DefNoteStyle;
+
+  /* Default tempo */
+  oldtempo=DefNoteTempo;
+
+  /* Notes packing */
+  for(i=StartNote; i<(EndNote+StartNote); i++) {
+
+    /* we don't write Scale info before "Pause" note - it saves place */
+    if (GSM_GetNote(ringtone->notes[i].note)!=Note_Pause) {
+      if (ringtone->allnotesscale ||
+          oldscale!=(newscale=GSM_GetScale(ringtone->notes[i].note))) {
+#ifdef DEBUG
+//    fprintf(stdout,_("Scale\n"));
+#endif
+        oldscale=newscale;
+        StartBit=BitPackByte(package, StartBit, ScaleInstructionId, 3);
+        StartBit=BitPackByte(package, StartBit, GSM_GetScale(ringtone->notes[i].note), 2);
+      }
+      if (ringtone->notes[i].style!=oldstyle) {
+        /* Style */
+        StartBit=BitPackByte(package, StartBit, StyleInstructionId, 3);
+        StartBit=BitPackByte(package, StartBit, ringtone->notes[i].style, 2);
+        oldstyle=ringtone->notes[i].style;
+      }
+    }
+
+    if (ringtone->notes[i].tempo!=oldtempo) {
+      /* Beats per minute/tempo of the tune */
+      StartBit=BitPackByte(package, StartBit, TempoInstructionId, 3);
+      StartBit=BitPackByte(package, StartBit, GSM_GetTempo(ringtone->notes[i].tempo), 5);
+      oldtempo=ringtone->notes[i].tempo;
+    }    
+    
+    /* Note */
+    StartBit=BitPackByte(package, StartBit, NoteInstructionId, 3);
+    StartBit=BitPackByte(package, StartBit, GSM_GetNote(ringtone->notes[i].note), 4);
+    StartBit=BitPackByte(package, StartBit, GSM_GetDuration(ringtone->notes[i].duration,&spec), 3);
+    StartBit=BitPackByte(package, StartBit, spec, 2);
 
-       /* Default scale */
-       oldscale=10;
+#ifdef DEBUG    
+//    fprintf(stdout,_("note(%i): %i, scale: %i, duration: %i, spec: %i\n"),i,ringtone->notes[i].note,GSM_GetScale(ringtone->notes[i].note),GSM_GetDuration(ringtone->notes[i].duration,&spec),spec);
+#endif
 
-       /* Notes packing */
-       for(i=StartNote; i<(EndNote+StartNote); i++) {
-    
-               /* we don't write Scale info before "Pause" note - it saves place */
-               if (GSM_GetNote(ringtone->notes[i].note)!=Note_Pause &&
-                   oldscale!=(newscale=GSM_GetScale(ringtone->notes[i].note))) {
-                       oldscale=newscale;
-                       StartBit=BitPackByte(package, StartBit, ScaleInstructionId, 3);
-                       StartBit=BitPackByte(package, StartBit, GSM_GetScale(ringtone->notes[i].note), 2);
-               }
-
-               /* Note */
-               StartBit=BitPackByte(package, StartBit, NoteInstructionId, 3);
-               StartBit=BitPackByte(package, StartBit, GSM_GetNote(ringtone->notes[i].note), 4);
-               StartBit=BitPackByte(package, StartBit, GSM_GetDuration(ringtone->notes[i].duration,&spec), 3);
-               StartBit=BitPackByte(package, StartBit, spec, 2);
-       }
+  }
 
-       StartBit=OctetAlign(package, StartBit);
+  StartBit=OctetAlign(package, StartBit);
 
-       StartBit=BitPackByte(package, StartBit, CommandEnd, 8);
+  StartBit=BitPackByte(package, StartBit, CommandEnd, 8);
   
-       if (StartBit!=OctetAlignNumber(HowLong))
-               dprintf("Error in PackRingtone - StartBit different to HowLong %d - %d)\n", StartBit,OctetAlignNumber(HowLong));
+#ifdef DEBUG
+  if (StartBit!=OctetAlignNumber(HowLong)+8)
+    fprintf(stdout,_("Error in PackRingtone - StartBit different to HowLong %d - %d)\n"),StartBit,OctetAlignNumber(HowLong)+8);
+#endif
 
-       *maxlength=StartBit/8;  
+  *maxlength=StartBit/8;  
 
-       return(EndNote+StartNote);
+  return(EndNote+StartNote);
 }
 
-
 int BitUnPack(unsigned char *Dest, int CurrentBit, unsigned char *Source, int Bits)
 {
-       int i;
+  int i;
 
-       for (i=0; i<Bits; i++)
-               if (GetBit(Dest, CurrentBit+i)) {
-                       SetBit(Source, i);
-               } else {
-                       ClearBit(Source, i);
-               }
+  for (i=0; i<Bits; i++)
+    if (GetBit(Dest, CurrentBit+i)) {   SetBit(Source, i); }
+                               else { ClearBit(Source, i); }
 
-       return CurrentBit+Bits;
+  return CurrentBit+Bits;
 }
 
-int BitUnPackInt(unsigned char *Src, int CurrentBit, int *integer, int Bits)
-{
-       int l=0,z=128,i;
+int BitUnPackInt(unsigned char *Src, int CurrentBit, int *integer, int Bits) {
 
-       for (i=0; i<Bits; i++) {
-               if (GetBit(Src, CurrentBit+i)) l=l+z;
-               z=z/2;
-       }
+  int l=0,z=128,i;
 
-       *integer=l;
+  for (i=0; i<Bits; i++) {
+    if (GetBit(Src, CurrentBit+i)) l=l+z;
+    z=z/2;
+  }
+
+  *integer=l;
   
-       return CurrentBit+i;
+  return CurrentBit+i;
 }
 
 int OctetUnAlign(int CurrentBit)
 {
-       int i=0;
+  int i=0;
 
-       while((CurrentBit+i)%8) i++;
+  while((CurrentBit+i)%8) i++;
 
-       return CurrentBit+i;
+  return CurrentBit+i;
 }
 
-
 /* TODO: better checking, if contents of ringtone is OK */
-
 GSM_Error GSM_UnPackRingtone(GSM_Ringtone *ringtone, char *package, int maxlength)
 {
-       int StartBit = 0;
-       int spec, duration, scale;
-       int HowMany;
-       int l, q, i;
-
-       StartBit = BitUnPackInt(package, StartBit, &l, 8);
-       if (l != 0x02) {
-               dprintf("Not header\n");
-               return GE_SUBFORMATNOTSUPPORTED;
-       }
+  int StartBit=0;
+  int HowMany;
+  int l,q,i;
+  int spec;
 
-       StartBit = BitUnPackInt(package, StartBit, &l, 7);
-       if (l != RingingToneProgramming) {
-               dprintf("Not RingingToneProgramming\n");
-               return GE_SUBFORMATNOTSUPPORTED;
-       }
+  /* Default ringtone parameters */
+  u8 DefNoteScale=2, DefNoteDuration=4;
+  int DefNoteTempo=63;
+  u8 DefNoteStyle=NaturalStyle;
+
+  ringtone->allnotesscale=false;
+  
+  StartBit=BitUnPackInt(package,StartBit,&l,8);
+#ifdef DEBUG
+  if (l!=0x02)
+    fprintf(stdout,_("Not header\n"));  
+#endif
+  if (l!=0x02) return GE_SUBFORMATNOTSUPPORTED;
+
+  StartBit=BitUnPackInt(package,StartBit,&l,7);    
+#ifdef DEBUG
+  if (l!=RingingToneProgramming)
+    fprintf(stdout,_("Not RingingToneProgramming\n"));  
+#endif
+  if (l!=RingingToneProgramming) return GE_SUBFORMATNOTSUPPORTED;
+    
+  /* The page 3-23 of the specs says that <command-part> is always
+     octet-aligned. */
+  StartBit=OctetUnAlign(StartBit);
+
+  StartBit=BitUnPackInt(package,StartBit,&l,7);    
+#ifdef DEBUG
+  if (l!=Sound)
+    fprintf(stdout,_("Not Sound\n"));  
+#endif
+  if (l!=Sound) return GE_SUBFORMATNOTSUPPORTED;
+
+  StartBit=BitUnPackInt(package,StartBit,&l,3);    
+#ifdef DEBUG
+  if (l!=BasicSongType)
+    fprintf(stdout,_("Not BasicSongType\n"));  
+#endif
+  if (l!=BasicSongType) return GE_SUBFORMATNOTSUPPORTED;
+
+  /* Getting length of the tune name */
+  StartBit=BitUnPackInt(package,StartBit,&l,4);
+  l=l>>4;
+#ifdef DEBUG
+//  fprintf(stdout,_("Length of name: %i\n"),l);
+#endif
+
+  /* Unpacking the name of the tune. */
+  StartBit=BitUnPack(package, StartBit, ringtone->name, 8*l);
+  ringtone->name[l]=0;
+
+  /* Set special chars in ringtone name */
+  for (i=0;i<strlen(ringtone->name);i++) {
+    if (ringtone->name[i]==1) ringtone->name[i]='~'; //enables/disables blinking
+    if (ringtone->name[i]==0) ringtone->name[i]='`'; //hides rest ot contents
+  }
+
+#ifdef DEBUG
+//   fprintf(stdout,_("Name: %s\n"),ringtone->name);
+#endif
+
+  StartBit=BitUnPackInt(package,StartBit,&l,8);    
+#ifdef DEBUG
+//  fprintf(stdout,_("Number of song patterns: %i\n"),l);
+#endif
+  if (l!=1) return GE_SUBFORMATNOTSUPPORTED; //we support only one song pattern
+
+  StartBit=BitUnPackInt(package,StartBit,&l,3);          
+#ifdef DEBUG
+  if (l!=PatternHeaderId)
+    fprintf(stdout,_("Not PatternHeaderId\n"));
+#endif
+  if (l!=PatternHeaderId) return GE_SUBFORMATNOTSUPPORTED;
+
+  StartBit+=2; //Pattern ID - we ignore it
+
+  StartBit=BitUnPackInt(package,StartBit,&l,4);          
+  l=l>>4;
+#ifdef DEBUG
+  fprintf(stdout,_("Loop value: %i\n"),l);
+#endif
+  ringtone->Loop=l;
+
+  HowMany=0;
+  StartBit=BitUnPackInt(package, StartBit, &HowMany, 8);
+#ifdef DEBUG
+  fprintf(stdout,_("length of new pattern: %i %i\n"),HowMany,StartBit);
+#endif
+
+  ringtone->NrNotes=0;
     
-/* The page 3-23 of the specs says that <command-part> is always
-   octet-aligned. */
-       StartBit = OctetUnAlign(StartBit);
-
-       StartBit = BitUnPackInt(package, StartBit, &l, 7);
-       if (l != Sound) {
-               dprintf("Not Sound\n");
-               return GE_SUBFORMATNOTSUPPORTED;
+  for (i=0;i<HowMany;i++) {
+
+    StartBit=BitUnPackInt(package,StartBit,&q,3);              
+    switch (q) {
+      case VolumeInstructionId:
+#ifdef DEBUG
+//        fprintf(stdout,_("Volume\n"));
+#endif
+        StartBit+=4;
+        break;
+      case StyleInstructionId:
+        StartBit=BitUnPackInt(package,StartBit,&l,2);              
+#ifdef DEBUG
+//     fprintf(stdout,_("Style %i\n"),l>>6);
+#endif
+       switch (l) {
+         case StaccatoStyle  : DefNoteStyle=StaccatoStyle;   break;
+         case ContinuousStyle: DefNoteStyle=ContinuousStyle; break;
+         case NaturalStyle   : DefNoteStyle=NaturalStyle;    break;
        }
+       break;
+      case TempoInstructionId:
+        StartBit=BitUnPackInt(package,StartBit,&l,5);                  
+        l=l>>3;
+        DefNoteTempo=BeatsPerMinute[l];
+#ifdef DEBUG
+//     fprintf(stdout,_("Tempo %i\n"),l);
+#endif
+        break;
+      case ScaleInstructionId:
+        StartBit=BitUnPackInt(package,StartBit,&l,2);
+       DefNoteScale=l>>6;
+#ifdef DEBUG
+//     fprintf(stdout,_("scale: %i %i\n"),DefNoteScale,ringtone->NrNotes);
+#endif
+       break;
+      case NoteInstructionId:
+        StartBit=BitUnPackInt(package,StartBit,&l,4);    
+
+        switch (l) {
+          case Note_C  :ringtone->notes[ringtone->NrNotes].note=0;break;
+          case Note_Cis:ringtone->notes[ringtone->NrNotes].note=1;break;
+          case Note_D  :ringtone->notes[ringtone->NrNotes].note=2;break;
+          case Note_Dis:ringtone->notes[ringtone->NrNotes].note=3;break;
+          case Note_E  :ringtone->notes[ringtone->NrNotes].note=4;break;
+          case Note_F  :ringtone->notes[ringtone->NrNotes].note=6;break;
+          case Note_Fis:ringtone->notes[ringtone->NrNotes].note=7;break;
+          case Note_G  :ringtone->notes[ringtone->NrNotes].note=8;break;
+          case Note_Gis:ringtone->notes[ringtone->NrNotes].note=9;break;
+          case Note_A  :ringtone->notes[ringtone->NrNotes].note=10;break;
+          case Note_Ais:ringtone->notes[ringtone->NrNotes].note=11;break;
+          case Note_H  :ringtone->notes[ringtone->NrNotes].note=12;break;
+          default      :ringtone->notes[ringtone->NrNotes].note=255;break; //Pause ?
+        }
+      
+        if (ringtone->notes[ringtone->NrNotes].note!=255)
+          ringtone->notes[ringtone->NrNotes].note=ringtone->notes[ringtone->NrNotes].note+DefNoteScale*14;
+
+        StartBit=BitUnPackInt(package,StartBit,&l,3);    
+       DefNoteDuration=l;
+
+        StartBit=BitUnPackInt(package,StartBit,&spec,2);    
+
+        if (DefNoteDuration==Duration_Full && spec==DottedNote)
+            ringtone->notes[ringtone->NrNotes].duration=128*3/2;
+        if (DefNoteDuration==Duration_Full && spec==Length_2_3)
+            ringtone->notes[ringtone->NrNotes].duration=128*2/3;
+        if (DefNoteDuration==Duration_Full && spec==NoSpecialDuration)
+            ringtone->notes[ringtone->NrNotes].duration=128;
+        if (DefNoteDuration==Duration_1_2 && spec==DottedNote)
+            ringtone->notes[ringtone->NrNotes].duration=64*3/2;
+        if (DefNoteDuration==Duration_1_2 && spec==Length_2_3)
+            ringtone->notes[ringtone->NrNotes].duration=64*2/3;
+        if (DefNoteDuration==Duration_1_2 && spec==NoSpecialDuration)
+            ringtone->notes[ringtone->NrNotes].duration=64;
+        if (DefNoteDuration==Duration_1_4 && spec==DottedNote)
+            ringtone->notes[ringtone->NrNotes].duration=32*3/2;
+        if (DefNoteDuration==Duration_1_4 && spec==Length_2_3)
+            ringtone->notes[ringtone->NrNotes].duration=32*2/3;
+        if (DefNoteDuration==Duration_1_4 && spec==NoSpecialDuration)
+            ringtone->notes[ringtone->NrNotes].duration=32;
+        if (DefNoteDuration==Duration_1_8 && spec==DottedNote)
+            ringtone->notes[ringtone->NrNotes].duration=16*3/2;
+        if (DefNoteDuration==Duration_1_8 && spec==Length_2_3)
+            ringtone->notes[ringtone->NrNotes].duration=16*2/3;
+        if (DefNoteDuration==Duration_1_8 && spec==NoSpecialDuration)
+            ringtone->notes[ringtone->NrNotes].duration=16;
+        if (DefNoteDuration==Duration_1_16 && spec==DottedNote)
+            ringtone->notes[ringtone->NrNotes].duration=8*3/2;
+        if (DefNoteDuration==Duration_1_16 && spec==Length_2_3)
+            ringtone->notes[ringtone->NrNotes].duration=8*2/3;
+        if (DefNoteDuration==Duration_1_16 && spec==NoSpecialDuration)
+            ringtone->notes[ringtone->NrNotes].duration=8;
+        if (DefNoteDuration==Duration_1_32 && spec==DottedNote)
+            ringtone->notes[ringtone->NrNotes].duration=4*3/2;
+        if (DefNoteDuration==Duration_1_32 && spec==Length_2_3)
+            ringtone->notes[ringtone->NrNotes].duration=4*2/3;
+        if (DefNoteDuration==Duration_1_32 && spec==NoSpecialDuration)
+            ringtone->notes[ringtone->NrNotes].duration=4;
+
+        ringtone->notes[ringtone->NrNotes].style=DefNoteStyle;
+
+        ringtone->notes[ringtone->NrNotes].tempo=DefNoteTempo;
+       
+#ifdef DEBUG    
+//    fprintf(stdout,_("note(%i): %i, scale: %i, duration: %i, spec: %i\n"),ringtone->NrNotes,ringtone->notes[ringtone->NrNotes].note,DefNoteScale,DefNoteDuration,spec);
+#endif
+        if (ringtone->NrNotes==FB61_MAX_RINGTONE_NOTES) break;
+       
+        ringtone->NrNotes++;
+        break;
+      default:
+#ifdef DEBUG
+    fprintf(stdout,_("Unsupported block %i %i\n"),q,i);  
+#endif
+        return GE_SUBFORMATNOTSUPPORTED;
+    } 
+  }
+
+#ifdef DEBUG
+//  printf("Number of notes=%d\n",ringtone->NrNotes);
+#endif
+
+  return GE_NONE;
+}
 
-       StartBit = BitUnPackInt(package, StartBit, &l, 3);
-       if (l != BasicSongType) {
-               dprintf("Not BasicSongType\n");
-               return GE_SUBFORMATNOTSUPPORTED;
-       }
+GSM_Error GSM_ReadRingtone(GSM_SMSMessage *message, GSM_Ringtone *ringtone)
+{
+  if (message->UDHType==GSM_RingtoneUDH) {
+    return GSM_UnPackRingtone(ringtone, message->MessageText, message->Length);
+  } else return GE_SUBFORMATNOTSUPPORTED;
+}
+
+int GSM_GetFrequency(int number) {
+  
+  int freq=0;
 
-/* Getting length of the tune name */
-       StartBit = BitUnPackInt(package, StartBit, &l, 4);
-       l = l >> 4;
+  /* Values according to the software from http://iki.fi/too/sw/xring/
+     generated with:
+     perl -e 'print int(4400 * (2 **($_/12)) + .5)/10, "\n" for(3..14)'
+  */ 
+  if (number!=255) {
+    freq=number%14;
+    switch (freq) {
 
-/* Unpacking the name of the tune. */
-       StartBit = BitUnPack(package, StartBit, ringtone->name, 8*l);
-       ringtone->name[l] = 0;
+    case  0: freq=523.3; break; // C
+    case  1: freq=554.4; break; // Cis
 
-       StartBit = BitUnPackInt(package, StartBit, &l, 8);    
-       if (l != 1) return GE_SUBFORMATNOTSUPPORTED; //we support only one song pattern
+    case  2: freq=587.3; break; //D
+    case  3: freq=622.3; break; //Dis
+    
+    case  4: freq=659.3; break; //E
 
-       StartBit = BitUnPackInt(package, StartBit, &l, 3);          
-       if (l != PatternHeaderId) {
-               dprintf("Not PatternHeaderId\n");
-               return GE_SUBFORMATNOTSUPPORTED;
-       }
+    case  6: freq=698.5; break; //F
+    case  7: freq=740;   break; //Fis
 
-       StartBit += 2; //Pattern ID - we ignore it
+    case  8: freq=784;   break; //G
+    case  9: freq=830.6; break; //Gis
 
-       StartBit = BitUnPackInt(package, StartBit, &l, 4);          
+    case 10: freq=880;   break; //A
+    case 11: freq=932.3; break; //Ais
     
-       HowMany = 0;
-       StartBit = BitUnPackInt(package, StartBit, &HowMany, 8);
+    case 12: freq=987.8; break; //H
+
+    default: freq=0; break;
+    }
+  }
+  else freq = 0;
+
+  if ((number/14)!=0) freq=freq*(number/14);
+                else freq=freq/2;
+
+  return freq;
+
+}
+
+/* Very fast hack. It should be written correctly ! */
+void GSM_PlayOneNote (GSM_RingtoneNote note) {
+  int Hz;
+
+  Hz=GSM_GetFrequency(note.note);
+       
+  GSM->PlayTone(Hz,5);
+
+  /* Is it correct ? Experimental values here */
+  switch (note.style) {
+    case StaccatoStyle:
+      usleep (7500);
+      GSM->PlayTone(0,0);      
+      usleep ((1500000/note.tempo*note.duration)-(7500));
+      break;
+    case ContinuousStyle:
+      usleep  (1500000/note.tempo*note.duration);
+      break;
+    case NaturalStyle:
+      usleep  (1500000/note.tempo*note.duration-50);
+      GSM->PlayTone(0,0);      
+      usleep (50);
+      break;   
+  }
+}
+
+void GSM_PlayRingtone (GSM_Ringtone *ringtone) {
+
+  int i;
+  
+  for (i=0;i<ringtone->NrNotes;i++) {
+     GSM_PlayOneNote(ringtone->notes[i]);
+  }      
+
+  /* Disables buzzer */
+  GSM->PlayTone(255*255,0);  
+}
 
-       scale = 0;
-       ringtone->NrNotes = 0;
+/* Initializes one ringtone: first is number of ringtone in 
+   RingingTones in gnokii.h, second its' code, last position in phone menu */
+void RT(int number, int code, int menu) {
+  RingingTones[number].code=code;
+  RingingTones[number].menu=menu;
+}
+
+/* This function initializes structures with ringtones names adequate for
+   your phone model and firmware; if your phone is not now supported:
+   1.set first ringtone in 1'st profile in your phone
+   2.make ./gnokii --getprofile 1
+   3.read ringtone code
+   4.see in gnokii.h, if ringtone name is gnokii.h in RingingTones (if not, add)
+   5.put here RT(a,b,c), where a is number of name in RingingTones in gnokii.h,
+     b is its' code and c is number of ringtone in phone menu
+   6.repeat steps 1-5 for all ringtones
+   7.send me (Marcin-Wiacek@Topnet.PL) all RT and phone model */
+void PrepareRingingTones(char model[64], char rev[64]) {
+
+  char rev2[64];
+  int i;
+  bool doit;
+
+  if (!RingingTones[0].code) {
+    if (!strcmp(model,"NSE-1")) //5110
+    {
+      RT( 2,18, 1);RT( 3,19, 2);RT( 7,23, 3);RT( 5,21, 4);RT( 9,25, 5);
+                   RT(20,48, 7);RT(11,27, 8);RT(33,59, 9);RT(35,62,10);
+      RT(46,60,11);RT(16,36,12);RT(17,37,13);RT(13,32,14);RT(14,34,15);
+      RT(19,43,16);RT(18,39,17);RT(24,50,18);RT(31,57,19);RT(28,54,20);
+      RT(30,56,21);RT(40,73,22);RT(39,72,23);RT(37,69,24);
+      RT(23,49,26);RT(38,71,27);             RT(41,74,29);
+      
+      strcpy(rev2,"05.23"); //5.24 and higher
+      doit=false;
+      for(i=0;i<5;i++)
+      {
+        if (rev[i]<rev2[i]) break;
+       if (rev[i]>rev2[i]) doit=true;
+      }
+      
+      if (doit) {
+         RT(22,47, 6);RT(47,58,25);RT(45,80,28);RT(43,75,30);
+      } else
+      {
+         RT(21,47, 6);RT(32,58,25);RT(44,80,28);RT(42,75,30);
+      }
+      RingingTones[0].menu=30; /* How many ringtones in phone */
+    }
+    if (!strcmp(model,"NSM-1")) //6150
+    {
+      RT( 2,18, 1);RT( 3,19, 2);RT( 7,23, 3);RT( 6,22, 4);
+      RT( 4,20, 5);RT( 5,21, 6);RT(15,35, 7);RT(12,30, 8);
+      RT( 9,25, 9);RT(20,47,10);RT( 8,24,11);RT(11,27,12);
+      RT(10,26,13);RT(34,60,14);RT(33,58,15);RT(35,61,16);
+      RT(16,36,17);RT(13,32,18);RT(19,43,19);RT(18,39,20);
+      RT(24,49,21);RT(31,56,22);RT(25,50,23);RT(27,52,24);
+      RT(26,51,25);RT(28,53,26);RT(29,54,27);RT(30,55,28);
+      RT(39,71,29);RT(37,68,30);RT(47,57,31);RT(23,48,32);
+      RT(38,70,33);RT(36,67,34);RT(41,73,35);
+      /*uploadable ringtone*/
+      RT( 1,17,36);
+      RingingTones[0].menu=36; /* How many ringtones in phone */
+    }
+    if (!strcmp(model,"NPE-3")) //6210
+    {
+      RT(19,64, 1);RT( 2,65, 2);RT( 3,66, 3);RT(15,67, 4);RT( 6,68, 5);
+      RT(49,69, 6);RT(50,70, 7);RT( 7,71, 8);RT(35,72, 9);RT(33,73,10);
+      RT(18,74,11);RT( 5,75,12);RT(51,76,13);RT(52,77,14);RT(53,78,15);
+      RT(37,79,16);RT(54,80,17);RT(55,81,18);RT(56,82,19);RT(57,83,20);
+      RT(58,84,21);RT(59,85,22);RT(25,86,23);RT(27,87,24);RT(30,88,25);
+      RT(39,89,26);RT(24,90,27);RT( 8,91,28);RT(60,92,29);RT(61,93,30);
+      RT(31,94,31);RT(62,95,32);RT(63,96,33);RT(64,97,34);RT(48,98,35);
+      /* Uploadable ringtones */
+      RT( 1,137,36);RT(65,138,37);RT(66,139,38);RT(67,140,39);RT(68,141,40);
+
+      RingingTones[0].menu=40; /* How many ringtones in phone */
+    }
+    RingingTones[0].code=true;
+  }
+}
+
+/* returns names from code or number in menu */
+char *RingingToneName(int code, int menu)
+{
+  int index=1,i;
+  GSM_Error error;
+
+  if (code==0)
+  {
+    while (strcmp(RingingTones[index].name,"")) {
+      if (RingingTones[index].menu==menu) break;
+      index++;
+    }
+  } else
+  {
+    while (strcmp(RingingTones[index].name,"")) {
+      if (RingingTones[index].code==code) break;
+      index++;
+    }
+  }
+
+  if (!strncmp(RingingTones[index].name,"Uploaded ",9)) {
+     ringtone.location=atoi(&RingingTones[index].name[10]);
+
+     error=GSM->GetBinRingtone(&ringtone);
+
+     if (error==GE_NONE) return ringtone.name;
+     if (error==GE_UNKNOWNMODEL) {
     
-       for (i = 0; i < HowMany; i++) {
-
-               StartBit = BitUnPackInt(package, StartBit, &q, 3);
-               switch (q) {
-               case VolumeInstructionId:
-                       StartBit += 4;
-                       break;
-               case StyleInstructionId:
-                       StartBit = BitUnPackInt(package,StartBit,&l,2);
-                       l = l >> 3;
-                       break;
-               case TempoInstructionId:
-                       StartBit = BitUnPackInt(package, StartBit, &l, 5);
-                       l = l >> 3;
-                       ringtone->tempo = BeatsPerMinute[l];
-                       break;
-               case ScaleInstructionId:
-                       StartBit = BitUnPackInt(package, StartBit, &scale, 2);
-                       scale = scale >> 6;
-                       break;
-               case NoteInstructionId:
-                       StartBit = BitUnPackInt(package, StartBit, &l, 4);
-
-                       switch (l) {
-                       case Note_C   :ringtone->notes[ringtone->NrNotes].note = 0;   break;
-                       case Note_Cis :ringtone->notes[ringtone->NrNotes].note = 1;   break;
-                       case Note_D   :ringtone->notes[ringtone->NrNotes].note = 2;   break;
-                       case Note_Dis :ringtone->notes[ringtone->NrNotes].note = 3;   break;
-                       case Note_E   :ringtone->notes[ringtone->NrNotes].note = 4;   break;
-                       case Note_F   :ringtone->notes[ringtone->NrNotes].note = 6;   break;
-                       case Note_Fis :ringtone->notes[ringtone->NrNotes].note = 7;   break;
-                       case Note_G   :ringtone->notes[ringtone->NrNotes].note = 8;   break;
-                       case Note_Gis :ringtone->notes[ringtone->NrNotes].note = 9;   break;
-                       case Note_A   :ringtone->notes[ringtone->NrNotes].note = 10;  break;
-                       case Note_Ais :ringtone->notes[ringtone->NrNotes].note = 11;  break;
-                       case Note_H   :ringtone->notes[ringtone->NrNotes].note = 12;  break;
-                       default       :ringtone->notes[ringtone->NrNotes].note = 255; break; //Pause ?
-                       }
+        /* In 33x we have normal "Smart Messaging" format */
+        if (GetModelFeature (FN_RINGTONES)==F_RING_SM) {
       
-                       if (ringtone->notes[ringtone->NrNotes].note != 255)
-                               ringtone->notes[ringtone->NrNotes].note = ringtone->notes[ringtone->NrNotes].note + scale*14;
-
-                       StartBit = BitUnPackInt(package, StartBit, &duration, 3);
-
-                       StartBit = BitUnPackInt(package, StartBit, &spec, 2);    
-
-                       if (duration==Duration_Full && spec==DottedNote)
-                               ringtone->notes[ringtone->NrNotes].duration=128*3/2;
-                       if (duration==Duration_Full && spec==Length_2_3)
-                               ringtone->notes[ringtone->NrNotes].duration=128*2/3;
-                       if (duration==Duration_Full && spec==NoSpecialDuration)
-                               ringtone->notes[ringtone->NrNotes].duration=128;
-                       if (duration==Duration_1_2 && spec==DottedNote)
-                               ringtone->notes[ringtone->NrNotes].duration=64*3/2;
-                       if (duration==Duration_1_2 && spec==Length_2_3)
-                               ringtone->notes[ringtone->NrNotes].duration=64*2/3;
-                       if (duration==Duration_1_2 && spec==NoSpecialDuration)
-                               ringtone->notes[ringtone->NrNotes].duration=64;
-                       if (duration==Duration_1_4 && spec==DottedNote)
-                               ringtone->notes[ringtone->NrNotes].duration=32*3/2;
-                       if (duration==Duration_1_4 && spec==Length_2_3)
-                               ringtone->notes[ringtone->NrNotes].duration=32*2/3;
-                       if (duration==Duration_1_4 && spec==NoSpecialDuration)
-                               ringtone->notes[ringtone->NrNotes].duration=32;
-                       if (duration==Duration_1_8 && spec==DottedNote)
-                               ringtone->notes[ringtone->NrNotes].duration=16*3/2;
-                       if (duration==Duration_1_8 && spec==Length_2_3)
-                               ringtone->notes[ringtone->NrNotes].duration=16*2/3;
-                       if (duration==Duration_1_8 && spec==NoSpecialDuration)
-                               ringtone->notes[ringtone->NrNotes].duration=16;
-                       if (duration==Duration_1_16 && spec==DottedNote)
-                               ringtone->notes[ringtone->NrNotes].duration=8*3/2;
-                       if (duration==Duration_1_16 && spec==Length_2_3)
-                               ringtone->notes[ringtone->NrNotes].duration=8*2/3;
-                       if (duration==Duration_1_16 && spec==NoSpecialDuration)
-                               ringtone->notes[ringtone->NrNotes].duration=8;
-                       if (duration==Duration_1_32 && spec==DottedNote)
-                               ringtone->notes[ringtone->NrNotes].duration=4*3/2;
-                       if (duration==Duration_1_32 && spec==Length_2_3)
-                               ringtone->notes[ringtone->NrNotes].duration=4*2/3;
-                       if (duration==Duration_1_32 && spec==NoSpecialDuration)
-                               ringtone->notes[ringtone->NrNotes].duration=4;
-
-                       if (ringtone->NrNotes==MAX_RINGTONE_NOTES) break;
+          i=7;
+         if (ringtone.frame[9]==0x4a && ringtone.frame[10]==0x3a) i=8;
+         ringtone.frame[i]=0x02;
        
-                       ringtone->NrNotes++;
-                       break;
-               default:
-                       dprintf("Unsupported block\n");
-                       return GE_SUBFORMATNOTSUPPORTED;
-               } 
-       }
+          GSM_UnPackRingtone(&SMringtone, ringtone.frame+i, ringtone.length-i);
 
-       return GE_NONE;
+          return SMringtone.name;
+       }
+     }
+  }
+  
+  return RingingTones[index].name;
 }
 
+/* returns code from number in menu */
+int RingingToneCode(int menu)
+{
+  int index=1;
+
+  while ( RingingTones[index].menu!=menu) index++;
 
-GSM_Error GSM_ReadRingtoneFromSMS(GSM_SMSMessage *message, GSM_Ringtone *ringtone)
+  return RingingTones[index].code;
+}
+
+/* returns number in menu from code */
+int RingingToneMenu(int code)
 {
-       if (message->UDH[0].Type==SMS_Ringtone) {
-               return GSM_UnPackRingtone(ringtone, message->MessageText, message->Length);
-       } else return GE_SUBFORMATNOTSUPPORTED;
+  int index=1;
+
+  while ( RingingTones[index].code!=code) index++;
+
+  return RingingTones[index].menu;
 }
 
+int NumberOfRingtones()
+{
+  return RingingTones[0].menu;
+}
 
-int GSM_SaveRingtoneToSMS(GSM_SMSMessage *message, GSM_Ringtone *ringtone)
+int GSM_SaveRingtoneToSMS(GSM_MultiSMSMessage *SMS,
+                          GSM_Ringtone *ringtone, bool profilestyle)
 {  
-       int i, j = GSM_MAX_8BIT_SMS_LENGTH;
-  
-       char UserDataHeader[7]= { 0x06,  /* User Data Header Length */
-                                 0x05,  /* IEI: application port addressing scheme, 16 bit address */
-                                 0x04,  /* IEDL (IED length ?) */
-                                 0x15,  /* destination address: high byte */
-                                 0x81,  /* destination address: low byte */
-                                 0x15,  /* originator address: high byte */
-                                 0x81}; /* originator address: low byte */
-
-       /* Default settings for SMS message:
-          - no delivery report
-          - Class Message 1
-          - no compression
-          - 8 bit data
-          - SMSC no. 1
-          - validity 3 days
-          - set UserDataHeaderIndicator
-       */
-
-       message->Type = SMS_Sent;
-
-       /* Data Coding Scheme */
-       message->DCS.Type = SMS_GeneralDataCoding;
-       message->DCS.u.General.Class = 2;
-       message->DCS.u.General.Compressed = false;
-       message->DCS.u.General.Alphabet = SMS_8bit;
-
-       message->MessageCenter.No = 1;
-       message->Validity.VPF = SMS_RelativeFormat;
-       message->Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
-       message->ReplyViaSameSMSC = false;
-
-       message->UDH_No = 1;
-       message->UDH[0].Type = SMS_Ringtone;
+  int i, j;
+  unsigned char MessageBuffer[GSM_MAX_SMS_8_BIT_LENGTH*4];
+  unsigned char MessageBuffer2[GSM_MAX_SMS_8_BIT_LENGTH*4];
+  int MessageLength;
+  GSM_UDH UDHType;
   
-       message->Length = j;
-  
-       memcpy(message->MessageText, UserDataHeader, 7);
-       i = GSM_PackRingtone(ringtone, message->MessageText + 7, &j);
-  
-       return i;
+  EncodeUDHHeader(MessageBuffer, GSM_RingtoneUDH);
+  MessageLength=GSM_MAX_SMS_8_BIT_LENGTH-(MessageBuffer[0]+1);
+  i=GSM_PackRingtone(ringtone, MessageBuffer, &MessageLength);
+
+  if (i!=ringtone->NrNotes && profilestyle)
+  {
+    MessageLength=0;
+    MessageBuffer[MessageLength++]=0x30;          //SM version. Here 3.0
+    MessageBuffer[MessageLength++]=SM30_RINGTONE; //ID for ringtone
+
+    MessageBuffer[MessageLength++]=0x01;          //length hi.Later changed
+    MessageBuffer[MessageLength++]=0x00;          //length lo.Later changed
+
+    j=SM30_MAX_RINGTONE_FRAME_LENGTH;
+    i=GSM_PackRingtone(ringtone, MessageBuffer2, &j);
+    MessageLength=MessageLength+j;
+    memcpy(MessageBuffer+4,MessageBuffer2,j);
+      
+    MessageBuffer[2]=j/256;
+    MessageBuffer[3]=j%256;
+
+    UDHType=GSM_ProfileUDH;
+  } else
+    UDHType=GSM_RingtoneUDH;
+
+  GSM_MakeMultiPartSMS2(SMS,MessageBuffer,MessageLength, UDHType, GSM_Coding_Default);
+
+  return i;
 }
index 6006de5..5a35034 100644 (file)
 /*
 
-  $Id$
-
   G N O K I I
 
   A Linux/Unix toolset and driver for Nokia mobile phones.
 
-  Copyright (C) 2001 Pawe³ Kot <pkot@linuxnews.pl>
-
   Released under the terms of the GNU GPL, see file COPYING for more details.
-
-  Library for parsing and creating Short Messages (SMS).
-
+       
 */
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
+#include <time.h>
 
-#include "gsm-common.h"
-#include "gsm-encoding.h"
-#include "gsm-bitmaps.h"
-
-SMSMessage_PhoneLayout layout;
-static SMSMessage_Layout llayout;
-
-struct udh_data {
-       unsigned int length;
-       char *header;
-};
+#include "gsm-api.h"
+#include "gsm-coding.h"
 
 /* User data headers */
-static struct udh_data headers[] = {
-       { 0x00, "" },
-       { 0x05, "\x00\x03\x01\x00\x00" },     /* Concatenated messages */
-       { 0x06, "\x05\x04\x15\x82\x00\x00" }, /* Operator logos */
-       { 0x06, "\x05\x04\x15\x83\x00\x00" }, /* Caller logos */
-       { 0x06, "\x05\x04\x15\x81\x00\x00" }, /* Ringtones */
-       { 0x04, "\x03\x01\x00\x00" },         /* Voice Messages */
-       { 0x04, "\x03\x01\x01\x00" },         /* Fax Messages */
-       { 0x04, "\x03\x01\x02\x00" },         /* Email Messages */
-       { 0x06, "\x05\x04\x23\xf4\x00\x00" }, /* Business Card */
-       { 0x00, "" }
+GSM_UDHHeader UDHHeaders[] = {
+  { GSM_ConcatenatedMessages, 0x05, "\x00\x03\x01\x00\x00" },
+      /* See GSM 03.40 section 9.2.3.24.1 */
+  { GSM_DisableVoice,         0x04, "\x01\x02\x00\x00" },
+  { GSM_DisableFax,           0x04, "\x01\x02\x01\x00" },
+  { GSM_DisableEmail,         0x04, "\x01\x02\x02\x00" },
+  { GSM_EnableVoice,          0x04, "\x01\x02\x00\x01" },
+  { GSM_EnableFax,            0x04, "\x01\x02\x01\x01" },
+  { GSM_EnableEmail,          0x04, "\x01\x02\x02\x01" },
+      /* See GSM 03.40 section 9.2.3.24.2 for voice, fax and email messages */
+  { GSM_VoidSMS,              0x08, "\x01\x02\x02\x01\x01\x02\x02\x00" },
+      /* When send such SMS to some phones, they don't display anything,
+         only beep and enable vibra/light */
+  { GSM_BugSMS,               0x09, "\x01\x02\x02\x01\x01\x02\x02\x00\xc0" },
+
+  /* Short Smart Messaging UDH */
+  /* General format: */
+  /* 1 byte  0x05     : IEI application port addressing scheme, 16 bit address */
+  /* 1 byte  0x04     : IEI length */
+  /* 2 bytes          : destination address: high & low byte */
+  /* 2 bytes 0x00 0x00: originator address: high & low byte */
+  { GSM_RingtoneUDH,          0x06, "\x05\x04\x15\x81\x00\x00" },
+  { GSM_OpLogo,               0x06, "\x05\x04\x15\x82\x00\x00" },
+  { GSM_CallerIDLogo,         0x06, "\x05\x04\x15\x83\x00\x00" },
+  { GSM_WAPBookmarkUDH,       0x06, "\x05\x04\xc3\x4f\x00\x00" },
+
+  /* Long Smart Messaging UDH */
+  /* General format: */
+  /* 1 byte 0x05      : IEI application port addressing scheme, 16 bit address */
+  /* 1 byte 0x04      : IEI length */
+  /* 2 bytes 0x00 0x00: destination address: high & low byte */
+  /* 2 bytes 0x00 0x00: originator address: high & low byte */
+  /* 1 byte 0x00      : null byte for end first part ? */
+  /* 1 byte 0x03      : length for rest ? */
+  /* 1 byte                               */
+  /* 1 byte           : number of all SMS */
+  /* 1 byte           : number of current SMS */
+  { GSM_CalendarNoteUDH,      0x0b, "\x05\x04\x00\xe4\x00\x00\x00\x03\xc7\x00\x00" }, //from 3310 ?
+  { GSM_CalendarNoteUDH2,     0x0b, "\x05\x04\x23\xf5\x00\x00\x00\x03\x01\x00\x00" }, //from 6210 or 9210 Note: last 0x01 changes according to note type
+  { GSM_ProfileUDH,           0x0b, "\x05\x04\x15\x8a\x00\x00\x00\x03\xce\x00\x00" },
+  { GSM_WAPBookmarkUDH,       0x0b, "\x05\x04\xc3\x4f\x00\x00\x00\x03\x01\x00\x00" },//note last 0x01 can change
+  { GSM_WAPSettingsUDH,       0x0b, "\x05\x04\xc3\x4f\x00\x00\x00\x03\x7f\x00\x00" },
+  { GSM_PhonebookUDH,         0x0b, "\x05\x04\x23\xf4\x00\x00\x00\x03\x01\x00\x00" },
+
+  { GSM_NoUDH,                0x00, "" }
 };
 
+#define ByteMask ((1 << Bits) - 1)
 
-/***
- *** Util functions
- ***/
-
-/* This function implements packing of numbers (SMS Center number and
-   destination number) for SMS sending function. */
-int SemiOctetPack(char *Number, unsigned char *Output, SMS_NumberType type)
+int GSM_PackSevenBitsToEight(int offset, unsigned char *input, unsigned char *output)
 {
-       unsigned char *IN = Number;  /* Pointer to the input number */
-       unsigned char *OUT = Output; /* Pointer to the output */
-       int count = 0; /* This variable is used to notify us about count of already
-                         packed numbers. */
-
-       /* The first byte in the Semi-octet representation of the address field is
-          the Type-of-Address. This field is described in the official GSM
-          specification 03.40 version 6.1.0, section 9.1.2.5, page 33. We support
-          only international and unknown number. */
-
-       *OUT++ = type;
-       if (type == SMS_International) IN++; /* Skip '+' */
-       if ((type == SMS_Unknown) && (*IN == '+')) IN++; /* Optional '+' in Unknown number type */
-
-       /* The next field is the number. It is in semi-octet representation - see
-          GSM scpecification 03.40 version 6.1.0, section 9.1.2.3, page 31. */
-       while (*IN) {
-               if (count & 0x01) {
-                       *OUT = *OUT | ((*IN - '0') << 4);
-                       OUT++;
-               }
-               else
-                       *OUT = *IN - '0';
-               count++; IN++;
-       }
-
-       /* We should also fill in the most significant bits of the last byte with
-          0x0f (1111 binary) if the number is represented with odd number of
-          digits. */
-       if (count & 0x01) {
-               *OUT = *OUT | 0xf0;
-               OUT++;
-       }
-
-       return (2 * (OUT - Output - 1) - (count % 2));
+        unsigned char *OUT = output; /* Current pointer to the output buffer */
+        unsigned char *IN  = input;  /* Current pointer to the input buffer */
+        int Bits;                    /* Number of bits directly copied to
+                                        the output buffer */
+        Bits = (7 + offset) % 8;
+
+        /* If we don't begin with 0th bit, we will write only a part of the
+           first octet */
+        if (offset) {
+                *OUT = 0x00;
+                OUT++;
+        }
+
+        while ((IN - input) < strlen(input)) {
+                unsigned char Byte = EncodeWithDefaultAlphabet(*IN);
+
+                *OUT = Byte >> (7 - Bits);
+                /* If we don't write at 0th bit of the octet, we should write
+                   a second part of the previous octet */
+                if (Bits != 7)
+                        *(OUT-1) |= (Byte & ((1 << (7-Bits)) - 1)) << (Bits+1);
+
+                Bits--;
+
+                if (Bits == -1) Bits = 7;
+                else OUT++;
+
+                IN++;
+        }
+        return (OUT - output);
 }
 
-char *GetBCDNumber(u8 *Number)
+int GSM_UnpackEightBitsToSeven(int offset, int in_length, int out_length,
+                           unsigned char *input, unsigned char *output)
 {
-       static char Buffer[20] = "";
-       int length = Number[0]; /* This is the length of BCD coded number */
-       int count, Digit;
-
-       memset(Buffer, 0, 20);
-       switch (Number[1]) {
-       case SMS_Alphanumeric:
-               Unpack7BitCharacters(0, length, length, Number+2, Buffer);
-               Buffer[length] = 0;
-               break;
-       case SMS_International:
-               sprintf(Buffer, "+");
-       case SMS_Unknown:
-       case SMS_National:
-       case SMS_Network:
-       case SMS_Subscriber:
-       case SMS_Abbreviated:
-       default:
-               for (count = 0; count < length - 1; count++) {
-                       Digit = Number[count+2] & 0x0f;
-                       if (Digit < 10) sprintf(Buffer, "%s%d", Buffer, Digit);
-                       Digit = Number[count+2] >> 4;
-                       if (Digit < 10) sprintf(Buffer, "%s%d", Buffer, Digit);
-               }
-               break;
-       }
-       return Buffer;
+        unsigned char *OUT = output; /* Current pointer to the output buffer */
+        unsigned char *IN  = input;  /* Current pointer to the input buffer */
+        unsigned char Rest = 0x00;
+        int Bits;
+
+        Bits = offset ? offset : 7;
+
+        while ((IN - input) < in_length) {
+
+                *OUT = ((*IN & ByteMask) << (7 - Bits)) | Rest;
+                Rest = *IN >> Bits;
+
+                /* If we don't start from 0th bit, we shouldn't go to the
+                   next char. Under *OUT we have now 0 and under Rest -
+                   _first_ part of the char. */
+                if ((IN != input) || (Bits == 7)) OUT++;
+                IN++;
+
+                if ((OUT - output) >= out_length) break;
+
+                /* After reading 7 octets we have read 7 full characters but
+                   we have 7 bits as well. This is the next character */
+                if (Bits == 1) {
+                        *OUT = Rest;
+                        OUT++;
+                        Bits = 7;
+                        Rest = 0x00;
+                } else {
+                        Bits--;
+                }
+        }
+
+        return OUT - output;
 }
 
-static char *PrintDateTime(u8 *Number) 
-{
-       static char Buffer[23] = "";
-
-       memset(Buffer, 0, 23);
-       if (Number[0] < 70) sprintf(Buffer, "20");
-       else sprintf(Buffer, "19");
-       sprintf(Buffer, "%s%d%d-", Buffer, Number[0] & 0x0f, Number[0] >> 4);
-       sprintf(Buffer, "%s%d%d-", Buffer, Number[1] & 0x0f, Number[1] >> 4);
-       sprintf(Buffer, "%s%d%d ", Buffer, Number[2] & 0x0f, Number[2] >> 4);
-       sprintf(Buffer, "%s%d%d:", Buffer, Number[3] & 0x0f, Number[3] >> 4);
-       sprintf(Buffer, "%s%d%d:", Buffer, Number[4] & 0x0f, Number[4] >> 4);
-       sprintf(Buffer, "%s%d%d",  Buffer, Number[5] & 0x0f, Number[5] >> 4);
-       if (Number[6] & 0x08) 
-               sprintf(Buffer, "%s-", Buffer);
-       else
-               sprintf(Buffer, "%s+", Buffer);
-       sprintf(Buffer, "%s%02d00", Buffer, (10 * (Number[6] & 0x07) + (Number[6] >> 4)) / 4);
-
-       return Buffer;
+/* This function implements packing of numbers (SMS Center number and
+   destination number) for SMS sending function. */
+/* See GSM 03.40 9.1.1:
+   1 byte  - length of number given in semioctets or bytes (when given in bytes,
+             includes one byte for byte with number format.
+             Returned by function (set semioctet to true, if want result
+             in semioctets).
+   1 byte  - format of number. See GSM_NumberType; in gsm-common.h. Returned
+             in u8 *Output.
+   n bytes - 2n or 2n-1 semioctets with number. For some types of numbers
+             in the most significant bits of the last byte with 0x0f
+             (1111 binary) are filled if the number is represented
+             with odd number of digits. Returned in u8 *Output. */
+/* 1 semioctet = 4 bits = half of byte */
+int GSM_PackSemiOctetNumber(u8 *Number, u8 *Output, bool semioctet) {
+
+  u8 *IN=Number;  /* Pointer to the input number */
+  u8 *OUT=Output; /* Pointer to the output */
+  int length=0,j;
+  unsigned char format=GNT_UNKNOWN; // format of number used by us
+
+  /* Checking for format number */
+  while (*IN) {
+    if (length==0 && *IN=='+')
+      format=GNT_INTERNATIONAL;  // first byte is '+'. It can be international
+    else {
+      if (*IN>'9' || *IN<'0') { 
+        format=GNT_ALPHANUMERIC; //char is not number. It must be alphanumeric
+      }
+    }
+    IN++;length++;
+  }
+
+  /* Now we return to first byte */
+  for (j=0;j<length;j++) IN--;
+
+  /* The first byte in the Semi-octet representation of the address field is
+     the Type-of-Address. This field is described in the official GSM
+     specification 03.40 version 5.3.0, section 9.1.2.5, page 33.*/
+  *OUT++=format;
+
+  /* The next field is the number. See GSM 03.40 section 9.1.2 */
+  switch (format) {
+    case GNT_ALPHANUMERIC:
+      length=GSM_PackSevenBitsToEight(0, IN, OUT)*2;
+      break;
+
+    case GNT_INTERNATIONAL:
+      length--;
+      EncodeBCD (OUT, IN+1, length, true);
+      break;
+
+    default:
+      EncodeBCD (OUT, IN, length, true);
+      break;
+  }
+
+  if (semioctet) {
+    return length;
+  } else {
+    /* Convert number of semioctets to number of chars */
+    if (length % 2) length++;
+    return length / 2 + 1;
+  }
 }
 
-SMS_DateTime *UnpackDateTime(u8 *Number, SMS_DateTime *dt)
-{
-       dt->Year     =  10 * (Number[0] & 0x0f) + (Number[0] >> 4);
-       if (dt->Year < 70) dt->Year += 2000;
-       else dt->Year += 1900;
-       dt->Month    =  10 * (Number[1] & 0x0f) + (Number[1] >> 4);
-       dt->Day      =  10 * (Number[2] & 0x0f) + (Number[2] >> 4);
-       dt->Hour     =  10 * (Number[3] & 0x0f) + (Number[3] >> 4);
-       dt->Minute   =  10 * (Number[4] & 0x0f) + (Number[4] >> 4);
-       dt->Second   =  10 * (Number[5] & 0x0f) + (Number[5] >> 4);
-       dt->Timezone = (10 * (Number[6] & 0x07) + (Number[6] >> 4)) / 4;
-       if (Number[6] & 0x08) dt->Timezone = -dt->Timezone;
-
-       return dt;
-}
+char *GSM_UnpackSemiOctetNumber(u8 *Number, bool semioctet) {
 
-/***
- *** ENCODING SMS
- ***/
+  static char Buffer[20]="";  
+  int length=Number[0];
 
-static GSM_Error EncodeData(GSM_SMSMessage *SMS, char *dcs, char *message)
-{
-       SMS_AlphabetType al;
-       unsigned short length = strlen(SMS->MessageText);
-
-       switch (SMS->DCS.Type) {
-       case SMS_GeneralDataCoding:
-               switch (SMS->DCS.u.General.Class) {
-               case 1: dcs[0] |= 0xf0; break;
-               case 2: dcs[0] |= 0xf1; break;
-               case 3: dcs[0] |= 0xf2; break;
-               case 4: dcs[0] |= 0xf3; break;
-               default: break;
-               }
-               if (SMS->DCS.u.General.Compressed) {
-                       /* Compression not supported yet */
-                       /* dcs[0] |= 0x20; */
-               }
-               al = SMS->DCS.u.General.Alphabet;
-               break;
-       case SMS_MessageWaiting:
-               al = SMS->DCS.u.MessageWaiting.Alphabet;
-               if (SMS->DCS.u.MessageWaiting.Discard) dcs[0] |= 0xc0;
-               else if (SMS->DCS.u.MessageWaiting.Alphabet == SMS_UCS2) dcs[0] |= 0xe0;
-               else dcs[0] |= 0xd0;
+  if (semioctet) {
+    /* Convert number of semioctets to number of chars */
+    if (length % 2) length++;
+    length=length / 2 + 1;
+  }
+  
+  length--; //without leading byte with format of number
 
-               if (SMS->DCS.u.MessageWaiting.Active) dcs[0] |= 0x08;
-               dcs[0] |= (SMS->DCS.u.MessageWaiting.Type & 0x03);
+  switch (Number[1]) {
+    case GNT_ALPHANUMERIC:
+      GSM_UnpackEightBitsToSeven(0, length, length, Number+2, Buffer);
+      Buffer[length]=0;
+      break;
 
-               break;
-       default:
-               return GE_SMSWRONGFORMAT;
-       }
-       switch (al) {
-       case SMS_DefaultAlphabet:
-               Pack7BitCharacters((7 - (SMS->UDH_Length % 7)) % 7, SMS->MessageText, message);
-               SMS->Length = 8 * SMS->UDH_Length + (7 - (SMS->UDH_Length % 7)) % 7 + length;
-               break;
-       case SMS_8bit:
-               dcs[0] |= 0xf4;
-               memcpy(message, SMS->MessageText + 1, SMS->MessageText[0]);
-               SMS->Length = SMS->UDH_Length + SMS->MessageText[0];
-               break;
-       case SMS_UCS2:
-               dcs[0] |= 0x08;
-               EncodeUnicode(message, SMS->MessageText, length);
-               SMS->Length = length;
-               break;
-       default:
-               return GE_SMSWRONGFORMAT;
-       }
-       return GE_NONE;
+    case GNT_INTERNATIONAL:
+      Buffer[0]='+';
+      DecodeBCD (Buffer+1, Number+2, length);
+      break;
+
+    default:
+      DecodeBCD (Buffer, Number+2, length);
+      break;
+  }
+
+  return Buffer;
 }
 
-/* This function encodes the UserDataHeader as described in:
-   - GSM 03.40 version 6.1.0 Release 1997, section 9.2.3.24
-   - Smart Messaging Specification, Revision 1.0.0, September 15, 1997
-*/
-static GSM_Error EncodeUDH(SMS_UDHInfo UDHi, char *UDH)
+/* See GSM 03.40 section 9.2.3.11 */
+GSM_Error GSM_EncodeSMSDateTime(GSM_DateTime *DT, unsigned char *req)
 {
-       unsigned char pos;
+#ifdef DEBUG
+  fprintf(stdout,_("Date & time in saved SMS: %02i/%02i/%04i %02i:%02i:%02i\n"),
+    DT->Day,DT->Month,DT->Year,DT->Hour,DT->Minute,DT->Second);
+#endif
+  
+  req[0]=EncodeWithBCDAlphabet(DT->Year);
+  req[1]=EncodeWithBCDAlphabet(DT->Month);
+  req[2]=EncodeWithBCDAlphabet(DT->Day);
+  req[3]=EncodeWithBCDAlphabet(DT->Hour);
+  req[4]=EncodeWithBCDAlphabet(DT->Minute);
+  req[5]=EncodeWithBCDAlphabet(DT->Second);
+
+  /* FIXME: do it */
+  req[6]=0; /* TimeZone = +-0 */
+
+  return GE_NONE;
+}
 
-       pos = UDH[0];
-       switch (UDHi.Type) {
-       case SMS_NoUDH:
-               break;
-       case SMS_VoiceMessage:
-       case SMS_FaxMessage:
-       case SMS_EmailMessage:
-               UDH[pos+4] = UDHi.u.SpecialSMSMessageIndication.MessageCount;
-               if (UDHi.u.SpecialSMSMessageIndication.Store) UDH[pos+3] |= 0x80;
-       case SMS_ConcatenatedMessages:
-       case SMS_OpLogo:
-       case SMS_CallerIDLogo:
-       case SMS_Ringtone:
-               UDH[0] += headers[UDHi.Type].length;
-               memcpy(UDH+pos+1, headers[UDHi.Type].header, headers[UDHi.Type].length);
-               break;
-       default:
-               dprintf("Not supported User Data Header type\n");
-               break;
-       }
-       return GE_NONE;
+/* See GSM 03.40 section 9.2.3.11 */
+GSM_Error GSM_DecodeSMSDateTime(GSM_DateTime *DT, unsigned char *req)
+{
+  DT->Year    = DecodeWithBCDAlphabet(req[0]);
+  DT->Month   = DecodeWithBCDAlphabet(req[1]);
+  DT->Day     = DecodeWithBCDAlphabet(req[2]);
+  DT->Hour    = DecodeWithBCDAlphabet(req[3]);
+  DT->Minute  = DecodeWithBCDAlphabet(req[4]);
+  DT->Second  = DecodeWithBCDAlphabet(req[5]);
+
+  DT->Timezone=(10*(req[6]&0x07)+(req[6]>>4))/4;
+  if (req[6]&0x08) DT->Timezone = -DT->Timezone;
+
+#ifdef DEBUG
+  fprintf(stdout, _("%d%d-"), req[0]&0xf, req[0]>>4);
+  fprintf(stdout, _("%d%d-"), req[1]&0xf, req[1]>>4);
+  fprintf(stdout, _("%d%d "), req[2]&0xf, req[2]>>4);
+  fprintf(stdout, _("%d%d:"), req[3]&0xf, req[3]>>4);
+  fprintf(stdout, _("%d%d:"), req[4]&0xf, req[4]>>4);
+  fprintf(stdout, _("%d%d "), req[5]&0xf, req[5]>>4);
+
+  if (req[6]) {
+    if (req[6] & 0x08) fprintf(stdout, "-");
+                  else fprintf(stdout, "+");
+
+    fprintf(stdout, _("%02d00"), (10*(req[6]&0x07)+(req[6]>>4))/4);
+  }
+
+  fprintf(stdout, "\n");
+#endif
+
+  return GE_NONE;
 }
 
-static GSM_Error EncodeSMSSubmitHeader(GSM_SMSMessage *SMS, char *frame)
+int GSM_EncodeETSISMSSubmitData(GSM_SMSMessage *SMS, GSM_ETSISMSMessage *ETSI)
 {
-       GSM_Error error = GE_NONE;
-
-       /* Standard Header: */
-       memcpy(frame + llayout.UserDataHeader, "\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa9\x00\x00\x00\x00\x00\x00", 24);
-
-       /* Reply Path */
-       if (llayout.ReplyViaSameSMSC > -1) {
-               if (SMS->ReplyViaSameSMSC) frame[llayout.ReplyViaSameSMSC] |= 0x80;
-       }
-
-       /* User Data Header Indicator */
-       if (llayout.UserDataHeader > -1) {
-               if (SMS->UDH_No) frame[llayout.UserDataHeader] |= 0x40;
-       }
-
-       /* Status (Delivery) Report Request */
-       if (llayout.Report > -1) {
-               if (SMS->Report) frame[llayout.Report] |= 0x20;
-       }
-
-       /* Validity Period Format: mask - 0x00, 0x10, 0x08, 0x18 */
-       if (llayout.Validity > -1) {
-               frame[llayout.Validity] |= ((SMS->Validity.VPF & 0x03) << 3);
-       }
-
-       /* Reject Duplicates */
-       if (llayout.RejectDuplicates > -1) {
-               if (SMS->RejectDuplicates) frame[llayout.RejectDuplicates] |= 0x04;
-       }
-
-       /* Message Type is already set */
-
-       /* Message Reference */
-       /* Can we set this? */
-
-       /* Protocol Identifier */
-       /* FIXME: allow to change this in better way.
-          currently only 0x5f == `Return Call Message' is used */
-       if (llayout.PID > -1) {
-               if (SMS->PID) frame[llayout.PID] = SMS->PID;
-       }
-
-       /* Data Coding Scheme */
-       if (llayout.DataCodingScheme > -1) {
-               switch (SMS->DCS.Type) {
-               case SMS_GeneralDataCoding:
-                       if (SMS->DCS.u.General.Compressed) frame[llayout.DataCodingScheme] |= 0x20;
-                       if (SMS->DCS.u.General.Class) frame[llayout.DataCodingScheme] |= (0x10 | (SMS->DCS.u.General.Class - 1));
-                       frame[llayout.DataCodingScheme] |= ((SMS->DCS.u.General.Alphabet & 0x03) << 2);
-                       break;
-               case SMS_MessageWaiting:
-                       if (SMS->DCS.u.MessageWaiting.Discard) frame[llayout.DataCodingScheme] |= 0xc0;
-                       else if (SMS->DCS.u.MessageWaiting.Alphabet == SMS_UCS2) frame[llayout.DataCodingScheme] |= 0xe0;
-                       else frame[llayout.DataCodingScheme] |= 0xd0;
-                       if (SMS->DCS.u.MessageWaiting.Active) frame[llayout.DataCodingScheme] |= 0x80;
-                       frame[llayout.DataCodingScheme] |= (SMS->DCS.u.MessageWaiting.Type & 0x03);
-                       break;
-               default:
-                       dprintf("Wrong Data Coding Scheme (DCS) format\n");
-                       return GE_SMSWRONGFORMAT;
-               }
-       }
-
-       /* Destination Address */
-       if (llayout.RemoteNumber > -1) {
-               frame[llayout.RemoteNumber] = SemiOctetPack(SMS->RemoteNumber.number, frame + llayout.RemoteNumber + 1, SMS->RemoteNumber.type);
-       }
-
-       /* Validity Period */
-       switch (SMS->Validity.VPF) {
-       case SMS_EnhancedFormat:
-               break;
-       case SMS_RelativeFormat:
-               break;
-       case SMS_AbsoluteFormat:
-               break;
-       default:
-               break;
-       }
+  int off,size=0,size2=0,w,i;
+
+  /* off - length of the user data header */
+  off = 0;
+
+  if (SMS->UDHType) {
+    /* GSM 03.40 section 9.2.3.23 (TP-User-Data-Header-Indicator) */
+    ETSI->firstbyte |= 0x40;
+
+    /* off - length of the user data header */
+    off = 1 + SMS->UDH[0];
+
+    /* we copy the udh */
+    memcpy(ETSI->MessageText, SMS->UDH, off);
+
+//  if (SMS->UDHType==GSM_HangSMS) ETSI->TPDCS=0x08; //Such SMS hangs phone (5110, 5.07),
+                                                     //when saved to Outbox atry try to read it
+                                                    /*from phone's menu*/
+  }
+
+  switch (SMS->Coding) {
+    /* When save SMS to SIM and it's 8 bit SMS,
+       "Edit" is not displayed in phone menu and
+       "Message cannot be displayed here" instead of message text */
+    case GSM_Coding_8bit:
+
+      /* the mask for the 8-bit data */
+      /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme) and GSM 03.38 section 4 */
+      ETSI->TPDCS |= 0xf4;
+    
+      memcpy(ETSI->MessageText + off, SMS->MessageText, SMS->Length);
+
+      size2 = size = SMS->Length+off;
+
+      break;
+
+    case GSM_Coding_Default:
+
+      w=(7-off)%7;
+      if (w<0) w=(14-off)%14;
+
+      size = GSM_PackSevenBitsToEight(w, SMS->MessageText, ETSI->MessageText + off);
+      size += off;
+      size2 = (off*8 + w) / 7 + strlen(SMS->MessageText);
+
+      break;
 
-       return error;
+    case GSM_Coding_Unicode:
+
+      /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme) and GSM 03.38 section 4 */
+      ETSI->TPDCS |= 0x08;
+
+#ifdef DEBUG
+      fprintf(stdout,_("SMS Length is %i\n"),strlen(SMS->MessageText));
+#endif
+
+      EncodeUnicode (ETSI->MessageText+off,SMS->MessageText,strlen(SMS->MessageText));
+      /* here we code "special" chars */
+      for (i=0;i<strlen(SMS->MessageText);i++) {
+       if (SMS->MessageText[i]=='~') ETSI->MessageText[off+1+i*2]=1; //enables/disables blinking
+        if (SMS->MessageText[i]=='`') ETSI->MessageText[off+1+i*2]=0; //hides rest ot contents
+      }
+
+      size=size2=strlen(SMS->MessageText)*2+off;
+
+      break;
+  }
+
+  /* FIXME: support for compression */
+  /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme) and GSM 03.38 section 4 */
+  /* See also GSM 03.42 */
+  /* if (SMS->Compression) ETSI->TPDCS |= 0x20; */
+
+  /* SMS->Length is:
+       - integer representation of the number od octets within the user data when UD is coded using 8bit data
+       - the sum of the number of septets in UDH including any padding and number of septets in UD in other case */
+  /* GSM 03.40 section 9.2.3.16 (TP-User-Data-Length) */
+  ETSI->TPUDL = size2;
+
+  return size;
 }
 
-static GSM_Error EncodeSMSDeliverHeader()
+GSM_Error GSM_DecodeETSISMSSubmitData(GSM_SMSMessage *SMS, GSM_ETSISMSMessage *ETSI)
 {
-       return GE_NONE;
+  int off,w,i,tmp=0;
+  unsigned char output[161];
+  bool UDHOK;
+
+  /* off - length of the user data header */
+  off = 0;
+  
+  SMS->UDHType = GSM_NoUDH;
+
+  if (ETSI->firstbyte & 64) { /* UDH header available */
+
+    off = (ETSI->MessageText[0] + 1); /* Length of UDH header */
+    
+    /* Copy UDH header into SMS->UDH */
+    for (i = 0; i < off; i++) SMS->UDH[i] = ETSI->MessageText[i];
+
+#ifdef DEBUG
+    fprintf(stdout, "   UDH header available (length %i",off);
+#endif
+    
+    SMS->UDHType = GSM_UnknownUDH;
+
+    i=-1;
+    while (true) {
+      i++;
+      if (UDHHeaders[i].UDHType==GSM_NoUDH) break;
+      tmp=UDHHeaders[i].Length;
+      if (tmp==SMS->UDH[0]) { //if length is the same
+
+        if (tmp==0x05) tmp=tmp-2;/*two last bytes can be different for such UDH*/
+        if (tmp==0x0b) tmp=tmp-3;/*three last bytes can be different for such UDH*/
+
+        UDHOK=true;
+        for (w=0;w<tmp;w++) {
+          if (UDHHeaders[i].Text[w]!=SMS->UDH[w+1]) {
+            UDHOK=false;
+            break;
+          }
+        }
+        if (UDHOK) {
+          SMS->UDHType=UDHHeaders[i].UDHType;
+          break;
+        }
+      }
+    }
+
+#ifdef DEBUG
+    switch (SMS->UDHType) {
+      case GSM_ConcatenatedMessages:
+        fprintf(stdout,_(", concatenated (linked) message %d/%d"),SMS->UDH[5],SMS->UDH[4]);break;
+      case GSM_DisableVoice:
+        fprintf(stdout,_(", disables voice indicator"));break;
+      case GSM_EnableVoice:
+        fprintf(stdout,_(", enables voice indicator"));break;
+      case GSM_DisableFax:
+        fprintf(stdout,_(", disables fax indicator"));break;
+      case GSM_EnableFax:
+        fprintf(stdout,_(", enables fax indicator"));break;
+      case GSM_DisableEmail:
+        fprintf(stdout,_(", disables email indicator"));break;
+      case GSM_EnableEmail:
+        fprintf(stdout,_(", enables email indicator"));break;
+      case GSM_VoidSMS:
+        fprintf(stdout,_(", void SMS"));break;
+      case GSM_WAPBookmarkUDH:
+        fprintf(stdout,_(", WAP Bookmark"));break;
+      case GSM_WAPBookmarkUDHLong:
+        fprintf(stdout,_(", WAP Bookmark, part %i/%i"),SMS->UDH[11],SMS->UDH[10]);break;
+      case GSM_WAPSettingsUDH:
+        fprintf(stdout,_(", WAP Settings, part %i/%i"),SMS->UDH[11],SMS->UDH[10]);break;
+      case GSM_RingtoneUDH:
+        fprintf(stdout,_(", ringtone"));break;
+      case GSM_OpLogo:
+        fprintf(stdout,_(", GSM Operator Logo"));break;
+      case GSM_CallerIDLogo:
+        fprintf(stdout,_(", Caller Logo"));break;
+      case GSM_ProfileUDH:
+        fprintf(stdout,_(", Profile SMS, part %i/%i"),SMS->UDH[11],SMS->UDH[10]);break;
+      case GSM_CalendarNoteUDH:
+        fprintf(stdout,_(", Calendar note SMS, part %i/%i"),SMS->UDH[11],SMS->UDH[10]);break;
+      case GSM_CalendarNoteUDH2:
+        fprintf(stdout,_(", Calendar note SMS, part %i/%i"),SMS->UDH[11],SMS->UDH[10]);break;
+      case GSM_PhonebookUDH:
+        fprintf(stdout,_(", Phonebook Entry, part %i/%i"),SMS->UDH[11],SMS->UDH[10]);break;
+      default:
+        fprintf(stdout,_(", UNKNOWN"));break;
+    }
+               
+    fprintf(stdout, ")\n");
+
+    hexdump(off,SMS->UDH);
+#endif
+  }
+
+  SMS->Coding = GSM_Coding_Default;
+
+  /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme) and GSM 03.38 section 4 */
+  if ((ETSI->TPDCS & 0xf4) == 0xf4) SMS->Coding=GSM_Coding_8bit;
+  if ((ETSI->TPDCS & 0x08) == 0x08) SMS->Coding=GSM_Coding_Unicode;
+
+  switch (SMS->Coding) {
+    case GSM_Coding_Default:
+      w=(7-off)%7;
+      if (w<0) w=(14-off)%14;
+  
+      SMS->Length=ETSI->TPUDL - (off*8 + w) / 7;
+
+      tmp=GSM_UnpackEightBitsToSeven(w,ETSI->TPUDL-off, SMS->Length, ETSI->MessageText+off, output);
+
+#ifdef DEBUG
+      fprintf(stdout, "   7 bit SMS, body is (length %i): ",SMS->Length);
+#endif /* DEBUG */
+
+      DecodeDefault (SMS->MessageText, output, tmp);
+
+#ifdef DEBUG
+      fprintf(stdout, "%s\n",SMS->MessageText);          
+#endif
+
+      break;
+    case GSM_Coding_8bit:
+      SMS->Length=ETSI->TPUDL - off;
+
+      memcpy(SMS->MessageText,ETSI->MessageText+off,SMS->Length);
+
+#ifdef DEBUG
+      fprintf(stdout, "   8 bit SMS, body is (length %i)\n",SMS->Length);
+      hexdump(SMS->Length,SMS->MessageText);
+#endif /* DEBUG */
+
+      break;
+    case GSM_Coding_Unicode:
+      SMS->Length=(ETSI->TPUDL - off) / 2;
+
+#ifdef DEBUG
+      fprintf(stdout, "   7 bit SMS, body is (length %i), Unicode coding: ",SMS->Length);
+      for (i=0; i<SMS->Length;i++) {
+        fprintf(stdout, "[%02x %02x]", ETSI->MessageText[off+i*2] , ETSI->MessageText[off+i*2+1]);
+      }
+      fprintf(stdout, "\n");             
+#endif /* DEBUG */
+
+      /* here we decode "special" chars */
+      for (i=0; i<SMS->Length;i++) {
+        if (ETSI->MessageText[off+i*2]  ==0x00 &&
+           ETSI->MessageText[off+i*2+1]==0x01)
+         ETSI->MessageText[off+i*2+1]='~'; //enables/disables blinking
+        if (ETSI->MessageText[off+i*2]  ==0x00 &&
+            ETSI->MessageText[off+i*2+1]==0x00)
+         ETSI->MessageText[off+i*2+1]='`'; //hides rest ot contents
+      }
+
+      DecodeUnicode (SMS->MessageText, ETSI->MessageText+off, SMS->Length);
+
+      break;
+  }
+
+  return GE_NONE;
 }
 
-static GSM_Error EncodeSMSHeader(GSM_SMSMessage *SMS, char *frame)
-/* We can create either SMS DELIVER (for saving in Inbox) or SMS SUBMIT
-   (for sending or saving in Outbox) message */
+GSM_Error GSM_DecodeETSISMSStatusReportData(GSM_SMSMessage *SMS, GSM_ETSISMSMessage *ETSI)
 {
-       /* Set SMS type */
-       switch (SMS->Type) {
-       case SMS_Submit: /* we send SMS or save it in Outbox */
-               return EncodeSMSSubmitHeader(SMS, frame);
-       case SMS_Deliver: /* we save SMS in Inbox */
-               return EncodeSMSDeliverHeader(SMS, frame);
-       default: /* we don't create other formats of SMS */
-               return GE_SMSWRONGFORMAT;
-       }
+  /* See GSM 03.40 section 9.2.3.11 (TP-Service-Centre-Time-Stamp) */
+#ifdef DEBUG
+  fprintf(stdout, _("   SMSC response date: "));
+#endif
+  GSM_DecodeSMSDateTime(&SMS->SMSCTime, ETSI->SMSCDateTime);
+    
+  if (ETSI->TPStatus < 0x03) {
+    strcpy(SMS->MessageText,_("Delivered"));
+
+#ifdef DEBUG
+    /* more detailed reason only for debug */
+    /* See GSM 03.40 section 9.2.3.15 (TP-Status) */
+    switch (ETSI->TPStatus) {
+      case 0x00: fprintf(stdout, _("   SM received by the SME"));break;
+      case 0x01: fprintf(stdout, _("   SM forwarded by the SC to the SME but the SC is unable to confirm delivery"));break;
+      case 0x02: fprintf(stdout, _("   SM replaced by the SC"));break;
+    }
+#endif /* DEBUG */
+
+    SMS->Length = 10;
+      
+  } else if (ETSI->TPStatus & 0x40) {
+
+    strcpy(SMS->MessageText,_("Failed"));
+
+#ifdef DEBUG
+    /* more detailed reason only for debug */
+    if (ETSI->TPStatus & 0x20) {
+
+      /* See GSM 03.40 section 9.2.3.15 (TP-Status) */
+      fprintf(stdout, _("   Temporary error, SC is not making any more transfer attempts\n"));
+      switch (ETSI->TPStatus) {
+        case 0x60: fprintf(stdout, _("   Congestion"));break;
+        case 0x61: fprintf(stdout, _("   SME busy"));break;
+        case 0x62: fprintf(stdout, _("   No response from SME"));break;
+        case 0x63: fprintf(stdout, _("   Service rejected"));break;
+        case 0x64: fprintf(stdout, _("   Quality of service not available"));break;
+        case 0x65: fprintf(stdout, _("   Error in SME"));break;
+        default  : fprintf(stdout, _("   Reserved/Specific to SC: %x"),ETSI->TPStatus);break;
+      }
+
+    } else {
+
+      /* See GSM 03.40 section 9.2.3.15 (TP-Status) */
+      fprintf(stdout, _("   Permanent error, SC is not making any more transfer attempts\n"));
+      switch (ETSI->TPStatus) {
+        case 0x40: fprintf(stdout, _("   Remote procedure error"));break;
+        case 0x41: fprintf(stdout, _("   Incompatibile destination"));break;
+        case 0x42: fprintf(stdout, _("   Connection rejected by SME"));break;
+        case 0x43: fprintf(stdout, _("   Not obtainable"));break;
+        case 0x44: fprintf(stdout, _("   Quality of service not available"));break;
+        case 0x45: fprintf(stdout, _("   No internetworking available"));break;
+        case 0x46: fprintf(stdout, _("   SM Validity Period Expired"));break;
+        case 0x47: fprintf(stdout, _("   SM deleted by originating SME"));break;
+        case 0x48: fprintf(stdout, _("   SM Deleted by SC Administration"));break;
+        case 0x49: fprintf(stdout, _("   SM does not exist"));break;
+        default  : fprintf(stdout, _("   Reserved/Specific to SC: %x"),ETSI->TPStatus);break;
+      }
+    }
+#endif /* DEBUG */
+      
+      SMS->Length = 6;
+  } else if (ETSI->TPStatus & 0x20) {
+    strcpy(SMS->MessageText,_("Pending"));
+
+#ifdef DEBUG
+    /* more detailed reason only for debug */
+    /* See GSM 03.40 section 9.2.3.15 (TP-Status) */
+    fprintf(stdout, _("   Temporary error, SC still trying to transfer SM\n"));
+    switch (ETSI->TPStatus) {
+      case 0x20: fprintf(stdout, _("   Congestion"));break;
+      case 0x21: fprintf(stdout, _("   SME busy"));break;
+      case 0x22: fprintf(stdout, _("   No response from SME"));break;
+      case 0x23: fprintf(stdout, _("   Service rejected"));break;
+      case 0x24: fprintf(stdout, _("   Quality of service not aviable"));break;
+      case 0x25: fprintf(stdout, _("   Error in SME"));break;
+      default  : fprintf(stdout, _("   Reserved/Specific to SC: %x"),ETSI->TPStatus);break;
+    }
+#endif /* DEBUG */
+    SMS->Length = 7;
+  } else {
+    strcpy(SMS->MessageText,_("Unknown"));
+
+#ifdef DEBUG
+    /* more detailed reason only for debug */
+    fprintf(stdout, _("   Reserved/Specific to SC: %x"),ETSI->TPStatus);
+#endif /* DEBUG */
+    SMS->Length = 8;
+  }
+
+#ifdef DEBUG
+  fprintf(stdout, _("\n"));
+#endif /* DEBUG */
+
+  return GE_NONE;
 }
 
-/* This function encodes SMS as described in:
-   - GSM 03.40 version 6.1.0 Release 1997, section 9
-*/
-int EncodePDUSMS(GSM_SMSMessage *SMS, char *message)
+GSM_Error GSM_EncodeETSISMSSubmitHeader(GSM_SMSMessage *SMS,GSM_ETSISMSMessage *ETSI)
 {
-       GSM_Error error = GE_NONE;
-       int i;
-
-       switch (SMS->Type) {
-       case SMS_Submit:
-               llayout = layout.Submit;
-               dprintf("Sending SMS to %s via message center %s\n", SMS->RemoteNumber.number, SMS->MessageCenter.Number);
-               break;
-       case SMS_Deliver:
-               llayout = layout.Deliver;
-               dprintf("Saving SMS to Inbox\n");
-               break;
-       case SMS_Picture:
-               llayout = layout.Picture;
-               dprintf("Sending Picture Message\n");
-               break;
-       case SMS_Delivery_Report:
-       default:
-               dprintf("Not supported message type: %d\n", SMS->Type);
-               return GE_NOTSUPPORTED;
-       }
-
-       /* SMSC number */
-       if (llayout.MessageCenter > -1) {
-               dprintf("%d %s\n", SMS->MessageCenter.Type, SMS->MessageCenter.Number);
-               message[llayout.MessageCenter] = SemiOctetPack(SMS->MessageCenter.Number, message + llayout.MessageCenter + 1, SMS->MessageCenter.Type);
-               if (message[llayout.MessageCenter] % 2) message[llayout.MessageCenter]++;
-               message[llayout.MessageCenter] = message[llayout.MessageCenter] / 2 + 1;
-       }
-
-       /* Common Header */
-       error = EncodeSMSHeader(SMS, message);
-       if (error != GE_NONE) return error;
-
-       /* User Data Header - if present */
-//     for (i = 0; i < SMS->UDH_No; i++) {
-//             error = EncodeUDH(SMS->UDH[i], message + 24);
-//             if (error != GE_NONE) return error;
-//     }
-       SMS->UDH_Length = 0;
-
-       /* User Data */
-       EncodeData(SMS, message + llayout.DataCodingScheme, message + llayout.UserData + SMS->UDH_Length);
-       message[llayout.Length] = SMS->Length;
-       return SMS->Length + llayout.UserData - 1;
+  GSM_Error error;
+
+  /* First of all we should get SMSC number */
+  if (SMS->MessageCenter.No) {
+    error = GSM->GetSMSCenter(&SMS->MessageCenter);
+    if (error != GE_NONE) return error;
+    SMS->MessageCenter.No = 0;
+  }
+
+#ifdef DEBUG
+  fprintf(stdout, _("Packing SMS to \"%s\" via message center \"%s\"\n"), SMS->Destination, SMS->MessageCenter.Number);
+#endif /* DEBUG */
+
+  ETSI->SMSCNumber[0]=GSM_PackSemiOctetNumber(SMS->MessageCenter.Number, ETSI->SMSCNumber+1, false);
+
+  /* GSM 03.40 section 9.2.3.17 (TP-Reply-Path) */
+  if (SMS->ReplyViaSameSMSC) ETSI->firstbyte |= 128;
+  
+  /* When save to Outbox with SMS Class, "Edit" is not displayed in phone menu
+     and can forward it to another phone with set class (for example, 0=Flash) */
+  /* Message Class*/
+  /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme) and GSM 03.38 section 4 */
+  if (SMS->Class>=0 && SMS->Class<5) ETSI->TPDCS |= (240+SMS->Class);  
+
+  /* When is not set for SMS saved for Inbox, phone displays "Message" instead
+     of number and doesn't display "Details" info */
+  ETSI->Number[0] = GSM_PackSemiOctetNumber(SMS->Destination, ETSI->Number+1, true);
+
+  return GE_NONE;
 }
 
-/* This function does simple SMS encoding - no PDU coding */
-GSM_Error EncodeTextSMS()
+GSM_Error GSM_DecodeETSISMSHeader(GSM_SMSMessage *SMS, GSM_ETSISMSMessage *ETSI)
 {
-       return GE_NONE;
-}
+#ifdef DEBUG
+  fprintf(stdout, _("   SMS center number: %s"), GSM_UnpackSemiOctetNumber(ETSI->SMSCNumber,false));
+  if (SMS->folder==0 && (ETSI->firstbyte & 128)!=0) //GST_INBOX
+    fprintf(stdout, _(" (centre set for reply)"));
+#endif
 
-/***
- *** DECODING SMS
- ***/
+  strcpy(SMS->MessageCenter.Number, GSM_UnpackSemiOctetNumber(ETSI->SMSCNumber,false));
 
-static GSM_Error SMSStatus(unsigned char status, GSM_SMSMessage *SMS)
-{
-       if (status < 0x03) {
-               strcpy(SMS->MessageText, _("Delivered"));
-               switch (status) {
-               case 0x00:
-                       dprintf("SM received by the SME");
-                       break;
-               case 0x01:
-                       dprintf("SM forwarded by the SC to the SME but the SC is unable to confirm delivery");
-                       break;
-               case 0x02:
-                       dprintf("SM replaced by the SC");
-                       break;
-               }
-               SMS->Length = strlen(_("Delivered"));
-       } else if (status & 0x40) {
-
-               strcpy(SMS->MessageText, _("Failed"));
-
-               /* more detailed reason only for debug */
-
-               if (status & 0x20) {
-                       dprintf("Temporary error, SC is not making any more transfer attempts\n");
-
-                       switch (status) {
-                       case 0x60:
-                               dprintf("Congestion");
-                               break;
-                       case 0x61:
-                               dprintf("SME busy");
-                               break;
-                       case 0x62:
-                               dprintf("No response from SME");
-                               break;
-                       case 0x63:
-                               dprintf("Service rejected");
-                               break;
-                       case 0x64:
-                               dprintf("Quality of service not aviable");
-                               break;
-                       case 0x65:
-                               dprintf("Error in SME");
-                               break;
-                       default:
-                               dprintf("Reserved/Specific to SC: %x", status);
-                               break;
-                       }
-               } else {
-                       dprintf("Permanent error, SC is not making any more transfer attempts\n");
-                       switch (status) {
-                       case 0x40:
-                               dprintf("Remote procedure error");
-                               break;
-                       case 0x41:
-                               dprintf("Incompatibile destination");
-                               break;
-                       case 0x42:
-                               dprintf("Connection rejected by SME");
-                               break;
-                       case 0x43:
-                               dprintf("Not obtainable");
-                               break;
-                       case 0x44:
-                               dprintf("Quality of service not aviable");
-                               break;
-                       case 0x45:
-                               dprintf("No internetworking available");
-                               break;
-                       case 0x46:
-                               dprintf("SM Validity Period Expired");
-                               break;
-                       case 0x47:
-                               dprintf("SM deleted by originating SME");
-                               break;
-                       case 0x48:
-                               dprintf("SM Deleted by SC Administration");
-                               break;
-                       case 0x49:
-                               dprintf("SM does not exist");
-                               break;
-                       default:
-                               dprintf("Reserved/Specific to SC: %x", status);
-                               break;
-                       }
-               }
-               SMS->Length = strlen(_("Failed"));
-       } else if (status & 0x20) {
-               strcpy(SMS->MessageText, _("Pending"));
-
-               /* more detailed reason only for debug */
-               dprintf("Temporary error, SC still trying to transfer SM\n");
-               switch (status) {
-               case 0x20:
-                       dprintf("Congestion");
-                       break;
-               case 0x21:
-                       dprintf("SME busy");
-                       break;
-               case 0x22:
-                       dprintf("No response from SME");
-                       break;
-               case 0x23:
-                       dprintf("Service rejected");
-                       break;
-               case 0x24:
-                       dprintf("Quality of service not aviable");
-                       break;
-               case 0x25:
-                       dprintf("Error in SME");
-                       break;
-               default:
-                       dprintf("Reserved/Specific to SC: %x", status);
-                       break;
-               }
-               SMS->Length = strlen(_("Pending"));
-       } else {
-               strcpy(SMS->MessageText, _("Unknown"));
-
-               /* more detailed reason only for debug */
-               dprintf("Reserved/Specific to SC: %x", status);
-               SMS->Length = strlen(_("Unknown"));
-       }
-       dprintf("\n");
-       return GE_NONE;
+  SMS->ReplyViaSameSMSC=false;
+  if ((ETSI->firstbyte & 128)!=0) SMS->ReplyViaSameSMSC=true;
+
+#ifdef DEBUG      
+  fprintf(stdout, _("\n   Remote number (recipient or sender): %s\n"), GSM_UnpackSemiOctetNumber(ETSI->Number,true));
+#endif
+
+  strcpy(SMS->Sender, GSM_UnpackSemiOctetNumber(ETSI->Number,true));
+
+  return GE_NONE;
 }
 
-static GSM_Error DecodeData(char *message, char *output, int length, int size, int udhlen, SMS_DataCodingScheme dcs)
+/* FIXME: we should allow for all validity formats */
+GSM_Error GSM_EncodeETSISMSSubmitValidity(GSM_SMSMessage *SMS,GSM_ETSISMSMessage *ETSI)
 {
-       /* Unicode */
-       if ((dcs.Type & 0x08) == 0x08) {
-               dprintf("Unicode message\n");
-               length = (length - udhlen)/2;
-               DecodeUnicode(output, message, length);
-       } else {
-               /* 8bit SMS */
-               if ((dcs.Type & 0xf4) == 0xf4) {
-                       dprintf("8bit message\n");
-                       memcpy(output, message, length);
-               /* 7bit SMS */
-               } else {
-                       dprintf("Default Alphabet\n");
-                       length = length - (udhlen * 8 + ((7-(udhlen%7))%7)) / 7;
-                       Unpack7BitCharacters((7-udhlen)%7, size, length, message, output);
-                       DecodeAscii(output, output, length);
-               }
-       }
-       dprintf("%s\n", output);
-       return GE_NONE;
+  /* GSM 03.40 section 9.2.3.3 (TP-Validity-Period-Format) */
+  /* Bits 4 and 3: 10. TP-VP field present and integer represent (relative) */
+  ETSI->firstbyte |= 0x10;
+
+  /* GSM 03.40 section 9.2.3.12 (TP-Validity Period) */
+  /* FIXME: error-checking for correct Validity - it should not be bigger then
+     63 weeks and smaller then 5minutes. We should also test intervals because
+     the SMS->Validity to TP-VP is not continuos. I think that the simplest
+     solution will be an array of correct values. We should parse it and if we
+     find the closest TP-VP value we should use it. Or is it good to take
+     closest smaller TP-VP as we do now? I think it is :-) */
+
+  /* 5 minutes intervals up to 12 hours = 720 minutes */
+  if (SMS->Validity <= 720)
+    ETSI->TPVP = (unsigned char) (SMS->Validity/5)-1;
+
+  /* 30 minutes intervals up to 1 day */
+  else if ((SMS->Validity > 720) && (SMS->Validity <= 1440))
+    ETSI->TPVP = (unsigned char) ((SMS->Validity-720)/30)+143;
+
+  /* 1 day intervals up to 30 days */
+  else if ((SMS->Validity > 1440) && (SMS->Validity <= 43200))
+    ETSI->TPVP = (unsigned char) (SMS->Validity/1440)+166;
+
+  /* 1 week intervals up to 63 weeks */
+  else if ((SMS->Validity > 43200) && (SMS->Validity <= 635040))
+    ETSI->TPVP = (unsigned char) (SMS->Validity/10080)+192;
+
+  return GE_NONE;
 }
 
-/* This function decodes UDH as described in:
-   - GSM 03.40 version 6.1.0 Release 1997, section 9.2.3.24
-   - Smart Messaging Specification, Revision 1.0.0, September 15, 1997
-*/
-static GSM_Error DecodeUDH(char *message, GSM_SMSMessage *SMS)
+/* FIXME: do we need more than SMS_Submit and SMS_Deliver ? */
+GSM_Error GSM_EncodeETSISMS(GSM_SMSMessage *SMS, GSM_ETSISMSMessage *ETSI, SMS_MessageType PDU, int *length)
 {
-       unsigned char length, pos, nr;
-
-       SMS->UDH_Length = length = message[0] + 1;
-       pos = 1;
-       nr = 0;
-       while (length > 1) {
-               unsigned char udh_length;
-
-               udh_length = message[pos+1];
-               switch (message[pos]) {
-               case 0x00: // Concatenated short messages
-                       dprintf("Concatenated messages\n");
-                       SMS->UDH[nr].Type = SMS_ConcatenatedMessages;
-                       SMS->UDH[nr].u.ConcatenatedShortMessage.ReferenceNumber = message[pos + 2];
-                       SMS->UDH[nr].u.ConcatenatedShortMessage.MaximumNumber   = message[pos + 3];
-                       SMS->UDH[nr].u.ConcatenatedShortMessage.CurrentNumber   = message[pos + 4];
-                       break;
-               case 0x01: // Special SMS Message Indication
-                       switch (message[pos + 2] & 0x03) {
-                       case 0x00:
-                               dprintf("Voice Message\n");
-                               SMS->UDH[nr].Type = SMS_VoiceMessage;
-                               break;
-                       case 0x01:
-                               dprintf("Fax Message\n");
-                               SMS->UDH[nr].Type = SMS_FaxMessage;
-                               break;
-                       case 0x02:
-                               dprintf("Email Message\n");
-                               SMS->UDH[nr].Type = SMS_EmailMessage;
-                               break;
-                       default:
-                               dprintf("Unknown\n");
-                               SMS->UDH[nr].Type = SMS_UnknownUDH;
-                               break;
-                       }
-                       SMS->UDH[nr].u.SpecialSMSMessageIndication.Store = (message[pos + 2] & 0x80) >> 7;
-                       SMS->UDH[nr].u.SpecialSMSMessageIndication.MessageCount = message[pos + 3];
-                       break;
-               case 0x04: // Application port addression scheme, 8 bit address
-                       break;
-               case 0x05: // Application port addression scheme, 16 bit address
-                       switch (((0x00ff & message[pos + 2]) << 8) | (0x00ff & message[pos + 3])) {
-                       case 0x1581:
-                               dprintf("Ringtone\n");
-                               SMS->UDH[nr].Type = SMS_Ringtone;
-                               break;
-                       case 0x1582:
-                               dprintf("Operator Logo\n");
-                               SMS->UDH[nr].Type = SMS_OpLogo;
-                               break;
-                       case 0x1583:
-                               dprintf("Caller Icon\n");
-                               SMS->UDH[nr].Type = SMS_CallerIDLogo;
-                               break;
-                       case 0x23f4:
-                               dprintf("Business Card\n");
-                               SMS->UDH[nr].Type = SMS_BusinessCard;
-                               break;
-                       default:
-                               dprintf("Unknown\n");
-                               SMS->UDH[nr].Type = SMS_UnknownUDH;
-                               break;
-                       }
-                       break;
-               case 0x06: // SMSC Control Parameters
-                       break;
-               case 0x07: // UDH Source Indicator
-                       break;
-               default:
-                       dprintf("Not supported UDH\n");
-                       break;
-               }
-               length -= (udh_length + 2);
-               pos += (udh_length + 2);
-               nr++;
-       }
-       SMS->UDH_No = nr;
+  int size=0;
 
-       return GE_NONE;
+  ETSI->firstbyte=0;
+  ETSI->TPPID=0;
+  ETSI->TPDCS=0;
+  ETSI->TPUDL=0;
+  ETSI->TPStatus=0;
+  ETSI->TPVP=0;
+
+  switch (PDU) {
+    case SMS_Submit:
+
+      /* GSM 03.40 section 9.2.3.1 (TP-Message-Type-Indicator) */
+      /* Bits 1 and 0: 01. SMS-Submit */
+      ETSI->firstbyte |= 0x01;
+
+      /* GSM 03.40 section 9.2.3.5 (TP-Status-Raport-Request) */
+      /* Mask for request for delivery report from SMSC */
+      if (SMS->Type == GST_DR) ETSI->firstbyte |= 32;
+
+      GSM_EncodeETSISMSSubmitHeader(SMS, ETSI);
+      GSM_EncodeETSISMSSubmitValidity(SMS, ETSI);
+      size=GSM_EncodeETSISMSSubmitData(SMS, ETSI);
+
+      break;
+    case SMS_Deliver:
+
+      /* GSM 03.40 section 9.2.3.1 (TP-Message-Type-Indicator) */
+      /* Bits 1 and 0: 00. SMS-Deliver */
+      ETSI->firstbyte |= 0x00;
+
+      GSM_EncodeETSISMSSubmitHeader(SMS, ETSI);
+      GSM_EncodeSMSDateTime(&SMS->Time, ETSI->DeliveryDateTime);
+      size=GSM_EncodeETSISMSSubmitData(SMS, ETSI);
+
+      break;
+    default:
+      break;
+  }
+
+  /* size is the length of the data in octets including udh */
+  *length=size;
+
+  return GE_NONE;
 }
 
-static GSM_Error DecodeSMSHeader(unsigned char *message, GSM_SMSMessage *SMS)
+/* This function decodes parts of SMS coded according to GSM 03.40 
+   (given in GSM_ETSISMSMessage) to GSM_SMSMessage */
+GSM_Error GSM_DecodeETSISMS(GSM_SMSMessage *SMS, GSM_ETSISMSMessage *ETSI)
 {
-       /* Short Message Type */
-       SMS->Type = message[layout.Type];
-       switch (SMS->Type) {
-       case SMS_Deliver:
-               llayout = layout.Deliver;
-               dprintf("Mobile Terminated message:\n");
-               break;
-       case SMS_Delivery_Report:
-               llayout = layout.DeliveryReport;
-               dprintf("Delivery Report:\n");
-               break;
-       case SMS_Submit:
-               llayout = layout.Submit;
-               dprintf("Mobile Originated message:\n");
-               break;
-       case SMS_Picture:
-               llayout = layout.Picture;
-               dprintf("Picture Message:\n");
-               break;
-       default:
-               dprintf("Not supported message type: %d\n", SMS->Type);
-               return GE_NOTSUPPORTED;
-       }
-
-       if (!llayout.IsSupported) return GE_NOTSUPPORTED;
-
-       /* Delivery date */
-       if (llayout.Time > -1) {
-               UnpackDateTime(message + llayout.Time, &(SMS->SMSCTime));
-               dprintf("\tDelivery date: %s\n", PrintDateTime(message + llayout.Time));
-       }
-
-       /* Short Message location in memory */
-       if (llayout.Number > -1) {
-               SMS->Number = message[llayout.Number];
-               dprintf("\tLocation: %d\n", SMS->Number);
-       }
-
-       /* Short Message Center */
-       if (llayout.MessageCenter > -1) {
-               strcpy(SMS->MessageCenter.Number, GetBCDNumber(message + llayout.MessageCenter));
-               dprintf("\tSMS center number: %s\n", SMS->MessageCenter.Number);
-               SMS->ReplyViaSameSMSC = false;
-               if (SMS->RemoteNumber.number[0] == 0 && (message[llayout.ReplyViaSameSMSC] & 0x80)) {
-                       SMS->ReplyViaSameSMSC = true;
-               }
-       }
-
-       /* Remote number */
-       if (llayout.RemoteNumber > -1) {
-               message[llayout.RemoteNumber] = ((message[llayout.RemoteNumber])+1)/2+1;
-               strcpy(SMS->RemoteNumber.number, GetBCDNumber(message + llayout.RemoteNumber));
-               dprintf("\tRemote number (recipient or sender): %s\n", SMS->RemoteNumber.number);
-       }
-       
-       /* Sending time */
-       if (llayout.SMSCTime > -1) {
-               UnpackDateTime(message + llayout.SMSCTime, &(SMS->Time));
-               dprintf("\tDate: %s\n", PrintDateTime(message + llayout.SMSCTime));
-       }
-
-       /* Message length */
-       if (llayout.Length > -1)
-               SMS->Length = message[llayout.Length];
-
-       /* Data Coding Scheme */
-       if (llayout.DataCodingScheme > -1)
-               SMS->DCS.Type = message[llayout.DataCodingScheme];
-
-       /* User Data Header */
-       if (llayout.UserDataHeader > -1)
-               if (message[llayout.UserDataHeader] & 0x40) { /* UDH header available */
-                       dprintf("UDH found\n");
-                       DecodeUDH(message + llayout.UserData, SMS);
-               }
+  SMS_MessageType PDU=SMS_Deliver;
+
+  /* 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;
+
+  GSM_DecodeETSISMSHeader(SMS, ETSI);
+
+  switch (PDU) {
+    case SMS_Submit:
+#ifdef DEBUG
+      fprintf(stdout, _("   SMS submit "));
+#endif
+      SMS->SMSData=false; 
+      GSM_DecodeETSISMSSubmitData(SMS,ETSI);
+      break;
+    case SMS_Deliver:
+#ifdef DEBUG
+      fprintf(stdout, _("   SMS deliver "));
+      fprintf(stdout, _("   Date: "));
+#endif
+      SMS->SMSData=true; 
+      GSM_DecodeSMSDateTime(&SMS->Time, ETSI->DeliveryDateTime);
+      GSM_DecodeETSISMSSubmitData(SMS,ETSI);
+      break;
+    case SMS_Status_Report:
+#ifdef DEBUG
+      fprintf(stdout, _("   SMS status report "));
+      fprintf(stdout, _("   Date: "));
+#endif
+      SMS->SMSData=true; 
+      GSM_DecodeSMSDateTime(&SMS->Time, ETSI->DeliveryDateTime);
+      GSM_DecodeETSISMSStatusReportData(SMS,ETSI);
+      break;
+    default:
+      break;
+  }
+
+  SMS->MessageText[SMS->Length]=0;
+
+  return GE_NONE;
+}
 
-       return GE_NONE;
+void GSM_SetDefaultSMSData (GSM_SMSMessage *SMS)
+{
+  struct tm *now;
+  time_t nowh;
+  GSM_DateTime Date;
+
+  /* Default settings for SMS message:
+  - no delivery report
+  - Class Message 1
+  - no compression
+  - SMSC no. 1
+  - validity 3 days */
+
+  SMS->folder = GST_OUTBOX;
+  SMS->Type = GST_SMS;
+  SMS->Class = -1;
+  SMS->Compression = false;
+  SMS->MessageCenter.No = 1;
+  SMS->Validity = 4320; /* 4320 minutes == 72 hours */
+  SMS->ReplyViaSameSMSC = false;
+  SMS->UDHType = GSM_NoUDH;
+  SMS->Coding=GSM_Coding_Default;
+  strcpy(SMS->Destination,"");
+
+  /* This part is required to save SMS */    
+
+  SMS->Status = GSS_NOTSENTREAD;
+  SMS->Location = 0;
+
+  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;
+  }
+
+  /* We need to have only two last digits of year */
+  if (Date.Year>1900)
+  {
+    if (Date.Year<2000) Date.Year = Date.Year-1900;
+                   else Date.Year = Date.Year-2000;
+  }
+
+  SMS->Time.Year=Date.Year;
+  SMS->Time.Month=Date.Month;
+  SMS->Time.Day=Date.Day;
+  SMS->Time.Hour=Date.Hour;
+  SMS->Time.Minute=Date.Minute;
+  SMS->Time.Second=Date.Second;
+
+  SMS->Name[0]=0;
 }
 
-/* This function decodes SMS as described in:
-   - GSM 03.40 version 6.1.0 Release 1997, section 9
+/* This function encodes the UserDataHeader as described in:
+   - GSM 03.40 version 6.1.0 Release 1997, section 9.2.3.24
+   - Smart Messaging Specification, Revision 1.0.0, September 15, 1997
 */
-GSM_Error DecodePDUSMS(unsigned char *message, GSM_SMSMessage *SMS, int MessageLength)
+GSM_Error EncodeUDHHeader(char *text, GSM_UDH UDHType)
 {
-       int size;
-       GSM_Bitmap bitmap;
-       GSM_Error error;
-
-       error = DecodeSMSHeader(message, SMS);
-       if (error != GE_NONE) return error;
-       switch (SMS->Type) {
-       case SMS_Delivery_Report:
-               if (llayout.UserData > -1) SMSStatus(message[llayout.UserData], SMS);
+       int i=0;
+
+       if (UDHType!=GSM_NoUDH) {
+          while (true) {
+            if (UDHHeaders[i].UDHType==GSM_NoUDH) {
+#ifdef DEBUG
+               fprintf(stderr,_("Not supported User Data Header type\n"));
+#endif
                break;
-       case SMS_Picture:
-               GSM_ReadSMSBitmap(SMS_Picture, message + llayout.UserData, NULL, &bitmap);
-               GSM_PrintBitmap(&bitmap);
-               size = MessageLength - llayout.UserData - 4 - bitmap.size;
-               SMS->Length = message[llayout.UserData + 4 + bitmap.size];
-               DecodeData(message + llayout.UserData + 5 + bitmap.size,
-                          (unsigned char *)&(SMS->MessageText),
-                          SMS->Length, size, 0, SMS->DCS);
-               SMS->MessageText[SMS->Length] = 0;
+            }
+            if (UDHHeaders[i].UDHType==UDHType) {
+               text[0] = UDHHeaders[i].Length; // UDH Length
+               memcpy(text+1, UDHHeaders[i].Text, UDHHeaders[i].Length);
                break;
-       default:
-               size = MessageLength -
-                       llayout.UserData + 1 - /* Header Length */
-                       SMS->UDH_Length;       /* UDH Length */
-               DecodeData(message + llayout.UserData + SMS->UDH_Length,
-                          (unsigned char *)&(SMS->MessageText),
-                          SMS->Length, size, SMS->UDH_Length, SMS->DCS);
-               /* Just in case */
-               SMS->MessageText[SMS->Length] = 0;
-               break;
-       }
-
+            }
+            i++;
+          }
+        }
        return GE_NONE;
 }
 
-/* This function does simple SMS decoding - no PDU coding */
-GSM_Error DecodeTextSMS(unsigned char *message, GSM_SMSMessage *SMS)
-{
-       return GE_NONE;
+int GSM_MakeSinglePartSMS2(GSM_SMSMessage *SMS,
+    unsigned char *MessageBuffer,int cur, GSM_UDH UDHType, GSM_Coding_Type Coding){
+
+  int j;
+  int current,smsudhlength;
+
+  GSM_SetDefaultSMSData(SMS);
+
+  EncodeUDHHeader(SMS->UDH, UDHType);
+  SMS->UDHType=UDHType;
+
+  switch (UDHType) {
+    case GSM_EnableVoice:
+    case GSM_DisableVoice:
+    case GSM_EnableEmail:
+    case GSM_DisableEmail:
+    case GSM_EnableFax:
+    case GSM_DisableFax:
+      SMS->Class=1;
+      SMS->Coding=Coding;
+      break;
+    case GSM_NoUDH:
+    case GSM_ConcatenatedMessages:
+    case GSM_VoidSMS:
+    case GSM_HangSMS:
+    case GSM_BugSMS:
+    case GSM_PhonebookUDH:
+    case GSM_CalendarNoteUDH: //class=1?
+      SMS->Class=-1;
+      SMS->Coding=Coding;
+      break;
+    case GSM_OpLogo:
+    case GSM_CallerIDLogo:
+    case GSM_RingtoneUDH:
+    case GSM_WAPBookmarkUDH:
+    case GSM_WAPBookmarkUDHLong:
+    case GSM_WAPSettingsUDH:
+    case GSM_ProfileUDH:
+      SMS->Class=1;
+      SMS->Coding=GSM_Coding_8bit;
+      break;
+    default:
+      fprintf(stderr,_("Error in makesinglepartsms !\n\n\n"));
+  }
+
+  current=cur;
+
+  smsudhlength=0;
+  if (UDHType!=GSM_NoUDH)
+    smsudhlength=SMS->UDH[0]+1;
+
+  j=0;
+  switch (SMS->Coding) {
+    case GSM_Coding_8bit:
+      j=(GSM_MAX_SMS_8_BIT_LENGTH-smsudhlength);     //max=140
+      break;
+    case GSM_Coding_Default:
+      j=(GSM_MAX_SMS_8_BIT_LENGTH-smsudhlength)*8/7; //max=160
+      break;
+    case GSM_Coding_Unicode:
+      j=(GSM_MAX_SMS_8_BIT_LENGTH-smsudhlength)/2;   //max=70
+      break;
+  }
+  if (current>j) current=j;
+
+  memcpy(SMS->MessageText,MessageBuffer,current);    
+  SMS->MessageText[current]=0;
+  SMS->Length=current;
+
+  return current;
+}
+
+void GSM_MakeMultiPartSMS2(GSM_MultiSMSMessage *SMS,
+    unsigned char *MessageBuffer,int MessageLength, GSM_UDH UDHType, GSM_Coding_Type Coding){
+
+  int i=0,j,pos=0,current=0;
+
+  for (i=0;i<4;i++) {  
+    if (pos==MessageLength) break;
+
+    current=MessageLength-pos;
+
+    pos=pos+GSM_MakeSinglePartSMS2(&SMS->SMS[i],MessageBuffer+pos,current,UDHType,Coding);
+  }
+
+  for (j=0;j<i;j++)
+  {
+    switch (UDHType) {
+      case GSM_ProfileUDH:
+      case GSM_WAPBookmarkUDHLong:
+      case GSM_WAPSettingsUDH:
+      case GSM_CalendarNoteUDH:
+      case GSM_CalendarNoteUDH2:
+      case GSM_PhonebookUDH:
+        SMS->SMS[j].UDH[10]=i;
+        SMS->SMS[j].UDH[11]=j+1;
+        break;
+      case GSM_ConcatenatedMessages:
+        SMS->SMS[j].UDH[4]=i;
+        SMS->SMS[j].UDH[5]=j+1;
+        break;
+    default:
+      break;
+    }
+  }
+
+  SMS->number=i;
 }
index 9ab975f..34d81b7 100644 (file)
 
   A Linux/Unix toolset and driver for Nokia mobile phones.
 
-  Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
-
   Released under the terms of the GNU GPL, see file COPYING for more details.
 
-  $Id$
-  
-  $Log$
-  Revision 1.1.1.2  2001/11/27 04:19:24  short
-  :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Nov 27 05:17 CET 2001
-
-  Revision 1.20  2001/11/26 18:06:08  pkot
-  Checking for *printf functions, N_(x) for localization, generic ARRAY_LEN, SAFE_STRNCPY, G_GNUC_PRINTF (Jan Kratochvil)
-
-  Revision 1.19  2001/11/22 17:56:53  pkot
-  smslib update. sms sending
-
-  Revision 1.18  2001/09/09 21:45:49  machek
-  Cleanups from Ladislav Michl <ladis@psi.cz>:
-
-  *) do *not* internationalize debug messages
-
-  *) some whitespace fixes, do not use //
-
-  *) break is unneccessary after return
-
-  Revision 1.17  2001/08/09 12:34:34  pkot
-  3330 and 6250 support - I have no idea if it does work (mygnokii)
-
-  Revision 1.16  2001/03/21 23:36:04  chris
-  Added the statemachine
-  This will break gnokii --identify and --monitor except for 6210/7110
-
-  Revision 1.15  2001/03/06 10:38:52  machek
-  Dancall models added to the global list.
-
-  Revision 1.14  2001/02/06 13:55:23  pkot
-  Enabled authentication in 51xx models
-
-  Revision 1.13  2001/02/02 08:09:56  ja
-  New dialogs for 6210/7110 in xgnokii. Fixed the smsd for new capabilty code.
-
+*/
 
+#include <string.h>\r
+#include <ctype.h>\r
+#include <time.h>\r
+
+#ifndef WIN32
+  #include <sys/types.h>
+  #include <sys/stat.h>
+  #include <stdlib.h>
+  #include <fcntl.h>
+  #include <signal.h>
+  #include <unistd.h>
+  #include <errno.h>
+#endif\r
+\r
+#include "misc.h"\r
+#include "gsm-common.h"\r
+
+#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);
+}
 */
 
-#include <string.h>
-#include <stdlib.h>
-#include "misc.h"
+#endif
 
-int GetLine(FILE *File, char *Line, int count)
-{
-       char *ptr;
+int GetLine(FILE *File, char *Line, int count) {
 
-       if (fgets(Line, count, File)) {
-               ptr = Line + strlen(Line) - 1;
+  char *ptr;
 
-               while ( (*ptr == '\n' || *ptr == '\r') && ptr >= Line)
-                       *ptr-- = '\0';
+  if (fgets(Line, count, File)) {
+    ptr=Line+strlen(Line)-1;
 
-               return strlen(Line);
-       }
-       else
-               return 0;
+    while ( (*ptr == '\n' || *ptr == '\r') && ptr>=Line) *ptr--='\0';
+
+    return strlen(Line);
+  } else return -1;
 }
 
-static PhoneModel models[] = {
-       {NULL,    "", 0 },
-       {"2711",  "?????", PM_SMS },            /* Dancall */
-       {"2731",  "?????", PM_SMS },
-       {"1611",  "NHE-5", 0 },
-       {"2110i", "NHE-4", PM_SMS },
-       {"2148i", "NHK-4", 0 },
-       {"3110",  "0310" , PM_SMS | PM_DTMF | PM_DATA }, /* NHE-8 */
-       {"3210",  "NSE-8", PM_SMS | PM_DTMF },
-       {"3210",  "NSE-9", PM_SMS | PM_DTMF },
-       {"3310",  "NHM-5", PM_SMS | PM_DTMF },
-       {"3330",  "NHM-6", PM_SMS | PM_DTMF },
-       {"3810",  "0305" , PM_SMS | PM_DTMF | PM_DATA }, /* NHE-9 */
-       {"5110",  "NSE-1", PM_NETMONITOR | PM_KEYBOARD | PM_SMS | PM_DTMF | PM_DATA | PM_SPEEDDIAL | PM_AUTHENTICATION },
-       {"5130",  "NSK-1", PM_NETMONITOR | PM_KEYBOARD | PM_SMS | PM_DTMF | PM_DATA | PM_SPEEDDIAL | PM_AUTHENTICATION },
-       {"5160",  "NSW-1", PM_NETMONITOR | PM_KEYBOARD | PM_SMS | PM_DTMF | PM_DATA | PM_SPEEDDIAL | PM_AUTHENTICATION },
-       {"5190",  "NSB-1", PM_NETMONITOR | PM_KEYBOARD | PM_SMS | PM_DTMF | PM_DATA | PM_SPEEDDIAL | PM_AUTHENTICATION },
-       {"6110",  "NSE-3", PM_CALLERGROUP | PM_CALENDAR | PM_NETMONITOR | PM_KEYBOARD | PM_SMS | PM_DTMF | PM_DATA | PM_SPEEDDIAL | PM_AUTHENTICATION },
-       {"6120",  "NSC-3", PM_CALLERGROUP | PM_CALENDAR | PM_NETMONITOR | PM_KEYBOARD | PM_SMS | PM_DTMF | PM_DATA | PM_SPEEDDIAL | PM_AUTHENTICATION },
-       {"6130",  "NSK-3", PM_CALLERGROUP | PM_CALENDAR | PM_NETMONITOR | PM_KEYBOARD | PM_SMS | PM_DTMF | PM_DATA | PM_SPEEDDIAL | PM_AUTHENTICATION },
-       {"6150",  "NSM-1", PM_CALLERGROUP | PM_CALENDAR | PM_NETMONITOR | PM_KEYBOARD | PM_SMS | PM_DTMF | PM_DATA | PM_SPEEDDIAL | PM_AUTHENTICATION },
-       {"616x",  "NSW-3", PM_CALLERGROUP | PM_CALENDAR | PM_NETMONITOR | PM_KEYBOARD | PM_SMS | PM_DTMF | PM_DATA | PM_SPEEDDIAL | PM_AUTHENTICATION },
-       {"6185",  "NSD-3", PM_CALLERGROUP | PM_CALENDAR | PM_NETMONITOR | PM_KEYBOARD | PM_SMS | PM_DTMF | PM_DATA | PM_SPEEDDIAL | PM_AUTHENTICATION },
-       {"6190",  "NSB-3", PM_CALLERGROUP | PM_CALENDAR | PM_NETMONITOR | PM_KEYBOARD | PM_SMS | PM_DTMF | PM_DATA | PM_SPEEDDIAL | PM_AUTHENTICATION },
-       {"6210",  "NPE-3", PM_CALLERGROUP | PM_CALENDAR | PM_EXTPBK | PM_SMS},
-       {"6250",  "NHM-3", PM_CALLERGROUP | PM_CALENDAR | PM_EXTPBK },
-       {"7110",  "NSE-5", PM_CALLERGROUP | PM_SPEEDDIAL | PM_EXTPBK },
-       {"8810",  "NSE-6", PM_SMS | PM_DTMF | PM_DATA },
-       {"8110i", "0423",  PM_SMS | PM_DTMF | PM_DATA }, /* Guess for NHE-6 */
-       {"8110",  "0423" , PM_SMS | PM_DTMF | PM_DATA }, /* NHE-6BX */
-       {"9000i", "RAE-4", 0 },
-       {"9110",  "RAE-2", 0 },
-       {"550",   "THF-10", 0 },
-       {"540",   "THF-11", 0 },
-       {"650",   "THF-12", 0 },
-       {"640",   "THF-13", 0 },
-       {NULL,    NULL, 0 }
-};
-
-PhoneModel *GetPhoneModel (const char *num)
+/*
+ * like atoi, but of a non-null-terminated string of a specified portion
+ */
+int mem_to_int(const char str[], int len)
 {
-       register int i = 0;
+  char aux[81];
 
-       while (models[i].number != NULL) {
-               if (strcmp (num, models[i].number) == 0) {
-                       dprintf("Found model\n");
-                       return (&models[i]);
-               }
-               else {
-                       dprintf("comparing %s and %s\n", num, models[i].number);
-               }
-               i++;
-       }
+  strncpy(aux, str, len);
+  aux[len]=0;
+  return( atoi(aux) );
+} 
 
-       return (&models[0]);
+/*
+ * 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);
 }
 
-inline char *GetModel (const char *num)
-{
-       return (GetPhoneModel(num)->model);
+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 HAVE_VASPRINTF
-/* Adapted from snprintf(3) man page: */
-int gvasprintf(char **destp, const char *fmt, va_list ap)
-{
-       int n, size = 0x100;
-       char *p, *pnew;
+#ifndef WIN32
+
+#define max_buf_len 128
+#define lock_path "/var/lock/LCK.."
 
-       if (!(p = malloc(size))) {
-               *destp = NULL;
-               return(-1);
+/* 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;
        }
-       for (;;) {
-               /* Try to print in the allocated space. */
-               n = gvsprintf(p, size, fmt, ap);
-               /* If that worked, return the string. */
-               if (n > -1 && n < size) {
-                       *destp = p;
-                       return(n);
+       /* 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;
                }
-               /* Else try again with more space. */
-               if (n > -1)     /* glibc 2.1 */
-                       size = n + 1;   /* precisely what is needed */
-               else            /* glibc 2.0 */
-                       size *= 2;      /* twice the old size */
-               if (!(pnew = realloc(p, size))) {
-                       free(p);
-                       *destp = NULL;
-                       return(-1);
+               if (n == 0) {
+                       free(lock_file);
+                       fprintf(stderr, _("Device is already locked.\n"));
+                       return NULL;
                }
-               p = pnew;
        }
+
+       /* 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;
 }
-#endif
 
-#ifndef HAVE_ASPRINTF
-int gasprintf(char **destp, const char *fmt,...)
+/* Removes lock and frees memory */
+bool unlock_device(char *lock_file)
 {
-       va_list ap;
-       int r;
+       int err;
 
-       va_start(ap,fmt);
-       r = gvasprintf(destp, fmt, ap);
-       va_end(ap);
-       return(r);
+       if (!lock_file) {
+               fprintf(stderr, _("Cannot unlock device\n"));
+               return false;
+       }
+       err = unlink(lock_file);
+       free(lock_file);
+       return (err + 1);
 }
-#endif
+#endif /* WIN32 */
index 0a30589..87ea315 100644 (file)
@@ -16,7 +16,7 @@ AC_PREFIX_DEFAULT("/usr/local")
 
 dnl ======================== Default setting
 CFLAGS="-O2 -Wall"
-ALL_LINGUAS="cs de et fi nl sk pl it sl"
+ALL_LINGUAS="cs de et fi nl sk pl it"
 
 dnl ======================== Checks for programs.
 AC_PROG_CC
@@ -32,9 +32,7 @@ test x"$prefix" = xNONE && prefix="$ac_default_prefix"
 
 AC_ARG_ENABLE(debug, 
        [  --enable-debug          compile with debug code],
-       [ if test "x$GCC" = "xyes"; then
-               CFLAGS="-ggdb3 -Wall"
-         fi
+       [ CFLAGS="-g -Wall"
          AC_DEFINE(DEBUG)
          debug="yes" ],
        [ debug="no"  ]
@@ -330,7 +328,7 @@ else
       AC_MSG_WARN(Disabling xgnokii.)
    else
       AC_CHECK_LIB(Xpm, XpmWriteFileFromXpmImage,
-            [ XPM_CFLAGS="-I$x_includes" XPM_LIBS="-L$x_libraries -lX11 -lXpm"
+            [ XPM_CFLAGS="-I$x_includes" XPM_LIBS="-L$x_libraries -lXpm -lX11"
               AC_DEFINE(XPM) ],
             AC_MSG_WARN(Cannot found library libXpm - disabling XPM support.),
             [ -L$x_libraries -lX11 ]
@@ -439,7 +437,7 @@ AC_PROG_GCC_TRADITIONAL
 AC_FUNC_MEMCMP
 AC_TYPE_SIGNAL
 AC_FUNC_STRFTIME
-AC_CHECK_FUNCS(mktime select strdup strstr strtol strtok strsep snprintf vsnprintf asprintf vasprintf)
+AC_CHECK_FUNCS(mktime select strdup strstr strtol strtok strsep snprintf)
 
 CFLAGS="$CFLAGS $NLS_CFLAGS"
 LIBS="$LIBS $NLS_LIBS"
@@ -522,7 +520,9 @@ echo "
     Win32:              $win32 
     Prefix:             $prefix
 
-  Type '${MAKE}' for compilation and then '${MAKE} install',
-  '${MAKE} install-suid', '${MAKE} install-strip' or '${MAKE} install-ss' to
-  install gnokii.
+  Type '${MAKE}' for compilation or '${MAKE} makelib' when want to compile
+  all binaries with one shared library
+  
+  After it '${MAKE} install', '${MAKE} install-suid', '${MAKE} install-strip'
+  or '${MAKE} install-ss' to install gnokii.
 "
index 02def81..037269d 100644 (file)
@@ -20,7 +20,7 @@ distclean clean::
 
 #####
 # DO NOT DELETE THIS LINE -- make depend depends on it.
-
 ifeq (depend,$(wildcard depend))
 include depend
 endif
index 8373efe..2018e7d 100644 (file)
@@ -2,15 +2,16 @@
 #
 # Makefile for the GNOKII tool suite.
 #
-# Copyright (C) 1999 Hugh Blemings & Pavel Janík ml.
-#               2000 Karel Zak
-#
 
 TOPDIR=..
 include $(TOPDIR)/Makefile.global
 
+
+CFLAGS += $(PTHREAD_CFLAGS)
+LDLIBS += $(PTHREAD_LIBS)
+
 ifdef XPM_LIBS
-    LDFLAGS +=$(XPM_LIBS)
+    LDLIBS += $(XPM_LIBS)
 endif
 
 OBJS = gnokii.o
@@ -19,28 +20,40 @@ ifdef OWN_GETOPT
     OBJS += $(TOPDIR)/getopt/libgetopt.a
 endif
 
-LDFLAGS += -L$(TOPDIR)/common -lgnokii
-
 all: gnokii
 
-gnokii: $(OBJS) $(TOPDIR)/common/gsm-filetypes.o
+gnokii: $(OBJS) $(TOPDIR)/common/COMMON.o $(TOPDIR)/common/gsm-filetypes.o
+       $(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@
 
-$(TOPDIR)/common/gsm-filetypes.o:
+$(TOPDIR)/common/COMMON.o: 
+       $(MAKE) -C $(TOPDIR)/common COMMON.o
+
+$(TOPDIR)/common/gsm-filetypes.o: 
        $(MAKE) -C $(TOPDIR)/common gsm-filetypes.o
 
 $(TOPDIR)/getopt/libgetopt.a:
        $(MAKE) -C $(TOPDIR)/getopt
 
+$(TOPDIR)/common/libmygnokii.so:
+       $(MAKE) -C $(TOPDIR)/common makelib
+       
+gnokiilib: $(OBJS) $(TOPDIR)/common/libmygnokii.so
+       $(CC) $(LDFLAGS) $(TARGET_ARCH) $(OBJS) -L$(TOPDIR)/common -lmygnokii $(LOADLIBES) $(LDLIBS) -o $@
+
+makelib: gnokiilib
+
 clean:
-       $(RM) $(OBJS) *~ depend gnokii *.exe core *.bak
+       $(RM) $(OBJS) *~ depend gnokii gnokiilib *.exe core *.bak
 
 install: all
        $(INSTALL) -d $(bindir)
        $(INSTALL) gnokii $(bindir)
+       $(INSTALL) gnokiilib $(bindir)/gnokii
 
 install-strip: all
        $(INSTALL) -d $(bindir)
        $(INSTALL) -s gnokii $(bindir)
+       $(INSTALL) -s gnokiilib $(bindir)/gnokii
        @echo "done"
 
 install-suid: all
@@ -49,6 +62,7 @@ install-suid: all
        fi
        $(INSTALL) -d $(bindir)
        $(INSTALL) -o root -g gnokii -m 0750 gnokii $(bindir)
+       $(INSTALL) -o root -g gnokii -m 0750 gnokiilib $(bindir)/gnokii
        @echo
 
 install-ss: all
@@ -57,6 +71,7 @@ install-ss: all
        fi
        $(INSTALL) -d $(bindir)
        $(INSTALL) -o root -g gnokii -m 0750 -s gnokii $(bindir)
+       $(INSTALL) -o root -g gnokii -m 0750 -s gnokiilib $(bindir)/gnokii
        @echo
 
 depend dep:
index 120a83f..9daceb9 100644 (file)
 /*
 
-  $Id$
-  
   G N O K I I
 
   A Linux/Unix toolset and driver for Nokia mobile phones.
 
-  Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
-  Copyright (C) 2001       Pavel Machek
-  Copyright (C) 2001       Pawe³ Kot
-
   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.
 
-  WARNING: this code is the test tool. Well, our test tool is now
-  really powerful and useful :-)
-
 */
 
-#include "misc.h"
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <string.h>
-#if __unices__
-#  include <strings.h> /* for memset */
-#endif
+#include <ctype.h>
 #include <time.h>
-#include <sys/types.h>
 #include <sys/stat.h>
 
+#ifndef VC6
+  #if defined(__svr4__) || defined(__FreeBSD__)
+  #  include <strings.h>       /* for bzero */
+  #endif
+#else
+  /* for VC6 make scripts save VERSION constant in mversion.h file */
+  #include "mversion.h"
+#endif
+
 #ifdef WIN32
 
-#include <windows.h>
-#define sleep(x) Sleep((x) * 1000)
-#define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
-#define stat _stat
-#include "win32/getopt.h"
+  #include <windows.h>
+
+  #include "misc_win32.h"
+  #include "getopt.h"
+
+  #define DEV_CONSOLE "CON:"
 
 #else
 
-#include <unistd.h>
-#include <termios.h>
-#include <fcntl.h>
-#include <getopt.h>
+  #include <unistd.h>
+  #include <termios.h>
+  #include <fcntl.h>
+  #include <sys/types.h>
+  #include <sys/time.h>
+  #include <getopt.h>
 
-#endif
-#ifdef USE_NLS
-#include <locale.h>
+  #define DEV_CONSOLE "/dev/tty"
 #endif
 
-#include "gsm-sms.h"
+#include "misc.h"
 #include "gsm-common.h"
 #include "gsm-api.h"
 #include "gsm-networks.h"
-#include "cfgreader.h"
-#include "gnokii.h"
-#include "gsm-filetypes.h"
-#include "gsm-bitmaps.h"
 #include "gsm-ringtones.h"
-#include "gsm-statemachine.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"
 
-char *model;      /* Model from .gnokiirc file. */
-char *Port;       /* Serial port from .gnokiirc file */
-char *Initlength; /* Init length from .gnokiirc file */
-char *Connection; /* Connection type from .gnokiirc file */
-char *BinDir;     /* Binaries directory from .gnokiirc file - not used here yet */
-/* Local variables */
+#ifdef USE_NLS
+  #include <locale.h>
+#endif
 
-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 *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 */
 
-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";
-       }
+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 *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 *GetProfileVolumeString(int code) {
 
-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";
-       }
+  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 *GetProfileWarningToneString(int code)
-{
-       switch (code) {
-       case PROFILE_WARNING_OFF:               return "Off";
-       case PROFILE_WARNING_ON:                return "On";
-       default:                                return "Unknown";
-       }
-}
+char *GetProfileKeypadToneString(int code) {
 
-char *GetProfileVibrationString(int code)
-{
-       switch (code) {
-       case PROFILE_VIBRATION_OFF:             return "Off";
-       case PROFILE_VIBRATION_ON:              return "On";
-       default:                                return "Unknown";
-       }
+  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";
+  }
 }
 
-void short_version(void)
-{
-       fprintf(stderr, _("GNOKII Version %s\n"), VERSION);
-}
+char *GetProfileMessageToneString(int code) {
 
-/* This function shows the copyright and some informations usefull for
-   debugging. */
-void version(void)
-{
-       fprintf(stderr, _("Copyright (C) Hugh Blemings <hugh@blemings.org>, 1999, 2000\n"
-                         "Copyright (C) Pavel Janík ml. <Pavel.Janik@suse.cz>, 1999, 2000\n"
-                         "Copyright (C) Pavel Machek <pavel@ucw.cz>, 2001\n"
-                         "Copyright (C) Pawe³ Kot <pkot@linuxnews.pl>, 2001\n"
-                         "gnokii is free software, covered by the GNU General Public License, and you are\n"
-                         "welcome to change it and/or distribute copies of it under certain conditions.\n"
-                         "There is absolutely no warranty for gnokii.  See GPL for details.\n"
-                         "Built %s %s for %s on %s \n"), __TIME__, __DATE__, model, Port);
+  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";
+  }
 }
 
-/* The function usage is only informative - it prints this program's usage and
-   command-line options. */
-int usage(void)
-{
-       fprintf(stderr, _("   usage: gnokii [--help|--monitor|--version]\n"
-                         "          gnokii --getmemory memory_type start [end]\n"
-                         "          gnokii --writephonebook [-i]\n"
-                         "          gnokii --getspeeddial number\n"
-                         "          gnokii --setspeeddial number memory_type location\n"
-                         "          gnokii --getsms memory_type start [end] [-f file] [-F file] [-d]\n"
-                         "          gnokii --deletesms memory_type start [end]\n"
-                         "          gnokii --sendsms destination [--smsc message_center_number |\n"
-                         "                 --smscno message_center_index] [-r] [-C n] [-v n]\n"
-                         "                 [--long n]\n"
-                         "          gnokii --savesms [-m] [-l n] [-i]\n"
-                         "          gnokii --getsmsc message_center_number\n"
-                         "          gnokii --setdatetime [YYYY [MM [DD [HH [MM]]]]]\n"
-                         "          gnokii --getdatetime\n"
-                         "          gnokii --setalarm HH MM\n"
-                         "          gnokii --getalarm\n"
-                         "          gnokii --dialvoice number\n"
-                         "          gnokii --getcalendarnote start [end] [-v]\n"
-                         "          gnokii --writecalendarnote vcardfile number\n"
-                         "          gnokii --deletecalendarnote start [end]\n"
-                         "          gnokii --getdisplaystatus\n"
-                         "          gnokii --netmonitor {reset|off|field|devel|next|nr}\n"
-                         "          gnokii --identify\n"
-                         "          gnokii --senddtmf string\n"
-                         "          gnokii --sendlogo {caller|op} destination logofile [network code]\n"
-                         "          gnokii --sendringtone destination rtttlfile\n"
-                         "          gnokii --setlogo op [logofile] [network code]\n"
-                         "          gnokii --setlogo startup [logofile]\n"
-                         "          gnokii --setlogo caller [logofile] [caller group number] [group name]\n"
-                         "          gnokii --setlogo {dealer|text} [text]\n"
-                         "          gnokii --getlogo op [logofile] [network code]\n"
-                         "          gnokii --getlogo startup [logofile] [network code]\n"
-                         "          gnokii --getlogo caller [logofile][caller group number][network code]\n"
-                         "          gnokii --getlogo {dealer|text}\n"
-                         "          gnokii --viewlogo logofile\n"
-                         "          gnokii --setringtone rtttlfile\n"
-                         "          gnokii --reset [soft|hard]\n"
-                         "          gnokii --getprofile [number]\n"
-                         "          gnokii --displayoutput\n"
-                         "          gnokii --keysequence\n"
-                         "          gnokii --divert {--op|-o} {register|enable|query|disable|erasure}\n"
-                         "                 {--type|-t} {all|busy|noans|outofreach|notavail}\n"
-                         "                 {--call|-c} {all|voice|fax|data}\n"
-                         "                 [{--timeout|-m} time_in_seconds]\n"
-                         "                 [{--number|-n} number]\n"
-                       ));
-#ifdef SECURITY
-       fprintf(stderr, _(
-               "          gnokii --entersecuritycode PIN|PIN2|PUK|PUK2\n"
-               "          gnokii --getsecuritycodestatus\n"
-               ));
-#endif
-       exit(-1);
+char *GetProfileWarningToneString(int code) {
+
+  switch (code) {
+    case PROFILE_WARNING_OFF : return "Off";
+    case PROFILE_WARNING_ON  : return "On";
+    default                  : return "Unknown";
+  }
 }
 
-/* fbusinit is the generic function which waits for the FBUS link. The limit
-   is 10 seconds. After 10 seconds we quit. */
+char *GetProfileOnOffString(int code) {
 
-static GSM_Statemachine State;
-static GSM_Data data;
+  switch (code) {
+    case 0x00 : return "Off";
+    case 0x01 : return "On";
+    default   : return "Unknown";
+  }
+}
 
-void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame))
+static char *GetProfileVibrationString(int code)
 {
-       int count = 0;
-       GSM_Error error;
-       GSM_ConnectionType connection = GCT_Serial;
+       switch (code) {
+       case PROFILE_VIBRATION_OFF:     return "Off";
+       case PROFILE_VIBRATION_ON:      return "On";
+       case PROFILE_VIBRATION_FIRST:   return "Vibrate first";
+       default:                        return "Unknown";
+       }
+}
 
-       GSM_DataClear(&data);
+char BufferProfileGroups[90];
 
-       if (!strcasecmp(Connection, "dau9p"))    connection = GCT_DAU9P; /* Use only with 6210/7110 for faster connection with such cable */
-       if (!strcasecmp(Connection, "infrared")) connection = GCT_Infrared;
-       if (!strcasecmp(Connection, "irda"))     connection = GCT_Irda;
+char *GetProfileCallerGroups(int code) 
+{
+  static char az_group_name[5][MAX_BITMAP_TEXT_LENGTH];
+  static bool enteronce=false;
+  register int i;
+  GSM_Bitmap bitmap;
 
-       /* Initialise the code for the GSM interface. */     
+  if( code == PROFILE_CALLERGROUPS_ALL )
+       return _("All calls alert");
 
-       error = GSM_Initialise(model, Port, Initlength, connection, rlp_handler, &State);
+  if( !enteronce ) {
+    for(i=0;i<5;i++) az_group_name[i][0]='\0';
+    enteronce=true;
+  }
 
-       if (error != GE_NONE) {
-               fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
-               exit(-1);
-       }
+  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);
+    }
+    
+  }
 
-       /* First (and important!) wait for GSM link to be active. We allow 10
-          seconds... */
+  return BufferProfileGroups;
+}
 
-       while (count++ < 200 && *GSM_LinkOK == false)
-               usleep(50000);
+char *print_error(GSM_Error e)
+{
 
-       if (*GSM_LinkOK == false) {
-               fprintf (stderr, _("Hmmm... GSM_LinkOK never went true. Quitting.\n"));
-               exit(-1);
+//     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.";
        }
 }
 
-/* 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)
+
+GSM_Error GSM_ReadRingtoneFileOnConsole(char *FileName, GSM_Ringtone *ringtone)
 {
-       int i;
+  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;
+}
 
-       /* Walk through the whole array with options requiring arguments. */
-       for (i = 0; !(gals[i].gal_min == 0 && gals[i].gal_max == 0); i++) {
+GSM_Error GSM_SaveRingtoneFileOnConsole(char *FileName, GSM_Ringtone *ringtone)
+{
+  int confirm,confirm2;
+  char ans[4];
+  struct stat buf;
+  GSM_Error error;
 
-               /* Current option. */
-               if (gals[i].gal_opt == opt) {
+  /* 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;
+}
 
-                       /* 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;
-                       }
+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;
+}
 
-                       return 1;
-               }
-       }
+GSM_Error GSM_SaveBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
+{
+  int confirm,confirm2;
+  char ans[4];
+  struct stat buf;
+  GSM_Error error;
 
-       /* We do not have options without arguments in the array, so check them. */
-       if (argc == 0) return 0;
-       else return 1;
+  /* 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;
 }
 
-/* Main function - handles command line arguments, passes them to separate
-   functions accordingly. */
-int main(int argc, char *argv[])
+/* mode == 0 -> overwrite
+ * mode == 1 -> ask
+ * mode == 2 -> append
+ */
+int GSM_SaveTextFileOnConsole(char *FileName, char *text, int mode)
 {
-       int c, i, rc = -1;
-       int nargc = argc-2;
-       char **nargv;
+  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;
+  }
 
-       /* Every option should be in this array. */
-       static struct option long_options[] =
-       {
-               /* FIXME: these comments are nice, but they would be more usefull as docs for the user */
-               /* Display usage. */
-               { "help",               no_argument,       NULL, OPT_HELP },
+  return error;
+}
 
-               /* Display version and build information. */
-               { "version",            no_argument,       NULL, OPT_VERSION },
+int GSM_SendMultiPartSMSOnConsole(GSM_MultiSMSMessage *MultiSMS, int argnum, int argc, char *argv[],
+                                  bool unicode, bool profile, bool scale) {
 
-               /* Monitor mode */
-               { "monitor",            no_argument,       NULL, OPT_MONITOR },
+  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;w<MultiSMS->number;w++) {
+
+    if (argnum!=0) {
+      optarg = NULL;
+  
+      /* We check optional parameters from ... */
+      optind = argnum;
 
-#ifdef SECURITY
+      while ((i = getopt_long(argc, argv, "v:ds", options, NULL)) != -1) {
+        switch (i) {
 
-               /* Enter Security Code mode */
-               { "entersecuritycode",  required_argument, NULL, OPT_ENTERSECURITYCODE },
+          case '1': /* SMSC number */
+            MultiSMS->SMS[w].MessageCenter.No = 0;
+            strcpy(MultiSMS->SMS[w].MessageCenter.Number,optarg);
+            break;
 
-               // Get Security Code status
-               { "getsecuritycodestatus",  no_argument,   NULL, OPT_GETSECURITYCODESTATUS },
+          case '2': /* SMSC number index in phone memory */
+            MultiSMS->SMS[w].MessageCenter.No = atoi(optarg);
 
-#endif
+            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;
 
-               // Set date and time
-               { "setdatetime",        optional_argument, NULL, OPT_SETDATETIME },
+         case '3': /* Receiver/recipient */
+           strncpy(MultiSMS->SMS[w].Destination,optarg,11); break;
 
-               // Get date and time mode
-               { "getdatetime",        no_argument,       NULL, OPT_GETDATETIME },
+         case '4': /* Unicode */
+           if (unicode) break;
 
-               // Set alarm
-               { "setalarm",           required_argument, NULL, OPT_SETALARM },
+         case '5': /* Profile */
+           if (profile) break;
 
-               // Get alarm
-               { "getalarm",           no_argument,       NULL, OPT_GETALARM },
+         case '6': /* Scale */
+           if (scale) break;
 
-               // Voice call mode
-               { "dialvoice",          required_argument, NULL, OPT_DIALVOICE },
+          case 'v': /* Set validaty of SMS */
+            MultiSMS->SMS[w].Validity = atoi(optarg);
+            break;
 
-               // Get calendar note mode
-               { "getcalendarnote",    required_argument, NULL, OPT_GETCALENDARNOTE },
+          case 'd': /* delivery report */
+            MultiSMS->SMS[w].Type=GST_DR;
+            break;     
 
-               // Write calendar note mode
-               { "writecalendarnote",  required_argument, NULL, OPT_WRITECALENDARNOTE },
+          case 's': /* Set replying via the same SMSC */
+            MultiSMS->SMS[w].ReplyViaSameSMSC = true; break;
 
-               // Delete calendar note mode
-               { "deletecalendarnote", required_argument, NULL, OPT_DELCALENDARNOTE },
+        default:
+          fprintf(stderr,_("Unknown option number %i\n"),argc);
+          GSM->Terminate();    
+          return -1;
 
-               // Get display status mode
-               { "getdisplaystatus",   no_argument,       NULL, OPT_GETDISPLAYSTATUS },
+        }
+      }
+    }
 
-               // Get memory mode
-               { "getmemory",          required_argument, NULL, OPT_GETMEMORY },
+    error=GSM->SendSMSMessage(&MultiSMS->SMS[w]);
 
-               // Write phonebook (memory) mode
-               { "writephonebook",     optional_argument, NULL, OPT_WRITEPHONEBOOK },
+    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);
+    }
 
-               // Get speed dial mode
-               { "getspeeddial",       required_argument, NULL, OPT_GETSPEEDDIAL },
+  }
 
-               // Set speed dial mode
-               { "setspeeddial",       required_argument, NULL, OPT_SETSPEEDDIAL },
+  GSM->Terminate();  
 
-               // Get SMS message mode
-               { "getsms",             required_argument, NULL, OPT_GETSMS },
+  return 0;
+}
+
+int GSM_SaveMultiPartSMSOnConsole(GSM_MultiSMSMessage *MultiSMS, int argnum, int argc, char *argv[],
+                                  bool inter, bool unicode, bool profile, bool scale) {
 
-               // Delete SMS message mode
-               { "deletesms",          required_argument, NULL, OPT_DELETESMS },
+  int w,i;
+  
+  GSM_SMSMessage SMSold;
 
-               // Send SMS message mode
-               { "sendsms",            required_argument, NULL, OPT_SENDSMS },
+  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 }
+  };
 
-               // Ssve SMS message mode
-               { "savesms",            optional_argument, NULL, OPT_SAVESMS },
+  int interactive;
+  int confirm = -1;
+  char ans[8];
 
-               // Send logo as SMS message mode
-               { "sendlogo",           required_argument, NULL, OPT_SENDLOGO },
+  GSM_Error error;  
 
-               // Send ringtone as SMS message
-               { "sendringtone",       required_argument, NULL, OPT_SENDRINGTONE },
+  interactive = inter;
 
-               // Set ringtone
-               { "setringtone",        required_argument, NULL, OPT_SETRINGTONE },
+  for (w=0;w<MultiSMS->number;w++) {
 
-               // Get SMS center number mode
-               { "getsmsc",            required_argument, NULL, OPT_GETSMSC },
+    if (argnum!=0) {
+      optarg = NULL;
+  
+      /* We check optional parameters from ... */
+      optind = argnum;
 
-               // For development purposes: run in passive monitoring mode
-               { "pmon",               no_argument,       NULL, OPT_PMON },
+      while ((i = getopt_long(argc, argv, "risal:", options, NULL)) != -1) {
+        switch (i) {
 
-               // NetMonitor mode
-               { "netmonitor",         required_argument, NULL, OPT_NETMONITOR },
+          case '1': /* SMSC number */
+            MultiSMS->SMS[w].MessageCenter.No = 0;
+            strcpy(MultiSMS->SMS[w].MessageCenter.Number,optarg);
+            break;
 
-               // Identify
-               { "identify",           no_argument,       NULL, OPT_IDENTIFY },
+          case '2': /* SMSC number index in phone memory */
+            MultiSMS->SMS[w].MessageCenter.No = atoi(optarg);
 
-               // Send DTMF sequence
-               { "senddtmf",           required_argument, NULL, OPT_SENDDTMF },
+            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;
 
-               // Resets the phone
-               { "reset",              optional_argument, NULL, OPT_RESET },
+         case '3': /* Receiver/recipient */
+           strncpy(MultiSMS->SMS[w].Destination,optarg,11); break;
 
-               // Set logo
-               { "setlogo",            optional_argument, NULL, OPT_SETLOGO },
+         case '4': /* Unicode */
+           if (unicode) break;
 
-               // Get logo
-               { "getlogo",            required_argument, NULL, OPT_GETLOGO },
+         case '5': /* Profile */
+           if (profile) break;
 
-               // View logo
-               { "viewlogo",           required_argument, NULL, OPT_VIEWLOGO },
+         case '6': /* Scale */
+           if (scale) break;
 
-               // Show profile
-               { "getprofile",         optional_argument, NULL, OPT_GETPROFILE },
+          case 'r': /* mark as read */
+            MultiSMS->SMS[w].Status = GSS_SENTREAD; break;
 
-               // Show texts from phone's display
-               { "displayoutput",      no_argument,       NULL, OPT_DISPLAYOUTPUT },
+         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;
 
-               // Simulate pressing the keys
-               { "keysequence",        no_argument,       NULL, OPT_KEYPRESS },
+          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;
+      }
+    }
 
-               /* Divert calls */
-               { "divert",             required_argument, NULL, OPT_DIVERT },
+    error=GSM->SaveSMSMessage(&MultiSMS->SMS[w]);
 
-               // For development purposes: insert you function calls here
-               { "foogle",             no_argument,       NULL, OPT_FOOGLE },
+    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);
+  }
 
-               { 0, 0, 0, 0},
-       };
+  GSM->Terminate();  
 
-       /* Every command which requires arguments should have an appropriate entry
-          in this array. */
-       struct gnokii_arg_len gals[] =
-       {
+  return 0;
+}
 
-#ifdef SECURITY
-               { OPT_ENTERSECURITYCODE, 1, 1, 0 },
+void GSM_PlayRingtoneOnConsole(GSM_Ringtone *ringtone)
+{
+  int i;
+#ifdef VC6
+  char mychar;
 #endif
 
-               { OPT_SETDATETIME,       0, 5, 0 },
-               { OPT_SETALARM,          2, 2, 0 },
-               { OPT_DIALVOICE,         1, 1, 0 },
-               { OPT_GETCALENDARNOTE,   1, 3, 0 },
-               { OPT_WRITECALENDARNOTE, 2, 2, 0 },
-               { OPT_DELCALENDARNOTE,   1, 2, 0 },
-               { OPT_GETMEMORY,         2, 3, 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,           0, 6, 0 },
-               { OPT_SENDLOGO,          3, 4, GAL_XOR },
-               { OPT_SENDRINGTONE,      2, 2, 0 },
-               { OPT_GETSMSC,           1, 1, 0 },
-               { OPT_GETWELCOMENOTE,    1, 1, 0 },
-               { OPT_SETWELCOMENOTE,    1, 1, 0 },
-               { OPT_NETMONITOR,        1, 1, 0 },
-               { OPT_SENDDTMF,          1, 1, 0 },
-               { OPT_SETLOGO,           1, 4, 0 },
-               { OPT_GETLOGO,           1, 4, 0 },
-               { OPT_VIEWLOGO,          1, 1, 0 },
-               { OPT_SETRINGTONE,       1, 1, 0 },
-               { OPT_RESET,             0, 1, 0 },
-               { OPT_GETPROFILE,        0, 1, 0 },
-               { OPT_WRITEPHONEBOOK,    0, 1, 0 },
-               { OPT_DIVERT,            6, 10, 0 },
-
-               { 0, 0, 0, 0 },
-       };
-
-       opterr = 0;
-
-       /* For GNU gettext */
-#ifdef USE_NLS
-       textdomain("gnokii");
-       setlocale(LC_ALL, "");
+  for (i=0;i<ringtone->NrNotes;i++) {
+#ifdef VC6
+    if (_kbhit()) {
+      mychar=_getch();
+      break;
+    }
 #endif
+    GSM_PlayOneNote (ringtone->notes[i]);
+  }
+  GSM->PlayTone(255*255,0);
+}
 
-       /* Read config file */
-       if (readconfig(&model, &Port, &Initlength, &Connection, &BinDir) < 0) {
-               exit(-1);
-       }
+/* This function shows the copyright and some informations usefull for
+   debugging. */
+int version(void)
+{
 
-       /* Introduce yourself */
-       short_version();
+  fprintf(stdout, _("GNOKII Version %s\n"
+"Copyright (C) Hugh Blemings <hugh@linuxcare.com>, 1999, 2000\n"
+"Copyright (C) Pavel Janík ml. <Pavel.Janik@linux.cz>, 1999, 2000\n"
+"Built %s %s for %s on %s \n"), VERSION, __TIME__, __DATE__, model, Port);
 
-       /* Handle command line arguments. */
-       c = getopt_long(argc, argv, "", long_options, NULL);
-       if (c == -1)            /* No argument given - we should display usage. */
-               usage();
+  return 0;
+}
 
-       switch(c) {
-       /* First, error conditions */
-       case '?':
-       case ':':
-               fprintf(stderr, _("Use '%s --help' for usage informations.\n"), argv[0]);
-               exit(0);
-       /* Then, options with no arguments */
-       case OPT_HELP:
-               usage();
-       case OPT_VERSION:
-               version();
-               exit(0);
-       }
-       
-       /* 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();
-               }
+/* The function usage is only informative - it prints this program's usage and
+   command-line options. */
 
-#ifdef __svr4__
-               /* have to ignore SIGALARM */
-               sigignore(SIGALRM);
-#endif
+int usage(void)
+{
 
-               /* Initialise the code for the GSM interface. */     
-               fbusinit(NULL);
+  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"
+  ));
 
-               switch(c) {
-               case OPT_MONITOR:
-                       rc = monitormode();
-                       break;
 #ifdef SECURITY
-               case OPT_ENTERSECURITYCODE:
-                       rc = entersecuritycode(optarg);
-                       break;
-               case OPT_GETSECURITYCODESTATUS:
-                       rc = getsecuritycodestatus();
-                       break;
-#endif
-               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;
-               /* 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_GETCALENDARNOTE:
-                       rc = getcalendarnote(nargc, nargv);
-                       break;
-               case OPT_DELCALENDARNOTE:
-                       rc = deletecalendarnote(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_DELETESMS:
-                       rc = deletesms(nargc, nargv);
-                       break;
-               case OPT_SENDSMS:
-                       rc = sendsms(nargc, nargv);
-                       break;
-               case OPT_SAVESMS:
-                       rc = savesms(argc, argv);
-                       break;
-               case OPT_SENDLOGO:
-                       rc = sendlogo(nargc, nargv);
-                       break;
-               case OPT_GETSMSC:
-                       rc = getsmsc(optarg);
-                       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_VIEWLOGO:
-                       rc = viewlogo(optarg);
-                       break;
-               case OPT_SETRINGTONE:
-                       rc = setringtone(nargc, nargv);
-                       break;
-               case OPT_SENDRINGTONE:
-                       rc = sendringtone(nargc, nargv);
-                       break;
-               case OPT_GETPROFILE:
-                       rc = getprofile(nargc, nargv);
-          &