summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common
Side-by-side diff
Diffstat (limited to 'gammu/emb/common') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/common.pro1
-rw-r--r--gammu/emb/common/commonE.pro1
-rw-r--r--gammu/emb/common/device/bluetoth/bluez.c29
-rw-r--r--gammu/emb/common/device/devfunc.c12
-rw-r--r--gammu/emb/common/device/irda/irda.c8
-rw-r--r--gammu/emb/common/device/irda/irda_unx.h2
-rw-r--r--gammu/emb/common/device/serial/ser_djg.c10
-rw-r--r--gammu/emb/common/device/serial/ser_unx.c38
-rw-r--r--gammu/emb/common/device/serial/ser_w32.c6
-rw-r--r--gammu/emb/common/gsmcomon.c21
-rw-r--r--gammu/emb/common/gsmcomon.h3
-rw-r--r--gammu/emb/common/gsmstate.c74
-rw-r--r--gammu/emb/common/gsmstate.h31
-rw-r--r--gammu/emb/common/misc/coding/coding.c177
-rw-r--r--gammu/emb/common/misc/coding/coding.h27
-rw-r--r--gammu/emb/common/misc/coding/md5.c2
-rw-r--r--gammu/emb/common/misc/misc.c19
-rw-r--r--gammu/emb/common/misc/misc.h8
-rw-r--r--gammu/emb/common/phone/alcatel/alcatel.c298
-rw-r--r--gammu/emb/common/phone/at/atgen.c295
-rw-r--r--gammu/emb/common/phone/at/atgen.h8
-rw-r--r--gammu/emb/common/phone/at/samsung.c447
-rw-r--r--gammu/emb/common/phone/at/samsung.h16
-rw-r--r--gammu/emb/common/phone/at/siemens.c74
-rw-r--r--gammu/emb/common/phone/at/sonyeric.c141
-rw-r--r--gammu/emb/common/phone/nokia/dct3/dct3func.c16
-rw-r--r--gammu/emb/common/phone/nokia/dct3/dct3func.h2
-rw-r--r--gammu/emb/common/phone/nokia/dct3/n6110.c17
-rw-r--r--gammu/emb/common/phone/nokia/dct3/n7110.c9
-rw-r--r--gammu/emb/common/phone/nokia/dct3/n9210.c3
-rw-r--r--gammu/emb/common/phone/nokia/dct4/n3320.c3
-rw-r--r--gammu/emb/common/phone/nokia/dct4/n3650.c3
-rw-r--r--gammu/emb/common/phone/nokia/dct4/n6510.c168
-rw-r--r--gammu/emb/common/phone/nokia/dct4/n6510.h2
-rw-r--r--gammu/emb/common/phone/nokia/nauto.c2
-rw-r--r--gammu/emb/common/phone/nokia/nfunc.c14
-rw-r--r--gammu/emb/common/phone/obex/obexgen.c3
-rw-r--r--gammu/emb/common/phone/obex/obexgen.h4
-rw-r--r--gammu/emb/common/phone/symbian/mroutgen.c3
-rw-r--r--gammu/emb/common/protocol/at/at.c6
-rw-r--r--gammu/emb/common/protocol/nokia/fbus2.c6
-rw-r--r--gammu/emb/common/protocol/nokia/fbus2.h6
-rw-r--r--gammu/emb/common/protocol/nokia/mbus2.c2
-rw-r--r--gammu/emb/common/protocol/nokia/mbus2.h2
-rw-r--r--gammu/emb/common/protocol/nokia/phonet.c5
-rw-r--r--gammu/emb/common/protocol/nokia/phonet.h5
-rw-r--r--gammu/emb/common/service/backup/backgen.h4
-rw-r--r--gammu/emb/common/service/backup/backtext.c229
-rw-r--r--gammu/emb/common/service/backup/gsmback.c36
-rw-r--r--gammu/emb/common/service/backup/gsmback.h2
-rw-r--r--gammu/emb/common/service/gsmcal.h2
-rw-r--r--gammu/emb/common/service/gsmdata.c124
-rw-r--r--gammu/emb/common/service/gsmdata.h2
-rw-r--r--gammu/emb/common/service/gsmlogo.c47
-rw-r--r--gammu/emb/common/service/gsmlogo.h28
-rw-r--r--gammu/emb/common/service/gsmmisc.h7
-rw-r--r--gammu/emb/common/service/gsmring.c45
-rw-r--r--gammu/emb/common/service/gsmring.h8
-rw-r--r--gammu/emb/common/service/sms/gsmmulti.c5
-rw-r--r--gammu/emb/common/service/sms/gsmmulti.h11
-rw-r--r--gammu/emb/common/service/sms/gsmsms.c5
-rw-r--r--gammu/emb/common/service/sms/gsmsms.h5
62 files changed, 2118 insertions, 471 deletions
diff --git a/gammu/emb/common/common.pro b/gammu/emb/common/common.pro
index 0e719ee..797199b 100644
--- a/gammu/emb/common/common.pro
+++ b/gammu/emb/common/common.pro
@@ -1,187 +1,188 @@
######################################################################
# Automatically generated by qmake (1.07a) Fri Jul 30 22:13:34 2004
######################################################################
TEMPLATE = lib
DEPENDPATH += device \
misc \
phone \
protocol \
service \
device/bluetoth \
device/irda \
device/serial \
misc/coding \
phone/alcatel \
phone/at \
phone/nokia \
phone/obex \
phone/symbian \
protocol/alcatel \
protocol/at \
protocol/nokia \
protocol/obex \
protocol/symbian \
service/backup \
service/sms \
phone/nokia/dct3 \
phone/nokia/dct4
INCLUDEPATH += . \
misc/coding \
misc \
device \
phone/nokia/dct4 \
phone/nokia/dct3 \
phone/at \
phone/alcatel \
phone/obex \
phone/symbian \
protocol \
protocol/nokia \
protocol/at \
protocol/alcatel \
protocol/obex \
protocol/symbian \
device/serial \
device/irda \
device/bluetoth \
service \
service/sms \
service/backup \
phone/nokia \
phone
# Input
HEADERS += config.h \
gammu.h \
gsmcomon.h \
gsmstate.h \
device/devfunc.h \
misc/cfg.h \
misc/misc.h \
phone/pfunc.h \
protocol/protocol.h \
service/gsmcal.h \
service/gsmcall.h \
service/gsmdata.h \
service/gsmlogo.h \
service/gsmmisc.h \
service/gsmnet.h \
service/gsmpbk.h \
service/gsmprof.h \
service/gsmring.h \
device/bluetoth/affix.h \
device/bluetoth/blue_w32.h \
device/bluetoth/bluetoth.h \
device/bluetoth/bluez.h \
device/irda/irda.h \
device/irda/irda_unx.h \
device/irda/irda_w32.h \
device/serial/ser_djg.h \
device/serial/ser_unx.h \
device/serial/ser_w32.h \
misc/coding/coding.h \
misc/coding/md5.h \
phone/alcatel/alcatel.h \
phone/at/atgen.h \
phone/nokia/ncommon.h \
phone/nokia/nfunc.h \
phone/nokia/nfuncold.h \
phone/obex/obexgen.h \
phone/symbian/mroutgen.h \
protocol/alcatel/alcabus.h \
protocol/at/at.h \
protocol/nokia/fbus2.h \
protocol/nokia/mbus2.h \
protocol/nokia/phonet.h \
protocol/obex/obex.h \
protocol/symbian/mrouter.h \
service/backup/backgen.h \
service/backup/backics.h \
service/backup/backldif.h \
service/backup/backlmb.h \
service/backup/backtext.h \
service/backup/backvcf.h \
service/backup/backvcs.h \
service/backup/gsmback.h \
service/sms/gsmems.h \
service/sms/gsmmulti.h \
service/sms/gsmsms.h \
phone/nokia/dct3/dct3comm.h \
phone/nokia/dct3/dct3func.h \
phone/nokia/dct3/n6110.h \
phone/nokia/dct3/n7110.h \
phone/nokia/dct3/n9210.h \
phone/nokia/dct4/dct4func.h \
phone/nokia/dct4/n3320.h \
phone/nokia/dct4/n3650.h \
phone/nokia/dct4/n6510.h
SOURCES +=gsmcomon.c \
gsmstate.c \
misc/misc.c \
misc/cfg.c \
misc/coding/coding.c \
misc/coding/md5.c \
service/sms/gsmsms.c \
service/sms/gsmems.c \
service/sms/gsmmulti.c \
service/gsmcal.c \
service/gsmdata.c \
service/gsmpbk.c \
service/gsmring.c \
service/gsmlogo.c \
service/gsmmisc.c \
service/gsmnet.c \
service/backup/gsmback.c \
service/backup/backldif.c \
service/backup/backlmb.c \
service/backup/backtext.c \
service/backup/backvcs.c \
service/backup/backvcf.c \
service/backup/backics.c \
device/bluetoth/affix.c \
device/bluetoth/bluez.c \
device/bluetoth/blue_w32.c \
device/bluetoth/bluetoth.c \
device/serial/ser_djg.c \
device/irda/irda.c \
device/devfunc.c \
protocol/at/at.c \
protocol/alcatel/alcabus.c \
protocol/nokia/mbus2.c \
protocol/nokia/fbus2.c \
protocol/nokia/phonet.c \
protocol/obex/obex.c \
protocol/symbian/mrouter.c \
phone/pfunc.c \
phone/at/atgen.c \
phone/at/siemens.c \
+phone/at/samsung.c \
phone/at/sonyeric.c \
phone/alcatel/alcatel.c \
phone/nokia/dct3/n6110.c \
phone/nokia/dct3/n7110.c \
phone/nokia/dct3/n9210.c \
phone/nokia/dct3/dct3func.c \
phone/nokia/dct4/n3320.c \
phone/nokia/dct4/n3650.c \
phone/nokia/dct4/n6510.c \
phone/nokia/dct4/dct4func.c \
phone/nokia/nauto.c \
phone/nokia/nfunc.c \
phone/nokia/nfuncold.c \
phone/obex/obexgen.c \
phone/symbian/mroutgen.c
DEFINES += DESKTOP_VERSION
TARGET = microgammu
CONFIG = warn_off release console
DESTDIR = ../../../bin
OBJECTS_DIR = obj/unix
MOC_DIR = moc/unix
unix: {
SOURCES += device/serial/ser_unx.c
}
win32:{
SOURCES += device/serial/ser_w32.c
}
diff --git a/gammu/emb/common/commonE.pro b/gammu/emb/common/commonE.pro
index a36947b..f5b559d 100644
--- a/gammu/emb/common/commonE.pro
+++ b/gammu/emb/common/commonE.pro
@@ -1,180 +1,181 @@
######################################################################
# Automatically generated by qmake (1.07a) Fri Jul 30 22:13:34 2004
######################################################################
TEMPLATE = lib
DEPENDPATH += device \
misc \
phone \
protocol \
service \
device/bluetoth \
device/irda \
device/serial \
misc/coding \
phone/alcatel \
phone/at \
phone/nokia \
phone/obex \
phone/symbian \
protocol/alcatel \
protocol/at \
protocol/nokia \
protocol/obex \
protocol/symbian \
service/backup \
service/sms \
phone/nokia/dct3 \
phone/nokia/dct4
INCLUDEPATH += . \
misc/coding \
misc \
device \
phone/nokia/dct4 \
phone/nokia/dct3 \
phone/at \
phone/alcatel \
phone/obex \
phone/symbian \
protocol \
protocol/nokia \
protocol/at \
protocol/alcatel \
protocol/obex \
protocol/symbian \
device/serial \
device/irda \
device/bluetoth \
service \
service/sms \
service/backup \
phone/nokia \
phone
# Input
HEADERS += config.h \
gammu.h \
gsmcomon.h \
gsmstate.h \
device/devfunc.h \
misc/cfg.h \
misc/misc.h \
phone/pfunc.h \
protocol/protocol.h \
service/gsmcal.h \
service/gsmcall.h \
service/gsmdata.h \
service/gsmlogo.h \
service/gsmmisc.h \
service/gsmnet.h \
service/gsmpbk.h \
service/gsmprof.h \
service/gsmring.h \
device/bluetoth/affix.h \
device/bluetoth/blue_w32.h \
device/bluetoth/bluetoth.h \
device/bluetoth/bluez.h \
device/irda/irda.h \
device/irda/irda_unx.h \
device/irda/irda_w32.h \
device/serial/ser_djg.h \
device/serial/ser_unx.h \
device/serial/ser_w32.h \
misc/coding/coding.h \
misc/coding/md5.h \
phone/alcatel/alcatel.h \
phone/at/atgen.h \
phone/nokia/ncommon.h \
phone/nokia/nfunc.h \
phone/nokia/nfuncold.h \
phone/obex/obexgen.h \
phone/symbian/mroutgen.h \
protocol/alcatel/alcabus.h \
protocol/at/at.h \
protocol/nokia/fbus2.h \
protocol/nokia/mbus2.h \
protocol/nokia/phonet.h \
protocol/obex/obex.h \
protocol/symbian/mrouter.h \
service/backup/backgen.h \
service/backup/backics.h \
service/backup/backldif.h \
service/backup/backlmb.h \
service/backup/backtext.h \
service/backup/backvcf.h \
service/backup/backvcs.h \
service/backup/gsmback.h \
service/sms/gsmems.h \
service/sms/gsmmulti.h \
service/sms/gsmsms.h \
phone/nokia/dct3/dct3comm.h \
phone/nokia/dct3/dct3func.h \
phone/nokia/dct3/n6110.h \
phone/nokia/dct3/n7110.h \
phone/nokia/dct3/n9210.h \
phone/nokia/dct4/dct4func.h \
phone/nokia/dct4/n3320.h \
phone/nokia/dct4/n3650.h \
phone/nokia/dct4/n6510.h
SOURCES +=gsmcomon.c \
gsmstate.c \
misc/misc.c \
misc/cfg.c \
misc/coding/coding.c \
misc/coding/md5.c \
service/sms/gsmsms.c \
service/sms/gsmems.c \
service/sms/gsmmulti.c \
service/gsmcal.c \
service/gsmdata.c \
service/gsmpbk.c \
service/gsmring.c \
service/gsmlogo.c \
service/gsmmisc.c \
service/gsmnet.c \
service/backup/gsmback.c \
service/backup/backldif.c \
service/backup/backlmb.c \
service/backup/backtext.c \
service/backup/backvcs.c \
service/backup/backvcf.c \
service/backup/backics.c \
device/bluetoth/affix.c \
device/bluetoth/bluez.c \
device/bluetoth/blue_w32.c \
device/bluetoth/bluetoth.c \
device/serial/ser_unx.c \
device/serial/ser_djg.c \
device/irda/irda.c \
device/devfunc.c \
protocol/at/at.c \
protocol/alcatel/alcabus.c \
protocol/nokia/mbus2.c \
protocol/nokia/fbus2.c \
protocol/nokia/phonet.c \
protocol/obex/obex.c \
protocol/symbian/mrouter.c \
phone/pfunc.c \
phone/at/atgen.c \
phone/at/siemens.c \
+phone/at/samsung.c \
phone/at/sonyeric.c \
phone/alcatel/alcatel.c \
phone/nokia/dct3/n6110.c \
phone/nokia/dct3/n7110.c \
phone/nokia/dct3/n9210.c \
phone/nokia/dct3/dct3func.c \
phone/nokia/dct4/n3320.c \
phone/nokia/dct4/n3650.c \
phone/nokia/dct4/n6510.c \
phone/nokia/dct4/dct4func.c \
phone/nokia/nauto.c \
phone/nokia/nfunc.c \
phone/nokia/nfuncold.c \
phone/obex/obexgen.c \
phone/symbian/mroutgen.c
TARGET = kammu
DESTDIR = $(QPEDIR)/lib
OBJECTS_DIR = obj/$(PLATFORM)
MOC_DIR = moc/$(PLATFORM)
CONFIG = warn_off release console
diff --git a/gammu/emb/common/device/bluetoth/bluez.c b/gammu/emb/common/device/bluetoth/bluez.c
index 8a4807e..e7e8adf 100644
--- a/gammu/emb/common/device/bluetoth/bluez.c
+++ b/gammu/emb/common/device/bluetoth/bluez.c
@@ -1,207 +1,216 @@
-/* Based on work by Marcel Holtmann and other authors of Bluez */
+/* Based on some work from Bluez (www.bluez.org)
+ * (C) 2000-2001 Qualcomm Incorporated
+ * (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ * (C) 2002-2004 Marcel Holtmann <marcel@holtmann.org>
+ * GNU GPL version 2
+ */
+/* based on some Marcel Holtmann work from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
#include "../../gsmstate.h"
#ifdef GSM_ENABLE_BLUETOOTHDEVICE
#ifdef GSM_ENABLE_BLUEZ
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#include "../../gsmcomon.h"
#include "../devfunc.h"
#include "bluetoth.h"
GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device)
{
GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth;
struct sockaddr_rc laddr, raddr;
bdaddr_t bdaddr;
int fd;
smprintf(s, "Connecting to RF channel %i\n",port);
fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
if (fd < 0) {
dbgprintf("Can't create socket\n");
return ERR_DEVICENODRIVER;
}
bacpy(&laddr.rc_bdaddr, BDADDR_ANY);
laddr.rc_family = AF_BLUETOOTH;
laddr.rc_channel = 0;
if (bind(fd, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
dbgprintf("Can't bind socket\n");
close(fd);
return ERR_DEVICEOPENERROR;
}
str2ba(device, &bdaddr);
bacpy(&raddr.rc_bdaddr, &bdaddr);
raddr.rc_family = AF_BLUETOOTH;
raddr.rc_channel = port;
if (connect(fd, (struct sockaddr *)&raddr, sizeof(raddr)) < 0) {
dbgprintf("Can't connect\n");
close(fd);
return ERR_DEVICEOPENERROR;
}
d->hPhone = fd;
return ERR_NONE;
}
#ifdef BLUETOOTH_RF_SEARCHING
struct search_context {
char *svc;
uuid_t group;
int tree;
uint32_t handle;
};
static void print_service_desc(void *value, void *user)
{
sdp_data_t *p = (sdp_data_t *)value;
int i = 0, proto = 0, *channel = (int *)user;
for (; p; p = p->next, i++) {
switch (p->dtd) {
case SDP_UUID16:
case SDP_UUID32:
case SDP_UUID128:
- proto = 1;//sdp_uuid_to_proto(&p->val.uuid);
+ proto = sdp_uuid_to_proto(&p->val.uuid);
break;
case SDP_UINT8:
if (proto == RFCOMM_UUID) {
(*channel) = p->val.uint8;
return;
}
break;
}
}
}
void print_access_protos(value, user)
{
sdp_list_t *protDescSeq = (sdp_list_t *)value;
int *channel = (int *)user;
sdp_list_foreach(protDescSeq,print_service_desc,channel);
}
static GSM_Error bluetooth_checkdevice(GSM_StateMachine *s, bdaddr_t *bdaddr, struct search_context *context)
{
sdp_session_t *sess;
- sdp_list_t *attrid, *search, *seq, *next, *proto = 0;
- uint32_t range = 0x0000ffff;
- char str[20];
sdp_record_t *rec;
+ sdp_list_t *attrid, *search, *seq, *next, *proto = 0;
sdp_data_t *d;
bdaddr_t interface;
+ uint32_t range = 0x0000ffff;
struct search_context subcontext;
+ char str[20];
int channel,channel2;
bacpy(&interface,BDADDR_ANY);
ba2str(bdaddr, str);
smprintf(s,"%s\n", str);
sess = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY);
if (!sess) {
dbgprintf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno));
return ERR_UNKNOWN;
}
attrid = sdp_list_append(0, &range);
search = sdp_list_append(0, &context->group);
if (sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq)) {
dbgprintf("Service Search failed: %s\n", strerror(errno));
sdp_close(sess);
return ERR_UNKNOWN;
}
sdp_list_free(attrid, 0);
sdp_list_free(search, 0);
channel2 = -1;
for (; seq; seq = next) {
rec = (sdp_record_t *) seq->data;
if (channel2 == -1) {
if (!context->tree) {
d = sdp_data_get(rec,SDP_ATTR_SVCNAME_PRIMARY);
- if (false) {
+ if (sdp_get_access_protos(rec,&proto) == 0) {
channel = -1;
sdp_list_foreach(proto,print_access_protos,&channel);
- //sdp_list_free(proto,(sdp_free_func_t)sdp_data_free);
+ sdp_list_free(proto,(sdp_free_func_t)sdp_data_free);
}
smprintf(s,"Channel %i",channel);
if (d) smprintf(s," - \"%s\"",d->val.str);
smprintf(s,"\n");
if (channel2 == -1 && bluetooth_checkservicename(s, d->val.str) == ERR_NONE) {
channel2 = channel;
}
}
if (sdp_get_group_id(rec,&subcontext.group) != -1) {
memcpy(&subcontext, context, sizeof(struct search_context));
if (subcontext.group.value.uuid16 != context->group.value.uuid16) bluetooth_checkdevice(s,bdaddr,&subcontext);
}
}
next = seq->next;
free(seq);
- //sdp_record_free(rec);
+ sdp_record_free(rec);
}
sdp_close(sess);
if (channel2 != -1) return bluetooth_connect(s, channel2, str);
- return ERR_UNKNOWN;
+ return ERR_NOTSUPPORTED;
}
GSM_Error bluetooth_findchannel(GSM_StateMachine *s)
{
inquiry_info ii[20];
uint8_t count = 0;
int i;
struct search_context context;
GSM_Error error = ERR_NOTSUPPORTED;
memset(&context, '\0', sizeof(struct search_context));
- //sdp_uuid16_create(&(context.group),PUBLIC_BROWSE_GROUP);
+ sdp_uuid16_create(&(context.group),PUBLIC_BROWSE_GROUP);
if (!strcmp(s->CurrentConfig->Device,"/dev/ttyS1")) {
dbgprintf("Searching for devices\n");
if (sdp_general_inquiry(ii, 20, 8, &count) < 0) {
return ERR_UNKNOWN;
}
} else {
count = 1;
str2ba(s->CurrentConfig->Device,&ii[0].bdaddr);
}
for (i=0;i<count;i++) {
error = bluetooth_checkdevice(s,&ii[i].bdaddr,&context);
if (error == ERR_NONE) return error;
}
return error;
}
#endif
#endif
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/device/devfunc.c b/gammu/emb/common/device/devfunc.c
index d31ebbf..c58a01f 100644
--- a/gammu/emb/common/device/devfunc.c
+++ b/gammu/emb/common/device/devfunc.c
@@ -1,266 +1,274 @@
+/* Some source from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
+/* Some source from Minicom (http://alioth.debian.org/projects/minicom)
+ * (C) 1991,1992,1993,1994,1995,1996 by Miquel van Smoorenburg
+ * GNU GPL version 2
+ */
#include <string.h>
#ifdef WIN32
# include <io.h>
#else
# include <errno.h>
# include <signal.h>
#endif
#include "../gsmstate.h"
#ifdef GSM_ENABLE_BLUETOOTHDEVICE
#ifdef BLUETOOTH_RF_SEARCHING
GSM_Error bluetooth_checkservicename(GSM_StateMachine *s, char *name)
{
if (s->ConnectionType == GCT_BLUEPHONET && strstr(name,"Nokia PC Suite")!=NULL) return ERR_NONE;
if (s->ConnectionType == GCT_BLUEOBEX && strstr(name,"OBEX") !=NULL) return ERR_NONE;
if (s->ConnectionType == GCT_BLUEAT && strstr(name,"COM 1") !=NULL) return ERR_NONE;
return ERR_UNKNOWN;
}
#endif
#endif
#if defined (GSM_ENABLE_BLUETOOTHDEVICE) || defined (GSM_ENABLE_IRDADEVICE)
int socket_read(GSM_StateMachine *s, void *buf, size_t nbytes, int hPhone)
{
fd_set readfds;
#ifdef WIN32
struct timeval timer;
#endif
FD_ZERO(&readfds);
FD_SET(hPhone, &readfds);
#ifndef WIN32
if (select(hPhone+1, &readfds, NULL, NULL, 0)) {
return(read(hPhone, buf, nbytes));
}
#else
memset(&timer,0,sizeof(timer));
if (select(0, &readfds, NULL, NULL, &timer) != 0) {
return(recv(hPhone, buf, nbytes, 0));
}
#endif
return 0;
}
#ifdef WIN32
int socket_write(GSM_StateMachine *s, unsigned char *buf, size_t nbytes, int hPhone)
#else
int socket_write(GSM_StateMachine *s, void *buf, size_t nbytes, int hPhone)
#endif
{
int ret;
size_t actual = 0;
do {
ret = send(hPhone, buf, nbytes - actual, 0);
if (ret < 0) {
if (actual != nbytes) GSM_OSErrorInfo(s,"socket_write");
return actual;
}
actual += ret;
buf += ret;
} while (actual < nbytes);
return actual;
}
GSM_Error socket_close(GSM_StateMachine *s, int hPhone)
{
shutdown(hPhone, 0);
#ifdef WIN32
closesocket(hPhone); /*FIXME: error checking */
#else
close(hPhone); /*FIXME: error checking */
#endif
return ERR_NONE;
}
#endif
#ifdef ENABLE_LGPL
GSM_Error lock_device(const char* port, char **lock_device)
{
*lock_device = 0;
return ERR_NONE;
}
bool unlock_device(char **lock_file)
{
return true;
}
#else
#define max_buf_len 128
#define lock_path "/var/lock/LCK.."
/* Lock the device. Allocated string with a lock name is returned
* in lock_device
*/
GSM_Error lock_device(const char* port, char **lock_device)
{
-#ifndef WIN32
+#if !defined(WIN32) && !defined(DJGPP)
char *lock_file = NULL;
char buffer[max_buf_len];
const char *aux;
int fd, len;
GSM_Error error = ERR_NONE;
dbgprintf("Locking device\n");
aux = strrchr(port, '/');
/* Remove leading '/' */
if (aux) {
aux++;
} else {
/* No / in port */
aux = port;
}
len = strlen(aux) + strlen(lock_path);
memset(buffer, 0, sizeof(buffer));
lock_file = calloc(len + 1, 1);
if (!lock_file) {
dbgprintf("Out of memory error while locking device\n");
return ERR_MOREMEMORY;
}
/* 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) {
dbgprintf("Lockfile %s is stale. Overriding it..\n", lock_file);
sleep(1);
if (unlink(lock_file) == -1) {
dbgprintf("Overriding failed, please check the permissions\n");
dbgprintf("Cannot lock device\n");
error = ERR_PERMISSION;
goto failed;
}
} else {
dbgprintf("Device already locked by PID %d.\n", pid);
error = ERR_DEVICELOCKED;
goto failed;
}
}
/* this must not happen. because we could open the file */
/* no wrong permissions are set. only reason could be */
/* flock/lockf or a empty lockfile due to a broken binary */
/* which is more likely */
if (n == 0) {
dbgprintf("Unable to read lockfile %s.\n", lock_file);
dbgprintf("Please check for reason and remove the lockfile by hand.\n");
dbgprintf("Cannot lock device\n");
error = ERR_UNKNOWN;
goto failed;
}
}
/* Try to create a new file, with 0644 mode */
fd = open(lock_file, O_CREAT | O_EXCL | O_WRONLY, 0644);
if (fd == -1) {
if (errno == EEXIST) {
dbgprintf("Device seems to be locked by unknown process\n");
error = ERR_DEVICEOPENERROR;
} else if (errno == EACCES) {
dbgprintf("Please check permission on lock directory\n");
error = ERR_PERMISSION;
} else if (errno == ENOENT) {
dbgprintf("Cannot create lockfile %s. Please check for existence of path\n", lock_file);
error = ERR_UNKNOWN;
} else {
dbgprintf("Unknown error with creating lockfile %s\n", lock_file);
error = ERR_UNKNOWN;
}
goto failed;
}
sprintf(buffer, "%10ld gammu\n", (long)getpid());
write(fd, buffer, strlen(buffer));
close(fd);
*lock_device = lock_file;
return ERR_NONE;
failed:
free(lock_file);
*lock_device = 0;
return error;
#else
*lock_device = 0;
return ERR_NONE;
#endif
}
/* Removes lock and frees memory */
bool unlock_device(char **lock_file)
{
-#ifndef WIN32
+#if !defined(WIN32) && !defined(DJGPP)
int err;
if (!lock_file) {
dbgprintf("Cannot unlock device\n");
return false;
}
err = unlink(*lock_file);
free(*lock_file);
*lock_file = NULL;
return (err + 1);
#else
return true;
#endif
}
#endif
int FindSerialSpeed(char *buffer)
{
switch (atoi(buffer)) {
case 50 : return 50;
case 75 : return 75;
case 110 : return 110;
case 134 : return 134;
case 150 : return 150;
case 200 : return 200;
case 300 : return 300;
case 600 : return 600;
case 1200 : return 1200;
case 1800 : return 1800;
case 2400 : return 2400;
case 4800 : return 4800;
case 9600 : return 9600;
case 19200 : return 19200;
case 38400 : return 38400;
case 57600 : return 57600;
case 115200 : return 115200;
case 230400 : return 230400;
default : return 0;
}
}
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/device/irda/irda.c b/gammu/emb/common/device/irda/irda.c
index fef50ac..e680377 100644
--- a/gammu/emb/common/device/irda/irda.c
+++ b/gammu/emb/common/device/irda/irda.c
@@ -1,187 +1,191 @@
/* (c) 2001-2004 by Marcin Wiacek */
-/* based on some work from Ralf Thelen and MyGnokii */
-/* based on some work from Gnokii and MSDN */
+/* based on some work from Ralf Thelen and MyGnokii (www.mwiacek.com) */
+/* based on some work from MSDN */
+/* based on some work from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
/* You have to include wsock32.lib library to MS VC project to compile it */
#include "../../gsmstate.h"
#ifdef GSM_ENABLE_IRDADEVICE
#ifndef DJGPP
#ifndef WIN32
# 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>
#else
# include <windows.h>
# include <io.h>
#endif
#include "../../gsmcomon.h"
#include "../devfunc.h"
#include "irda.h"
static bool irda_discover_device(GSM_StateMachine *state)
{
GSM_Device_IrdaData *d = &state->Device.Data.Irda;
struct irda_device_list *list;
unsigned char *buf;
unsigned int sec;
int s, z, len, fd, i;
GSM_DateTime Date;
bool founddevice = false;
#ifdef WIN32
int index;
#endif
fd = socket(AF_IRDA, SOCK_STREAM, 0);
/* can handle maximally 10 devices during discovering */
len = sizeof(struct irda_device_list) + sizeof(struct irda_device_info) * 10;
buf = malloc(len);
list = (struct irda_device_list *)buf;
/* Trying to find device during 2 seconds */
for (z=0;z<2;z++) {
GSM_GetCurrentDateTime (&Date);
sec = Date.Second;
while (sec==Date.Second) {
s = len;
memset(buf, 0, s);
if (getsockopt(fd, SOL_IRLMP, IRLMP_ENUMDEVICES, buf, &s) == 0) {
for (i = 0; i < (int)list->numDevice; i++) {
dbgprintf("Irda: found device \"%s\" (address %x) - ",list->Device[i].irdaDeviceName,list->Device[i].irdaDeviceID);
if (strcmp(GetModelData(NULL,NULL,list->Device[i].irdaDeviceName)->number,"") != 0) {
founddevice = true;
/* Model AUTO */
if (state->CurrentConfig->Model[0]==0) strcpy(state->Phone.Data.Model,GetModelData(NULL,NULL,list->Device[i].irdaDeviceName)->number);
state->Phone.Data.ModelInfo = GetModelData(NULL,state->Phone.Data.Model,NULL);
}
if (founddevice) {
dbgprintf("correct\n");
#ifdef WIN32
for(index=0; index <= 3; index++)
d->peer.irdaDeviceID[index] = list->Device[i].irdaDeviceID[index];
#else
d->peer.irdaDeviceID = list->Device[i].irdaDeviceID;
#endif
break;
}
dbgprintf("\n");
}
}
if (founddevice) break;
my_sleep(10);
GSM_GetCurrentDateTime(&Date);
}
if (founddevice) break;
}
free(buf);
close(fd);
return founddevice;
}
static GSM_Error irda_open (GSM_StateMachine *s)
{
GSM_Device_IrdaData *d = &s->Device.Data.Irda;
int fd = -1;
#ifdef WIN32
int Enable9WireMode = 1;
WSADATA wsaData;
WSAStartup(MAKEWORD(1,1), &wsaData);
#else
if (s->ConnectionType == GCT_IRDAAT) return ERR_SOURCENOTAVAILABLE;
#endif
/* discovering devices */
if (irda_discover_device(s)==false) return ERR_TIMEOUT;
/* Creating socket */
fd = socket(AF_IRDA, SOCK_STREAM, 0);
d->peer.irdaAddressFamily = AF_IRDA;
#ifndef WIN32
d->peer.sir_lsap_sel = LSAP_ANY;
#endif
switch (s->ConnectionType) {
case GCT_IRDAAT:
strcpy(d->peer.irdaServiceName, "IrDA:IrCOMM");
#ifdef WIN32
if (setsockopt(fd, SOL_IRLMP, IRLMP_9WIRE_MODE, (const char *) &Enable9WireMode,
sizeof(int))==SOCKET_ERROR) return ERR_UNKNOWN;
#endif
break;
case GCT_IRDAPHONET:
strcpy(d->peer.irdaServiceName, "Nokia:PhoNet");
break;
case GCT_IRDAOBEX:
/* IrDA:OBEX not supported by N3650 */
// strcpy(d->peer.irdaServiceName, "IrDA:OBEX");
strcpy(d->peer.irdaServiceName, "OBEX");
/* Alternative server is "OBEX:IrXfer" */
break;
default:
return ERR_UNKNOWN;
}
/* Connecting to service */
if (connect(fd, (struct sockaddr *)&d->peer, sizeof(d->peer))) {
dbgprintf("Can't connect to service %s\n",d->peer.irdaServiceName);
close(fd);
return ERR_NOTSUPPORTED;
}
d->hPhone=fd;
return ERR_NONE;
}
static int irda_read(GSM_StateMachine *s, void *buf, size_t nbytes)
{
return socket_read(s, buf, nbytes, s->Device.Data.Irda.hPhone);
}
#ifdef WIN32
static int irda_write(GSM_StateMachine *s, unsigned char *buf, size_t nbytes)
#else
static int irda_write(GSM_StateMachine *s, void *buf, size_t nbytes)
#endif
{
return socket_write(s, buf, nbytes, s->Device.Data.Irda.hPhone);
}
static GSM_Error irda_close(GSM_StateMachine *s)
{
return socket_close(s, s->Device.Data.Irda.hPhone);
}
GSM_Device_Functions IrdaDevice = {
irda_open,
irda_close,
NONEFUNCTION,
NONEFUNCTION,
NONEFUNCTION,
irda_read,
irda_write
};
#endif
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/device/irda/irda_unx.h b/gammu/emb/common/device/irda/irda_unx.h
index 8dbcb97..7a55273 100644
--- a/gammu/emb/common/device/irda/irda_unx.h
+++ b/gammu/emb/common/device/irda/irda_unx.h
@@ -1,61 +1,61 @@
-/* part of irda.h available in Linux kernel source */
+/* part of irda.h available in Linux kernel source (www.kernel.org) */
/*********************************************************************
*
* Filename: irda.h
* Version:
* Description:
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Mon Mar 8 14:06:12 1999
* Modified at: Sat Dec 25 16:06:42 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* Neither Dag Brattli nor University of Tromsø admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
********************************************************************/
#ifndef __irda_unx_h
#define __irda_unx_h
#include <sys/types.h>
#include <sys/socket.h>
#define SOL_IRLMP 266 /* Same as SOL_IRDA for now */
#define IRLMP_ENUMDEVICES 1 /* Return discovery log */
#define LSAP_ANY 0xff
struct sockaddr_irda {
sa_family_t irdaAddressFamily; /* AF_IRDA */
u_int8_t sir_lsap_sel; /* LSAP selector */
u_int32_t irdaDeviceID; /* Device address */
char irdaServiceName[25]; /* Usually <service>:IrDA:TinyTP */
};
struct irda_device_info {
u_int32_t saddr; /* Address of local interface */
u_int32_t irdaDeviceID; /* Address of remote device */
char irdaDeviceName[22]; /* Description */
u_int8_t charset; /* Charset used for description */
u_int8_t hints[2]; /* Hint bits */
};
struct irda_device_list {
u_int32_t numDevice;
struct irda_device_info Device[1];
};
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/device/serial/ser_djg.c b/gammu/emb/common/device/serial/ser_djg.c
index ac9d7c8..2524187 100644
--- a/gammu/emb/common/device/serial/ser_djg.c
+++ b/gammu/emb/common/device/serial/ser_djg.c
@@ -1,74 +1,74 @@
#include "../../gsmstate.h"
#ifdef GSM_ENABLE_SERIALDEVICE
#ifdef DJGPP
#include "../../gsmcomon.h"
#include "ser_djg.h"
static GSM_Error serial_close(GSM_StateMachine *s)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
- return ERR_NONE;
+ return ERR_NOTIMPLEMENTED;
}
static GSM_Error serial_open (GSM_StateMachine *s)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
- return ERR_NONE;
+ return ERR_NOTIMPLEMENTED;
}
static GSM_Error serial_setparity(GSM_StateMachine *s, bool parity)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
- return ERR_NONE;
+ return ERR_NOTIMPLEMENTED;
}
static GSM_Error serial_setdtrrts(GSM_StateMachine *s, bool dtr, bool rts)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
- return ERR_NONE;
+ return ERR_NOTIMPLEMENTED;
}
static GSM_Error serial_setspeed(GSM_StateMachine *s, int speed)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
- return ERR_NONE;
+ return ERR_NOTIMPLEMENTED;
}
static int serial_read(GSM_StateMachine *s, void *buf, size_t nbytes)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
return 0;
}
static int serial_write(GSM_StateMachine *s, void *buf, size_t nbytes)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
return 0;
}
GSM_Device_Functions SerialDevice = {
serial_open,
serial_close,
serial_setparity,
serial_setdtrrts,
serial_setspeed,
serial_read,
serial_write
};
#endif
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/device/serial/ser_unx.c b/gammu/emb/common/device/serial/ser_unx.c
index 2a87b11..69c7515 100644
--- a/gammu/emb/common/device/serial/ser_unx.c
+++ b/gammu/emb/common/device/serial/ser_unx.c
@@ -1,291 +1,319 @@
/* (c) 2002-2004 by Marcin Wiacek */
/* locking device and settings all speeds by Michal Cihar */
+/* based on some work from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
#include "../../gsmstate.h"
#ifdef GSM_ENABLE_SERIALDEVICE
#ifndef WIN32
#ifndef DJGPP
#include <sys/file.h>
#include <sys/time.h>
#include <string.h>
#include <termios.h>
#include <errno.h>
#include "../../gsmcomon.h"
#include "ser_unx.h"
+#ifndef O_NONBLOCK
+# define O_NONBLOCK 0
+#endif
+
+#ifdef __NetBSD__
+# define FNONBLOCK O_NONBLOCK
+
+# define B57600 0010001
+# define B115200 0010002
+# define B230400 0010003
+# define B460800 0010004
+# define B500000 0010005
+# define B576000 0010006
+# define B921600 0010007
+# define B1000000 0010010
+# define B1152000 0010011
+# define B1500000 0010012
+# define B2000000 0010013
+# define B2500000 0010014
+# define B3000000 0010015
+# define B3500000 0010016
+# define B4000000 0010017
+#endif
+
static GSM_Error serial_close(GSM_StateMachine *s)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
/* Restores old settings */
tcsetattr(d->hPhone, TCSANOW, &d->old_settings);
/* Closes device */
close(d->hPhone);
return ERR_NONE;
}
-#ifndef O_NONBLOCK
-# define O_NONBLOCK 0
-#endif
-
static GSM_Error serial_open (GSM_StateMachine *s)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
struct termios t;
int i;
/* O_NONBLOCK MUST is required to avoid waiting for DCD */
d->hPhone = open(s->CurrentConfig->Device, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (d->hPhone < 0) {
i = errno;
GSM_OSErrorInfo(s,"open in serial_open");
if (i == 2) return ERR_DEVICENOTEXIST; //no such file or directory
if (i == 13) return ERR_DEVICENOPERMISSION; //permission denied
return ERR_DEVICEOPENERROR;
}
#ifdef TIOCEXCL
/* open() calls from other applications shall fail now */
ioctl(d->hPhone, TIOCEXCL, (char *) 0);
#endif
if (tcgetattr(d->hPhone, &d->old_settings) == -1) {
close(d->hPhone);
GSM_OSErrorInfo(s,"tcgetattr in serial_open");
return ERR_DEVICEREADERROR;
}
if (tcflush(d->hPhone, TCIOFLUSH) == -1) {
serial_close(s);
GSM_OSErrorInfo(s,"tcflush in serial_open");
return ERR_DEVICEOPENERROR;
}
memcpy(&t, &d->old_settings, sizeof(struct termios));
/* Opening without parity */
t.c_iflag = IGNPAR;
t.c_oflag = 0;
/* disconnect line, 8 bits, enable receiver,
* ignore modem lines,lower modem line after disconnect
*/
t.c_cflag = B0 | CS8 | CREAD | CLOCAL | HUPCL;
/* enable hardware (RTS/CTS) flow control (NON POSIX) */
/* t.c_cflag |= CRTSCTS; */
t.c_lflag = 0;
t.c_cc[VMIN] = 1;
t.c_cc[VTIME] = 0;
if (tcsetattr(d->hPhone, TCSANOW, &t) == -1) {
serial_close(s);
GSM_OSErrorInfo(s,"tcsetattr in serial_open");
return ERR_DEVICEOPENERROR;
}
/* Making file descriptor asynchronous. */
if (fcntl(d->hPhone, F_SETFL, FASYNC | FNONBLOCK) == -1) {
serial_close(s);
GSM_OSErrorInfo(s,"fcntl in serial_open");
return ERR_DEVICEOPENERROR;
}
return ERR_NONE;
}
static GSM_Error serial_setparity(GSM_StateMachine *s, bool parity)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
struct termios t;
if (tcgetattr(d->hPhone, &t)) {
GSM_OSErrorInfo(s,"tcgetattr in serial_setparity");
return ERR_DEVICEREADERROR;
}
if (parity) {
t.c_cflag |= (PARENB | PARODD);
t.c_iflag = 0;
} else {
t.c_iflag = IGNPAR;
}
if (tcsetattr(d->hPhone, TCSANOW, &t) == -1){
serial_close(s);
GSM_OSErrorInfo(s,"tcsetattr in serial_setparity");
return ERR_DEVICEPARITYERROR;
}
return ERR_NONE;
}
static GSM_Error serial_setdtrrts(GSM_StateMachine *s, bool dtr, bool rts)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
struct termios t;
unsigned int flags;
if (tcgetattr(d->hPhone, &t)) {
GSM_OSErrorInfo(s,"tcgetattr in serial_setdtrrts");
return ERR_DEVICEREADERROR;
}
#ifdef CRTSCTS
/* Disabling hardware flow control */
t.c_cflag &= ~CRTSCTS;
#endif
if (tcsetattr(d->hPhone, TCSANOW, &t) == -1) {
serial_close(s);
GSM_OSErrorInfo(s,"tcsetattr in serial_setdtrrts");
return ERR_DEVICEDTRRTSERROR;
}
flags = TIOCM_DTR;
if (dtr) {
ioctl(d->hPhone, TIOCMBIS, &flags);
} else {
ioctl(d->hPhone, TIOCMBIC, &flags);
}
flags = TIOCM_RTS;
if (rts) {
ioctl(d->hPhone, TIOCMBIS, &flags);
} else {
ioctl(d->hPhone, TIOCMBIC, &flags);
}
flags = 0;
ioctl(d->hPhone, TIOCMGET, &flags);
dbgprintf("Serial device:");
dbgprintf(" DTR is %s", flags&TIOCM_DTR?"up":"down");
dbgprintf(", RTS is %s", flags&TIOCM_RTS?"up":"down");
dbgprintf(", CAR is %s", flags&TIOCM_CAR?"up":"down");
dbgprintf(", CTS is %s\n", flags&TIOCM_CTS?"up":"down");
if (((flags&TIOCM_DTR)==TIOCM_DTR) != dtr) return ERR_DEVICEDTRRTSERROR;
if (((flags&TIOCM_RTS)==TIOCM_RTS) != rts) return ERR_DEVICEDTRRTSERROR;
return ERR_NONE;
}
static GSM_Error serial_setspeed(GSM_StateMachine *s, int speed)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
struct termios t;
- int speed2 = B19200;
+ int speed2 = B19200;
if (tcgetattr(d->hPhone, &t)) {
GSM_OSErrorInfo(s,"tcgetattr in serial_setspeed");
return ERR_DEVICEREADERROR;
}
smprintf(s, "Setting speed to %d\n", speed);
switch (speed) {
case 50: speed2 = B50; break;
case 75: speed2 = B75; break;
case 110: speed2 = B110; break;
case 134: speed2 = B134; break;
case 150: speed2 = B150; break;
case 200: speed2 = B200; break;
case 300: speed2 = B300; break;
case 600: speed2 = B600; break;
case 1200: speed2 = B1200; break;
case 1800: speed2 = B1800; break;
case 2400: speed2 = B2400; break;
case 4800: speed2 = B4800; break;
case 9600: speed2 = B9600; break;
case 19200: speed2 = B19200; break;
case 38400: speed2 = B38400; break;
+#ifdef B57600
case 57600: speed2 = B57600; break;
case 115200: speed2 = B115200; break;
case 230400: speed2 = B230400; break;
case 460800: speed2 = B460800; break;
+#ifdef B500000
case 500000: speed2 = B500000; break;
case 576000: speed2 = B576000; break;
case 921600: speed2 = B921600; break;
case 1000000: speed2 = B1000000; break;
case 1152000: speed2 = B1152000; break;
case 1500000: speed2 = B1500000; break;
case 2000000: speed2 = B2000000; break;
case 2500000: speed2 = B2500000; break;
case 3000000: speed2 = B3000000; break;
case 3500000: speed2 = B3500000; break;
case 4000000: speed2 = B4000000; break;
+#endif
+#endif
}
/* This should work on all systems because it is done according to POSIX */
cfsetispeed(&t, speed2);
cfsetospeed(&t, speed2);
if (tcsetattr(d->hPhone, TCSADRAIN, &t) == -1) {
serial_close(s);
GSM_OSErrorInfo(s,"tcsetattr in serial_setspeed");
return ERR_DEVICECHANGESPEEDERROR;
}
return ERR_NONE;
}
static int serial_read(GSM_StateMachine *s, void *buf, size_t nbytes)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
struct timeval timeout2;
fd_set readfds;
int actual = 0;
FD_ZERO(&readfds);
FD_SET(d->hPhone, &readfds);
timeout2.tv_sec = 0;
timeout2.tv_usec = 1;
if (select(d->hPhone+1, &readfds, NULL, NULL, &timeout2)) {
actual = read(d->hPhone, buf, nbytes);
if (actual == -1) GSM_OSErrorInfo(s,"serial_read");
}
return actual;
}
static int serial_write(GSM_StateMachine *s, void *buf, size_t nbytes)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
int ret;
size_t actual = 0;
do {
ret = write(d->hPhone, (unsigned char *)buf, nbytes - actual);
if (ret < 0 && errno == EAGAIN) continue;
if (ret < 0) {
if (actual != nbytes) GSM_OSErrorInfo(s,"serial_write");
return actual;
}
actual += ret;
buf += ret;
if (s->ConnectionType == GCT_FBUS2PL2303) my_sleep(1);
} while (actual < nbytes);
return actual;
}
GSM_Device_Functions SerialDevice = {
serial_open,
serial_close,
serial_setparity,
serial_setdtrrts,
serial_setspeed,
serial_read,
serial_write
};
#endif
#endif
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/device/serial/ser_w32.c b/gammu/emb/common/device/serial/ser_w32.c
index 9fa0135..7d88fc7 100644
--- a/gammu/emb/common/device/serial/ser_w32.c
+++ b/gammu/emb/common/device/serial/ser_w32.c
@@ -1,194 +1,198 @@
/* (c) 2002-2004 by Marcin Wiacek */
-/* based on some work from Gnokii, MSDN and others */
+/* based on some work from MSDN and others */
+/* based on some work from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
#include "../../gsmstate.h"
#ifdef GSM_ENABLE_SERIALDEVICE
#ifdef WIN32
#include <windows.h>
#include <string.h>
#include <stdio.h>
#include <io.h>
#include <memory.h>
#include "../../gsmcomon.h"
#include "ser_w32.h"
static GSM_Error serial_close(GSM_StateMachine *s)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
/* Disables all monitored events for device */
SetCommMask(d->hPhone, 0);
/* Discards all characters from input/output buffer and terminates
* pending read/write operations
*/
PurgeComm(d->hPhone, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR);
/* Clears the DTR (data-terminal-ready) signal */
EscapeCommFunction(d->hPhone, CLRDTR);
/* Restores old settings */
if (SetCommState(d->hPhone, &d->old_settings)==0) {
GSM_OSErrorInfo(s, "SetCommState in serial_close");
}
/* Closes device */
if (CloseHandle(d->hPhone)==0) {
GSM_OSErrorInfo(s, "CloseHandle in serial_close");
}
return ERR_NONE;
}
static GSM_Error serial_open (GSM_StateMachine *s)
{
GSM_Device_SerialData *d = &s->Device.Data.Serial;
DCB dcb;
unsigned char DeviceName[80],DeviceName2[80];
int i;
#ifdef GSM_ENABLE_FBUS2DKU5
HKEY hKey;
DWORD DeviceNameLen, KeyNameLen;
unsigned char KeyName[100];
#endif
strcpy(DeviceName2,s->CurrentConfig->Device);
#ifdef GSM_ENABLE_FBUS2DKU5
if (s->ConnectionType == GCT_FBUS2DKU5) {
smprintf(s,"Reading DKU5 device\n");
DeviceName2[0] = 0;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) {
smprintf(s,"Error opening key\n");
return ERR_DEVICENOTWORK;
}
i = 0;
while(1) {
DeviceNameLen = 80;
KeyNameLen = 100;
if (RegEnumValue(hKey,i,KeyName,&KeyNameLen,NULL,NULL,DeviceName2,&DeviceNameLen) != ERROR_SUCCESS) {
smprintf(s,"Error reading key value\n");
return ERR_DEVICENOTWORK;
}
// smprintf(s,"Key name is %s, value is %s\n",KeyName,DeviceName2);
if (!strncmp(KeyName,"\\Device\\AtmelVirtualPort",24)) break;
i++;
}
RegCloseKey(hKey);
if (strlen(DeviceName2) == 0) return ERR_DEVICENOTWORK;
smprintf(s,"DKU5 device is \"%s\"\n",DeviceName2);
//nodriver
}
#endif
if ((s->ConnectionType == GCT_FBUS2DKU5) ||
(!strncmp(DeviceName2,"com",3) && strlen(DeviceName2)>3)) {
sprintf(DeviceName,"\\\\.\\COM%i",atoi(DeviceName2+3));
} else {
strcpy(DeviceName,DeviceName2);
}
smprintf(s,"Device is %s\n",DeviceName);
/* Allows for reading/writing, no device sharing */
d->hPhone = CreateFile(DeviceName,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
if (d->hPhone == INVALID_HANDLE_VALUE) {
i = GetLastError();
GSM_OSErrorInfo(s, "CreateFile in serial_open");
if (i == 2) return ERR_DEVICENOTWORK; //can't find specified file
if (i == 5) return ERR_DEVICEBUSY; //access denied
if (i == 31) return ERR_DEVICENOTWORK; //attached device not working
if (i == 123) return ERR_DEVICENOTEXIST;
return ERR_DEVICEOPENERROR;
}
d->old_settings.DCBlength = sizeof(DCB);
if (GetCommState(d->hPhone, &d->old_settings)==0) {
GSM_OSErrorInfo(s, "ReadDevice in serial_open");
return ERR_DEVICEREADERROR;
}
/* When char will be received, we will receive notifications */
SetCommMask(d->hPhone, EV_RXCHAR);
/* Sets size for input/output buffer */
SetupComm(d->hPhone, 4096, 4096);
/* Discards all characters from input/output buffer and terminates
* pending read/write operations
*/
PurgeComm(d->hPhone, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR);
memcpy(&dcb, &d->old_settings, sizeof(DCB));
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
/* No Xon/Xof flow control */
// dcb.fOutX = false;
// dcb.fInX = false;
/* Hardware flow control */
// dcb.fOutxDsrFlow = true;
// dcb.fOutxCtsFlow = true;
// dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
// dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
/* Initialise the port settings */
if (SetCommState(d->hPhone, &dcb)==0) {
GSM_OSErrorInfo(s, "WriteDevice in serial_open");
return ERR_DEVICEOPENERROR;
}
return ERR_NONE;
}
static GSM_Error serial_setparity (GSM_StateMachine *s, bool parity)
{
DCB dcb;
GSM_Device_SerialData *d = &s->Device.Data.Serial;
dcb.DCBlength = sizeof(DCB);
if (GetCommState(d->hPhone, &dcb)==0) {
GSM_OSErrorInfo(s, "ReadDevice in serial_setparity");
return ERR_DEVICEREADERROR;
}
if (parity) {
dcb.Parity = ODDPARITY;
} else {
dcb.Parity = NOPARITY;
}
if (SetCommState(d->hPhone, &dcb)==0) {
GSM_OSErrorInfo(s, "WriteDevice in serial_setparity");
return ERR_DEVICEPARITYERROR;
}
return ERR_NONE;
}
static GSM_Error serial_setdtrrts(GSM_StateMachine *s, bool dtr, bool rts)
{
DCB dcb;
GSM_Device_SerialData *d = &s->Device.Data.Serial;
dcb.DCBlength = sizeof(DCB);
if (GetCommState(d->hPhone, &dcb)==0) {
GSM_OSErrorInfo(s, "ReadDevice in serial_setdtrrts");
return ERR_DEVICEREADERROR;
}
diff --git a/gammu/emb/common/gsmcomon.c b/gammu/emb/common/gsmcomon.c
index d094ef3..445c3a6 100644
--- a/gammu/emb/common/gsmcomon.c
+++ b/gammu/emb/common/gsmcomon.c
@@ -1,260 +1,261 @@
/* (c) 2002-2004 by Marcin Wiacek & Michal Cihar */
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <stdio.h>
#ifndef __OpenBSD__
# include <wchar.h>
#endif
#ifdef WIN32
# include <windows.h>
#else
# include <stdlib.h>
# include <errno.h>
# include <fcntl.h>
# include <signal.h>
#endif
#include "gsmcomon.h"
#include "misc/coding/coding.h"
GSM_Error NoneFunction(void)
{
return ERR_NONE;
}
GSM_Error NotImplementedFunction(void)
{
return ERR_NOTIMPLEMENTED;
}
GSM_Error NotSupportedFunction(void)
{
return ERR_NOTSUPPORTED;
}
unsigned char *GetMsg (INI_Section *cfg, unsigned char *default_string)
{
unsigned char *retval, buffer[40], buff2[40], buff[2000];
static unsigned char def_str[2000];
INI_Entry *e;
INI_Section *h;
int num;
int len;
if (cfg==NULL) return default_string;
EncodeUnicode (buff2, "common", 6);
/* Set all 0x0a to \n */
memset(def_str,0,sizeof(def_str));
for (num=0;num<((int)strlen(default_string));num++) {
if (default_string[num] == 0x0a) {
def_str[strlen(def_str)] = '\\';
def_str[strlen(def_str)] = 'n';
} else def_str[strlen(def_str)] = default_string[num];
}
e = NULL;
/* First find our section */
for (h = cfg; h != NULL; h = h->Next) {
if (mywstrncasecmp(buff2, h->SectionName, 0)) {
e = h->SubEntries;
break;
}
}
while (e != NULL) {
num = -1;
DecodeUnicode(e->EntryName,buffer);
if (strlen(buffer) == 5 && (buffer[0] == 'F' || buffer[0] == 'f')) {
num = atoi(buffer+2);
}
if (num!=-1) {
DecodeUnicode(e->EntryValue,buff);
/* Remove quotes */
if (buff[0] == '"') {
len = strlen(buff);
memmove(buff, buff + 1, len - 1);
if (buff[len - 2] == '"') buff[len - 2] = 0;
}
if (strcmp(buff, def_str) == 0) {
sprintf(buff,"T%04i",num);
EncodeUnicode (buffer, buff, 5);
retval = INI_GetValue(cfg, buff2, buffer, true);
if (retval) {
sprintf(buff,"%s",DecodeUnicodeConsole(retval+2));
buff[strlen(buff)-1] = 0;
/* Set all \n to 0x0a */
memset(def_str,0,sizeof(def_str));
num = 0;
while (num != (int)strlen(buff)) {
if (num < (int)strlen(buff) - 1) {
if (buff[num] == '\\' && buff[num+1] == 'n') {
def_str[strlen(def_str)] = 0x0a;
num+=2;
} else {
def_str[strlen(def_str)] = buff[num++];
}
} else {
def_str[strlen(def_str)] = buff[num++];
}
}
retval = def_str;
} else {
retval = default_string;
}
return retval;
}
}
e = e->Next;
}
return default_string;
}
typedef struct {
GSM_Error ErrorNum;
unsigned char *ErrorText;
} PrintErrorEntry;
static PrintErrorEntry PrintErrorEntries[] = {
{ERR_NONE, "No error."},
{ERR_DEVICEOPENERROR, "Error opening device. Unknown/busy or no permissions."},
{ERR_DEVICELOCKED, "Error opening device. Device locked."},
- {ERR_DEVICENOTEXIST, "Error opening device. Not exist."},
+ {ERR_DEVICENOTEXIST, "Error opening device. Doesn't exist."},
{ERR_DEVICEBUSY, "Error opening device. Already opened by other application."},
{ERR_DEVICENOPERMISSION, "Error opening device. No permissions."},
{ERR_DEVICENODRIVER, "Error opening device. No required driver in operating system."},
{ERR_DEVICENOTWORK, "Error opening device. Some hardware not connected/wrong configured."},
{ERR_DEVICEDTRRTSERROR, "Error setting device DTR or RTS."},
{ERR_DEVICECHANGESPEEDERROR, "Error setting device speed. Maybe speed not supported."},
{ERR_DEVICEWRITEERROR, "Error writing device."},
- {ERR_DEVICEREADERROR, "Error during reading device"},
- {ERR_DEVICEPARITYERROR, "Can't set parity on device"},
+ {ERR_DEVICEREADERROR, "Error during reading device."},
+ {ERR_DEVICEPARITYERROR, "Can't set parity on device."},
{ERR_TIMEOUT, "No response in specified timeout. Probably phone not connected."},
/* Some missed */
{ERR_UNKNOWNRESPONSE, "Unknown response from phone. See readme.txt, how to report it."},
/* Some missed */
{ERR_UNKNOWNCONNECTIONTYPESTRING,"Unknown connection type string. Check config file."},
{ERR_UNKNOWNMODELSTRING, "Unknown model type string. Check config file."},
{ERR_SOURCENOTAVAILABLE, "Some required functions not compiled for your OS. Please contact."},
{ERR_NOTSUPPORTED, "Function not supported by phone."},
{ERR_EMPTY, "Entry is empty"},
{ERR_SECURITYERROR, "Security error. Maybe no PIN ?"},
{ERR_INVALIDLOCATION, "Invalid location. Maybe too high ?"},
{ERR_NOTIMPLEMENTED, "Function not implemented. Help required."},
{ERR_FULL, "Memory full."},
{ERR_UNKNOWN, "Unknown error."},
/* Some missed */
{ERR_CANTOPENFILE, "Can't open specified file. Read only ?"},
{ERR_MOREMEMORY, "More memory required..."},
{ERR_PERMISSION, "Permission to file/device required..."},
- {ERR_EMPTYSMSC, "Empty SMSC number. Set in phone or use -smscnumber"},
+ {ERR_EMPTYSMSC, "Empty SMSC number. Set in phone or use -smscnumber."},
{ERR_INSIDEPHONEMENU, "You're inside phone menu (during editing ?). Leave it and try again."},
{ERR_WORKINPROGRESS, "Function is during writing. If want help, please contact with authors."},
- {ERR_PHONEOFF, "Phone is disabled and connected to charger"},
- {ERR_FILENOTSUPPORTED, "File format not supported by Gammu"},
+ {ERR_PHONEOFF, "Phone is disabled and connected to charger."},
+ {ERR_FILENOTSUPPORTED, "File format not supported by Gammu."},
{ERR_BUG, "Nobody is perfect, some bug appeared in protocol implementation. Please contact authors."},
- {ERR_CANCELED, "Transfer was canceled by phone (you pressed cancel on phone?)."},
+ {ERR_CANCELED, "Transfer was canceled by phone (you pressed cancel on phone?)"},
/* Some missed */
{ERR_OTHERCONNECTIONREQUIRED, "Current connection type doesn't support called function."},
- /* Some missed */
+ {ERR_WRONGCRC, "CRC error."},
{ERR_INVALIDDATETIME, "Invalid date or time specified."},
- {ERR_MEMORY, "Phone memory error, maybe it is read only"},
- {ERR_INVALIDDATA, "Invalid data"},
+ {ERR_MEMORY, "Phone memory error, maybe it is read only."},
+ {ERR_INVALIDDATA, "Invalid data."},
+ {ERR_FILEALREADYEXIST, "File with specified name already exist."},
{0, ""}
};
unsigned char *print_error(GSM_Error e, FILE *df, INI_Section *cfg)
{
unsigned char *def = NULL;
int i = 0;
while (PrintErrorEntries[i].ErrorNum != 0) {
if (PrintErrorEntries[i].ErrorNum == e) {
def = PrintErrorEntries[i].ErrorText;
break;
}
i++;
}
if (def == NULL) def = "Unknown error.";
if (df!=NULL && di.dl!=0) fprintf(df,"[ERROR %i: %s]\n",e,def);
return GetMsg(cfg,def);
}
const char *GetGammuLocalePath(void)
{
#ifdef LOCALE_PATH
static const char Buffer[] = LOCALE_PATH;
return Buffer;
#else
return NULL;
#endif
}
const char *GetGammuVersion(void)
{
static const char Buffer[] = VERSION;
return Buffer;
}
GSM_Error GSM_SetDebugFile(char *info, Debug_Info *privdi)
{
FILE *testfile;
/* If we should use global file descriptor, use it */
if (privdi->use_global) {
/* Aren't we the changing the global di? */
if (privdi != &di) {
if (privdi->df != di.df &&
privdi->dl!=0 &&
fileno(privdi->df) != 1 &&
fileno(privdi->df) != 2)
fclose(privdi->df);
privdi->df = di.df;
return ERR_NONE;
}
} else {
/* If we should not use global file descriptor, don't even try use it */
if (privdi->df == di.df) privdi->df = stdout;
}
if (info[0]!=0 && privdi->dl != 0) {
switch (privdi->dl) {
case DL_BINARY:
testfile = fopen(info,"wcb");
break;
case DL_TEXTERROR:
case DL_TEXTERRORDATE:
testfile = fopen(info,"ac");
if (!testfile) {
dbgprintf("Can't open debug file\n");
return ERR_CANTOPENFILE;
}
fseek(testfile, 0, SEEK_END);
if (ftell(testfile) > 5000000) {
fclose(testfile);
testfile = fopen(info,"wc");
}
break;
default:
testfile = fopen(info,"wc");
}
if (!testfile) {
dbgprintf("Can't open debug file\n");
return ERR_CANTOPENFILE;
} else {
if (privdi->df && privdi->df != stdout) {
fclose(privdi->df);
}
privdi->df = testfile;
}
}
return ERR_NONE;
}
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/gsmcomon.h b/gammu/emb/common/gsmcomon.h
index cd36708..e067955 100644
--- a/gammu/emb/common/gsmcomon.h
+++ b/gammu/emb/common/gsmcomon.h
@@ -1,92 +1,93 @@
/* (c) 2002-2004 by Marcin Wiacek & Michal Cihar */
#ifndef __gsm_comon_h
#define __gsm_comon_h
#include <stdio.h>
#ifndef WIN32
# include <unistd.h>
#endif
#include "config.h"
#include "misc/misc.h"
#include "misc/cfg.h"
#define MAX_MANUFACTURER_LENGTH 50
#define MAX_MODEL_LENGTH 50
#define MAX_VERSION_LENGTH 50
#define MAX_VERSION_DATE_LENGTH 50
#define MAX_IMEI_LENGTH 20
#define PHONE_MAXSMSINFOLDER 200
#define GSM_MAX_NUMBER_LENGTH 50
#define GSM_MAXCALENDARTODONOTES 300
/* GSM_Error is used to notify about errors */
typedef enum {
/* 1*/ ERR_NONE=1,
ERR_DEVICEOPENERROR, /* Error during opening device */
ERR_DEVICELOCKED, /* Device locked */
ERR_DEVICENOTEXIST,
ERR_DEVICEBUSY,
ERR_DEVICENOPERMISSION,
ERR_DEVICENODRIVER,
ERR_DEVICENOTWORK,
ERR_DEVICEDTRRTSERROR, /* Error during setting DTR/RTS in device */
/*10*/ ERR_DEVICECHANGESPEEDERROR, /* Error during changing speed in device */
ERR_DEVICEWRITEERROR, /* Error during writing device */
ERR_DEVICEREADERROR, /* Error during reading device */
ERR_DEVICEPARITYERROR, /* Can't set parity on device */
ERR_TIMEOUT, /* Command timed out */
ERR_FRAMENOTREQUESTED, /* Frame handled, but not requested in this moment */
ERR_UNKNOWNRESPONSE, /* Response not handled by gammu */
ERR_UNKNOWNFRAME, /* Frame not handled by gammu */
ERR_UNKNOWNCONNECTIONTYPESTRING,/* Unknown connection type given by user */
ERR_UNKNOWNMODELSTRING, /* Unknown model given by user */
/*20*/ ERR_SOURCENOTAVAILABLE, /* Some functions not compiled in your OS */
ERR_NOTSUPPORTED, /* Not supported by phone */
ERR_EMPTY, /* Empty phonebook entry, ... */
ERR_SECURITYERROR, /* Not allowed */
ERR_INVALIDLOCATION, /* Too high or too low location... */
ERR_NOTIMPLEMENTED, /* Function not implemented */
ERR_FULL, /* Memory is full */
ERR_UNKNOWN,
ERR_CANTOPENFILE, /* Error during opening file */
ERR_MOREMEMORY, /* More memory required */
/*30*/ ERR_PERMISSION, /* No permission */
ERR_EMPTYSMSC, /* SMSC number is empty */
ERR_INSIDEPHONEMENU, /* Inside phone menu - can't make something */
ERR_NOTCONNECTED, /* Phone NOT connected - can't make something */
ERR_WORKINPROGRESS, /* Work in progress */
ERR_PHONEOFF, /* Phone is disabled and connected to charger */
ERR_FILENOTSUPPORTED, /* File format not supported by Gammu */
ERR_BUG, /* Found bug in implementation or phone */
ERR_CANCELED, /* Action was canceled by user */
ERR_NEEDANOTHERANSWER, /* Inside Gammu: phone module need to send another answer frame */
/*40*/ ERR_OTHERCONNECTIONREQUIRED,
ERR_WRONGCRC,
ERR_INVALIDDATETIME, /* Invalid date/time */
ERR_MEMORY, /* Phone memory error, maybe it is read only */
- ERR_INVALIDDATA /* Invalid data */
+ ERR_INVALIDDATA, /* Invalid data */
+ ERR_FILEALREADYEXIST /* File with specified name already exist */
} GSM_Error;
extern GSM_Error NoneFunction (void);
extern GSM_Error NotImplementedFunction (void);
extern GSM_Error NotSupportedFunction (void);
#define NONEFUNCTION (void *) NoneFunction
#define NOTIMPLEMENTED (void *) NotImplementedFunction
#define NOTSUPPORTED (void *) NotSupportedFunction
unsigned char *GetMsg (INI_Section *cfg, unsigned char *default_string);
unsigned char *print_error (GSM_Error e, FILE *df, INI_Section *cfg);
GSM_Error GSM_SetDebugFile(char *info, Debug_Info *privdi);
const char *GetGammuLocalePath(void);
const char *GetGammuVersion(void);
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/gsmstate.c b/gammu/emb/common/gsmstate.c
index b8f5f89..31e365d 100644
--- a/gammu/emb/common/gsmstate.c
+++ b/gammu/emb/common/gsmstate.c
@@ -1,1198 +1,1230 @@
/* (c) 2002-2004 by Marcin Wiacek */
/* Phones ID (c) partially by Walek */
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include "gsmcomon.h"
#include "gsmstate.h"
#include "misc/cfg.h"
#include "misc/coding/coding.h"
#include "device/devfunc.h"
static void GSM_RegisterConnection(GSM_StateMachine *s, unsigned int connection,
GSM_Device_Functions *device, GSM_Protocol_Functions *protocol)
{
if ((unsigned int)s->ConnectionType == connection) {
s->Device.Functions = device;
s->Protocol.Functions = protocol;
}
}
static GSM_Error GSM_RegisterAllConnections(GSM_StateMachine *s, char *connection)
{
/* We check here is used connection string type is correct for ANY
* OS. If not, we return with error, that string is incorrect at all
*/
s->ConnectionType = 0;
if (mystrncasecmp("mbus" ,connection,0)) s->ConnectionType = GCT_MBUS2;
if (mystrncasecmp("fbus" ,connection,0)) s->ConnectionType = GCT_FBUS2;
if (mystrncasecmp("fbusdlr3" ,connection,0)) s->ConnectionType = GCT_FBUS2DLR3;
if (mystrncasecmp("fbusdku5" ,connection,0)) s->ConnectionType = GCT_FBUS2DKU5;
if (mystrncasecmp("fbuspl2303" ,connection,0)) s->ConnectionType = GCT_FBUS2PL2303;
if (mystrncasecmp("fbusblue" ,connection,0)) s->ConnectionType = GCT_FBUS2BLUE;
if (mystrncasecmp("fbusirda" ,connection,0)) s->ConnectionType = GCT_FBUS2IRDA;
if (mystrncasecmp("phonetblue" ,connection,0)) s->ConnectionType = GCT_PHONETBLUE;
if (mystrncasecmp("mrouterblue" ,connection,0)) s->ConnectionType = GCT_MROUTERBLUE;
if (mystrncasecmp("irdaphonet" ,connection,0)) s->ConnectionType = GCT_IRDAPHONET;
if (mystrncasecmp("irdaat" ,connection,0)) s->ConnectionType = GCT_IRDAAT;
if (mystrncasecmp("irdaobex" ,connection,0)) s->ConnectionType = GCT_IRDAOBEX;
if (mystrncasecmp("blueobex" ,connection,0)) s->ConnectionType = GCT_BLUEOBEX;
if (mystrncasecmp("bluefbus" ,connection,0)) s->ConnectionType = GCT_BLUEFBUS2;
if (mystrncasecmp("bluephonet" ,connection,0)) s->ConnectionType = GCT_BLUEPHONET;
if (mystrncasecmp("blueat" ,connection,0)) s->ConnectionType = GCT_BLUEAT;
if (mystrncasecmp("bluerfobex" ,connection,0)) s->ConnectionType = GCT_BLUEOBEX;
if (mystrncasecmp("bluerffbus" ,connection,0)) s->ConnectionType = GCT_BLUEFBUS2;
if (mystrncasecmp("bluerfphonet",connection,0)) s->ConnectionType = GCT_BLUEPHONET;
if (mystrncasecmp("bluerfat" ,connection,0)) s->ConnectionType = GCT_BLUEAT;
/* These are for compatibility only */
if (mystrncasecmp("atblue" ,connection,0)) s->ConnectionType = GCT_BLUEAT;
if (mystrncasecmp("dlr3blue" ,connection,0)) s->ConnectionType = GCT_BLUEFBUS2;
if (mystrncasecmp("irda" ,connection,0)) s->ConnectionType = GCT_IRDAPHONET;
if (mystrncasecmp("dlr3" ,connection,0)) s->ConnectionType = GCT_FBUS2DLR3;
if (mystrncasecmp("infrared" ,connection,0)) s->ConnectionType = GCT_FBUS2IRDA;
if (mystrncasecmp("at" ,connection,2)) {
/* Use some resonable default, when no speed defined */
if (strlen(connection) == 2) {
s->Speed = 19200;
} else {
s->Speed = FindSerialSpeed(connection+2);
}
if (s->Speed != 0) s->ConnectionType = GCT_AT;
}
if (s->ConnectionType==0) return ERR_UNKNOWNCONNECTIONTYPESTRING;
/* We check now if user gave connection type compiled & available
* for used OS (if not, we return, that source not available)
*/
s->Device.Functions = NULL;
s->Protocol.Functions = NULL;
#ifdef GSM_ENABLE_MBUS2
GSM_RegisterConnection(s, GCT_MBUS2, &SerialDevice, &MBUS2Protocol);
#endif
#ifdef GSM_ENABLE_FBUS2
GSM_RegisterConnection(s, GCT_FBUS2, &SerialDevice, &FBUS2Protocol);
#endif
#ifdef GSM_ENABLE_FBUS2DLR3
GSM_RegisterConnection(s, GCT_FBUS2DLR3, &SerialDevice, &FBUS2Protocol);
#endif
#ifdef GSM_ENABLE_FBUS2DKU5
GSM_RegisterConnection(s, GCT_FBUS2DKU5, &SerialDevice, &FBUS2Protocol);
#endif
#ifdef GSM_ENABLE_FBUS2PL2303
GSM_RegisterConnection(s, GCT_FBUS2PL2303,&SerialDevice, &FBUS2Protocol);
#endif
#ifdef GSM_ENABLE_FBUS2BLUE
GSM_RegisterConnection(s, GCT_FBUS2BLUE, &SerialDevice, &FBUS2Protocol);
#endif
#ifdef GSM_ENABLE_FBUS2IRDA
GSM_RegisterConnection(s, GCT_FBUS2IRDA, &SerialDevice, &FBUS2Protocol);
#endif
#ifdef GSM_ENABLE_PHONETBLUE
GSM_RegisterConnection(s, GCT_PHONETBLUE,&SerialDevice, &PHONETProtocol);
#endif
#ifdef GSM_ENABLE_MROUTERBLUE
GSM_RegisterConnection(s, GCT_MROUTERBLUE,&SerialDevice, &MROUTERProtocol);
#endif
#ifdef GSM_ENABLE_IRDAPHONET
GSM_RegisterConnection(s, GCT_IRDAPHONET,&IrdaDevice, &PHONETProtocol);
#endif
#ifdef GSM_ENABLE_BLUEFBUS2
GSM_RegisterConnection(s, GCT_BLUEFBUS2, &BlueToothDevice,&FBUS2Protocol);
#endif
#ifdef GSM_ENABLE_BLUEPHONET
GSM_RegisterConnection(s, GCT_BLUEPHONET,&BlueToothDevice,&PHONETProtocol);
#endif
#ifdef GSM_ENABLE_BLUEAT
GSM_RegisterConnection(s, GCT_BLUEAT, &BlueToothDevice,&ATProtocol);
#endif
#ifdef GSM_ENABLE_AT
GSM_RegisterConnection(s, GCT_AT, &SerialDevice, &ATProtocol);
#endif
#ifdef GSM_ENABLE_IRDAAT
GSM_RegisterConnection(s, GCT_IRDAAT, &IrdaDevice, &ATProtocol);
#endif
#ifdef GSM_ENABLE_IRDAOBEX
GSM_RegisterConnection(s, GCT_IRDAOBEX, &IrdaDevice, &OBEXProtocol);
#endif
#ifdef GSM_ENABLE_BLUEOBEX
GSM_RegisterConnection(s, GCT_BLUEOBEX, &BlueToothDevice,&OBEXProtocol);
#endif
if (s->Device.Functions==NULL || s->Protocol.Functions==NULL)
return ERR_SOURCENOTAVAILABLE;
return ERR_NONE;
}
static void GSM_RegisterModule(GSM_StateMachine *s,GSM_Phone_Functions *phone)
{
/* Auto model */
if (s->CurrentConfig->Model[0] == 0) {
if (strstr(phone->models,GetModelData(NULL,s->Phone.Data.Model,NULL)->model) != NULL) {
smprintf(s,"[Module - \"%s\"]\n",phone->models);
s->Phone.Functions = phone;
}
} else {
if (strstr(phone->models,s->CurrentConfig->Model) != NULL) {
smprintf(s,"[Module - \"%s\"]\n",phone->models);
s->Phone.Functions = phone;
}
}
}
GSM_Error GSM_RegisterAllPhoneModules(GSM_StateMachine *s)
{
OnePhoneModel *model;
/* Auto model */
if (s->CurrentConfig->Model[0] == 0) {
model = GetModelData(NULL,s->Phone.Data.Model,NULL);
#ifdef GSM_ENABLE_ALCATEL
if (model->model[0] != 0 && IsPhoneFeatureAvailable(model, F_ALCATEL)) {
smprintf(s,"[Module - \"%s\"]\n",ALCATELPhone.models);
s->Phone.Functions = &ALCATELPhone;
return ERR_NONE;
}
#endif
#ifdef GSM_ENABLE_ATGEN
/* With ATgen and auto model we can work with unknown models too */
if (s->ConnectionType==GCT_AT || s->ConnectionType==GCT_BLUEAT || s->ConnectionType==GCT_IRDAAT) {
smprintf(s,"[Module - \"%s\"]\n",ATGENPhone.models);
s->Phone.Functions = &ATGENPhone;
return ERR_NONE;
}
#endif
if (model->model[0] == 0) return ERR_UNKNOWNMODELSTRING;
}
s->Phone.Functions=NULL;
#ifdef GSM_ENABLE_ATGEN
/* AT module can have the same models ID to "normal" Nokia modules */
if (s->ConnectionType==GCT_AT || s->ConnectionType==GCT_BLUEAT || s->ConnectionType==GCT_IRDAAT) {
GSM_RegisterModule(s,&ATGENPhone);
if (s->Phone.Functions!=NULL) return ERR_NONE;
}
#endif
#ifdef GSM_ENABLE_OBEXGEN
GSM_RegisterModule(s,&OBEXGENPhone);
#endif
#ifdef GSM_ENABLE_MROUTERGEN
GSM_RegisterModule(s,&MROUTERGENPhone);
#endif
#ifdef GSM_ENABLE_NOKIA3320
GSM_RegisterModule(s,&N3320Phone);
#endif
#ifdef GSM_ENABLE_NOKIA3650
GSM_RegisterModule(s,&N3650Phone);
#endif
+#ifdef GSM_ENABLE_NOKIA650
+ GSM_RegisterModule(s,&N650Phone);
+#endif
#ifdef GSM_ENABLE_NOKIA6110
GSM_RegisterModule(s,&N6110Phone);
#endif
#ifdef GSM_ENABLE_NOKIA6510
GSM_RegisterModule(s,&N6510Phone);
#endif
#ifdef GSM_ENABLE_NOKIA7110
GSM_RegisterModule(s,&N7110Phone);
#endif
#ifdef GSM_ENABLE_NOKIA9210
GSM_RegisterModule(s,&N9210Phone);
#endif
#ifdef GSM_ENABLE_ALCATEL
GSM_RegisterModule(s,&ALCATELPhone);
#endif
if (s->Phone.Functions==NULL) return ERR_UNKNOWNMODELSTRING;
return ERR_NONE;
}
GSM_Error GSM_InitConnection(GSM_StateMachine *s, int ReplyNum)
{
GSM_Error error;
GSM_DateTime time;
int i;
- char Buffer[80];
for (i=0;i<s->ConfigNum;i++) {
s->CurrentConfig = &s->Config[i];
s->Speed = 0;
s->ReplyNum = ReplyNum;
s->Phone.Data.ModelInfo = GetModelData("unknown",NULL,NULL);
s->Phone.Data.Manufacturer[0] = 0;
s->Phone.Data.Model[0] = 0;
s->Phone.Data.Version[0] = 0;
s->Phone.Data.VerDate[0] = 0;
s->Phone.Data.VerNum = 0;
s->Phone.Data.StartInfoCounter = 0;
s->Phone.Data.SentMsg = NULL;
s->Phone.Data.HardwareCache[0] = 0;
s->Phone.Data.ProductCodeCache[0] = 0;
s->Phone.Data.EnableIncomingCall = false;
s->Phone.Data.EnableIncomingSMS = false;
s->Phone.Data.EnableIncomingCB = false;
s->Phone.Data.EnableIncomingUSSD = false;
s->User.UserReplyFunctions = NULL;
s->User.IncomingCall = NULL;
s->User.IncomingSMS = NULL;
s->User.IncomingCB = NULL;
s->User.IncomingUSSD = NULL;
s->User.SendSMSStatus = NULL;
s->LockFile = NULL;
s->opened = false;
s->Phone.Functions = NULL;
s->di = di;
s->di.use_global = s->CurrentConfig->UseGlobalDebugFile;
GSM_SetDebugLevel(s->CurrentConfig->DebugLevel, &s->di);
error=GSM_SetDebugFile(s->CurrentConfig->DebugFile, &s->di);
if (error != ERR_NONE) return error;
if (s->di.dl == DL_TEXTALL || s->di.dl == DL_TEXT || s->di.dl == DL_TEXTERROR ||
s->di.dl == DL_TEXTALLDATE || s->di.dl == DL_TEXTDATE || s->di.dl == DL_TEXTERRORDATE) {
- smprintf(s,"[Gammu - version %s built %s %s]\n",VERSION,__TIME__,__DATE__);
- smprintf(s,"[Connection - \"%s\"]\n",s->CurrentConfig->Connection);
+ smprintf(s,"[Gammu - %s built %s %s",VERSION,__TIME__,__DATE__);
+ if (strlen(GetCompiler()) != 0) {
+ smprintf(s," in %s",GetCompiler());
+ }
+ smprintf(s,"]\n[Connection - \"%s\"]\n",s->CurrentConfig->Connection);
smprintf(s,"[Model type - \"%s\"]\n",s->CurrentConfig->Model);
smprintf(s,"[Device - \"%s\"]\n",s->CurrentConfig->Device);
-
- Buffer[0] = 0;
- if (strlen(GetOS()) != 0) sprintf(Buffer,"%s",GetOS());
- if (strlen(GetCompiler()) != 0) {
- if (Buffer[0] != 0) strcat(Buffer+strlen(Buffer),", ");
- strcat(Buffer+strlen(Buffer),GetCompiler());
+ if (strlen(GetOS()) != 0) {
+ smprintf(s,"[Run on - %s]\n",GetOS());
}
- if (Buffer[0] != 0) smprintf(s,"[OS/compiler - %s]\n",Buffer);
}
if (s->di.dl==DL_BINARY) {
smprintf(s,"%c",((unsigned char)strlen(VERSION)));
smprintf(s,"%s",VERSION);
}
error=GSM_RegisterAllConnections(s, s->CurrentConfig->Connection);
if (error!=ERR_NONE) return error;
/* Model auto */
if (s->CurrentConfig->Model[0]==0) {
if (mystrncasecmp(s->CurrentConfig->LockDevice,"yes",0)) {
error = lock_device(s->CurrentConfig->Device, &(s->LockFile));
if (error != ERR_NONE) return error;
}
/* Irda devices can set now model to some specific and
* we don't have to make auto detection later */
error=s->Device.Functions->OpenDevice(s);
if (i != s->ConfigNum - 1) {
if (error == ERR_DEVICEOPENERROR) continue;
if (error == ERR_DEVICELOCKED) continue;
if (error == ERR_DEVICENOTEXIST) continue;
if (error == ERR_DEVICEBUSY) continue;
if (error == ERR_DEVICENOPERMISSION) continue;
if (error == ERR_DEVICENODRIVER) continue;
if (error == ERR_DEVICENOTWORK) continue;
}
if (error!=ERR_NONE) {
if (s->LockFile!=NULL) unlock_device(&(s->LockFile));
return error;
}
s->opened = true;
error=s->Protocol.Functions->Initialise(s);
if (error!=ERR_NONE) return error;
/* If still auto model, try to get model by asking phone for it */
if (s->Phone.Data.Model[0]==0) {
smprintf(s,"[Module - \"auto\"]\n");
switch (s->ConnectionType) {
#ifdef GSM_ENABLE_ATGEN
case GCT_AT:
case GCT_BLUEAT:
case GCT_IRDAAT:
s->Phone.Functions = &ATGENPhone;
break;
#endif
#ifdef GSM_ENABLE_OBEXGEN
case GCT_IRDAOBEX:
case GCT_BLUEOBEX:
s->Phone.Functions = &OBEXGENPhone;
break;
#endif
#ifdef GSM_ENABLE_MROUTERGEN
case GCT_MROUTERBLUE:
s->Phone.Functions = &MROUTERGENPhone;
break;
#endif
#if defined(GSM_ENABLE_NOKIA_DCT3) || defined(GSM_ENABLE_NOKIA_DCT4)
case GCT_MBUS2:
case GCT_FBUS2:
case GCT_FBUS2DLR3:
case GCT_FBUS2DKU5:
case GCT_FBUS2PL2303:
case GCT_FBUS2BLUE:
case GCT_FBUS2IRDA:
case GCT_PHONETBLUE:
case GCT_IRDAPHONET:
case GCT_BLUEFBUS2:
case GCT_BLUEPHONET:
s->Phone.Functions = &NAUTOPhone;
break;
#endif
default:
s->Phone.Functions = NULL;
}
if (s->Phone.Functions == NULL) return ERR_UNKNOWN;
/* Please note, that AT module need to send first
* command for enabling echo
*/
error=s->Phone.Functions->Initialise(s);
if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) continue;
if (error != ERR_NONE) return error;
error=s->Phone.Functions->GetModel(s);
if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) continue;
if (error != ERR_NONE) return error;
}
}
/* Switching to "correct" module */
error=GSM_RegisterAllPhoneModules(s);
if (error!=ERR_NONE) return error;
/* We didn't open device earlier ? Make it now */
if (!s->opened) {
if (mystrncasecmp(s->CurrentConfig->LockDevice,"yes",0)) {
error = lock_device(s->CurrentConfig->Device, &(s->LockFile));
if (error != ERR_NONE) return error;
}
error=s->Device.Functions->OpenDevice(s);
if (i != s->ConfigNum - 1) {
if (error == ERR_DEVICEOPENERROR) continue;
if (error == ERR_DEVICELOCKED) continue;
if (error == ERR_DEVICENOTEXIST) continue;
if (error == ERR_DEVICEBUSY) continue;
if (error == ERR_DEVICENOPERMISSION) continue;
if (error == ERR_DEVICENODRIVER) continue;
if (error == ERR_DEVICENOTWORK) continue;
}
if (error!=ERR_NONE) {
if (s->LockFile!=NULL) unlock_device(&(s->LockFile));
return error;
}
s->opened = true;
error=s->Protocol.Functions->Initialise(s);
if (error!=ERR_NONE) return error;
}
error=s->Phone.Functions->Initialise(s);
if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) continue;
if (error != ERR_NONE) return error;
if (mystrncasecmp(s->CurrentConfig->StartInfo,"yes",0)) {
s->Phone.Functions->ShowStartInfo(s,true);
s->Phone.Data.StartInfoCounter = 30;
}
if (mystrncasecmp(s->CurrentConfig->SyncTime,"yes",0)) {
GSM_GetCurrentDateTime (&time);
s->Phone.Functions->SetDateTime(s,&time);
}
/* For debug it's good to have firmware and real model version and manufacturer */
error=s->Phone.Functions->GetManufacturer(s);
if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) continue;
if (error != ERR_NONE) return error;
error=s->Phone.Functions->GetModel(s);
if (error != ERR_NONE) return error;
error=s->Phone.Functions->GetFirmware(s);
if (error != ERR_NONE) return error;
return ERR_NONE;
}
return ERR_UNKNOWN;
}
int GSM_ReadDevice (GSM_StateMachine *s, bool wait)
{
unsigned char buff[255];
int res = 0, count;
unsigned int i;
GSM_DateTime Date;
GSM_GetCurrentDateTime (&Date);
i=Date.Second;
while (i==Date.Second) {
res = s->Device.Functions->ReadDevice(s, buff, 255);
if (!wait) break;
if (res > 0) break;
my_sleep(5);
GSM_GetCurrentDateTime(&Date);
}
for (count = 0; count < res; count++)
s->Protocol.Functions->StateMachine(s,buff[count]);
return res;
}
GSM_Error GSM_TerminateConnection(GSM_StateMachine *s)
{
GSM_Error error;
if (!s->opened) return ERR_UNKNOWN;
smprintf(s,"[Closing]\n");
if (mystrncasecmp(s->CurrentConfig->StartInfo,"yes",0)) {
if (s->Phone.Data.StartInfoCounter > 0) s->Phone.Functions->ShowStartInfo(s,false);
}
if (s->Phone.Functions != NULL) {
error=s->Phone.Functions->Terminate(s);
if (error!=ERR_NONE) return error;
}
error=s->Protocol.Functions->Terminate(s);
if (error!=ERR_NONE) return error;
error = s->Device.Functions->CloseDevice(s);
if (error!=ERR_NONE) return error;
s->Phone.Data.ModelInfo = NULL;
s->Phone.Data.Manufacturer[0] = 0;
s->Phone.Data.Model[0] = 0;
s->Phone.Data.Version[0] = 0;
s->Phone.Data.VerDate[0] = 0;
s->Phone.Data.VerNum = 0;
if (s->LockFile!=NULL) unlock_device(&(s->LockFile));
if (!s->di.use_global && s->di.dl!=0 && fileno(s->di.df) != 1 && fileno(s->di.df) != 2) fclose(s->di.df);
s->opened = false;
return ERR_NONE;
}
GSM_Error GSM_WaitForOnce(GSM_StateMachine *s, unsigned char *buffer,
int length, unsigned char type, int time)
{
GSM_Phone_Data *Phone = &s->Phone.Data;
GSM_Protocol_Message sentmsg;
int i;
i=0;
do {
if (length != 0) {
sentmsg.Length = length;
sentmsg.Type = type;
sentmsg.Buffer = (unsigned char *)malloc(length);
memcpy(sentmsg.Buffer,buffer,length);
Phone->SentMsg = &sentmsg;
}
/* Some data received. Reset timer */
if (GSM_ReadDevice(s,true)!=0) i=0;
if (length != 0) {
free (sentmsg.Buffer);
Phone->SentMsg = NULL;
}
/* Request completed */
if (Phone->RequestID==ID_None) return Phone->DispatchError;
i++;
} while (i<time);
return ERR_TIMEOUT;
}
GSM_Error GSM_WaitFor (GSM_StateMachine *s, unsigned char *buffer,
int length, unsigned char type, int time,
GSM_Phone_RequestID request)
{
GSM_Phone_Data *Phone = &s->Phone.Data;
GSM_Error error;
int reply;
if (mystrncasecmp(s->CurrentConfig->StartInfo,"yes",0)) {
if (Phone->StartInfoCounter > 0) {
Phone->StartInfoCounter--;
if (Phone->StartInfoCounter == 0) s->Phone.Functions->ShowStartInfo(s,false);
}
}
Phone->RequestID = request;
Phone->DispatchError = ERR_TIMEOUT;
for (reply=0;reply<s->ReplyNum;reply++) {
if (reply!=0) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl == DL_TEXTERROR ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl == DL_TEXTERRORDATE)
{
smprintf(s, "[Retrying %i type 0x%02X]\n", reply, type);
}
}
error = s->Protocol.Functions->WriteMessage(s, buffer, length, type);
if (error!=ERR_NONE) return error;
error = GSM_WaitForOnce(s, buffer, length, type, time);
if (error != ERR_TIMEOUT) return error;
}
return Phone->DispatchError;
}
static GSM_Error CheckReplyFunctions(GSM_StateMachine *s, GSM_Reply_Function *Reply, int *reply)
{
GSM_Phone_Data *Data = &s->Phone.Data;
GSM_Protocol_Message *msg = s->Phone.Data.RequestMsg;
bool execute;
bool available = false;
int i = 0;
+// int j;
while (Reply[i].requestID!=ID_None) {
execute=false;
/* Binary frames like in Nokia */
if (strlen(Reply[i].msgtype) < 2) {
if (Reply[i].msgtype[0]==msg->Type) {
if (Reply[i].subtypechar!=0) {
if (Reply[i].subtypechar<=msg->Length) {
if (msg->Buffer[Reply[i].subtypechar]==Reply[i].subtype)
execute=true;
}
} else execute=true;
}
} else {
- if (strncmp(Reply[i].msgtype,msg->Buffer,strlen(Reply[i].msgtype))==0) {
- execute=true;
+// printf("msg length %i %i\n",strlen(Reply[i].msgtype),msg->Length);
+ if ((int)strlen(Reply[i].msgtype)<msg->Length) {
+// printf("Comparing \"%s\" and \"",Reply[i].msgtype);
+// for (j=0;j<strlen(Reply[i].msgtype);j++) {
+// if (msg->Buffer[j]!=13 && msg->Buffer[j]!=10) {
+// printf("%c",msg->Buffer[j]);
+// }
+// }
+// printf("\"\n");
+ if (strncmp(Reply[i].msgtype,msg->Buffer,strlen(Reply[i].msgtype))==0) {
+ execute=true;
+ }
}
}
if (execute) {
*reply=i;
if (Reply[i].requestID == ID_IncomingFrame ||
Reply[i].requestID == Data->RequestID ||
Data->RequestID == ID_EachFrame) {
return ERR_NONE;
}
available=true;
}
i++;
}
if (available) {
return ERR_FRAMENOTREQUESTED;
} else {
return ERR_UNKNOWNFRAME;
}
}
GSM_Error GSM_DispatchMessage(GSM_StateMachine *s)
{
GSM_Error error = ERR_UNKNOWNFRAME;
GSM_Protocol_Message *msg = s->Phone.Data.RequestMsg;
GSM_Phone_Data *Phone = &s->Phone.Data;
bool disp = false;
GSM_Reply_Function *Reply;
int reply, i;
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
smprintf(s, "RECEIVED frame ");
smprintf(s, "type 0x%02X/length 0x%02X/%i", msg->Type, msg->Length, msg->Length);
DumpMessage(s->di.use_global ? di.df : s->di.df, s->di.dl, msg->Buffer, msg->Length);
if (msg->Length == 0) smprintf(s, "\n");
fflush(s->di.df);
}
if (s->di.dl==DL_BINARY) {
smprintf(s,"%c",0x02); /* Receiving */
smprintf(s,"%c",msg->Type);
smprintf(s,"%c",msg->Length/256);
smprintf(s,"%c",msg->Length%256);
for (i=0;i<msg->Length;i++) {
smprintf(s,"%c",msg->Buffer[i]);
}
}
Reply=s->User.UserReplyFunctions;
if (Reply!=NULL) error=CheckReplyFunctions(s,Reply,&reply);
if (error==ERR_UNKNOWNFRAME) {
Reply=s->Phone.Functions->ReplyFunctions;
error=CheckReplyFunctions(s,Reply,&reply);
}
if (error==ERR_NONE) {
error=Reply[reply].Function(*msg, s);
if (Reply[reply].requestID==Phone->RequestID) {
if (error == ERR_NEEDANOTHERANSWER) {
error = ERR_NONE;
} else {
Phone->RequestID=ID_None;
}
}
}
if (strcmp(s->Phone.Functions->models,"NAUTO")) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
disp = true;
switch (error) {
case ERR_UNKNOWNRESPONSE:
smprintf(s, "\nUNKNOWN response");
break;
case ERR_UNKNOWNFRAME:
smprintf(s, "\nUNKNOWN frame");
break;
case ERR_FRAMENOTREQUESTED:
smprintf(s, "\nFrame not request now");
break;
default:
disp = false;
}
}
if (error == ERR_UNKNOWNFRAME || error == ERR_FRAMENOTREQUESTED) {
error = ERR_TIMEOUT;
}
}
if (disp) {
smprintf(s,". If you can, PLEASE report it (see readme.txt). THANK YOU\n");
if (Phone->SentMsg != NULL) {
smprintf(s,"LAST SENT frame ");
smprintf(s, "type 0x%02X/length %i", Phone->SentMsg->Type, Phone->SentMsg->Length);
DumpMessage(s->di.use_global ? di.df : s->di.df, s->di.dl, Phone->SentMsg->Buffer, Phone->SentMsg->Length);
}
smprintf(s, "RECEIVED frame ");
smprintf(s, "type 0x%02X/length 0x%02X/%i", msg->Type, msg->Length, msg->Length);
DumpMessage(s->di.use_global ? di.df : s->di.df, s->di.dl, msg->Buffer, msg->Length);
smprintf(s, "\n");
}
return error;
}
INI_Section *GSM_FindGammuRC(void)
{
INI_Section *ini_file;
char *HomeDrive,*HomePath,*FileName=malloc(1);
int FileNameUsed=1;
FileName[0] = 0;
#if defined(WIN32) || defined(DJGPP)
HomeDrive = getenv("HOMEDRIVE");
if (HomeDrive) {
FileName = realloc(FileName,FileNameUsed+strlen(HomeDrive)+1);
FileName = strcat(FileName, HomeDrive);
FileNameUsed += strlen(HomeDrive)+1;
}
HomePath = getenv("HOMEPATH");
if (HomePath) {
FileName = realloc(FileName,FileNameUsed+strlen(HomePath)+1);
FileName = strcat(FileName, HomePath);
FileNameUsed += strlen(HomePath)+1;
}
FileName = realloc(FileName,FileNameUsed+8+1);
strcat(FileName, "\\gammurc");
#else
HomeDrive = NULL;
HomePath = getenv("HOME");
if (HomePath) {
FileName = realloc(FileName,FileNameUsed+strlen(HomePath)+1);
FileName = strcat(FileName, HomePath);
FileNameUsed += strlen(HomePath)+1;
}
FileName = realloc(FileName,FileNameUsed+9+1);
strcat(FileName, "/.gammurc");
#endif
// dbgprintf("\"%s\"\n",FileName);
ini_file = INI_ReadFile(FileName, false);
free(FileName);
if (ini_file == NULL) {
#if defined(WIN32) || defined(DJGPP)
ini_file = INI_ReadFile("gammurc", false);
if (ini_file == NULL) return NULL;
#else
ini_file = INI_ReadFile("/etc/gammurc", false);
if (ini_file == NULL) return NULL;
#endif
}
return ini_file;
}
bool GSM_ReadConfig(INI_Section *cfg_info, GSM_Config *cfg, int num)
{
INI_Section *h;
unsigned char section[50];
bool found = false;
#if defined(WIN32) || defined(DJGPP)
char *DefaultPort = "com2:";
#else
char *DefaultPort = "/dev/ttyS1";
#endif
char *DefaultModel = "";
char *DefaultConnection = "fbus";
char *DefaultSynchronizeTime = "no";
char *DefaultDebugFile = "";
char *DefaultDebugLevel = "";
char *DefaultLockDevice = "no";
char *DefaultStartInfo = "no";
char *Temp;
/* By default all debug output will go to one filedescriptor */
bool DefaultUseGlobalDebugFile = true;
cfg->Device = DefaultPort;
cfg->Connection = DefaultConnection;
cfg->SyncTime = DefaultSynchronizeTime;
cfg->DebugFile = DefaultDebugFile;
strcpy(cfg->Model,DefaultModel);
strcpy(cfg->DebugLevel,DefaultDebugLevel);
cfg->LockDevice = DefaultLockDevice;
cfg->StartInfo = DefaultStartInfo;
cfg->DefaultDevice = true;
cfg->DefaultModel = true;
cfg->DefaultConnection = true;
cfg->DefaultSyncTime = true;
cfg->DefaultDebugFile = true;
cfg->DefaultDebugLevel = true;
cfg->DefaultLockDevice = true;
cfg->DefaultStartInfo = true;
cfg->UseGlobalDebugFile = DefaultUseGlobalDebugFile;
if (cfg_info==NULL) return false;
if (num == 0) {
sprintf(section,"gammu");
} else {
sprintf(section,"gammu%i",num);
}
for (h = cfg_info; h != NULL; h = h->Next) {
if (mystrncasecmp(section, h->SectionName, strlen(section))) {
found = true;
break;
}
}
if (!found) return false;
cfg->Device = INI_GetValue(cfg_info, section, "port", false);
if (!cfg->Device) {
free(cfg->Device);
cfg->Device = strdup(DefaultPort);
} else {
cfg->DefaultDevice = false;
}
cfg->Connection = INI_GetValue(cfg_info, section, "connection", false);
if (!cfg->Connection) {
free(cfg->Connection);
cfg->Connection = strdup(DefaultConnection);
} else {
cfg->DefaultConnection = false;
}
cfg->SyncTime = INI_GetValue(cfg_info, section, "synchronizetime", false);
if (!cfg->SyncTime) {
free(cfg->SyncTime);
cfg->SyncTime = strdup(DefaultSynchronizeTime);
} else {
cfg->DefaultSyncTime = false;
}
cfg->DebugFile = INI_GetValue(cfg_info, section, "logfile", false);
if (!cfg->DebugFile) {
free(cfg->DebugFile);
cfg->DebugFile = strdup(DefaultDebugFile);
} else {
cfg->DefaultDebugFile = false;
}
cfg->LockDevice = INI_GetValue(cfg_info, section, "use_locking", false);
if (!cfg->LockDevice) {
free(cfg->LockDevice);
cfg->LockDevice = strdup(DefaultLockDevice);
} else {
cfg->DefaultLockDevice = false;
}
Temp = INI_GetValue(cfg_info, section, "model", false);
if (!Temp) {
strcpy(cfg->Model,DefaultModel);
} else {
cfg->DefaultModel = false;
strcpy(cfg->Model,Temp);
}
Temp = INI_GetValue(cfg_info, section, "logformat", false);
if (!Temp) {
strcpy(cfg->DebugLevel,DefaultDebugLevel);
} else {
cfg->DefaultDebugLevel = false;
strcpy(cfg->DebugLevel,Temp);
}
cfg->StartInfo = INI_GetValue(cfg_info, section, "startinfo", false);
if (!cfg->StartInfo) {
free(cfg->StartInfo);
cfg->StartInfo = strdup(DefaultStartInfo);
} else {
cfg->DefaultStartInfo = false;
}
return true;
}
static OnePhoneModel allmodels[] = {
+#ifdef GSM_ENABLE_NOKIA650
+ {"0650" ,"THF-12","", {0}},
+#endif
#ifdef GSM_ENABLE_NOKIA6510
- {"1100", "RH-18" ,"", {0}},
+ {"1100" ,"RH-18" ,"", {0}},
{"1100a","RH-38" ,"", {0}},
{"1100b","RH-36" ,"", {0}},
#endif
#ifdef GSM_ENABLE_NOKIA6110
{"2100" ,"NAM-2" ,"", {F_NOWAP,F_NOCALLER,F_RING_SM,F_CAL33,F_POWER_BATT,F_PROFILES33,F_NOCALLINFO,F_NODTMF,0}},//quess
#endif
#ifdef GSM_ENABLE_NOKIA6510
- {"3100" ,"RH-19" ,"", {F_PBKTONEGAL,F_PBKSMSLIST,0}},
- {"3100b","RH-50" ,"", {F_PBKTONEGAL,F_PBKSMSLIST,0}},
+ {"3100" ,"RH-19" ,"", {F_PBKTONEGAL,F_PBKSMSLIST,0}},//fixme
+ {"3100b","RH-50" ,"", {F_PBKTONEGAL,F_PBKSMSLIST,0}},//fixme
{"3108", "RH-6", "Nokia 3108", {0}}, //does it have irda ?
- {"3200", "RH-30" ,"Nokia 3200", {F_PBKTONEGAL,0}},
- {"3200a","RH-31" ,"Nokia 3200", {F_PBKTONEGAL,0}},
+ {"3200", "RH-30" ,"Nokia 3200", {F_PBKTONEGAL,0}},//fixme
+ {"3200a","RH-31" ,"Nokia 3200", {F_PBKTONEGAL,0}},//fixme
#endif
#ifdef GSM_ENABLE_NOKIA6110
{"3210" ,"NSE-8" ,"", {F_NOWAP,F_NOCALLER,F_NOCALENDAR,F_NOPBKUNICODE,F_POWER_BATT,F_PROFILES51,F_NOPICTUREUNI,F_NOCALLINFO,F_NODTMF,0}},
{"3210" ,"NSE-9" ,"", {F_NOWAP,F_NOCALLER,F_NOCALENDAR,F_NOPBKUNICODE,F_POWER_BATT,F_PROFILES51,F_NOPICTUREUNI,F_NOCALLINFO,F_NODTMF,0}},
#endif
#ifdef GSM_ENABLE_NOKIA6510
- {"3300" ,"NEM-1" ,"Nokia 3300", {F_PBKTONEGAL,0}},
- {"3300" ,"NEM-2" ,"Nokia 3300", {F_PBKTONEGAL,0}},
+ {"3300" ,"NEM-1" ,"Nokia 3300", {F_PBKTONEGAL,0}},//fixme
+ {"3300" ,"NEM-2" ,"Nokia 3300", {F_PBKTONEGAL,0}},//fixme
#endif
#ifdef GSM_ENABLE_NOKIA6110
{"3310" ,"NHM-5" ,"", {F_NOWAP,F_NOCALLER,F_RING_SM,F_CAL33,F_POWER_BATT,F_PROFILES33,F_NOCALLINFO,F_NODTMF,0}},
#endif
#ifdef GSM_ENABLE_NOKIA3320
{"3320" ,"NPC-1" ,"Nokia 3320", {F_CAL62,F_DAYMONTH,0}},//fixme
#endif
#ifdef GSM_ENABLE_NOKIA6110
{"3330" ,"NHM-6" ,"", {F_NOCALLER,F_RING_SM,F_CAL33,F_PROFILES33,F_NOPICTUREUNI,F_NOCALLINFO,F_NODTMF,0}},
{"3390" ,"NPB-1" ,"", {F_NOWAP,F_NOCALLER,F_RING_SM,F_CAL33,F_PROFILES33,F_NOPICTUREUNI,F_NOCALLINFO,F_NODTMF,0}},
{"3410" ,"NHM-2" ,"", {F_RING_SM,F_CAL33,F_PROFILES33,F_NOCALLINFO,F_NODTMF,0}},
#endif
#ifdef GSM_ENABLE_NOKIA6510
{"3510" ,"NHM-8" ,"", {F_CAL35,F_PBK35,F_NOGPRSPOINT,F_VOICETAGS,0}},
{"3510i","RH-9" ,"", {F_CAL35,F_PBK35,F_NOGPRSPOINT,F_VOICETAGS,0}},
{"3530" ,"RH-9" ,"", {F_CAL35,F_PBK35,F_NOGPRSPOINT,F_VOICETAGS,0}},
{"3589i","RH-44" ,"", {F_VOICETAGS,0}},
{"3590" ,"NPM-8" ,"", {0}},//irda?
{"3595" ,"NPM-10" ,"", {0}},//irda?
#endif
#ifdef GSM_ENABLE_NOKIA6110
{"3610" ,"NAM-1" ,"", {F_NOCALLER,F_RING_SM,F_CAL33,F_POWER_BATT,F_PROFILES33,F_NOCALLINFO,F_NODTMF,0}},//quess
#endif
#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA3650)
{"3650" ,"NHL-8" ,"Nokia 3650", {0}},
{"NGAGE","NEM-4" ,"", {F_RADIO,0}},
#endif
#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6510)
{"5100" ,"NPM-6" ,"Nokia 5100", {F_PBKTONEGAL,F_TODO66,F_RADIO,0}},
{"5100" ,"NPM-6U","Nokia 5100", {F_PBKTONEGAL,F_TODO66,F_RADIO,0}},
{"5100" ,"NPM-6X","Nokia 5100", {F_PBKTONEGAL,F_TODO66,F_RADIO,0}},
+ {"5140" ,"NPL-4" ,"Nokia 5140", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKUSER,F_WAPMMSPROXY,0}},
+ {"5140" ,"NPL-5" ,"Nokia 5140", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKUSER,F_WAPMMSPROXY,0}},
#endif
#ifdef GSM_ENABLE_NOKIA6110
{"5110" ,"NSE-1" ,"", {F_NOWAP,F_NOCALLER,F_NORING,F_NOPICTURE,F_NOSTARTUP,F_NOCALENDAR,F_NOPBKUNICODE,F_PROFILES51,F_MAGICBYTES,F_DISPSTATUS,0}},
{"5110i","NSE-2" ,"", {F_NOWAP,F_NOCALLER,F_NORING,F_NOPICTURE,F_NOSTARTUP,F_NOCALENDAR,F_NOPBKUNICODE,F_PROFILES51,F_MAGICBYTES,F_DISPSTATUS,0}},
{"5130" ,"NSK-1" ,"", {F_NOWAP,F_NOCALLER,F_NORING,F_NOPICTURE,F_NOSTARTUP,F_NOCALENDAR,F_NOPBKUNICODE,F_PROFILES51,F_MAGICBYTES,F_DISPSTATUS,0}},
{"5190" ,"NSB-1" ,"", {F_NOWAP,F_NOCALLER,F_NORING,F_NOPICTURE,F_NOSTARTUP,F_NOCALENDAR,F_NOPBKUNICODE,F_PROFILES51,F_MAGICBYTES,F_DISPSTATUS,0}},
#endif
#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6110)
{"5210" ,"NSM-5" ,"Nokia 5210", {F_CAL52,F_NOSTARTANI,F_NOPICTUREUNI,F_NODTMF,0}},
#endif
#ifdef GSM_ENABLE_NOKIA6110
{"5510" ,"NPM-5" ,"", {F_NOCALLER,F_PROFILES33,F_NOPICTUREUNI,0}},
#endif
#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6510)
{"6100" ,"NPL-2" ,"Nokia 6100", {F_PBKTONEGAL,F_TODO66,0}},
#endif
#ifdef GSM_ENABLE_NOKIA6110
{"6110" ,"NSE-3" ,"", {F_NOWAP,F_NOPICTURE,F_NOSTARTANI,F_NOPBKUNICODE,F_MAGICBYTES,F_DISPSTATUS,0}},
{"6130" ,"NSK-3" ,"", {F_NOWAP,F_NOPICTURE,F_NOSTARTANI,F_NOPBKUNICODE,F_MAGICBYTES,F_DISPSTATUS,0}},
{"6150" ,"NSM-1" ,"", {F_NOWAP,F_NOSTARTANI,F_NOPBKUNICODE,F_MAGICBYTES,F_DISPSTATUS,F_NOPICTUREUNI,0}},
{"6190" ,"NSB-3" ,"", {F_NOWAP,F_NOPICTURE,F_NOSTARTANI,F_NOPBKUNICODE,F_MAGICBYTES,F_DISPSTATUS,0}},
#endif
#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6510)
{"6200" ,"NPL-3" ,"Nokia 6200", {F_PBKTONEGAL,0}},
- {"6220" ,"RH-20" ,"Nokia 6220", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKSMSLIST,F_PBKUSER,F_WAPMMSPROXY,0}},
+ {"6220" ,"RH-20" ,"Nokia 6220", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKSMSLIST,F_PBKUSER,F_WAPMMSPROXY,F_NOTES,0}},
#endif
#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA7110)
{"6210" ,"NPE-3" ,"Nokia 6210", {F_VOICETAGS,F_CAL62,0}},
{"6250" ,"NHM-3" ,"Nokia 6250", {F_VOICETAGS,F_CAL62,0}},
#endif
#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6510)
- {"6230" ,"RH-12" ,"Nokia 6230", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKSMSLIST,F_PBKUSER,0}},
+ {"6230" ,"RH-12" ,"Nokia 6230", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKSMSLIST,F_PBKUSER,F_WAPMMSPROXY,F_NOTES,0}},
{"6310" ,"NPE-4" ,"Nokia 6310", {F_TODO63,F_CAL65,F_NOMIDI,F_NOMMS,F_VOICETAGS,0}},
{"6310i","NPL-1" ,"Nokia 6310i",{F_TODO63,F_CAL65,F_NOMIDI,F_BLUETOOTH,F_NOMMS,F_VOICETAGS,0}},
{"6385" ,"NHP-2AX","Nokia 6385",{F_TODO63,F_CAL65,F_NOMIDI,F_NOMMS,F_VOICETAGS,0}},
{"6510" ,"NPM-9" ,"Nokia 6510", {F_TODO63,F_CAL65,F_NOMIDI,F_RADIO,F_NOFILESYSTEM,F_NOMMS,F_VOICETAGS,0}},
{"6610" ,"NHL-4U","Nokia 6610", {F_PBKTONEGAL,F_TODO66,F_RADIO,0}},
+ {"6610i","RM-37" ,"Nokia 6610i",{F_PBKTONEGAL,F_TODO66,F_RADIO,0}},
{"6800" ,"NSB-9" ,"Nokia 6800", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKSMSLIST,0}},
{"6800" ,"NHL-6" ,"Nokia 6800", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKSMSLIST,0}},
+ {"6810" ,"RM-2" ,"Nokia 6810", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKSMSLIST,0}},//quess
+ {"6820" ,"NHL-9" ,"Nokia 6820", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKSMSLIST,0}},//quess
#endif
#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA7110)
{"7110" ,"NSE-5" ,"Nokia 7110", {F_CAL62,0}},
{"7190" ,"NSB-5" ,"Nokia 7190", {F_CAL62,0}},
#endif
#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6510)
+ {"7200" ,"RH-23" ,"Nokia 7200", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKSMSLIST,F_PBKUSER,0}},//quess
{"7210" ,"NHL-4" ,"Nokia 7210", {F_PBKTONEGAL,F_TODO66,F_RADIO,0}},
{"7250" ,"NHL-4J","Nokia 7250", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKIMG,0}},
{"7250i","NHL-4JX","Nokia 7250i",{F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKIMG,0}},
{"7600", "NMM-3", "Nokia 7600", {F_TODO66,0}},
#endif
#if defined(GSM_ENABLE_ATGEN)
{"7650" ,"NHL-2" ,"Nokia 7650", {0}},
#endif
#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6110)
{"8210" ,"NSM-3" ,"Nokia 8210", {F_NOWAP,F_NOSTARTANI,F_NOPBKUNICODE,F_NOPICTUREUNI,0}},
{"8250" ,"NSM-3D","Nokia 8250", {F_NOWAP,F_NOSTARTANI,F_CAL82,F_NOPICTUREUNI,0}},
{"8290" ,"NSB-7" ,"Nokia 8290", {F_NOWAP,F_NOSTARTANI,F_NOPBKUNICODE,F_NOPICTUREUNI,0}},
#endif
#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6510)
{"8310" ,"NHM-7" ,"Nokia 8310", {F_CAL62,F_NOMIDI,F_RADIO,F_NOFILESYSTEM,F_NOMMS,F_VOICETAGS,0}},
{"8390" ,"NSB-8" ,"Nokia 8390", {F_CAL62,F_NOMIDI,F_RADIO,F_NOFILESYSTEM,F_NOMMS,F_VOICETAGS,0}},
#endif
#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6110)
{"8850" ,"NSM-2" ,"Nokia 8850", {0}},
{"8855" ,"NSM-4" ,"Nokia 8855", {0}},
{"8890" ,"NSB-6" ,"Nokia 8890", {0}},
#endif
#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6510)
{"8910" ,"NHM-4" ,"Nokia 8910", {F_CAL62,F_NOMIDI,F_NOFILESYSTEM,F_NOMMS,0}},
{"8910i","NHM-4" ,"Nokia 8910i",{F_CAL62,F_NOMIDI,F_NOFILESYSTEM,F_NOMMS,0}},
#endif
#ifdef GSM_ENABLE_NOKIA9210
{"9210" ,"RAE-3" ,"", {0}},
{"9210i","RAE-5" ,"", {0}},
#endif
#ifdef GSM_ENABLE_ATGEN
{"at" , "at", "", {0}},
+ /* Siemens */
{"M20" , "M20", "", {F_M20SMS,F_SLOWWRITE,0}},
{"MC35" , "MC35", "", {0}},
+ {"TC35" , "TC35", "", {0}},
{"S25", "S25", "SIEMENS S25", {0}},
{"C35i" , "C35i", "", {0}},
{"S35i" , "S35i", "", {0}},
{"M35i" , "M35i", "", {0}},
{"S40" , "Siemens S40", "", {0}},
{"C45" , "C45", "", {0}},
{"S45" , "S45", "", {0}},
{"ME45" , "ME45", "", {0}},
{"SL45" , "SL45", "", {0}},
{"SL45i" , "SL45i", "", {0}},
{"M50" , "M50", "", {0}},
{"S45" , "6618" , "", {0}},
{"ME45" , "3618" , "", {0}},
{"S55" , "S55" , "", {0}},
+ /* Samsung */
+ {"S100" , "SGH-S100" , "", {0}},
+ {"S200" , "SGH-S200" , "", {0}},
+ {"S300" , "SGH-S300" , "", {0}},
+ {"S500" , "SGH-S500" , "", {0}},
+ {"V200" , "SGH-V200" , "", {0}},
+ {"T100" , "SGH-T100" , "", {0}},
+ {"E700" , "SGH-E700" , "", {0}},
+ /* Ericsson/Sony Ericsson */
{"T28s", "1101101-BVT28s","", {0}},
{"R320s" , "1101201-BV R320s","", {0}},
{"R380s", "7100101-BVR380s" ,"", {0}},
{"R520m", "1130101-BVR520m" ,"", {0}},
{"T39m", "1130102-BVT39m" ,"", {0}},
{"T65", "1101901-BVT65" , "", {0}},
{"T68", "1130201-BVT68" , "", {0}},
{"T68i", "1130202-BVT68" , "", {0}},
{"R600", "102001-BVR600" , "", {0}},
{"T200", "1130501-BVT200" ,"", {0}},
{"T300", "1130601-BVT300" ,"T300", {0}},
{"T310", "1130602-BVT310" ,"", {0}},
{"P800", "7130501-BVP800" ,"", {0}},
+ /* Other */
{"iPAQ" , "iPAQ" , "" , {0}},
{"A2D" , "A2D" , "" , {0}},
{"9210" , "RAE-3", "Nokia Communicator GSM900/1800",{0}},
{"myV-65", "myV-65 GPRS", "", {F_SMSME900,0}},
#endif
#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_ALCATEL)
{"BE5", "ONE TOUCH 500","", {F_ALCATEL,F_SMSONLYSENT,F_BROKENCPBS,0}},
{"BH4", "ONE TOUCH 535","ALCATEL OT535", {F_ALCATEL,F_SMSONLYSENT,0}},
{"BF5", "ONE TOUCH 715","ALCATEL OT715", {F_ALCATEL,F_SMSONLYSENT,F_BROKENCPBS,0}},
#endif
{"unknown", "" ,"", {0}}
};
OnePhoneModel *GetModelData(char *model, char *number, char *irdamodel)
{
int i = 0;
while (strcmp(allmodels[i].number,"") != 0) {
if (model !=NULL) {
if (strcmp (model, allmodels[i].model) == 0) {
return (&allmodels[i]);
}
}
if (number !=NULL) {
if (strcmp (number, allmodels[i].number) == 0) {
return (&allmodels[i]);
}
}
if (irdamodel !=NULL) {
if (strcmp (irdamodel, allmodels[i].irdamodel) == 0) {
return (&allmodels[i]);
}
}
i++;
}
return (&allmodels[i]);
}
bool IsPhoneFeatureAvailable(OnePhoneModel *model, Feature feature)
{
int i = 0;
bool retval = false;
while (model->features[i] != 0) {
if (model->features[i] == feature) {
retval = true;
break;
}
i++;
}
return retval;
}
void GSM_DumpMessageLevel2(GSM_StateMachine *s, unsigned char *message, int messagesize, int type)
{
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
smprintf(s,"SENDING frame ");
smprintf(s,"type 0x%02X/length 0x%02X/%i", type, messagesize, messagesize);
DumpMessage(s->di.use_global ? di.df : s->di.df, s->di.dl, message, messagesize);
if (messagesize == 0) smprintf(s,"\n");
if (s->di.df) fflush(s->di.df);
}
}
void GSM_DumpMessageLevel3(GSM_StateMachine *s, unsigned char *message, int messagesize, int type)
{
int i;
if (s->di.dl==DL_BINARY) {
smprintf(s,"%c",0x01); /* Sending */
smprintf(s,"%c",type);
smprintf(s,"%c",messagesize/256);
smprintf(s,"%c",messagesize%256);
for (i=0;i<messagesize;i++) smprintf(s,"%c",message[i]);
}
}
#ifdef __GNUC__
__attribute__((format(printf, 2, 3)))
#endif
int smprintf(GSM_StateMachine *s, const char *format, ...)
{
va_list argp;
int result=0;
unsigned char buffer[2000];
Debug_Level dl;
FILE *df;
va_start(argp, format);
if (s == NULL) {
dl = di.dl;
df = di.df;
} else {
dl = s->di.dl;
if (s->di.use_global) {
df = di.df;
} else {
df = s->di.df;
}
}
if (dl != 0) {
result = vsprintf(buffer, format, argp);
result = smfprintf(df, dl, "%s", buffer);
}
va_end(argp);
return result;
}
void GSM_OSErrorInfo(GSM_StateMachine *s, char *description)
{
#ifdef WIN32
int i;
unsigned char *lpMsgBuf;
/* We don't use errno in win32 - GetLastError gives better info */
if (GetLastError()!=-1) {
if (s->di.dl == DL_TEXTERROR || s->di.dl == DL_TEXT || s->di.dl == DL_TEXTALL ||
s->di.dl == DL_TEXTERRORDATE || s->di.dl == DL_TEXTDATE || s->di.dl == DL_TEXTALLDATE) {
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
for (i=0;i<(int)strlen(lpMsgBuf);i++) {
if (lpMsgBuf[i] == 13 || lpMsgBuf[i] == 10) {
lpMsgBuf[i] = ' ';
}
}
smprintf(s,"[System error - %s, %i, \"%s\"]\n",description,GetLastError(),(LPCTSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
}
}
return;
#endif
if (errno!=-1) {
if (s->di.dl == DL_TEXTERROR || s->di.dl == DL_TEXT || s->di.dl == DL_TEXTALL ||
s->di.dl == DL_TEXTERRORDATE || s->di.dl == DL_TEXTDATE || s->di.dl == DL_TEXTALLDATE) {
smprintf(s,"[System error - %s, %i, \"%s\"]\n",description,errno,strerror(errno));
}
}
}
#ifdef GSM_ENABLE_BACKUP
void GSM_GetPhoneFeaturesForBackup(GSM_StateMachine *s, GSM_Backup_Info *info)
{
GSM_Error error;
GSM_MemoryStatus MemStatus;
GSM_ToDoStatus ToDoStatus;
GSM_CalendarEntry Note;
GSM_WAPBookmark Bookmark;
GSM_MultiWAPSettings WAPSettings;
GSM_FMStation FMStation;
GSM_GPRSAccessPoint GPRSPoint;
// GSM_Profile Profile;
if (info->PhonePhonebook) {
MemStatus.MemoryType = MEM_ME;
error=s->Phone.Functions->GetMemoryStatus(s, &MemStatus);
if (error==ERR_NONE && MemStatus.MemoryUsed != 0) {
} else {
info->PhonePhonebook = false;
}
}
if (info->SIMPhonebook) {
MemStatus.MemoryType = MEM_SM;
error=s->Phone.Functions->GetMemoryStatus(s, &MemStatus);
if (error==ERR_NONE && MemStatus.MemoryUsed != 0) {
} else {
info->SIMPhonebook = false;
}
}
if (info->Calendar) {
error=s->Phone.Functions->GetNextCalendar(s,&Note,true);
if (error!=ERR_NONE) info->Calendar = false;
}
if (info->ToDo) {
error=s->Phone.Functions->GetToDoStatus(s,&ToDoStatus);
if (error == ERR_NONE && ToDoStatus.Used != 0) {
} else {
info->ToDo = false;
}
diff --git a/gammu/emb/common/gsmstate.h b/gammu/emb/common/gsmstate.h
index cb17623..2b4806c 100644
--- a/gammu/emb/common/gsmstate.h
+++ b/gammu/emb/common/gsmstate.h
@@ -1,1562 +1,1579 @@
/* (c) 2002-2004 by Marcin Wiacek & Michal Cihar */
#ifndef __gsm_state_h
#define __gsm_state_h
#include <time.h>
#include "config.h"
#include "misc/cfg.h"
+typedef struct _GSM_StateMachine GSM_StateMachine;
+typedef struct _GSM_User GSM_User;
+typedef struct _OnePhoneModel OnePhoneModel;
+typedef struct _GSM_Reply_Function GSM_Reply_Function;
+
#ifdef GSM_ENABLE_NOKIA3320
# include "phone/nokia/dct4/n3320.h"
#endif
#ifdef GSM_ENABLE_NOKIA3650
# include "phone/nokia/dct4/n3650.h"
#endif
+#ifdef GSM_ENABLE_NOKIA650
+# include "phone/nokia/dct3/n0650.h"
+#endif
#ifdef GSM_ENABLE_NOKIA6110
# include "phone/nokia/dct3/n6110.h"
#endif
#ifdef GSM_ENABLE_NOKIA6510
# include "phone/nokia/dct4/n6510.h"
#endif
#ifdef GSM_ENABLE_NOKIA7110
# include "phone/nokia/dct3/n7110.h"
#endif
#ifdef GSM_ENABLE_NOKIA9210
# include "phone/nokia/dct3/n9210.h"
#endif
#ifdef GSM_ENABLE_ATGEN
# include "phone/at/atgen.h"
#endif
#ifdef GSM_ENABLE_ALCATEL
# include "phone/alcatel/alcatel.h"
#endif
#ifdef GSM_ENABLE_OBEXGEN
# include "phone/obex/obexgen.h"
#endif
#ifdef GSM_ENABLE_MROUTERGEN
# include "phone/symbian/mroutgen.h"
#endif
#ifndef GSM_USED_MBUS2
# undef GSM_ENABLE_MBUS2
#endif
#ifndef GSM_USED_FBUS2
# undef GSM_ENABLE_FBUS2
#endif
#ifndef GSM_USED_FBUS2DLR3
# undef GSM_ENABLE_FBUS2DLR3
#endif
#ifndef GSM_USED_FBUS2DKU5
# undef GSM_ENABLE_FBUS2DKU5
#endif
#ifndef GSM_USED_FBUS2PL2303
# undef GSM_ENABLE_FBUS2PL2303
#endif
#ifndef GSM_USED_FBUS2BLUE
# undef GSM_ENABLE_FBUS2BLUE
#endif
#ifndef GSM_USED_FBUS2IRDA
# undef GSM_ENABLE_FBUS2IRDA
#endif
#ifndef GSM_USED_PHONETBLUE
# undef GSM_ENABLE_PHONETBLUE
#endif
#ifndef GSM_USED_AT
# undef GSM_ENABLE_AT
#endif
#ifndef GSM_USED_IRDAOBEX
# undef GSM_ENABLE_IRDAOBEX
#endif
#ifndef GSM_USED_BLUEOBEX
# undef GSM_ENABLE_BLUEOBEX
#endif
#ifndef GSM_USED_ALCABUS
# undef GSM_ENABLE_ALCABUS
#endif
#ifndef GSM_USED_IRDAPHONET
# undef GSM_ENABLE_IRDAPHONET
#endif
#ifndef GSM_USED_BLUEFBUS2
# undef GSM_ENABLE_BLUEFBUS2
#endif
#ifndef GSM_USED_BLUEPHONET
# undef GSM_ENABLE_BLUEPHONET
#endif
#ifndef GSM_USED_BLUEAT
# undef GSM_ENABLE_BLUEAT
#endif
#ifndef GSM_USED_IRDAAT
# undef GSM_ENABLE_IRDAAT
#endif
#ifndef GSM_USED_MROUTERBLUE
# undef GSM_ENABLE_MROUTERBLUE
#endif
-#if defined(GSM_ENABLE_NOKIA3320) || defined(GSM_ENABLE_NOKIA6110) || defined(GSM_ENABLE_NOKIA7110) || defined(GSM_ENABLE_NOKIA9210)
+#if defined(GSM_ENABLE_NOKIA3320) || defined(GSM_ENABLE_NOKIA650) || defined(GSM_ENABLE_NOKIA6110) || defined(GSM_ENABLE_NOKIA7110) || defined(GSM_ENABLE_NOKIA9210)
# define GSM_ENABLE_NOKIA_DCT3
#endif
#if defined(GSM_ENABLE_NOKIA3650) || defined(GSM_ENABLE_NOKIA6510)
# define GSM_ENABLE_NOKIA_DCT4
#endif
#include "protocol/protocol.h"
#if defined(GSM_ENABLE_FBUS2) || defined(GSM_ENABLE_FBUS2IRDA) || defined(GSM_ENABLE_FBUS2DLR3) || defined(GSM_ENABLE_FBUS2BLUE) || defined(GSM_ENABLE_BLUEFBUS2) || defined(GSM_ENABLE_FBUS2DKU5) || defined(GSM_ENABLE_FBUS2PL2303)
# include "protocol/nokia/fbus2.h"
#endif
#ifdef GSM_ENABLE_MBUS2
# include "protocol/nokia/mbus2.h"
#endif
#if defined(GSM_ENABLE_PHONETBLUE) || defined(GSM_ENABLE_IRDAPHONET) || defined(GSM_ENABLE_BLUEPHONET)
# include "protocol/nokia/phonet.h"
#endif
#if defined(GSM_ENABLE_AT) || defined(GSM_ENABLE_BLUEAT) || defined(GSM_ENABLE_IRDAAT)
# include "protocol/at/at.h"
#endif
#ifdef GSM_ENABLE_ALCABUS
# include "protocol/alcatel/alcabus.h"
#endif
#if defined(GSM_ENABLE_IRDAOBEX) || defined(GSM_ENABLE_BLUEOBEX)
# include "protocol/obex/obex.h"
#endif
#if defined(GSM_ENABLE_MROUTERBLUE)
# include "protocol/symbian/mrouter.h"
#endif
#define GSM_ENABLE_SERIALDEVICE
#ifndef GSM_USED_SERIALDEVICE
# undef GSM_ENABLE_SERIALDEVICE
#endif
#define GSM_ENABLE_IRDADEVICE
#ifndef GSM_USED_IRDADEVICE
# undef GSM_ENABLE_IRDADEVICE
#endif
#define GSM_ENABLE_BLUETOOTHDEVICE
#ifndef GSM_USED_BLUETOOTHDEVICE
# undef GSM_ENABLE_BLUETOOTHDEVICE
#endif
#ifdef DJGPP
# undef GSM_ENABLE_IRDADEVICE
# undef GSM_ENABLE_IRDAPHONET
# undef GSM_ENABLE_IRDAOBEX
# undef GSM_ENABLE_IRDAAT
# undef GSM_ENABLE_FBUS2IRDA
# undef GSM_ENABLE_BLUETOOTHDEVICE
# undef GSM_ENABLE_BLUEPHONET
# undef GSM_ENABLE_BLUEOBEX
# undef GSM_ENABLE_BLUEAT
# undef GSM_ENABLE_BLUEFBUS2
# undef GSM_ENABLE_PHONETBLUE
# undef GSM_ENABLE_FBUS2BLUE
# undef GSM_ENABLE_MROUTERBLUE
#endif
#ifndef WIN32
# ifdef ENABLE_LGPL
# undef GSM_ENABLE_IRDADEVICE
# undef GSM_ENABLE_IRDAPHONET
# undef GSM_ENABLE_IRDAOBEX
# undef GSM_ENABLE_IRDAAT
# undef GSM_ENABLE_FBUS2IRDA
# undef GSM_ENABLE_BLUETOOTHDEVICE
# undef GSM_ENABLE_BLUEPHONET
# undef GSM_ENABLE_BLUEOBEX
# undef GSM_ENABLE_BLUEAT
# undef GSM_ENABLE_BLUEFBUS2
# undef GSM_ENABLE_PHONETBLUE
# undef GSM_ENABLE_FBUS2BLUE
# undef GSM_ENABLE_MROUTERBLUE
# endif
#endif
#ifdef GSM_ENABLE_SERIALDEVICE
# include "device/serial/ser_w32.h"
# include "device/serial/ser_unx.h"
# include "device/serial/ser_djg.h"
#endif
#ifdef GSM_ENABLE_IRDADEVICE
# include "device/irda/irda.h"
#endif
#ifdef GSM_ENABLE_BLUETOOTHDEVICE
# include "device/bluetoth/bluetoth.h"
#endif
#include "service/gsmpbk.h"
#include "service/gsmnet.h"
#include "service/gsmring.h"
#include "service/gsmcal.h"
#include "service/gsmdata.h"
#include "service/gsmlogo.h"
#include "service/gsmmisc.h"
#include "service/gsmprof.h"
#include "service/gsmcall.h"
#include "service/sms/gsmsms.h"
#include "service/sms/gsmems.h"
#include "service/sms/gsmmulti.h"
#include "service/backup/gsmback.h"
-typedef struct _GSM_StateMachine GSM_StateMachine;
-typedef struct _GSM_User GSM_User;
-typedef struct _OnePhoneModel OnePhoneModel;
/* ------------------------- Device layer ---------------------------------- */
/**
* Device functions, each device has to provide these.
*/
typedef struct {
/**
* Opens device.
*/
GSM_Error (*OpenDevice) (GSM_StateMachine *s);
/**
* Closes device.
*/
GSM_Error (*CloseDevice) (GSM_StateMachine *s);
/**
* Sets parity for device.
*/
GSM_Error (*DeviceSetParity) (GSM_StateMachine *s, bool parity);
/**
* Sets dtr (data to read) and rts (ready to send) flags.
*/
GSM_Error (*DeviceSetDtrRts) (GSM_StateMachine *s, bool dtr, bool rts);
/**
* Sets device speed.
*/
GSM_Error (*DeviceSetSpeed) (GSM_StateMachine *s, int speed);
/**
* Attempts to read nbytes from device.
*/
int (*ReadDevice) (GSM_StateMachine *s, void *buf, size_t nbytes);
/**
* Attempts to read nbytes from device.
*/
int (*WriteDevice) (GSM_StateMachine *s, void *buf, size_t nbytes);
} GSM_Device_Functions;
#ifdef GSM_ENABLE_SERIALDEVICE
extern GSM_Device_Functions SerialDevice;
#endif
#ifdef GSM_ENABLE_IRDADEVICE
extern GSM_Device_Functions IrdaDevice;
#endif
#ifdef GSM_ENABLE_BLUETOOTHDEVICE
extern GSM_Device_Functions BlueToothDevice;
#endif
/**
* Structure containing device specific data and pointer to device functions -
* @ref GSM_Device_Functions. The data are in a union, so you can use only
* one device at one time.
*/
typedef struct {
union {
char fake;
#ifdef GSM_ENABLE_SERIALDEVICE
GSM_Device_SerialData Serial;
#endif
#ifdef GSM_ENABLE_IRDADEVICE
GSM_Device_IrdaData Irda;
#endif
#ifdef GSM_ENABLE_BLUETOOTHDEVICE
GSM_Device_BlueToothData BlueTooth;
#endif
} Data;
GSM_Device_Functions *Functions;
} GSM_Device;
/* ---------------------- Protocol layer ----------------------------------- */
/**
* Protocol functions, each protocol has to implement these.
*/
typedef struct {
/**
* Writes message to device.
*/
GSM_Error (*WriteMessage) (GSM_StateMachine *s, unsigned char *buffer,
int length, unsigned char type);
/**
* This one is called when character is received from device.
*/
GSM_Error (*StateMachine) (GSM_StateMachine *s, unsigned char rx_char);
/**
* Protocol initialisation.
*/
GSM_Error (*Initialise) (GSM_StateMachine *s);
/**
* Protocol termination.
*/
GSM_Error (*Terminate) (GSM_StateMachine *s);
} GSM_Protocol_Functions;
#ifdef GSM_ENABLE_MBUS2
extern GSM_Protocol_Functions MBUS2Protocol;
#endif
#if defined(GSM_ENABLE_FBUS2) || defined(GSM_ENABLE_FBUS2IRDA) || defined(GSM_ENABLE_FBUS2DLR3) || defined(GSM_ENABLE_FBUS2DKU5) || defined(GSM_ENABLE_FBUS2BLUE) || defined(GSM_ENABLE_BLUEFBUS2) || defined(GSM_ENABLE_FBUS2PL2303)
extern GSM_Protocol_Functions FBUS2Protocol;
#endif
#if defined(GSM_ENABLE_PHONETBLUE) || defined(GSM_ENABLE_IRDAPHONET) || defined(GSM_ENABLE_BLUEPHONET)
extern GSM_Protocol_Functions PHONETProtocol;
#endif
#if defined(GSM_ENABLE_AT) || defined(GSM_ENABLE_BLUEAT) || defined(GSM_ENABLE_IRDAAT)
extern GSM_Protocol_Functions ATProtocol;
#endif
#ifdef GSM_ENABLE_ALCABUS
extern GSM_Protocol_Functions ALCABUSProtocol;
#endif
#if defined(GSM_ENABLE_IRDAOBEX) || defined(GSM_ENABLE_BLUEOBEX)
extern GSM_Protocol_Functions OBEXProtocol;
#endif
#if defined(GSM_ENABLE_MROUTERBLUE)
extern GSM_Protocol_Functions MROUTERProtocol;
#endif
/**
* Structure containing protocol specific data and pointer to protocol
* functions - @ref GSM_Protocol_Functions. The data are in a structure, so
* you may use more protocols at once and switch between them.
*/
typedef struct {
struct {
char fake;
#ifdef GSM_ENABLE_MBUS2
GSM_Protocol_MBUS2Data MBUS2;
#endif
#if defined(GSM_ENABLE_FBUS2) || defined(GSM_ENABLE_FBUS2IRDA) || defined(GSM_ENABLE_FBUS2DLR3) || defined(GSM_ENABLE_FBUS2DKU5) || defined(GSM_ENABLE_FBUS2PL2303) || defined(GSM_ENABLE_FBUS2BLUE) || defined(GSM_ENABLE_BLUEFBUS2)
GSM_Protocol_FBUS2Data FBUS2;
#endif
#if defined(GSM_ENABLE_PHONETBLUE) || defined(GSM_ENABLE_IRDAPHONET) || defined(GSM_ENABLE_BLUEPHONET)
GSM_Protocol_PHONETData PHONET;
#endif
#if defined(GSM_ENABLE_AT) || defined(GSM_ENABLE_BLUEAT) || defined(GSM_ENABLE_IRDAAT)
GSM_Protocol_ATData AT;
#endif
#ifdef GSM_ENABLE_ALCABUS
GSM_Protocol_ALCABUSData ALCABUS;
#endif
#if defined(GSM_ENABLE_IRDAOBEX) || defined(GSM_ENABLE_BLUEOBEX)
GSM_Protocol_OBEXData OBEX;
#endif
#if defined(GSM_ENABLE_MROUTERBLUE)
GSM_Protocol_MROUTERData MROUTER;
#endif
} Data;
GSM_Protocol_Functions *Functions;
} GSM_Protocol;
/* -------------------------- Phone layer ---------------------------------- */
/**
* Phone requests identificators, these are used for internally identifying
* which operation is being performed.
*/
typedef enum {
ID_None=1,
ID_GetModel,
ID_GetFirmware,
ID_EnableSecurity,
ID_GetIMEI,
ID_GetDateTime,
ID_GetAlarm,
ID_GetMemory,
ID_GetMemoryStatus,
ID_GetSMSC,
ID_GetSMSMessage,
ID_EnableEcho,
ID_EnableErrorInfo,
ID_SetOBEX,
+ ID_SetUSSD,
+ ID_GetNote,
ID_GetSignalQuality,
ID_GetBatteryCharge,
ID_GetSMSFolders,
ID_GetSMSFolderStatus,
ID_GetSMSStatus,
ID_AddSMSFolder,
ID_GetNetworkInfo,
ID_GetRingtone,
ID_DialVoice,
ID_GetCalendarNotesInfo,
ID_GetCalendarNote,
ID_GetSecurityCode,
ID_GetWAPBookmark,
ID_GetBitmap,
ID_SaveSMSMessage,
ID_CancelCall,
ID_SetDateTime,
ID_SetAlarm,
ID_DisableConnectFunc,
ID_EnableConnectFunc,
ID_AnswerCall,
ID_SetBitmap,
ID_SetRingtone,
ID_DeleteSMSMessage,
ID_DeleteCalendarNote,
ID_SetPath,
ID_SetSMSC,
ID_SetProfile,
ID_SetMemory,
ID_DeleteMemory,
ID_SetCalendarNote,
ID_SetIncomingSMS,
ID_SetIncomingCB,
ID_GetCalendarNotePos,
ID_Initialise,
ID_GetConnectSet,
ID_SetWAPBookmark,
ID_GetLocale,
ID_SetLocale,
ID_GetCalendarSettings,
ID_SetCalendarSettings,
ID_GetGPRSPoint,
ID_SetGPRSPoint,
ID_EnableGPRSPoint,
ID_DeleteWAPBookmark,
ID_Netmonitor,
ID_HoldCall,
ID_UnholdCall,
ID_ConferenceCall,
ID_SplitCall,
ID_TransferCall,
ID_SwitchCall,
ID_GetManufactureMonth,
ID_GetProductCode,
ID_GetOriginalIMEI,
ID_GetHardware,
ID_GetPPM,
ID_GetSMSMode,
ID_GetSMSMemories,
ID_GetManufacturer,
ID_SetMemoryType,
ID_SetMemoryCharset,
ID_GetMMSSettings,
ID_SetSMSParameters,
ID_GetFMStation,
ID_SetFMStation,
ID_GetLanguage,
+ ID_SetFastSMSSending,
ID_Reset,
ID_GetToDo,
ID_PressKey,
ID_DeleteAllToDo,
ID_SetLight,
ID_Divert,
ID_SetToDo,
ID_PlayTone,
ID_GetChatSettings,
ID_GetSyncMLSettings,
ID_GetSyncMLName,
ID_GetSecurityStatus,
ID_EnterSecurityCode,
ID_GetProfile,
ID_GetRingtonesInfo,
ID_MakeAuthentication,
ID_GetSpeedDial,
ID_ResetPhoneSettings,
ID_SendDTMF,
ID_GetDisplayStatus,
ID_SetAutoNetworkLogin,
ID_SetConnectSet,
ID_SetMMSSettings,
ID_GetSIMIMSI,
ID_GetFileInfo,
ID_FileSystemStatus,
ID_GetFile,
ID_AddFile,
ID_AddFolder,
ID_DeleteFile,
#ifdef GSM_ENABLE_ALCATEL
/* AT mode */
ID_SetFlowControl,
ID_AlcatelConnect,
ID_AlcatelProtocol,
/* Binary mode */
ID_AlcatelAttach,
ID_AlcatelDetach,
ID_AlcatelCommit,
ID_AlcatelCommit2,
ID_AlcatelEnd,
ID_AlcatelClose,
ID_AlcatelStart,
ID_AlcatelSelect1,
ID_AlcatelSelect2,
ID_AlcatelSelect3,
ID_AlcatelBegin1,
ID_AlcatelBegin2,
ID_AlcatelGetIds1,
ID_AlcatelGetIds2,
ID_AlcatelGetCategories1,
ID_AlcatelGetCategories2,
ID_AlcatelGetCategoryText1,
ID_AlcatelGetCategoryText2,
ID_AlcatelAddCategoryText1,
ID_AlcatelAddCategoryText2,
ID_AlcatelGetFields1,
ID_AlcatelGetFields2,
ID_AlcatelGetFieldValue1,
ID_AlcatelGetFieldValue2,
ID_AlcatelDeleteItem1,
ID_AlcatelDeleteItem2,
ID_AlcatelDeleteField,
ID_AlcatelCreateField,
ID_AlcatelUpdateField,
#endif
ID_IncomingFrame,
ID_User1,
ID_User2,
ID_User3,
ID_User4,
ID_User5,
ID_User6,
ID_User7,
ID_User8,
ID_User9,
ID_User10,
ID_EachFrame
} GSM_Phone_RequestID;
/**
* Phone related data are stored here.
*/
typedef struct {
/**
* Phone IMEI (or serial number).
*/
char IMEI[MAX_IMEI_LENGTH];
/**
* Phone manufacturer as reported by phone.
*/
char Manufacturer[MAX_MANUFACTURER_LENGTH];
/**
* Phone model as reported by phone.
*/
char Model[MAX_MODEL_LENGTH];
/**
* Model information, pointer to static @ref allmodels array.
*/
OnePhoneModel *ModelInfo;
/**
* Phone version as reported by phone. It doesn't have to be numerical
* at all.
*/
char Version[MAX_VERSION_LENGTH];
/**
* Phone version date, might be empty for some models.
*/
char VerDate[MAX_VERSION_DATE_LENGTH];
/**
* Phone version as number, if applicable.
*/
double VerNum;
/**
* Cache for hardware version used by some modules.
*/
char HardwareCache[50];
/**
* Cache for product code version used by some modules.
*/
char ProductCodeCache[50];
/**
* Counter used for disabling startup info on phone, see
* @ref GSM_Phone_Functions::ShowStartInfo . After this is 0, the startup info is hidden.
*/
int StartInfoCounter;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_GPRSAccessPoint *GPRSPoint;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_SpeedDial *SpeedDial;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_DateTime *DateTime;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_Alarm *Alarm;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_MemoryEntry *Memory;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_MemoryStatus *MemoryStatus;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_SMSC *SMSC;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_MultiSMSMessage *GetSMSMessage;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_SMSMessage *SaveSMSMessage;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_SMSMemoryStatus *SMSStatus;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_SMSFolders *SMSFolders;
/**
* Used internally by phone drivers.
*/
int *VoiceRecord;
/**
* Used internally by phone drivers.
*/
int CallID;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_SignalQuality *SignalQuality;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_BatteryCharge *BatteryCharge;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_NetworkInfo *NetworkInfo;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_Ringtone *Ringtone;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_CalendarEntry *Cal;
/**
* Used internally by phone drivers.
*/
unsigned char *SecurityCode;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_WAPBookmark *WAPBookmark;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_MultiWAPSettings *WAPSettings;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_Bitmap *Bitmap;
/**
* Used internally by phone drivers.
*/
unsigned char *Netmonitor;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_MultiCallDivert *Divert;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_ToDoEntry *ToDo;
+ GSM_NoteEntry *Note;
/**
* Used internally by phone drivers.
*/
bool PressKey;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_SecurityCodeType *SecurityStatus;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_Profile *Profile;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_AllRingtonesInfo *RingtonesInfo;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_DisplayFeatures *DisplayFeatures;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_FMStation *FMStation;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_Locale *Locale;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_CalendarSettings *CalendarSettings;
/**
* Used internally by phone drivers.
*/
unsigned char *PhoneString;
/**
* Used internally by phone drivers.
*/
int StartPhoneString;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_File *FileInfo;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_File *File;
/**
* Pointer to structure used internally by phone drivers.
*/
GSM_FileSystemStatus *FileSystemStatus;
GSM_ChatSettings *ChatSettings;
GSM_SyncMLSettings *SyncMLSettings;
/**
* Should phone notify about incoming calls?
*/
bool EnableIncomingCall;
/**
* Should phone notify about incoming SMSes?
*/
bool EnableIncomingSMS;
/**
* Should phone notify about incoming CBs?
*/
bool EnableIncomingCB;
/**
* Should phone notify about incoming USSDs?
*/
bool EnableIncomingUSSD;
/**
* Last message received from phone.
*/
GSM_Protocol_Message *RequestMsg;
/**
* Last message sent by Gammu.
*/
GSM_Protocol_Message *SentMsg;
/**
* What operation is being performed now, see @ref GSM_Phone_RequestID
* for possible values.
*/
GSM_Phone_RequestID RequestID;
/**
* Error returned by function in phone module.
*/
GSM_Error DispatchError;
/**
* Structure with private phone modules data.
*/
struct {
int fake;
#ifdef GSM_ENABLE_NOKIA3320
GSM_Phone_N3320Data N3320;
#endif
#ifdef GSM_ENABLE_NOKIA3650
GSM_Phone_N3650Data N3650;
#endif
+#ifdef GSM_ENABLE_NOKIA650
+ GSM_Phone_N650Data N650;
+#endif
#ifdef GSM_ENABLE_NOKIA6110
GSM_Phone_N6110Data N6110;
#endif
#ifdef GSM_ENABLE_NOKIA6510
GSM_Phone_N6510Data N6510;
#endif
#ifdef GSM_ENABLE_NOKIA7110
GSM_Phone_N7110Data N7110;
#endif
#ifdef GSM_ENABLE_ATGEN
GSM_Phone_ATGENData ATGEN;
#endif
#ifdef GSM_ENABLE_ALCATEL
GSM_Phone_ALCATELData ALCATEL;
#endif
#ifdef GSM_ENABLE_OBEXGEN
GSM_Phone_OBEXGENData OBEXGEN;
#endif
#ifdef GSM_ENABLE_MROUTERGEN
GSM_Phone_MROUTERGENData MROUTERGEN;
#endif
} Priv;
} GSM_Phone_Data;
/**
* Structure for defining reply functions.
*
* Function is called when requestID matches current operation or is
* ID_IncomingFrame and msgtype matches start message and (if msgtype is just
* one character) subtypechar is zero or subtypechar-th character of message
* matches subtype.
*
* Should be used in array with last element containing ID_None as requestID.
*/
-typedef struct {
+struct _GSM_Reply_Function {
/**
* Pointer to function that should be executed.
*/
GSM_Error (*Function) (GSM_Protocol_Message msg, GSM_StateMachine *s);
/**
* Message type, if it is longer than 1 character, it disables subtype
* checking.
*/
unsigned char *msgtype;
/**
* Which character of message should be checked as subtype. Zero to
* disable subtype checking.
*/
int subtypechar;
/**
* Subtype to be checked.
*/
unsigned char subtype;
/**
* Phone request when this can be called, use ID_IncomingFrame when
* you want to use this in any state.
*/
GSM_Phone_RequestID requestID;
-} GSM_Reply_Function;
+};
/**
* Structure defining phone functions.
*/
typedef struct {
/**
* Names of supported models separated by |. Must contain at least one
* name.
*/
char *models;
/**
* Array of reply functions for the phone, see
* @ref GSM_Reply_Function for details about it.
*/
GSM_Reply_Function *ReplyFunctions;
/**
* Initializes phone.
*/
GSM_Error (*Initialise) (GSM_StateMachine *s);
/**
* Terminates phone communication.
*/
GSM_Error (*Terminate) (GSM_StateMachine *s);
/**
* Dispatches messages from phone, at the end it should call
* @ref GSM_DispatchMessage.
*/
GSM_Error (*DispatchMessage) (GSM_StateMachine *s);
/**
* Enables showing information on phone display.
*/
GSM_Error (*ShowStartInfo) (GSM_StateMachine *s, bool enable);
/**
* Reads manufacturer from phone.
*/
GSM_Error (*GetManufacturer) (GSM_StateMachine *s);
/**
* Reads model from phone.
*/
GSM_Error (*GetModel) (GSM_StateMachine *s);
/**
* Reads firmware information from phone.
*/
GSM_Error (*GetFirmware) (GSM_StateMachine *s);
/**
* Reads IMEI/serial number from phone.
*/
GSM_Error (*GetIMEI) (GSM_StateMachine *s);
/**
* Gets date and time from phone.
*/
GSM_Error (*GetOriginalIMEI) (GSM_StateMachine *s, char *value);
/**
* Gets month when device was manufactured.
*/
GSM_Error (*GetManufactureMonth)(GSM_StateMachine *s, char *value);
/**
* Gets product code of device.
*/
GSM_Error (*GetProductCode) (GSM_StateMachine *s, char *value);
/**
* Gets hardware information about device.
*/
GSM_Error (*GetHardware) (GSM_StateMachine *s, char *value);
/**
* Gets PPM (Post Programmable Memory) info from phone
* (in other words for Nokia get, which language pack is in phone)
*/
GSM_Error (*GetPPM) (GSM_StateMachine *s, char *value);
/**
* Gets SIM IMSI from phone.
*/
GSM_Error (*GetSIMIMSI) (GSM_StateMachine *s, char *IMSI);
/**
* Reads date and time from phone.
*/
GSM_Error (*GetDateTime) (GSM_StateMachine *s, GSM_DateTime *date_time);
/**
* Sets date and time in phone.
*/
GSM_Error (*SetDateTime) (GSM_StateMachine *s, GSM_DateTime *date_time);
/**
* Reads alarm set in phone.
*/
GSM_Error (*GetAlarm) (GSM_StateMachine *s, GSM_Alarm *alarm);
/**
* Sets alarm in phone.
*/
GSM_Error (*SetAlarm) (GSM_StateMachine *s, GSM_Alarm *alarm);
/**
* Gets locale from phone.
*/
GSM_Error (*GetLocale) (GSM_StateMachine *s, GSM_Locale *locale);
/**
* Sets locale of phone.
*/
GSM_Error (*SetLocale) (GSM_StateMachine *s, GSM_Locale *locale);
/**
* Emulates key press or key release.
*/
GSM_Error (*PressKey) (GSM_StateMachine *s, GSM_KeyCode Key, bool Press);
/**
* Performs phone reset.
*/
GSM_Error (*Reset) (GSM_StateMachine *s, bool hard);
/**
* Resets phone settings.
*/
GSM_Error (*ResetPhoneSettings) (GSM_StateMachine *s, GSM_ResetSettingsType Type);
/**
* Enters security code (PIN, PUK,...) .
*/
GSM_Error (*EnterSecurityCode) (GSM_StateMachine *s, GSM_SecurityCode Code);
/**
* Queries whether some security code needs to be entered./
*/
GSM_Error (*GetSecurityStatus) (GSM_StateMachine *s, GSM_SecurityCodeType *Status);
/**
* Acquired display status.
*/
GSM_Error (*GetDisplayStatus) (GSM_StateMachine *s, GSM_DisplayFeatures *features);
/**
* Enables network auto login.
*/
GSM_Error (*SetAutoNetworkLogin)(GSM_StateMachine *s);
/**
* Gets information about batery charge and phone charging state.
*/
GSM_Error (*GetBatteryCharge) (GSM_StateMachine *s, GSM_BatteryCharge *bat);
/**
* Reads signal quality (strength and error rate).
*/
GSM_Error (*GetSignalQuality) (GSM_StateMachine *s, GSM_SignalQuality *sig);
/**
* Gets network information.
*/
GSM_Error (*GetNetworkInfo) (GSM_StateMachine *s, GSM_NetworkInfo *netinfo);
/**
* Reads category from phone.
*/
GSM_Error (*GetCategory) (GSM_StateMachine *s, GSM_Category *Category);
/**
* Adds category to phone.
*/
GSM_Error (*AddCategory) (GSM_StateMachine *s, GSM_Category *Category);
/**
* Reads category status (number of used entries) from phone.
*/
GSM_Error (*GetCategoryStatus) (GSM_StateMachine *s, GSM_CategoryStatus *Status);
/**
* Gets memory (phonebooks or calls) status (eg. number of used and
* free entries).
*/
GSM_Error (*GetMemoryStatus) (GSM_StateMachine *s, GSM_MemoryStatus *status);
/**
* Reads entry from memory (phonebooks or calls). Which entry should
* be read is defined in entry.
*/
GSM_Error (*GetMemory) (GSM_StateMachine *s, GSM_MemoryEntry *entry);
/**
* Reads entry from memory (phonebooks or calls). Which entry should
* be read is defined in entry. This can be easily used for reading all entries.
*/
GSM_Error (*GetNextMemory) (GSM_StateMachine *s, GSM_MemoryEntry *entry, bool start);
/**
* Sets memory (phonebooks or calls) entry.
*/
GSM_Error (*SetMemory) (GSM_StateMachine *s, GSM_MemoryEntry *entry);
/**
* Deletes memory (phonebooks or calls) entry.
*/
GSM_Error (*AddMemory) (GSM_StateMachine *s, GSM_MemoryEntry *entry);
/**
* Deletes memory (phonebooks or calls) entry.
*/
GSM_Error (*DeleteMemory) (GSM_StateMachine *s, GSM_MemoryEntry *entry);
/**
* Deletes all memory (phonebooks or calls) entries of specified type.
*/
GSM_Error (*DeleteAllMemory) (GSM_StateMachine *s, GSM_MemoryType MemoryType);
/**
* Gets speed dial.
*/
GSM_Error (*GetSpeedDial) (GSM_StateMachine *s, GSM_SpeedDial *Speed);
/**
* Sets speed dial.
*/
GSM_Error (*SetSpeedDial) (GSM_StateMachine *s, GSM_SpeedDial *Speed);
/**
* Gets SMS Service Center number and SMS settings.
*/
GSM_Error (*GetSMSC) (GSM_StateMachine *s, GSM_SMSC *smsc);
/**
* Sets SMS Service Center number and SMS settings.
*/
GSM_Error (*SetSMSC) (GSM_StateMachine *s, GSM_SMSC *smsc);
/**
* Gets information about SMS memory (read/unread/size of memory for
* both SIM and phone).
*/
GSM_Error (*GetSMSStatus) (GSM_StateMachine *s, GSM_SMSMemoryStatus *status);
/**
* Reads SMS message.
*/
GSM_Error (*GetSMS) (GSM_StateMachine *s, GSM_MultiSMSMessage *sms);
/**
* Reads next (or first if start set) SMS message. This might be
* faster for some phones than using @ref GetSMS for each message.
*/
GSM_Error (*GetNextSMS) (GSM_StateMachine *s, GSM_MultiSMSMessage *sms, bool start);
/**
* Sets SMS.
*/
GSM_Error (*SetSMS) (GSM_StateMachine *s, GSM_SMSMessage *sms);
/**
* Adds SMS to specified folder.
*/
GSM_Error (*AddSMS) (GSM_StateMachine *s, GSM_SMSMessage *sms);
/**
* Deletes SMS.
*/
GSM_Error (*DeleteSMS) (GSM_StateMachine *s, GSM_SMSMessage *sms);
/**
* Sends SMS.
*/
GSM_Error (*SendSMS) (GSM_StateMachine *s, GSM_SMSMessage *sms);
/**
* Sends SMS already saved in phone.
*/
GSM_Error (*SendSavedSMS) (GSM_StateMachine *s, int Folder, int Location);
+ GSM_Error (*SetFastSMSSending) (GSM_StateMachine *s, bool enable);
/**
* Enable/disable notification on incoming SMS.
*/
GSM_Error (*SetIncomingSMS) (GSM_StateMachine *s, bool enable);
/**
* Gets network information from phone.
*/
GSM_Error (*SetIncomingCB) (GSM_StateMachine *s, bool enable);
/**
* Returns SMS folders information.
*/
GSM_Error (*GetSMSFolders) (GSM_StateMachine *s, GSM_SMSFolders *folders);
/**
* Creates SMS folder.
*/
GSM_Error (*AddSMSFolder) (GSM_StateMachine *s, unsigned char *name);
/**
* Deletes SMS folder.
*/
GSM_Error (*DeleteSMSFolder) (GSM_StateMachine *s, int ID);
/**
* Dials number and starts voice call.
*/
GSM_Error (*DialVoice) (GSM_StateMachine *s, char *Number, GSM_CallShowNumber ShowNumber);
/**
* Accept current incoming call.
*/
GSM_Error (*AnswerCall) (GSM_StateMachine *s, int ID, bool all);
/**
* Deny current incoming call.
*/
GSM_Error (*CancelCall) (GSM_StateMachine *s, int ID, bool all);
/**
* Holds call.
*/
GSM_Error (*HoldCall) (GSM_StateMachine *s, int ID);
/**
* Unholds call.
*/
GSM_Error (*UnholdCall) (GSM_StateMachine *s, int ID);
/**
* Initiates conference call.
*/
GSM_Error (*ConferenceCall) (GSM_StateMachine *s, int ID);
/**
* Splits call.
*/
GSM_Error (*SplitCall) (GSM_StateMachine *s, int ID);
/**
* Transfers call.
*/
GSM_Error (*TransferCall) (GSM_StateMachine *s, int ID, bool next);
/**
* Switches call.
*/
GSM_Error (*SwitchCall) (GSM_StateMachine *s, int ID, bool next);
/**
* Gets call diverts.
*/
GSM_Error (*GetCallDivert) (GSM_StateMachine *s, GSM_MultiCallDivert *divert);
/**
* Sets call diverts.
*/
GSM_Error (*SetCallDivert) (GSM_StateMachine *s, GSM_MultiCallDivert *divert);
/**
* Cancels all diverts.
*/
GSM_Error (*CancelAllDiverts) (GSM_StateMachine *s);
/**
* Activates/deactivates noticing about incoming calls.
*/
GSM_Error (*SetIncomingCall) (GSM_StateMachine *s, bool enable);
/**
* Activates/deactivates noticing about incoming USSDs (UnStructured Supplementary Services).
*/
GSM_Error (*SetIncomingUSSD) (GSM_StateMachine *s, bool enable);
/**
* Sends DTMF (Dual Tone Multi Frequency) tone.
*/
GSM_Error (*SendDTMF) (GSM_StateMachine *s, char *sequence);
/**
* Gets ringtone from phone.
*/
GSM_Error (*GetRingtone) (GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone);
/**
* Sets ringtone in phone.
*/
GSM_Error (*SetRingtone) (GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength);
/**
* Acquires ringtone informaiton.
*/
GSM_Error (*GetRingtonesInfo) (GSM_StateMachine *s, GSM_AllRingtonesInfo *Info);
/**
* Deletes user defined ringtones from phone.
*/
GSM_Error (*DeleteUserRingtones)(GSM_StateMachine *s);
/**
* Plays tone.
*/
GSM_Error (*PlayTone) (GSM_StateMachine *s, int Herz, unsigned char Volume, bool start);
/**
* Reads WAP bookmark.
*/
GSM_Error (*GetWAPBookmark) (GSM_StateMachine *s, GSM_WAPBookmark *bookmark);
/**
* Sets WAP bookmark.
*/
GSM_Error (*SetWAPBookmark) (GSM_StateMachine *s, GSM_WAPBookmark *bookmark);
/**
* Deletes WAP bookmark.
*/
GSM_Error (*DeleteWAPBookmark) (GSM_StateMachine *s, GSM_WAPBookmark *bookmark);
/**
* Acquires WAP settings.
*/
GSM_Error (*GetWAPSettings) (GSM_StateMachine *s, GSM_MultiWAPSettings *settings);
/**
* Changes WAP settings.
*/
GSM_Error (*SetWAPSettings) (GSM_StateMachine *s, GSM_MultiWAPSettings *settings);
/**
* Acquires MMS settings.
*/
GSM_Error (*GetMMSSettings) (GSM_StateMachine *s, GSM_MultiWAPSettings *settings);
/**
* Changes MMS settings.
*/
GSM_Error (*SetMMSSettings) (GSM_StateMachine *s, GSM_MultiWAPSettings *settings);
/**
* Acquires SyncML settings.
*/
GSM_Error (*GetSyncMLSettings) (GSM_StateMachine *s, GSM_SyncMLSettings *settings);
/**
* Changes SyncML settings.
*/
GSM_Error (*SetSyncMLSettings) (GSM_StateMachine *s, GSM_SyncMLSettings *settings);
/**
* Acquires chat/presence settings.
*/
GSM_Error (*GetChatSettings) (GSM_StateMachine *s, GSM_ChatSettings *settings);
/**
* Changes chat/presence settings.
*/
GSM_Error (*SetChatSettings) (GSM_StateMachine *s, GSM_ChatSettings *settings);
/**
* Gets bitmap.
*/
GSM_Error (*GetBitmap) (GSM_StateMachine *s, GSM_Bitmap *Bitmap);
/**
* Sets bitmap.
*/
GSM_Error (*SetBitmap) (GSM_StateMachine *s, GSM_Bitmap *Bitmap);
/**
* Gets status of ToDos (count of used entries).
*/
GSM_Error (*GetToDoStatus) (GSM_StateMachine *s, GSM_ToDoStatus *status);
/**
* Reads ToDo from phone.
*/
GSM_Error (*GetToDo) (GSM_StateMachine *s, GSM_ToDoEntry *ToDo);
/**
* Reads ToDo from phone.
*/
GSM_Error (*GetNextToDo) (GSM_StateMachine *s, GSM_ToDoEntry *ToDo, bool start);
/**
* Sets ToDo in phone.
*/
GSM_Error (*SetToDo) (GSM_StateMachine *s, GSM_ToDoEntry *ToDo);
/**
* Adds ToDo in phone.
*/
GSM_Error (*AddToDo) (GSM_StateMachine *s, GSM_ToDoEntry *ToDo);
/**
* Deletes ToDo entry in phone.
*/
GSM_Error (*DeleteToDo) (GSM_StateMachine *s, GSM_ToDoEntry *ToDo);
/**
* Deletes all todo entries in phone.
*/
GSM_Error (*DeleteAllToDo) (GSM_StateMachine *s);
/**
* Retrieves calendar status (number of used entries).
*/
GSM_Error (*GetCalendarStatus) (GSM_StateMachine *s, GSM_CalendarStatus *Status);
/**
* Retrieves calendar entry.
*/
GSM_Error (*GetCalendar) (GSM_StateMachine *s, GSM_CalendarEntry *Note);
/**
* Retrieves calendar entry. This is useful for continuous reading of all
* calendar entries.
*/
GSM_Error (*GetNextCalendar) (GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start);
/**
* Sets calendar entry
*/
GSM_Error (*SetCalendar) (GSM_StateMachine *s, GSM_CalendarEntry *Note);
/**
* Adds calendar entry.
*/
GSM_Error (*AddCalendar) (GSM_StateMachine *s, GSM_CalendarEntry *Note);
/**
* Deletes calendar entry.
*/
GSM_Error (*DeleteCalendar) (GSM_StateMachine *s, GSM_CalendarEntry *Note);
/**
* Deletes all calendar entries.
*/
GSM_Error (*DeleteAllCalendar) (GSM_StateMachine *s);
/**
* Reads calendar settings.
*/
GSM_Error (*GetCalendarSettings)(GSM_StateMachine *s, GSM_CalendarSettings *settings);
/**
* Sets calendar settings.
*/
GSM_Error (*SetCalendarSettings)(GSM_StateMachine *s, GSM_CalendarSettings *settings);
/**
* Gets note.
*/
- GSM_Error (*GetNote) (GSM_StateMachine *s, GSM_NoteEntry *Note, bool refresh);
+ GSM_Error (*GetNextNote) (GSM_StateMachine *s, GSM_NoteEntry *Note, bool refresh);
/**
* Reads profile.
*/
GSM_Error (*GetProfile) (GSM_StateMachine *s, GSM_Profile *Profile);
/**
* Updates profile.
*/
GSM_Error (*SetProfile) (GSM_StateMachine *s, GSM_Profile *Profile);
/**
* Reads FM station.
*/
GSM_Error (*GetFMStation) (GSM_StateMachine *s, GSM_FMStation *FMStation);
/**
* Sets FM station.
*/
GSM_Error (*SetFMStation) (GSM_StateMachine *s, GSM_FMStation *FMStation);
/**
* Clears defined FM stations.
*/
GSM_Error (*ClearFMStations) (GSM_StateMachine *s);
/**
* Gets next filename from filesystem.
*/
GSM_Error (*GetNextFileFolder) (GSM_StateMachine *s, GSM_File *File, bool start);
/**
* Gets file part from filesystem.
*/
GSM_Error (*GetFilePart) (GSM_StateMachine *s, GSM_File *File);
/**
* Adds file part to filesystem.
*/
GSM_Error (*AddFilePart) (GSM_StateMachine *s, GSM_File *File, int *Pos);
/**
* Acquires filesystem status.
*/
GSM_Error (*GetFileSystemStatus)(GSM_StateMachine *s, GSM_FileSystemStatus *Status);
/**
* Deletes file from filessytem.
*/
GSM_Error (*DeleteFile) (GSM_StateMachine *s, unsigned char *ID);
/**
* Adds folder to filesystem.
*/
GSM_Error (*AddFolder) (GSM_StateMachine *s, GSM_File *File);
/**
* Gets GPRS access point.
*/
GSM_Error (*GetGPRSAccessPoint) (GSM_StateMachine *s, GSM_GPRSAccessPoint *point);
/**
* Sets GPRS access point.
*/
GSM_Error (*SetGPRSAccessPoint) (GSM_StateMachine *s, GSM_GPRSAccessPoint *point);
} GSM_Phone_Functions;
extern GSM_Phone_Functions NAUTOPhone;
#ifdef GSM_ENABLE_NOKIA3320
extern GSM_Phone_Functions N3320Phone;
#endif
#ifdef GSM_ENABLE_NOKIA3650
extern GSM_Phone_Functions N3650Phone;
#endif
#ifdef GSM_ENABLE_NOKIA6110
extern GSM_Phone_Functions N6110Phone;
#endif
+#ifdef GSM_ENABLE_NOKIA650
+ extern GSM_Phone_Functions N650Phone;
+#endif
#ifdef GSM_ENABLE_NOKIA6510
extern GSM_Phone_Functions N6510Phone;
#endif
#ifdef GSM_ENABLE_NOKIA7110
extern GSM_Phone_Functions N7110Phone;
#endif
#ifdef GSM_ENABLE_NOKIA9210
extern GSM_Phone_Functions N9210Phone;
#endif
#ifdef GSM_ENABLE_ATGEN
extern GSM_Phone_Functions ATGENPhone;
#endif
#ifdef GSM_ENABLE_ALCATEL
extern GSM_Phone_Functions ALCATELPhone;
#endif
#ifdef GSM_ENABLE_OBEXGEN
extern GSM_Phone_Functions OBEXGENPhone;
#endif
#ifdef GSM_ENABLE_MROUTERGEN
extern GSM_Phone_Functions MROUTERGENPhone;
#endif
typedef struct {
GSM_Phone_Data Data;
GSM_Phone_Functions *Functions;
} GSM_Phone;
/* --------------------------- User layer ---------------------------------- */
struct _GSM_User {
GSM_Reply_Function *UserReplyFunctions;
void (*IncomingCall) (char *Device, GSM_Call call);
void (*IncomingSMS) (char *Device, GSM_SMSMessage sms);
void (*IncomingCB) (char *Device, GSM_CBMessage cb);
void (*IncomingUSSD) (char *Device, char *Text);
void (*SendSMSStatus) (char *Device, int status, int MessageReference);
};
/* --------------------------- Statemachine layer -------------------------- */
typedef enum {
GCT_MBUS2=1,
GCT_FBUS2,
GCT_FBUS2DLR3,
GCT_FBUS2DKU5,
GCT_FBUS2PL2303,
GCT_FBUS2BLUE,
GCT_FBUS2IRDA,
GCT_PHONETBLUE,
GCT_AT,
GCT_MROUTERBLUE,
GCT_IRDAOBEX,
GCT_IRDAAT,
GCT_IRDAPHONET,
GCT_BLUEFBUS2,
GCT_BLUEAT,
GCT_BLUEPHONET,
GCT_BLUEOBEX
} GSM_ConnectionType;
typedef struct {
/* Config file (or Registry or...) variables */
char Model[50]; /* Model from config file */
char DebugLevel[50]; /* Debug level */
char *Device; /* Device name from config file */
char *Connection; /* Connection type as string */
char *SyncTime; /* Synchronize time on startup? */
char *LockDevice; /* Lock device ? (Unix) */
char *DebugFile; /* Name of debug file */
char *Localize; /* Name of localisation file */
char *StartInfo; /* Display something during start ? */
bool UseGlobalDebugFile;/* Should we use global debug file? */
bool DefaultModel;
bool DefaultDebugLevel;
bool DefaultDevice;
bool DefaultConnection;
bool DefaultSyncTime;
bool DefaultLockDevice;
bool DefaultDebugFile;
bool DefaultLocalize;
bool DefaultStartInfo;
} GSM_Config;
#define MAX_CONFIG_NUM 5
struct _GSM_StateMachine {
GSM_ConnectionType ConnectionType; /* Type of connection as int */
char *LockFile; /* Lock file name for Unix */
Debug_Info di; /* Debug information */
bool opened; /* Is connection opened ? */
GSM_Config Config[MAX_CONFIG_NUM + 1];
GSM_Config *CurrentConfig; /* Config file (or Registry or...) variables */
int ConfigNum;
INI_Section *msg; /* Localisation strings structure */
int ReplyNum; /* How many times make sth. */
int Speed; /* For some protocols used speed */
GSM_Device Device;
GSM_Protocol Protocol;
GSM_Phone Phone;
GSM_User User;
};
/* ------------------------ Other general definitions ---------------------- */
GSM_Error GSM_RegisterAllPhoneModules (GSM_StateMachine *s);
GSM_Error GSM_InitConnection (GSM_StateMachine *s, int ReplyNum);
GSM_Error GSM_TerminateConnection (GSM_StateMachine *s);
int GSM_ReadDevice (GSM_StateMachine *s, bool wait);
GSM_Error GSM_WaitForOnce (GSM_StateMachine *s, unsigned char *buffer,
int length, unsigned char type, int time);
GSM_Error GSM_WaitFor (GSM_StateMachine *s, unsigned char *buffer,
int length, unsigned char type, int time,
GSM_Phone_RequestID request);
GSM_Error GSM_DispatchMessage (GSM_StateMachine *s);
INI_Section *GSM_FindGammuRC(void);
bool GSM_ReadConfig (INI_Section *cfg_info, GSM_Config *cfg, int num);
void GSM_DumpMessageLevel2 (GSM_StateMachine *s, unsigned char *message, int messagesize, int type);
void GSM_DumpMessageLevel3 (GSM_StateMachine *s, unsigned char *message, int messagesize, int type);
/* ---------------------- Phone features ----------------------------------- */
typedef enum {
/* n6110.c */
F_CAL33 = 1, /* Calendar,3310 style - 10 reminders, Unicode, 3 coding types */
F_CAL52, /* Calendar,5210 style - full Unicode, etc. */
F_CAL82, /* Calendar,8250 style - "normal", but with Unicode */
F_RING_SM, /* Ringtones returned in SM format - 33xx */
F_NORING, /* No ringtones */
F_NOPBKUNICODE, /* No phonebook in Unicode */
F_NOWAP, /* No WAP */
F_NOCALLER, /* No caller groups */
F_NOPICTURE, /* No Picture Images */
F_NOPICTUREUNI, /* No Picture Images text in Unicode */
F_NOSTARTUP, /* No startup logo */
F_NOCALENDAR, /* No calendar */
F_NOSTARTANI, /* Startup logo is not animated */
F_POWER_BATT, /* Network and battery level get from netmonitor */
F_PROFILES33, /* Phone profiles in 3310 style */
F_PROFILES51, /* Phone profiles in 5110 style */
F_MAGICBYTES, /* Phone can make authentication with magic bytes */
F_NODTMF, /* Phone can't send DTMF */
F_DISPSTATUS, /* Phone return display status */
F_NOCALLINFO,
/* n3320.c */
F_DAYMONTH, /* Day and month reversed in pbk, when compare to GSM models */
/* n6510.c */
F_PBK35, /* Phonebook in 3510 style with ringtones ID */
F_PBKIMG, /* Phonebook in 7250 style with picture ID */
F_PBKTONEGAL, /* Phonebook with selecting ringtones from gallery */
F_PBKSMSLIST, /* Phonebook with SMS list */
F_PBKUSER, /* Phonebook with user ID */
F_RADIO, /* Phone with FM radio */
F_TODO63, /* ToDo in 6310 style - 0x55 msg type */
F_TODO66, /* ToDo in 6610 style - like calendar, with date and other */
F_NOMIDI, /* No ringtones in MIDI */
F_BLUETOOTH, /* Bluetooth support */
F_NOFILESYSTEM, /* No images, ringtones, java saved in special filesystem */
F_NOMMS, /* No MMS sets in phone */
F_NOGPRSPOINT, /* GPRS point are not useable */
F_CAL35, /* Calendar,3510 style - Reminder,Call,Birthday */
F_CAL65, /* Calendar,6510 style - CBMM, method 3 */
F_WAPMMSPROXY, /* WAP & MMS settings contains first & second proxy */
/* n6510.c && n7110.c */
F_VOICETAGS, /* Voice tags available */
F_CAL62, /* Calendar,6210 style - Call,Birthday,Memo,Meeting */
+ F_NOTES,
/* AT modules */
F_SMSONLYSENT, /* Phone supports only sent/unsent messages */
F_BROKENCPBS, /* CPBS on some memories can hang phone */
F_M20SMS, /* Siemens M20 like SMS handling */
F_SLOWWRITE, /* Use slower writing which some phone need */
F_SMSME900, /* SMS in ME start from location 900 - case of Sagem */
F_ALCATEL /* Phone supports Alcatel protocol */
} Feature;
/* For models table */
struct _OnePhoneModel {
char *model;
char *number;
char *irdamodel;
Feature features[12];
};
bool IsPhoneFeatureAvailable (OnePhoneModel *model, Feature feature);
OnePhoneModel *GetModelData (char *model, char *number, char *irdamodel);
#ifdef __GNUC__
__attribute__((format(printf, 2, 3)))
#endif
int smprintf(GSM_StateMachine *s, const char *format, ...);
void GSM_OSErrorInfo(GSM_StateMachine *s, char *description);
#ifdef GSM_ENABLE_BACKUP
void GSM_GetPhoneFeaturesForBackup(GSM_StateMachine *s, GSM_Backup_Info *info);
#endif
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/misc/coding/coding.c b/gammu/emb/common/misc/coding/coding.c
index 62543ac..b30b645 100644
--- a/gammu/emb/common/misc/coding/coding.c
+++ b/gammu/emb/common/misc/coding/coding.c
@@ -1,210 +1,363 @@
/* (c) 2002-2004 by Marcin Wiacek, Michal Cihar and others */
-/* based on some work from MyGnokii and Gnokii */
+/* based on some work from MyGnokii (www.mwiacek.com) */
+/* based on some work from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>
#ifndef __OpenBSD__
# include <wctype.h>
#endif
#ifdef WIN32
# include "windows.h"
#endif
#include "../misc.h"
#include "coding.h"
+/* function changes #10 #13 chars to \n \r */
+char *EncodeUnicodeSpecialChars(unsigned char *buffer)
+{
+ int Pos=0, Pos2=0;
+ static unsigned char Buf[20000];
+
+ while (buffer[Pos*2]!=0x00 || buffer[Pos*2+1]!=0x00) {
+ if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == 10) {
+ Buf[Pos2*2] = 0x00;
+ Buf[Pos2*2+1] = '\\';
+ Pos2++;
+ Buf[Pos2*2] = 0x00;
+ Buf[Pos2*2+1] = 'n';
+ Pos2++;
+ } else if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == 13) {
+ Buf[Pos2*2] = 0x00;
+ Buf[Pos2*2+1] = '\\';
+ Pos2++;
+ Buf[Pos2*2] = 0x00;
+ Buf[Pos2*2+1] = 'r';
+ Pos2++;
+ } else if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == '\\') {
+ Buf[Pos2*2] = 0x00;
+ Buf[Pos2*2+1] = '\\';
+ Pos2++;
+ Buf[Pos2*2] = 0x00;
+ Buf[Pos2*2+1] = '\\';
+ Pos2++;
+ } else {
+ Buf[Pos2*2] = buffer[Pos*2];
+ Buf[Pos2*2+1] = buffer[Pos*2+1];
+ Pos2++;
+ }
+ Pos++;
+ }
+ Buf[Pos2*2] = 0;
+ Buf[Pos2*2+1] = 0;
+ return Buf;
+}
+
+/* function changes #10 #13 chars to \n \r */
+char *EncodeSpecialChars(unsigned char *buffer)
+{
+ int Pos=0, Pos2=0;
+ static unsigned char Buf[10000];
+
+ while (buffer[Pos]!=0x00) {
+ switch (buffer[Pos]) {
+ case 10:
+ Buf[Pos2++] = '\\';
+ Buf[Pos2++] = 'n';
+ break;
+ case 13:
+ Buf[Pos2++] = '\\';
+ Buf[Pos2++] = 'r';
+ break;
+ case '\\':
+ Buf[Pos2++] = '\\';
+ Buf[Pos2++] = '\\';
+ break;
+ default:
+ Buf[Pos2++] = buffer[Pos];
+ }
+ Pos++;
+ }
+ Buf[Pos2] = 0;
+ return Buf;
+}
+
+char *DecodeUnicodeSpecialChars(unsigned char *buffer)
+{
+ int Pos=0, Pos2=0, level=0;
+ static unsigned char Buf[10000];
+
+ while (buffer[Pos*2]!=0x00 || buffer[Pos*2+1]!=0x00) {
+ Buf[Pos2*2] = buffer[Pos*2];
+ Buf[Pos2*2+1] = buffer[Pos*2+1];
+ switch (level) {
+ case 0:
+ if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == '\\') {
+ level = 1;
+ } else {
+ Pos2++;
+ }
+ break;
+ case 1:
+ if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == 'n') {
+ Buf[Pos2*2] = 0;
+ Buf[Pos2*2+1] = 10;
+ }
+ if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == 'r') {
+ Buf[Pos2*2] = 0;
+ Buf[Pos2*2+1] = 13;
+ }
+ if (buffer[Pos*2] == 0x00 && buffer[Pos*2+1] == '\\') {
+ Buf[Pos2*2] = 0;
+ Buf[Pos2*2+1] = '\\';
+ }
+ Pos2++;
+ level = 0;
+ }
+ Pos++;
+ }
+ Buf[Pos2*2] = 0;
+ Buf[Pos2*2+1] = 0;
+ return Buf;
+}
+
+char *DecodeSpecialChars(unsigned char *buffer)
+{
+ int Pos=0, Pos2=0, level=0;
+ static unsigned char Buf[10000];
+
+ while (buffer[Pos]!=0x00) {
+ Buf[Pos2] = buffer[Pos];
+ switch (level) {
+ case 0:
+ if (buffer[Pos] == '\\') {
+ level = 1;
+ } else {
+ Pos2++;
+ }
+ break;
+ case 1:
+ if (buffer[Pos] == 'n') Buf[Pos2] = 10;
+ if (buffer[Pos] == 'r') Buf[Pos2] = 13;
+ if (buffer[Pos] == '\\') Buf[Pos2] = '\\';
+ Pos2++;
+ level = 0;
+ }
+ Pos++;
+ }
+ Buf[Pos2] = 0;
+ return Buf;
+}
+
+char *mystrcasestr(unsigned const char *a, unsigned const char *b)
+{
+ unsigned char A[2000], B[200];
+ int i;
+
+ memset(A,0,sizeof(A));
+ memset(B,0,sizeof(B));
+ for (i=0;i<(int)strlen(a);i++) A[i] = tolower(a[i]);
+ for (i=0;i<(int)strlen(b);i++) B[i] = tolower(b[i]);
+
+ return strstr(A,B);
+}
+
unsigned int UnicodeLength(const unsigned char *str)
{
unsigned int len = 0;
if (str == NULL) return 0;
while(str[len*2] != 0 || str[len*2+1] != 0) len++;
return len;
}
/* Convert Unicode char saved in src to dest */
unsigned int EncodeWithUnicodeAlphabet(const unsigned char *src, wchar_t *dest)
{
char retval;
switch (retval = mbtowc(dest, src, MB_CUR_MAX)) {
case -1 :
case 0 : return 1;
default : return retval;
}
}
/* Convert Unicode char saved in src to dest */
unsigned int DecodeWithUnicodeAlphabet(wchar_t src, unsigned char *dest)
{
int retval;
switch (retval = wctomb(dest, src)) {
case -1:
*dest = '?';
return 1;
default:
return retval;
}
}
void DecodeUnicode (const unsigned char *src, unsigned char *dest)
{
int i=0,o=0;
wchar_t wc;
while (src[(2*i)+1]!=0x00 || src[2*i]!=0x00) {
wc = src[(2*i)+1] | (src[2*i] << 8);
o += DecodeWithUnicodeAlphabet(wc, dest + o);
i++;
}
dest[o]=0;
}
/* Decode Unicode string and return as function result */
unsigned char *DecodeUnicodeString (const unsigned char *src)
{
static char dest[500];
DecodeUnicode(src,dest);
return dest;
}
/* Decode Unicode string to UTF8 or other console charset
* and return as function result
*/
unsigned char *DecodeUnicodeConsole(const unsigned char *src)
{
static char dest[500];
if (di.coding[0] != 0) {
if (!strcmp(di.coding,"utf8")) {
EncodeUTF8(dest, src);
} else {
#ifdef WIN32
setlocale(LC_ALL, di.coding);
#endif
DecodeUnicode(src,dest);
}
} else {
#ifdef WIN32
setlocale(LC_ALL, ".OCP");
#endif
DecodeUnicode(src,dest);
#ifdef WIN32
setlocale(LC_ALL, ".ACP");
#endif
}
return dest;
}
/* Encode string to Unicode. Len is number of input chars */
void EncodeUnicode (unsigned char *dest, const unsigned char *src, int len)
{
int i_len = 0, o_len;
wchar_t wc;
for (o_len = 0; i_len < len; o_len++) {
i_len += EncodeWithUnicodeAlphabet(&src[i_len], &wc);
dest[o_len*2] = (wc >> 8) & 0xff;
dest[(o_len*2)+1] = wc & 0xff;
}
dest[o_len*2] = 0;
dest[(o_len*2)+1] = 0;
}
unsigned char EncodeWithBCDAlphabet(int value)
{
div_t division;
division=div(value,10);
return ( ( (value-division.quot*10) & 0x0f) << 4) | (division.quot & 0xf);
}
int DecodeWithBCDAlphabet(unsigned char value)
{
return 10*(value & 0x0f)+(value >> 4);
}
void DecodeBCD (unsigned char *dest, const unsigned char *src, int len)
{
int i,current=0,digit;
for (i = 0; i < len; i++) {
digit=src[i] & 0x0f;
if (digit<10) dest[current++]=digit + '0';
digit=src[i] >> 4;
if (digit<10) dest[current++]=digit + '0';
}
dest[current++]=0;
}
void EncodeBCD (unsigned char *dest, const unsigned char *src, int len, bool fill)
{
int i,current=0;
for (i = 0; i < len; i++) {
if (i & 0x01) {
dest[current]=dest[current] | ((src[i]-'0') << 4);
current++;
} else {
dest[current]=src[i]-'0';
}
}
/* When fill is set: if number consist of odd number of digits,
we fill last bits in last byte with 0x0f
*/
if (fill && (len & 0x01)) dest[current]=dest[current] | 0xf0;
}
int DecodeWithHexBinAlphabet (unsigned char mychar)
{
if (mychar>='A' && mychar<='F') return mychar-'A'+10;
if (mychar>='a' && mychar<='f') return mychar-'a'+10;
if (mychar>='0' && mychar<='9') return mychar-'0';
return -1;
}
unsigned char EncodeWithHexBinAlphabet (int digit)
{
if (digit >= 0 && digit <= 9) return '0'+(digit);
if (digit >=10 && digit <=15) return 'A'+(digit-10);
return 0;
}
void DecodeHexUnicode (unsigned char *dest, const unsigned char *src, int len)
{
int i,current=0;
bool first = false;
if (len != 0 && src[0] == '0' && src[1] == '0') {
first = true;
} else if (len != 0 && src[2] == '0' && src[3] == '0') {
first = false;
} else {
first = (10 * (src[0] - '0') + (src[1] - '0')) < (10 * (src[2] - '0')+ (src[3] - '0'));
}
for (i = 0; i < len/4 ; i++) {
if (first) {
dest[current++] = DecodeWithHexBinAlphabet(src[i*4+0])*16+
DecodeWithHexBinAlphabet(src[i*4+1]);
dest[current++] = DecodeWithHexBinAlphabet(src[i*4+2])*16+
DecodeWithHexBinAlphabet(src[i*4+3]);
} else {
dest[current++] = DecodeWithHexBinAlphabet(src[i*4+2])*16+
DecodeWithHexBinAlphabet(src[i*4+3]);
dest[current++] = DecodeWithHexBinAlphabet(src[i*4+0])*16+
DecodeWithHexBinAlphabet(src[i*4+1]);
}
}
dest[current++] = 0;
dest[current++] = 0;
}
void EncodeHexUnicode (unsigned char *dest, const unsigned char *src, int len)
@@ -397,814 +550,814 @@ void EncodeDefault(unsigned char *dest, const unsigned char *src, int *len, bool
if (src[i*2] == GSM_DefaultAlphabetUnicode[j][0] &&
src[i*2+1] == GSM_DefaultAlphabetUnicode[j][1]) {
ret = j;
FoundNormal = true;
break;
}
j++;
}
if (ExtraAlphabet!=NULL && !FoundNormal) {
j = 0;
while (ExtraAlphabet[j] != 0x00 || ExtraAlphabet[j+1] != 0x00 || ExtraAlphabet[j+2] != 0x00) {
if (ExtraAlphabet[j+1] == src[i*2] &&
ExtraAlphabet[j+2] == src[i*2 + 1]) {
ret = ExtraAlphabet[j];
FoundSpecial = true;
break;
}
j=j+3;
}
}
if (!FoundNormal && !FoundSpecial) {
j = 0;
FoundNormal = false;
while (ConvertTable[j*4] != 0x00 ||
ConvertTable[j*4+1] != 0x00) {
if (src[i*2] == ConvertTable[j*4] &&
src[i*2+1] == ConvertTable[j*4+1]) {
z = 0;
while (GSM_DefaultAlphabetUnicode[z][1]!=0x00) {
if (ConvertTable[j*4+2] == GSM_DefaultAlphabetUnicode[z][0] &&
ConvertTable[j*4+3] == GSM_DefaultAlphabetUnicode[z][1]) {
ret = z;
FoundNormal = true;
break;
}
z++;
}
if (FoundNormal) break;
}
j++;
}
}
dest[current++]=ret;
}
}
dest[current]=0;
#ifdef DEBUG
if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, dest, current);
#endif
*len = current;
}
/* You don't have to use ConvertTable here - 1 char is replaced there by 1 char */
void FindDefaultAlphabetLen(const unsigned char *src, int *srclen, int *smslen, int maxlen)
{
int current=0,j,i;
bool FoundSpecial;
i = 0;
while (src[i*2] != 0x00 || src[i*2+1] != 0x00) {
FoundSpecial = false;
j = 0;
while (GSM_DefaultAlphabetCharsExtension[j][0]!=0x00) {
if (src[i*2] == GSM_DefaultAlphabetCharsExtension[j][2] &&
src[i*2+1] == GSM_DefaultAlphabetCharsExtension[j][3]) {
FoundSpecial = true;
if (current+2 > maxlen) {
*srclen = i;
*smslen = current;
return;
}
current+=2;
break;
}
j++;
}
if (!FoundSpecial) {
if (current+1 > maxlen) {
*srclen = i;
*smslen = current;
return;
}
current++;
}
i++;
}
*srclen = i;
*smslen = current;
}
#ifndef ENABLE_LGPL
# define ByteMask ((1 << Bits) - 1)
#endif
int GSM_UnpackEightBitsToSeven(int offset, int in_length, int out_length,
unsigned char *input, unsigned char *output)
{
#ifndef ENABLE_LGPL
/* (c) by Pavel Janik and Pawel Kot */
unsigned char *OUTPUT = output; /* Current pointer to the output buffer */
unsigned char *INPUT = input; /* Current pointer to the input buffer */
unsigned char Rest = 0x00;
int Bits;
Bits = offset ? offset : 7;
while ((INPUT - input) < in_length) {
*OUTPUT = ((*INPUT & ByteMask) << (7 - Bits)) | Rest;
Rest = *INPUT >> Bits;
/* If we don't start from 0th bit, we shouldn't go to the
next char. Under *OUTPUT we have now 0 and under Rest -
_first_ part of the char. */
if ((INPUT != input) || (Bits == 7)) OUTPUT++;
INPUT++;
if ((OUTPUT - 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) {
*OUTPUT = Rest;
OUTPUT++;
Bits = 7;
Rest = 0x00;
} else {
Bits--;
}
}
return OUTPUT - output;
#else
return 0;
#endif
}
int GSM_PackSevenBitsToEight(int offset, unsigned char *input, unsigned char *output, int length)
{
#ifndef ENABLE_LGPL
/* (c) by Pavel Janik and Pawel Kot */
unsigned char *OUTPUT = output; /* Current pointer to the output buffer */
unsigned char *INPUT = 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) {
*OUTPUT = 0x00;
OUTPUT++;
}
while ((INPUT - input) < length) {
unsigned char Byte = *INPUT;
*OUTPUT = 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)
*(OUTPUT-1) |= (Byte & ((1 << (7-Bits)) - 1)) << (Bits+1);
Bits--;
if (Bits == -1) Bits = 7; else OUTPUT++;
INPUT++;
}
return (OUTPUT - output);
#else
return 0;
#endif
}
void GSM_UnpackSemiOctetNumber(unsigned char *retval, unsigned char *Number, bool semioctet)
{
unsigned char Buffer[50] = "";
int length = Number[0];
if (semioctet) {
/* Convert number of semioctets to number of chars */
if (length % 2) length++;
length=length / 2 + 1;
}
/*without leading byte with format of number*/
length--;
- switch (Number[1]) {
- case NUMBER_ALPHANUMERIC:
+ switch ((Number[1] & 112)) {
+ case (NUMBER_ALPHANUMERIC_NUMBERING_PLAN_UNKNOWN & 112):
if (length > 6) length++;
dbgprintf("Alphanumeric number, length %i\n",length);
GSM_UnpackEightBitsToSeven(0, length, length, Number+2, Buffer);
Buffer[length]=0;
break;
- case NUMBER_INTERNATIONAL:
+ case (NUMBER_INTERNATIONAL_NUMBERING_PLAN_ISDN & 112):
dbgprintf("International number\n");
Buffer[0]='+';
DecodeBCD(Buffer+1,Number+2, length);
break;
default:
dbgprintf("Default number %02x\n",Number[1]);
DecodeBCD (Buffer, Number+2, length);
break;
}
EncodeUnicode(retval,Buffer,strlen(Buffer));
}
/**
* Packing some phone numbers (SMSC, SMS destination and others)
*
* 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 coding.h). Returned
* in unsigned char *Output.
* n bytes - 2n or 2n-1 semioctets with number. Returned in unsigned char
* *Output.
*
* 1 semioctet = 4 bits = half of byte
*/
int GSM_PackSemiOctetNumber(unsigned char *Number, unsigned char *Output, bool semioctet)
{
unsigned char format, buffer[50];
int length, i;
length=UnicodeLength(Number);
memcpy(buffer,DecodeUnicodeString(Number),length+1);
/* Checking for format number */
- format = NUMBER_UNKNOWN;
+ format = NUMBER_UNKNOWN_NUMBERING_PLAN_ISDN;
for (i=0;i<length;i++) {
/* first byte is '+'. Number can be international */
if (i==0 && buffer[i]=='+') {
- format=NUMBER_INTERNATIONAL;
+ format=NUMBER_INTERNATIONAL_NUMBERING_PLAN_ISDN;
} else {
/*char is not number. It must be alphanumeric*/
- if (!isdigit(buffer[i])) format=NUMBER_ALPHANUMERIC;
+ if (!isdigit(buffer[i])) format=NUMBER_ALPHANUMERIC_NUMBERING_PLAN_UNKNOWN;
}
}
/**
* First byte is used for saving type of number. See GSM 03.40
* section 9.1.2.5
*/
Output[0]=format;
/* After number type we will have number. GSM 03.40 section 9.1.2 */
switch (format) {
- case NUMBER_ALPHANUMERIC:
+ case NUMBER_ALPHANUMERIC_NUMBERING_PLAN_UNKNOWN:
length=GSM_PackSevenBitsToEight(0, buffer, Output+1, strlen(buffer))*2;
if (strlen(buffer)==7) length--;
break;
- case NUMBER_INTERNATIONAL:
+ case NUMBER_INTERNATIONAL_NUMBERING_PLAN_ISDN:
length--;
EncodeBCD (Output+1, buffer+1, length, true);
break;
default:
EncodeBCD (Output+1, buffer, length, true);
break;
}
if (semioctet) return length;
/* Convert number of semioctets to number of chars */
if (length % 2) length++;
return length / 2 + 1;
}
void CopyUnicodeString(unsigned char *Dest, unsigned char *Source)
{
int j = 0;
while (Source[j]!=0x00 || Source[j+1]!=0x00) {
Dest[j] = Source[j];
Dest[j+1] = Source[j+1];
j=j+2;
}
Dest[j] = 0;
Dest[j+1] = 0;
}
/* Changes minor/major order in Unicode string */
void ReverseUnicodeString(unsigned char *String)
{
int j = 0;
unsigned char byte1, byte2;
while (String[j]!=0x00 || String[j+1]!=0x00) {
byte1 = String[j];
byte2 = String[j+1];
String[j+1] = byte1;
String[j] = byte2;
j=j+2;
}
String[j] = 0;
String[j+1] = 0;
}
/* All input is in Unicode. First char can show Unicode minor/major order.
Output is Unicode string in Gammu minor/major order */
void ReadUnicodeFile(unsigned char *Dest, unsigned char *Source)
{
int j = 0, current = 0;
if (Source[0] == 0xFF && Source[1] == 0xFE) j = 2;
if (Source[0] == 0xFE && Source[1] == 0xFF) j = 2;
while (Source[j]!=0x00 || Source[j+1]!=0x00) {
if (Source[0] == 0xFF) {
Dest[current++] = Source[j+1];
Dest[current++] = Source[j];
} else {
Dest[current++] = Source[j];
Dest[current++] = Source[j+1];
}
j=j+2;
}
Dest[current++] = 0;
Dest[current++] = 0;
}
int GetBit(unsigned char *Buffer, int BitNum)
{
return Buffer[BitNum/8] & 1<<(7-(BitNum%8));
}
int SetBit(unsigned char *Buffer, int BitNum)
{
return Buffer[BitNum/8] |= 1<<(7-(BitNum%8));
}
int ClearBit(unsigned char *Buffer, int BitNum)
{
return Buffer[BitNum/8] &= 255 - (1 << (7-(BitNum%8)));
}
void BufferAlign(unsigned char *Destination, int *CurrentBit)
{
int i=0;
while(((*CurrentBit) + i) % 8 != 0) {
ClearBit(Destination, (*CurrentBit)+i);
i++;
}
(*CurrentBit) = (*CurrentBit) + i;
}
void BufferAlignNumber(int *CurrentBit)
{
int i=0;
while(((*CurrentBit) + i) % 8 != 0) {
i++;
}
(*CurrentBit) = (*CurrentBit) + i;
}
void AddBuffer(unsigned char *Destination,
int *CurrentBit,
unsigned char *Source,
int BitsToProcess)
{
int i=0;
while (i!=BitsToProcess) {
if (GetBit(Source, i)) {
SetBit(Destination, (*CurrentBit)+i);
} else {
ClearBit(Destination, (*CurrentBit)+i);
}
i++;
}
(*CurrentBit) = (*CurrentBit) + BitsToProcess;
}
void AddBufferByte(unsigned char *Destination,
int *CurrentBit,
unsigned char Source,
int BitsToProcess)
{
unsigned char Byte;
Byte = Source;
AddBuffer(Destination, CurrentBit, &Byte, BitsToProcess);
}
void GetBuffer(unsigned char *Source,
int *CurrentBit,
unsigned char *Destination,
int BitsToProcess)
{
int i=0;
while (i!=BitsToProcess) {
if (GetBit(Source, (*CurrentBit)+i)) {
SetBit(Destination, i);
} else {
ClearBit(Destination, i);
}
i++;
}
(*CurrentBit) = (*CurrentBit) + BitsToProcess;
}
void GetBufferInt(unsigned char *Source,
int *CurrentBit,
int *integer,
int BitsToProcess)
{
int l=0,z=128,i=0;
while (i!=BitsToProcess) {
if (GetBit(Source, (*CurrentBit)+i)) l=l+z;
z=z/2;
i++;
}
*integer=l;
(*CurrentBit) = (*CurrentBit) + i;
}
void GetBufferI(unsigned char *Source,
int *CurrentBit,
int *result,
int BitsToProcess)
{
int l=0,z,i=0;
z = 1<<(BitsToProcess-1);
while (i!=BitsToProcess) {
if (GetBit(Source, (*CurrentBit)+i)) l=l+z;
z=z>>1;
i++;
}
*result=l;
(*CurrentBit) = (*CurrentBit) + i;
}
/* Unicode char 0x00 0x01 makes blinking in some Nokia phones.
* We replace single ~ chars into it. When user give double ~, it's replaced
* to single ~
*/
void EncodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, int len)
{
int i,current = 0;
bool special=false;
for (i = 0; i < len; i++) {
if (special) {
if (src[i*2] == 0x00 && src[i*2+1] == '~') {
dest[current++] = 0x00;
dest[current++] = '~';
} else {
dest[current++] = 0x00;
dest[current++] = 0x01;
dest[current++] = src[i*2];
dest[current++] = src[i*2+1];
}
special = false;
} else {
if (src[i*2] == 0x00 && src[i*2+1] == '~') {
special = true;
} else {
dest[current++] = src[i*2];
dest[current++] = src[i*2+1];
}
}
}
if (special) {
dest[current++] = 0x00;
dest[current++] = 0x01;
}
dest[current++] = 0x00;
dest[current++] = 0x00;
}
void DecodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, int len)
{
int i=0,current=0;
for (i=0;i<len;i++) {
switch (src[2*i]) {
case 0x00:
switch (src[2*i+1]) {
case 0x01:
dest[current++] = 0x00;
dest[current++] = '~';
break;
case '~':
dest[current++] = 0x00;
dest[current++] = '~';
dest[current++] = 0x00;
dest[current++] = '~';
break;
default:
dest[current++] = src[i*2];
dest[current++] = src[i*2+1];
}
break;
default:
dest[current++] = src[i*2];
dest[current++] = src[i*2+1];
}
}
dest[current++] = 0x00;
dest[current++] = 0x00;
}
bool mystrncasecmp(unsigned const char *a, unsigned const char *b, int num)
{
int i;
if (a == NULL || b == NULL) return false;
- num--;
+ if (num == 0) num = -1;
for (i = 0; i != num; i++) {
if (a[i] == 0x00 && b[i] == 0x00) return true;
if (a[i] == 0x00 || b[i] == 0x00) return false;
if (tolower(a[i]) != tolower(b[i])) return false;
}
return true;
}
/* Compares two Unicode strings without regarding to case.
* Return true, when they're equal
*/
bool mywstrncasecmp(unsigned const char *a, unsigned const char *b, int num)
{
int i;
wchar_t wc,wc2;
if (a == NULL || b == NULL) return false;
- num--;
+ if (num == 0) num = -1;
for (i = 0; i != num; i++) {
if ((a[i*2] == 0x00 && a[i*2+1] == 0x00) && (b[i*2] == 0x00 && b[i*2+1] == 0x00)) return true;
if ((a[i*2] == 0x00 && a[i*2+1] == 0x00) || (b[i*2] == 0x00 && b[i*2+1] == 0x00)) return false;
wc = a[i*2+1] | (a[i*2] << 8);
wc2 = b[i*2+1] | (b[i*2] << 8);
if (mytowlower(wc) != mytowlower(wc2)) return false;
}
return true;
}
/* wcscmp in Mandrake 9.0 is wrong */
bool mywstrncmp(unsigned const char *a, unsigned const char *b, int num)
{
int i=0;
while (1) {
if (a[i*2] != b[i*2] || a[i*2+1] != b[i*2+1]) return false;
if (a[i*2] == 0x00 && a[i*2+1] == 0x00) return true;
i++;
if (num == i) return true;
}
}
/* FreeBSD boxes 4.7-STABLE does't have it, although it's ANSI standard */
bool myiswspace(unsigned const char *src)
{
#ifndef HAVE_ISWSPACE
int o;
unsigned char dest[10];
#endif
wchar_t wc;
wc = src[1] | (src[0] << 8);
#ifndef HAVE_ISWSPACE
o = DecodeWithUnicodeAlphabet(wc, dest);
if (o == 1) {
if (isspace(((int)dest[0]))!=0) return true;
return false;
}
return false;
#else
return iswspace(wc);
#endif
}
/* FreeBSD boxes 4.7-STABLE does't have it, although it's ANSI standard */
int mytowlower(wchar_t c)
{
#ifndef HAVE_TOWLOWER
unsigned char dest[10];
DecodeWithUnicodeAlphabet(c, dest);
return tolower(dest[0]);
#else
return towlower(c);
#endif
}
/*
* Following code is based on wcsstr from the GNU C Library, original
* comment follows:
*/
/*
* The original strstr() file contains the following comment:
*
* My personal strstr() implementation that beats most other algorithms.
* Until someone tells me otherwise, I assume that this is the
* fastest implementation of strstr() in C.
* I deliberately chose not to comment it. You should have at least
* as much fun trying to understand it, as I had to write it :-).
*
* Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */
-unsigned char *mystrstr (const unsigned char *haystack, const unsigned char *needle)
+unsigned char *mywstrstr (const unsigned char *haystack, const unsigned char *needle)
{
/* One crazy define to convert unicode used in Gammu to standard wchar_t */
#define tolowerwchar(x) (mytowlower((wchar_t)( (((&(x))[0] & 0xff) << 8) | (((&(x))[1] & 0xff)) )))
register wchar_t b, c;
if ((b = tolowerwchar(*needle)) != L'\0') {
haystack -= 2; /* possible ANSI violation */
do {
haystack += 2;
if ((c = tolowerwchar(*haystack)) == L'\0')
goto ret0;
} while (c != b);
needle += 2;
if ((c = tolowerwchar(*needle)) == L'\0')
goto foundneedle;
needle += 2;
goto jin;
for (;;) {
register wchar_t a;
register const unsigned char *rhaystack, *rneedle;
do {
haystack += 2;
if ((a = tolowerwchar(*haystack)) == L'\0')
goto ret0;
if (a == b)
break;
haystack += 2;
if ((a = tolowerwchar(*haystack)) == L'\0')
goto ret0;
shloop: ;
} while (a != b);
jin: haystack += 2;
if ((a = tolowerwchar(*haystack)) == L'\0')
goto ret0;
if (a != c)
goto shloop;
rhaystack = haystack + 2;
haystack -= 2;
rneedle = needle;
if (tolowerwchar(*rhaystack) == (a = tolowerwchar(*rneedle)))
do {
if (a == L'\0')
goto foundneedle;
rhaystack += 2;
needle += 2;
if (tolowerwchar(*rhaystack) != (a = tolowerwchar(*needle)))
break ;
if (a == L'\0')
goto foundneedle;
rhaystack += 2;
needle += 2;
} while (tolowerwchar(*rhaystack) == (a = tolowerwchar(*needle)));
needle = rneedle; /* took the register-poor approach */
if (a == L'\0')
break;
}
}
foundneedle:
return (unsigned char *)haystack;
ret0:
return NULL;
#undef tolowerwchar
}
void MyGetLine(unsigned char *Buffer, int *Pos, unsigned char *OutBuffer, int MaxLen)
{
OutBuffer[0] = 0;
if (Buffer == NULL) return;
while (1) {
if ((*Pos) >= MaxLen) return;
switch (Buffer[*Pos]) {
case 0x00:
return;
case 0x0A:
if (strlen(OutBuffer) != 0) return;
break;
case 0x0D:
if (strlen(OutBuffer) != 0) return;
break;
default :
OutBuffer[strlen(OutBuffer) + 1] = 0;
OutBuffer[strlen(OutBuffer)] = Buffer[*Pos];
}
(*Pos)++;
}
}
void StringToDouble(char *text, double *d)
{
bool before=true;
double multiply = 1;
unsigned int i;
*d = 0;
for (i=0;i<strlen(text);i++) {
if (isdigit(text[i])) {
if (before) {
(*d)=(*d)*10+(text[i]-'0');
} else {
multiply=multiply*0.1;
(*d)=(*d)+(text[i]-'0')*multiply;
}
}
if (text[i]=='.' || text[i]==',') before=false;
}
}
/* When char can be converted, convert it from Unicode to UTF8 */
bool EncodeWithUTF8Alphabet(unsigned char mychar1, unsigned char mychar2, unsigned char *ret1, unsigned char *ret2)
{
unsigned char mychar3,mychar4;
int j=0;
if (mychar1>0x00 || mychar2>128) {
mychar3=0x00;
mychar4=128;
while (true) {
if (mychar3==mychar1) {
if (mychar4+64>=mychar2) {
*ret1=j+0xc2;
*ret2=0x80+(mychar2-mychar4);
return true;
}
}
if (mychar4==192) {
mychar3++;
mychar4=0;
} else {
mychar4=mychar4+64;
}
j++;
}
}
return false;
}
/* Make UTF8 string from Unicode input string */
bool EncodeUTF8QuotedPrintable(unsigned char *dest, const unsigned char *src)
{
int i,j=0;
unsigned char mychar1, mychar2;
bool retval = false;
for (i = 0; i < (int)(UnicodeLength(src)); i++) {
if (EncodeWithUTF8Alphabet(src[i*2],src[i*2+1],&mychar1,&mychar2)) {
sprintf(dest+j, "=%02X=%02X",mychar1,mychar2);
j = j+6;
retval = true;
} else {
j += DecodeWithUnicodeAlphabet(((wchar_t)(src[i*2]*256+src[i*2+1])), dest + j);
}
}
dest[j++]=0;
return retval;
}
bool EncodeUTF8(unsigned char *dest, const unsigned char *src)
{
int i,j=0;
unsigned char mychar1, mychar2;
bool retval = false;
for (i = 0; i < (int)(UnicodeLength(src)); i++) {
if (EncodeWithUTF8Alphabet(src[i*2],src[i*2+1],&mychar1,&mychar2)) {
sprintf(dest+j, "%c%c",mychar1,mychar2);
j = j+2;
retval = true;
} else {
j += DecodeWithUnicodeAlphabet(((wchar_t)(src[i*2]*256+src[i*2+1])), dest + j);
}
}
dest[j++]=0;
return retval;
}
/* Decode UTF8 char to Unicode char */
wchar_t DecodeWithUTF8Alphabet(unsigned char mychar3, unsigned char mychar4)
{
unsigned char mychar1, mychar2;
int j;
mychar1=0x00;
mychar2=128;
for(j=0;j<mychar3-0xc2;j++) {
diff --git a/gammu/emb/common/misc/coding/coding.h b/gammu/emb/common/misc/coding/coding.h
index d0c334d..4cf0038 100644
--- a/gammu/emb/common/misc/coding/coding.h
+++ b/gammu/emb/common/misc/coding/coding.h
@@ -1,133 +1,148 @@
/* (c) 2002-2004 by Marcin Wiacek and others */
#ifndef __coding_h
#define __coding_h
+#if defined(_MSC_VER) && defined(__cplusplus)
+ extern "C" {
+#endif
+
#include <stdlib.h>
#include "../misc.h"
#ifdef __OpenBSD__
typedef int wint_t;
#endif
/* ---------------------------- Unicode ------------------------------------ */
bool mywstrncasecmp (unsigned const char *a, unsigned const char *b, int num);
-unsigned char *mystrstr (unsigned const char *haystack, unsigned const char *needle);
+unsigned char *mywstrstr (unsigned const char *haystack, unsigned const char *needle);
bool mywstrncmp (unsigned const char *a, unsigned const char *b, int num);
bool myiswspace (unsigned const char *src);
int mytowlower (wchar_t c);
unsigned int EncodeWithUnicodeAlphabet (const unsigned char *value, wchar_t *dest);
unsigned int DecodeWithUnicodeAlphabet (wchar_t value, unsigned char *dest);
unsigned int UnicodeLength (const unsigned char *str);
unsigned char *DecodeUnicodeString (const unsigned char *src);
unsigned char *DecodeUnicodeConsole (const unsigned char *src);
void DecodeUnicode (const unsigned char *src, unsigned char *dest);
void EncodeUnicode (unsigned char *dest, const unsigned char *src, int len);
void CopyUnicodeString (unsigned char *Dest, unsigned char *Source);
void ReverseUnicodeString (unsigned char *String);
void ReadUnicodeFile (unsigned char *Dest, unsigned char *Source);
void DecodeUnicodeSpecialNOKIAChars (unsigned char *dest, const unsigned char *src, int len);
void EncodeUnicodeSpecialNOKIAChars (unsigned char *dest, const unsigned char *src, int len);
+char *EncodeUnicodeSpecialChars (unsigned char *buffer);
+char *DecodeUnicodeSpecialChars (unsigned char *buffer);
+
/* ------------------------------- BCD ------------------------------------- */
unsigned char EncodeWithBCDAlphabet (int value);
int DecodeWithBCDAlphabet (unsigned char value);
void DecodeBCD (unsigned char *dest, const unsigned char *src, int len);
void EncodeBCD (unsigned char *dest, const unsigned char *src, int len, bool fill);
/* ------------------------------ UTF7 ------------------------------------- */
void DecodeUTF7 (unsigned char *dest, const unsigned char *src, int len);
/* ------------------------------ UTF8 ------------------------------------- */
wchar_t DecodeWithUTF8Alphabet (unsigned char mychar3, unsigned char mychar4);
bool EncodeWithUTF8Alphabet (unsigned char mychar1, unsigned char mychar2, unsigned char *ret1, unsigned char *ret2);
bool EncodeUTF8QuotedPrintable (unsigned char *dest, const unsigned char *src);
void DecodeUTF8QuotedPrintable (unsigned char *dest, const unsigned char *src, int len);
bool EncodeUTF8 (unsigned char *dest, const unsigned char *src);
void DecodeUTF8 (unsigned char *dest, const unsigned char *src, int len);
/* ------------------------------- BASE64 ---------------------------------- */
void EncodeBASE64 (const unsigned char *Input, unsigned char *Output, int Length);
int DecodeBASE64 (const unsigned char *Input, unsigned char *Output, int Length);
/* ----------------------------- HexBin ------------------------------------ */
void DecodeHexBin (unsigned char *dest, const unsigned char *src, int len);
void EncodeHexBin (unsigned char *dest, const unsigned char *src, int len);
/* ----------------------------- HexUnicode -------------------------------- */
void DecodeHexUnicode (unsigned char *dest, const unsigned char *src, int len);
void EncodeHexUnicode (unsigned char *dest, const unsigned char *src, int len);
/* ---------------------- DefaultAlphabet for SMS -------------------------- */
void EncodeDefault (unsigned char *dest, const unsigned char *src, int *len, bool UseExtensions, unsigned char *ExtraAlphabet);
void DecodeDefault (unsigned char *dest, const unsigned char *src, int len, bool UseExtensions, unsigned char *ExtraAlphabet);
void FindDefaultAlphabetLen (const unsigned char *src, int *srclen, int *smslen, int maxlen);
int GSM_PackSevenBitsToEight (int offset, unsigned char *input, unsigned char *output, int length);
int GSM_UnpackEightBitsToSeven (int offset, int in_length, int out_length,
unsigned char *input, unsigned char *output);
/* ----------------- Phone numbers according to GSM specs ------------------ */
/**
* Enum to handle types of phones numbers like
* specified in GSM 03.40 section 9.1.2.5
*/
typedef enum {
/**
* Unknown number type
*/
- NUMBER_UNKNOWN = 0x81,
+ NUMBER_UNKNOWN_NUMBERING_PLAN_ISDN = 0x81,
/**
* International number (full number with code of country)
*/
- NUMBER_INTERNATIONAL = 0x91,
+ NUMBER_INTERNATIONAL_NUMBERING_PLAN_ISDN = 0x91,
/**
* Alphanumeric number (with chars too)
*/
- NUMBER_ALPHANUMERIC = 0xD0
+ NUMBER_ALPHANUMERIC_NUMBERING_PLAN_UNKNOWN = 0xD0
/* specification give also other values */
} GSM_NumberType;
void GSM_UnpackSemiOctetNumber (unsigned char *retval, unsigned char *Number, bool semioctet);
int GSM_PackSemiOctetNumber (unsigned char *Number, unsigned char *Output, bool semioctet);
/* ---------------------------- Bits --------------------------------------- */
void BufferAlign (unsigned char *Destination, int *CurrentBit);
void BufferAlignNumber(int *CurrentBit);
void AddBuffer (unsigned char *Destination, int *CurrentBit, unsigned char *Source, int BitsToProcess);
void AddBufferByte(unsigned char *Destination, int *CurrentBit, unsigned char Source, int BitsToProcess);
void GetBuffer (unsigned char *Source, int *CurrentBit, unsigned char *Destination, int BitsToProcess);
void GetBufferInt (unsigned char *Source, int *CurrentBit, int *integer, int BitsToProcess);
void GetBufferI (unsigned char *Source, int *CurrentBit, int *result, int BitsToProcess);
int GetBit (unsigned char *Buffer, int BitNum);
int SetBit (unsigned char *Buffer, int BitNum);
int ClearBit (unsigned char *Buffer, int BitNum);
/* ---------------------------- Other -------------------------------------- */
void StringToDouble (char *text, double *d);
-bool mystrncasecmp (unsigned const char *a, unsigned const char *b, int num);
+bool mystrncasecmp (unsigned const char *a, unsigned const char *b, int num);
+char *mystrcasestr (unsigned const char *a, unsigned const char *b);
-void MyGetLine(unsigned char *Buffer, int *Pos, unsigned char *OutBuffer, int MaxLen);
+void MyGetLine (unsigned char *Buffer, int *Pos, unsigned char *OutBuffer, int MaxLen);
+
+char *EncodeSpecialChars(unsigned char *buffer);
+char *DecodeSpecialChars(unsigned char *buffer);
+
+#if defined(_MSC_VER) && defined(__cplusplus)
+ }
+#endif
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/misc/coding/md5.c b/gammu/emb/common/misc/coding/md5.c
index 30fe33f..abb61be 100644
--- a/gammu/emb/common/misc/coding/md5.c
+++ b/gammu/emb/common/misc/coding/md5.c
@@ -1,193 +1,193 @@
-/* Taken from ReHash (see http://www.reichlsoft.de.vu/) and released
+/* Taken from ReHash (www.reichlsoft.de.vu) and released
* under GPL/LGPL with permission from ReHash author
* Dominik Reichl <dominik.reichl@t-online.de>, Germany
*/
/*
**********************************************************************
** MD5.cpp **
** **
** - Style modified by Tony Ray, January 2001 **
** Added support for randomizing initialization constants **
** - Style modified by Dominik Reichl, April 2003 **
** Optimized code **
** **
** MD5.c **
** RSA Data Security, Inc. MD5 Message Digest Algorithm **
** Created: 2/17/90 RLR **
** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version **
**********************************************************************
*/
/*
**********************************************************************
** MD5.h -- Header file for implementation of MD5 **
** RSA Data Security, Inc. MD5 Message Digest Algorithm **
** Created: 2/17/90 RLR **
** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
** Revised (for MD5): RLR 4/27/91 **
** -- G modified to have y&~z instead of y&z **
** -- FF, GG, HH modified to add in last register done **
** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
** -- distinct additive constant for each step **
** -- round 4 added, working mod 7 **
**********************************************************************
*/
/*
**********************************************************************
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
** **
** License to copy and use this software is granted provided that **
** it is identified as the "RSA Data Security, Inc. MD5 Message **
** Digest Algorithm" in all material mentioning or referencing this **
** software or this function. **
** **
** License is also granted to make and use derivative works **
** provided that such works are identified as "derived from the RSA **
** Data Security, Inc. MD5 Message Digest Algorithm" in all **
** material mentioning or referencing the derived work. **
** **
** RSA Data Security, Inc. makes no representations concerning **
** either the merchantability of this software or the suitability **
** of this software for any particular purpose. It is provided "as **
** is" without express or implied warranty of any kind. **
** **
** These notices must be retained in any copies of any part of this **
** documentation and/or software. **
**********************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include "md5.h"
/* Typedef a 32 bit type */
#ifndef UINT4
typedef unsigned long int UINT4;
#endif
/* Data structure for MD5 (Message Digest) computation */
typedef struct {
UINT4 i[2]; /* Number of _bits_ handled mod 2^64 */
UINT4 buf[4]; /* Scratch buffer */
unsigned char in[64]; /* Input buffer */
unsigned char digest[16]; /* Actual digest after MD5Final call */
} MD5_CTX;
/* Padding */
static unsigned char MD5_PADDING[64] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* MD5_F, MD5_G and MD5_H are basic MD5 functions: selection, majority, parity */
#define MD5_F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define MD5_G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define MD5_H(x, y, z) ((x) ^ (y) ^ (z))
#define MD5_I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits */
#ifndef ROTATE_LEFT
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
#endif
/* MD5_FF, MD5_GG, MD5_HH, and MD5_II transformations for rounds 1, 2, 3, and 4 */
/* Rotation is separate from addition to prevent recomputation */
#define MD5_FF(a, b, c, d, x, s, ac) {(a) += MD5_F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
#define MD5_GG(a, b, c, d, x, s, ac) {(a) += MD5_G ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
#define MD5_HH(a, b, c, d, x, s, ac) {(a) += MD5_H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
#define MD5_II(a, b, c, d, x, s, ac) {(a) += MD5_I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
/* Constants for transformation */
#define MD5_S11 7 /* Round 1 */
#define MD5_S12 12
#define MD5_S13 17
#define MD5_S14 22
#define MD5_S21 5 /* Round 2 */
#define MD5_S22 9
#define MD5_S23 14
#define MD5_S24 20
#define MD5_S31 4 /* Round 3 */
#define MD5_S32 11
#define MD5_S33 16
#define MD5_S34 23
#define MD5_S41 6 /* Round 4 */
#define MD5_S42 10
#define MD5_S43 15
#define MD5_S44 21
/* Basic MD5 step. MD5_Transform buf based on in */
static void MD5_Transform (UINT4 *buf, UINT4 *in)
{
UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
/* Round 1 */
MD5_FF ( a, b, c, d, in[ 0], MD5_S11, (UINT4) 3614090360u); /* 1 */
MD5_FF ( d, a, b, c, in[ 1], MD5_S12, (UINT4) 3905402710u); /* 2 */
MD5_FF ( c, d, a, b, in[ 2], MD5_S13, (UINT4) 606105819u); /* 3 */
MD5_FF ( b, c, d, a, in[ 3], MD5_S14, (UINT4) 3250441966u); /* 4 */
MD5_FF ( a, b, c, d, in[ 4], MD5_S11, (UINT4) 4118548399u); /* 5 */
MD5_FF ( d, a, b, c, in[ 5], MD5_S12, (UINT4) 1200080426u); /* 6 */
MD5_FF ( c, d, a, b, in[ 6], MD5_S13, (UINT4) 2821735955u); /* 7 */
MD5_FF ( b, c, d, a, in[ 7], MD5_S14, (UINT4) 4249261313u); /* 8 */
MD5_FF ( a, b, c, d, in[ 8], MD5_S11, (UINT4) 1770035416u); /* 9 */
MD5_FF ( d, a, b, c, in[ 9], MD5_S12, (UINT4) 2336552879u); /* 10 */
MD5_FF ( c, d, a, b, in[10], MD5_S13, (UINT4) 4294925233u); /* 11 */
MD5_FF ( b, c, d, a, in[11], MD5_S14, (UINT4) 2304563134u); /* 12 */
MD5_FF ( a, b, c, d, in[12], MD5_S11, (UINT4) 1804603682u); /* 13 */
MD5_FF ( d, a, b, c, in[13], MD5_S12, (UINT4) 4254626195u); /* 14 */
MD5_FF ( c, d, a, b, in[14], MD5_S13, (UINT4) 2792965006u); /* 15 */
MD5_FF ( b, c, d, a, in[15], MD5_S14, (UINT4) 1236535329u); /* 16 */
/* Round 2 */
MD5_GG ( a, b, c, d, in[ 1], MD5_S21, (UINT4) 4129170786u); /* 17 */
MD5_GG ( d, a, b, c, in[ 6], MD5_S22, (UINT4) 3225465664u); /* 18 */
MD5_GG ( c, d, a, b, in[11], MD5_S23, (UINT4) 643717713u); /* 19 */
MD5_GG ( b, c, d, a, in[ 0], MD5_S24, (UINT4) 3921069994u); /* 20 */
MD5_GG ( a, b, c, d, in[ 5], MD5_S21, (UINT4) 3593408605u); /* 21 */
MD5_GG ( d, a, b, c, in[10], MD5_S22, (UINT4) 38016083u); /* 22 */
MD5_GG ( c, d, a, b, in[15], MD5_S23, (UINT4) 3634488961u); /* 23 */
MD5_GG ( b, c, d, a, in[ 4], MD5_S24, (UINT4) 3889429448u); /* 24 */
MD5_GG ( a, b, c, d, in[ 9], MD5_S21, (UINT4) 568446438u); /* 25 */
MD5_GG ( d, a, b, c, in[14], MD5_S22, (UINT4) 3275163606u); /* 26 */
MD5_GG ( c, d, a, b, in[ 3], MD5_S23, (UINT4) 4107603335u); /* 27 */
MD5_GG ( b, c, d, a, in[ 8], MD5_S24, (UINT4) 1163531501u); /* 28 */
MD5_GG ( a, b, c, d, in[13], MD5_S21, (UINT4) 2850285829u); /* 29 */
MD5_GG ( d, a, b, c, in[ 2], MD5_S22, (UINT4) 4243563512u); /* 30 */
MD5_GG ( c, d, a, b, in[ 7], MD5_S23, (UINT4) 1735328473u); /* 31 */
MD5_GG ( b, c, d, a, in[12], MD5_S24, (UINT4) 2368359562u); /* 32 */
/* Round 3 */
MD5_HH ( a, b, c, d, in[ 5], MD5_S31, (UINT4) 4294588738u); /* 33 */
MD5_HH ( d, a, b, c, in[ 8], MD5_S32, (UINT4) 2272392833u); /* 34 */
MD5_HH ( c, d, a, b, in[11], MD5_S33, (UINT4) 1839030562u); /* 35 */
MD5_HH ( b, c, d, a, in[14], MD5_S34, (UINT4) 4259657740u); /* 36 */
MD5_HH ( a, b, c, d, in[ 1], MD5_S31, (UINT4) 2763975236u); /* 37 */
MD5_HH ( d, a, b, c, in[ 4], MD5_S32, (UINT4) 1272893353u); /* 38 */
MD5_HH ( c, d, a, b, in[ 7], MD5_S33, (UINT4) 4139469664u); /* 39 */
MD5_HH ( b, c, d, a, in[10], MD5_S34, (UINT4) 3200236656u); /* 40 */
MD5_HH ( a, b, c, d, in[13], MD5_S31, (UINT4) 681279174u); /* 41 */
MD5_HH ( d, a, b, c, in[ 0], MD5_S32, (UINT4) 3936430074u); /* 42 */
MD5_HH ( c, d, a, b, in[ 3], MD5_S33, (UINT4) 3572445317u); /* 43 */
MD5_HH ( b, c, d, a, in[ 6], MD5_S34, (UINT4) 76029189u); /* 44 */
MD5_HH ( a, b, c, d, in[ 9], MD5_S31, (UINT4) 3654602809u); /* 45 */
MD5_HH ( d, a, b, c, in[12], MD5_S32, (UINT4) 3873151461u); /* 46 */
MD5_HH ( c, d, a, b, in[15], MD5_S33, (UINT4) 530742520u); /* 47 */
MD5_HH ( b, c, d, a, in[ 2], MD5_S34, (UINT4) 3299628645u); /* 48 */
/* Round 4 */
MD5_II ( a, b, c, d, in[ 0], MD5_S41, (UINT4) 4096336452u); /* 49 */
MD5_II ( d, a, b, c, in[ 7], MD5_S42, (UINT4) 1126891415u); /* 50 */
MD5_II ( c, d, a, b, in[14], MD5_S43, (UINT4) 2878612391u); /* 51 */
MD5_II ( b, c, d, a, in[ 5], MD5_S44, (UINT4) 4237533241u); /* 52 */
MD5_II ( a, b, c, d, in[12], MD5_S41, (UINT4) 1700485571u); /* 53 */
MD5_II ( d, a, b, c, in[ 3], MD5_S42, (UINT4) 2399980690u); /* 54 */
MD5_II ( c, d, a, b, in[10], MD5_S43, (UINT4) 4293915773u); /* 55 */
diff --git a/gammu/emb/common/misc/misc.c b/gammu/emb/common/misc/misc.c
index c2f09e4..7227e7b 100644
--- a/gammu/emb/common/misc/misc.c
+++ b/gammu/emb/common/misc/misc.c
@@ -1,591 +1,600 @@
/* (c) 2002-2004 by Marcin Wiacek and Michal Cihar */
/* Checking used compiler (c) 2002 by Michal Cihar */
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <stdarg.h>
#include <stdio.h>
#include <locale.h>
#include <sys/timeb.h>
#ifdef WIN32
# include "windows.h"
#endif
+#if defined(linux) || defined(__linux) || defined(__linux__)
+# include <sys/utsname.h>
+#endif
#include "../gsmstate.h"
#include "misc.h"
/* Based on article in Polish PC-Kurier 8/1998 page 104
* Archive on http://www.pckurier.pl
*/
char *DayOfWeek (int year, int month, int day)
{
int p,q,r,w;
static char DayOfWeekChar[10];
p=(14-month) / 12;
q=month+12*p-2;
r=year-p;
w=(day+(31*q) / 12 + r + r / 4 - r / 100 + r / 400) % 7;
strcpy(DayOfWeekChar,"");
switch (w) {
case 0: strcpy(DayOfWeekChar,"Sun"); break;
case 1: strcpy(DayOfWeekChar,"Mon"); break;
case 2: strcpy(DayOfWeekChar,"Tue"); break;
case 3: strcpy(DayOfWeekChar,"Wed"); break;
case 4: strcpy(DayOfWeekChar,"Thu"); break;
case 5: strcpy(DayOfWeekChar,"Fri"); break;
case 6: strcpy(DayOfWeekChar,"Sat"); break;
}
return DayOfWeekChar;
}
void Fill_GSM_DateTime(GSM_DateTime *Date, time_t timet)
{
struct tm *now;
now = localtime(&timet);
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;
}
void GSM_GetCurrentDateTime (GSM_DateTime *Date)
{
Fill_GSM_DateTime(Date, time(NULL));
if (Date->Year<1900) {
if (Date->Year>90) Date->Year = Date->Year+1900;
else Date->Year = Date->Year+2000;
}
}
time_t Fill_Time_T(GSM_DateTime DT, int TZ)
{
struct tm tm_starttime;
unsigned char buffer[30];
dbgprintf(" StartTime : %02i-%02i-%04i %02i:%02i:%02i\n",
DT.Day,DT.Month,DT.Year,DT.Hour,DT.Minute,DT.Second);
if (TZ != 0) {
#if defined(WIN32) || defined(__SVR4)
sprintf(buffer,"TZ=PST+%i",TZ);
putenv(buffer);
#else
sprintf(buffer,"PST+%i",TZ);
setenv("TZ",buffer,1);
#endif
}
tzset();
memset(&tm_starttime, 0, sizeof(tm_starttime));
tm_starttime.tm_year = DT.Year - 1900;
tm_starttime.tm_mon = DT.Month - 1;
tm_starttime.tm_mday = DT.Day;
tm_starttime.tm_hour = DT.Hour;
tm_starttime.tm_min = DT.Minute;
tm_starttime.tm_sec = DT.Second;
tm_starttime.tm_isdst = 0;
return mktime(&tm_starttime);
}
void GetTimeDifference(unsigned long diff, GSM_DateTime *DT, bool Plus, int multi)
{
time_t t_time;
t_time = Fill_Time_T(*DT,8);
if (Plus) {
t_time += diff*multi;
} else {
t_time -= diff*multi;
}
Fill_GSM_DateTime(DT, t_time);
DT->Year = DT->Year + 1900;
dbgprintf(" EndTime : %02i-%02i-%04i %02i:%02i:%02i\n",
DT->Day,DT->Month,DT->Year,DT->Hour,DT->Minute,DT->Second);
}
char *OSDateTime (GSM_DateTime dt, bool TimeZone)
{
struct tm timeptr;
static char retval[200],retval2[200];
int p,q,r,w;
#ifdef WIN32
setlocale(LC_ALL, ".OCP");
#endif
/* Based on article in Polish PC-Kurier 8/1998 page 104
* Archive on http://www.pckurier.pl
*/
p=(14-dt.Month) / 12;
q=dt.Month+12*p-2;
r=dt.Year-p;
w=(dt.Day+(31*q) / 12 + r + r / 4 - r / 100 + r / 400) % 7;
timeptr.tm_yday = 0; /* FIXME */
timeptr.tm_isdst = -1; /* FIXME */
timeptr.tm_year = dt.Year - 1900;
timeptr.tm_mon = dt.Month - 1;
timeptr.tm_mday = dt.Day;
timeptr.tm_hour = dt.Hour;
timeptr.tm_min = dt.Minute;
timeptr.tm_sec = dt.Second;
timeptr.tm_wday = w;
#ifdef _BSD_SOURCE
timeptr.tm_zone = NULL;
#endif
#ifdef WIN32
strftime(retval2, 200, "%#c", &timeptr);
#else
strftime(retval2, 200, "%c", &timeptr);
#endif
if (TimeZone) {
if (dt.Timezone >= 0) {
sprintf(retval," +%02i00",dt.Timezone);
} else {
sprintf(retval," -%02i00",dt.Timezone);
}
strcat(retval2,retval);
}
/* If don't have weekday name, include it */
strftime(retval, 200, "%A", &timeptr);
if (strstr(retval2,retval)==NULL) {
/* Check for abbreviated weekday */
strftime(retval, 200, "%a", &timeptr);
if (strstr(retval2,retval)==NULL) {
strcat(retval2," (");
strcat(retval2,retval);
strcat(retval2,")");
}
}
#ifdef WIN32
setlocale(LC_ALL, ".ACP");
#endif
return retval2;
}
char *OSDate (GSM_DateTime dt)
{
struct tm timeptr;
static char retval[200],retval2[200];
int p,q,r,w;
#ifdef WIN32
setlocale(LC_ALL, ".OCP");
#endif
/* Based on article in Polish PC-Kurier 8/1998 page 104
* Archive on http://www.pckurier.pl
*/
p=(14-dt.Month) / 12;
q=dt.Month+12*p-2;
r=dt.Year-p;
w=(dt.Day+(31*q) / 12 + r + r / 4 - r / 100 + r / 400) % 7;
timeptr.tm_yday = 0; /* FIXME */
timeptr.tm_isdst = -1; /* FIXME */
timeptr.tm_year = dt.Year - 1900;
timeptr.tm_mon = dt.Month - 1;
timeptr.tm_mday = dt.Day;
timeptr.tm_hour = dt.Hour;
timeptr.tm_min = dt.Minute;
timeptr.tm_sec = dt.Second;
timeptr.tm_wday = w;
#ifdef _BSD_SOURCE
timeptr.tm_zone = NULL;
#endif
#ifdef WIN32
strftime(retval2, 200, "%#x", &timeptr);
#else
strftime(retval2, 200, "%x", &timeptr);
#endif
/* If don't have weekday name, include it */
strftime(retval, 200, "%A", &timeptr);
if (strstr(retval2,retval)==NULL) {
/* Check also for short name */
strftime(retval, 200, "%a", &timeptr);
if (strstr(retval2,retval)==NULL) {
strcat(retval2," (");
strcat(retval2,retval);
strcat(retval2,")");
}
}
#ifdef WIN32
setlocale(LC_ALL, ".ACP");
#endif
return retval2;
}
bool CheckDate(GSM_DateTime *date)
-{
- /* FIXME: This could also check if day is correct for selected month */
+{
+ const unsigned int days[]={31,29,31,30,31,30,31,31,30,31,30,31};
+
+ /* FIXME: This could also check for leap years */
return date->Year != 0 &&
- date->Month >= 1 && date->Month <= 12 &&
- date->Day >= 1 && date->Day <= 31;
+ date->Month >= 1 && date->Month <= 12 &&
+ date->Day >= 1 && date->Day <= days[date->Month];
}
bool CheckTime(GSM_DateTime *date)
{
return date->Hour <= 23 && date->Hour >= 0 &&
date->Minute <= 59 && date->Minute >= 0 &&
date->Second <= 59 && date->Second >= 0;
}
int GetLine(FILE *File, char *Line, int count)
{
int num;
if (fgets(Line, count, File) != NULL) {
num = strlen(Line) - 1;
while(1) {
if (Line[num] != '\n' && Line[num] != '\r') break;
if (num == 0) break;
Line[num--] = 0;
}
return strlen(Line);
}
return -1;
}
void SplitLines(unsigned char *message, int messagesize, GSM_Lines *lines, unsigned char *whitespaces, int spaceslen, bool eot)
{
int i,number=0,j;
bool whitespace=true, nowwhite;
for (i=0;i<MAX_LINES*2;i++) lines->numbers[i]=0;
for (i=0;i<messagesize;i++) {
nowwhite = false;
for (j=0;j<spaceslen;j++) {
if (whitespaces[j] == message[i]) {
nowwhite = true;
break;
}
}
if (whitespace) {
if (!nowwhite) {
lines->numbers[number]=i;
number++;
whitespace=false;
}
} else {
if (nowwhite) {
lines->numbers[number]=i;
number++;
whitespace=true;
}
}
}
if (eot && !whitespace) lines->numbers[number]=messagesize;
}
char *GetLineString(unsigned char *message, GSM_Lines lines, int start)
{
static char retval[800];
memcpy(retval,message + lines.numbers[start*2-2],lines.numbers[start*2-2+1]-lines.numbers[start*2-2]);
retval[lines.numbers[start*2-2+1]-lines.numbers[start*2-2]]=0;
return retval;
}
void CopyLineString(unsigned char *dest, unsigned char *src, GSM_Lines lines, int start)
{
memcpy(dest,GetLineString(src, lines, start),strlen(GetLineString(src, lines, start)));
dest[strlen(GetLineString(src, lines, start))] = 0;
}
Debug_Info di = {0,NULL,false,""};
#ifdef DEBUG
#ifdef __GNUC__
__attribute__((format(printf, 1, 2)))
#endif
int dbgprintf(const char *format, ...)
{
va_list argp;
int result;
static unsigned char nextline[2000]="";
unsigned char buffer[2000];
GSM_DateTime date_time;
if (di.df != NULL && (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE)) {
va_start(argp, format);
result = vsprintf(buffer, format, argp);
strcat(nextline, buffer);
if (strstr(buffer, "\n")) {
if (di.dl == DL_TEXTALLDATE) {
GSM_GetCurrentDateTime(&date_time);
fprintf(di.df,"%s %4d/%02d/%02d %02d:%02d:%02d: %s",
DayOfWeek(date_time.Year, date_time.Month, date_time.Day),
date_time.Year, date_time.Month, date_time.Day,
date_time.Hour, date_time.Minute, date_time.Second,nextline);
} else {
fprintf(di.df,"%s",nextline);
}
strcpy(nextline, "");
}
fflush(di.df);
va_end(argp);
return result;
}
return 0;
}
#endif
/* assumption: if \n is present it is always the last char,
* string never of the form "......\n..."
*/
#ifdef __GNUC__
__attribute__((format(printf, 3, 4)))
#endif
int smfprintf(FILE *f, Debug_Level dl, const char *format, ...)
{
va_list argp;
int result=0;
static unsigned char prevline[2000] = "", nextline[2000]="";
static unsigned int linecount=0;
unsigned char buffer[2000];
GSM_DateTime date_time;
if (f == NULL) return 0;
va_start(argp, format);
result = vsprintf(buffer, format, argp);
strcat(nextline, buffer);
if (strstr(buffer, "\n")) {
if (ftell(f) < 5000000) {
GSM_GetCurrentDateTime(&date_time);
if (linecount > 0) {
if (dl == DL_TEXTALLDATE || dl == DL_TEXTERRORDATE || dl == DL_TEXTDATE) {
fprintf(f,"%s %4d/%02d/%02d %02d:%02d:%02d: <%i> %s",
DayOfWeek(date_time.Year, date_time.Month, date_time.Day),
date_time.Year, date_time.Month, date_time.Day,
date_time.Hour, date_time.Minute, date_time.Second,linecount,prevline);
} else {
fprintf(f,"%s",prevline);
}
}
linecount=0;
if (dl == DL_TEXTALLDATE || dl == DL_TEXTERRORDATE || dl == DL_TEXTDATE) {
fprintf(f,"%s %4d/%02d/%02d %02d:%02d:%02d: %s",
DayOfWeek(date_time.Year, date_time.Month, date_time.Day),
date_time.Year, date_time.Month, date_time.Day,
date_time.Hour, date_time.Minute, date_time.Second,nextline);
} else {
fprintf(f,"%s",nextline);
}
strcpy(prevline, nextline);
}
strcpy(nextline, "");
fflush(f);
}
va_end(argp);
return result;
}
bool GSM_SetDebugLevel(char *info, Debug_Info *di)
{
if (!strcmp(info,"nothing")) {di->dl = 0; return true;}
if (!strcmp(info,"text")) {di->dl = DL_TEXT; return true;}
if (!strcmp(info,"textall")) {di->dl = DL_TEXTALL; return true;}
if (!strcmp(info,"binary")) {di->dl = DL_BINARY; return true;}
if (!strcmp(info,"errors")) {di->dl = DL_TEXTERROR; return true;}
if (!strcmp(info,"textdate")) {di->dl = DL_TEXTDATE; return true;}
if (!strcmp(info,"textalldate")) {di->dl = DL_TEXTALLDATE; return true;}
if (!strcmp(info,"errorsdate")) {di->dl = DL_TEXTERRORDATE; return true;}
return false;
}
/* Dumps a message */
void DumpMessage(FILE *df, Debug_Level dl, const unsigned char *message, int messagesize)
{
int i,j=0,len=16;
unsigned char buffer[200];
if (df==NULL || messagesize == 0) return;
smfprintf(df, dl, "\n");
memset(buffer,0x20,sizeof(buffer));
buffer[len*5-1]=0;
for (i = 0; i < messagesize; i++) {
sprintf(buffer+j*4,"%02X",message[i]);
buffer[j*4+2] = 0x20;
if (isprint(message[i]) && message[i]!=0x09) {
if (j != len-1) buffer[j*4+2] = message[i];
buffer[(len-1)*4+j+3] = message[i];
} else {
buffer[(len-1)*4+j+3] = '.';
}
if (j != len-1 && i != messagesize-1) buffer[j*4+3] = '|';
if (j == len-1) {
smfprintf(df, dl, "%s\n", buffer);
memset(buffer,0x20,sizeof(buffer));
buffer[len*5-1]=0;
j = 0;
} else {
j++;
}
}
if (j != 0) smfprintf(df, dl, "%s\n", buffer);
}
char *GetOS(void)
{
#ifdef WIN32
OSVERSIONINFOEX Ver;
bool Extended = true;
#endif
+#if defined(linux) || defined(__linux) || defined(__linux__)
+ struct utsname Ver;
+#endif
static char Buffer[100] = {0x00};
#ifdef WIN32
memset(&Ver,sizeof(OSVERSIONINFOEX),0);
Ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if (!GetVersionEx((OSVERSIONINFO *)&Ver)) {
Extended = false;
Ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx((OSVERSIONINFO *)&Ver)) {
//#ifdef _MSC_VER
// Ver.dwMajorVersion = _winmajor;
// Ver.dwMinorVersion = _winminor;
// Ver.dwBuildNumber = _osver;
//#else
sprintf(Buffer, "Windows");
return Buffer;
//#endif
}
}
/* ----------------- 9x family ------------------ */
/* no info about Win95 SP1, Win95 OSR2.1, Win95 OSR2.5.... */
if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 950) {
sprintf(Buffer,"Win 95");
} else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 1111) {
sprintf(Buffer,"Win 95 OSR2.x");
/* no info about Win98 SP1.... */
} else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 10 && Ver.dwBuildNumber == 1998) {
sprintf(Buffer,"Win 98");
} else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 10 && Ver.dwBuildNumber == 2222) {
sprintf(Buffer,"Win 98 SE");
} else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 90 && Ver.dwBuildNumber == 3000) {
sprintf(Buffer,"Win ME");
/* ---------------- NT family ------------------- */
} else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 1381) {
sprintf(Buffer,"Win NT 4.0");
} else if (Ver.dwMajorVersion == 5 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 2195) {
sprintf(Buffer,"Win 2000");
} else if (Ver.dwMajorVersion == 5 && Ver.dwMinorVersion == 1 && Ver.dwBuildNumber == 2600) {
sprintf(Buffer,"Win XP");
#if _MSC_VER > 1200 //6.0 has it undeclared
if (Extended) {
if (Ver.wSuiteMask & VER_SUITE_PERSONAL) {
sprintf(Buffer+strlen(Buffer)," Home");
} else {
sprintf(Buffer+strlen(Buffer)," Pro");
}
}
#endif
} else if (Ver.dwMajorVersion == 5 && Ver.dwMinorVersion == 2) {
sprintf(Buffer,"Win 2003");
} else {
sprintf(Buffer, "Windows %i.%i.%i",Ver.dwMajorVersion,Ver.dwMinorVersion,Ver.dwBuildNumber);
}
if (Extended && Ver.wServicePackMajor != 0) {
sprintf(Buffer+strlen(Buffer)," SP%i",Ver.wServicePackMajor);
}
#elif defined(linux) || defined(__linux) || defined(__linux__)
- sprintf(Buffer, "Linux");
+ uname(&Ver);
+ sprintf(Buffer, "Linux, kernel %s",Ver.release);
#elif defined(__FreeBSD__)
sprintf(Buffer, "FreeBSD");
#elif defined(__NetBSD__)
sprintf(Buffer, "NetBSD");
#elif defined(__OpenBSD__)
sprintf(Buffer, "OpenBSD");
#elif defined(__GNU__)
sprintf(Buffer, "GNU/Hurd");
#elif defined(sun) || defined(__sun) || defined(__sun__)
# ifdef __SVR4
sprintf(Buffer, "Sun Solaris");
# else
sprintf(Buffer, "SunOS");
# endif
#elif defined(hpux) || defined(__hpux) || defined(__hpux__)
sprintf(Buffer, "HP-UX");
#elif defined(ultrix) || defined(__ultrix) || defined(__ultrix__)
sprintf(Buffer, "DEC Ultrix");
#elif defined(sgi) || defined(__sgi)
sprintf(Buffer, "SGI Irix");
#elif defined(__osf__)
sprintf(Buffer, "OSF Unix");
#elif defined(bsdi) || defined(__bsdi__)
sprintf(Buffer, "BSDI Unix");
#elif defined(_AIX)
sprintf(Buffer, "AIX Unix");
#elif defined(_UNIXWARE)
sprintf(Buffer, "SCO Unixware");
#elif defined(DGUX)
sprintf(Buffer, "DG Unix");
#elif defined(__QNX__)
sprintf(Buffer, "QNX");
#endif
return Buffer;
}
char *GetCompiler(void)
{
static char Buffer[100] = {0x00};
#ifdef WIN32
# ifdef _MSC_VER
if (_MSC_VER == 1200) { //?
sprintf(Buffer, "MS VC 6.0");
} else if (_MSC_VER == 1300) {
sprintf(Buffer, "MS VC .NET 2002");
} else if (_MSC_VER == 1310) {
sprintf(Buffer, "MS VC .NET 2003");
} else {
sprintf(Buffer, "MS VC %i",_MSC_VER);
}
# elif defined(__BORLANDC__)
sprintf(Buffer, "Borland C++ %i",__BORLANDC__);
# endif
#elif defined(DJGPP)
sprintf(Buffer, "djgpp");
#elif defined(__GNUC__)
sprintf(Buffer, "gcc %i.%i", __GNUC__, __GNUC_MINOR__);
#elif defined(__SUNPRO_CC)
sprintf(Buffer, "Sun C++ %x", __SUNPRO_CC);
#endif
return Buffer;
}
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/misc/misc.h b/gammu/emb/common/misc/misc.h
index 8b46170..c461001 100644
--- a/gammu/emb/common/misc/misc.h
+++ b/gammu/emb/common/misc/misc.h
@@ -1,137 +1,145 @@
/* (c) 2002-2004 by Marcin Wiacek */
#ifndef __misc_h
#define __misc_h
+#if defined(_MSC_VER) && defined(__cplusplus)
+ extern "C" {
+#endif
+
#include <stdio.h>
#include <time.h>
#ifdef WIN32
# include <windows.h>
#endif
#include "../config.h"
#ifndef __cplusplus
#ifndef false
# define false 0
#endif
#ifndef true
# define true !0
#endif
#ifndef bool
# define bool char
#endif
#endif /* __cplusplus */
#ifdef WIN32
# define my_sleep(x) ((x)<1000 ? Sleep(1) : Sleep((x)/1000))
#else
# define my_sleep(x) usleep(x)
#endif
#undef MAX
#define MAX(a,b) ((a)>(b) ? (a) : (b))
#undef MIN
#define MIN(a,b) ((a)<(b) ? (a) : (b))
/* ------------------------------------------------------------------------- */
#define MAX_LINES 50
int GetLine(FILE *File, char *Line, int count);
typedef struct {
int numbers[MAX_LINES*2];
} GSM_Lines;
void SplitLines(unsigned char *message, int messagesize, GSM_Lines *lines, unsigned char *whitespaces, int spaceslen, bool eot);
char *GetLineString(unsigned char *message, GSM_Lines lines, int start);
void CopyLineString(unsigned char *dest, unsigned char *src, GSM_Lines lines, int start);
/* ------------------------------------------------------------------------- */
typedef enum {
DL_BINARY = 1, /* Binary transmission dump */
DL_TEXT, /* Text transmission dump */
DL_TEXTALL, /* Everything */
DL_TEXTERROR, /* Only errors */
DL_TEXTDATE, /* Text transmission dump */
DL_TEXTALLDATE, /* Everything */
DL_TEXTERRORDATE /* Only errors */
} Debug_Level;
typedef struct {
Debug_Level dl;
FILE *df;
bool use_global;
char *coding;
} Debug_Info;
extern Debug_Info di;
#ifdef DEBUG
#ifdef __GNUC__
__attribute__((format(printf, 1, 2)))
#endif
int dbgprintf(const char *format, ...);
#else
# ifndef WIN32
# define dbgprintf(a...) do { } while (0)
# else
# define dbgprintf
# endif
#endif
#ifdef __GNUC__
__attribute__((format(printf, 3, 4)))
#endif
int smfprintf(FILE *f, Debug_Level dl, const char *format, ...);
void DumpMessage(FILE *df, Debug_Level dl, const unsigned char *message, int messagesize);
bool GSM_SetDebugLevel(char *info, Debug_Info *di);
/* ------------------------------------------------------------------------- */
/**
* Structure used for saving date and time
*/
typedef struct {
/**
* The difference between local time and GMT in hours
*/
int Timezone;
unsigned int Second;
unsigned int Minute;
unsigned int Hour;
unsigned int Day;
/**
* January = 1, February = 2, etc.
*/
unsigned int Month;
/**
* Complete year number. Not 03, but 2003
*/
unsigned int Year;
} GSM_DateTime;
void GSM_GetCurrentDateTime (GSM_DateTime *Date);
char *OSDateTime (GSM_DateTime dt, bool TimeZone);
char *OSDate (GSM_DateTime dt);
char *DayOfWeek (int year, int month, int day);
time_t Fill_Time_T (GSM_DateTime DT, int TZ);
void GetTimeDifference (unsigned long diff, GSM_DateTime *DT, bool Plus, int multi);
void Fill_GSM_DateTime (GSM_DateTime *Date, time_t timet);
bool CheckDate (GSM_DateTime *date);
bool CheckTime (GSM_DateTime *date);
char *GetCompiler(void);
char *GetOS(void);
+#if defined(_MSC_VER) && defined(__cplusplus)
+ }
+#endif
+
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/alcatel/alcatel.c b/gammu/emb/common/phone/alcatel/alcatel.c
index f004ad4..3821f13 100644
--- a/gammu/emb/common/phone/alcatel/alcatel.c
+++ b/gammu/emb/common/phone/alcatel/alcatel.c
@@ -1,2534 +1,2537 @@
/* (c) 2002-2004 by Michal Cihar */
/*
* High level functions for communication with Alcatel One Touch 501 and
* compatible mobile phone.
*
* This code implements functions to communicate with Alcatel phones,
* currently seem to work:
* - BE5 series (501/701)
* - BF5 series (715)
* - BH4 series (535/735)
- * For some functions it uses normal AT mode (not implemented here, look at
- * ../at/atgen.[ch]) for others it switches into binary mode and initialises
- * underlaying protocol (see ../../protocol/alcatel/alcabus.[ch]) and
+ * For some functions it uses normal AT mode (not implemented here, look at
+ * ../at/atgen.[ch]) for others it switches into binary mode and initialises
+ * underlaying protocol (see ../../protocol/alcatel/alcabus.[ch]) and
* communicates over it. Don't ask me why Alcatel uses such silly thing...
*
* Notes for future features:
* - max phone number length is 61 (BE5)
* - max name length is 50 (BE5)
*/
#include "../../gsmstate.h"
#ifdef GSM_ENABLE_ALCATEL
#ifdef GSM_ENABLE_ATGEN
#include <string.h>
#include <time.h>
#include "../../gsmcomon.h"
#include "../../misc/coding/coding.h"
#include "../../misc/misc.h"
#include "../../service/sms/gsmsms.h"
#include "../pfunc.h"
#include "alcatel.h"
/* Timeout for GSM_WaitFor calls. */
#define ALCATEL_TIMEOUT 64
/* Some magic numbers for protocol follow */
/* synchronisation types (for everything except begin transfer): */
#define ALCATEL_SYNC_TYPE_CALENDAR 0x64
#define ALCATEL_SYNC_TYPE_TODO 0x68
#define ALCATEL_SYNC_TYPE_CONTACTS 0x6C
/* synchronisation types (for begin transfer): */
#define ALCATEL_BEGIN_SYNC_CALENDAR 0x00
#define ALCATEL_BEGIN_SYNC_TODO 0x02
#define ALCATEL_BEGIN_SYNC_CONTACTS 0x01
/* category types */
#define ALCATEL_LIST_TODO_CAT 0x9B
#define ALCATEL_LIST_CONTACTS_CAT 0x96
/* We need lot of ATGEN functions, because Alcatel is an AT device. */
extern GSM_Reply_Function ALCATELReplyFunctions[];
extern GSM_Reply_Function ATGENReplyFunctions[];
extern GSM_Error ATGEN_Initialise (GSM_StateMachine *s);
extern GSM_Error ATGEN_Terminate (GSM_StateMachine *s);
extern GSM_Error ATGEN_GetIMEI (GSM_StateMachine *s);
extern GSM_Error ATGEN_GetFirmware (GSM_StateMachine *s);
extern GSM_Error ATGEN_GetModel (GSM_StateMachine *s);
extern GSM_Error ATGEN_GetDateTime (GSM_StateMachine *s, GSM_DateTime *date_time);
extern GSM_Error ATGEN_GetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry);
extern GSM_Error ATGEN_GetNextMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry, bool start);
extern GSM_Error ATGEN_SetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry);
extern GSM_Error ATGEN_AddMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry);
extern GSM_Error ATGEN_DeleteMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry);
extern GSM_Error ATGEN_GetMemoryStatus (GSM_StateMachine *s, GSM_MemoryStatus *Status);
extern GSM_Error ATGEN_GetSMSC (GSM_StateMachine *s, GSM_SMSC *smsc);
extern GSM_Error ATGEN_SetSMSC (GSM_StateMachine *s, GSM_SMSC *smsc);
extern GSM_Error ATGEN_GetSMSFolders (GSM_StateMachine *s, GSM_SMSFolders *folders);
extern GSM_Error ATGEN_GetSMSStatus (GSM_StateMachine *s, GSM_SMSMemoryStatus *status);
extern GSM_Error ATGEN_GetSMS (GSM_StateMachine *s, GSM_MultiSMSMessage *sms);
extern GSM_Error ATGEN_GetNextSMS (GSM_StateMachine *s, GSM_MultiSMSMessage *sms, bool start);
extern GSM_Error ATGEN_SendSavedSMS (GSM_StateMachine *s, int Folder, int Location);
extern GSM_Error ATGEN_SendSMS (GSM_StateMachine *s, GSM_SMSMessage *sms);
extern GSM_Error ATGEN_DeleteSMS (GSM_StateMachine *s, GSM_SMSMessage *sms);
extern GSM_Error ATGEN_AddSMS (GSM_StateMachine *s, GSM_SMSMessage *sms);
extern GSM_Error ATGEN_GetBatteryCharge (GSM_StateMachine *s, GSM_BatteryCharge *bat);
extern GSM_Error ATGEN_GetSignalQuality (GSM_StateMachine *s, GSM_SignalQuality *sig);
extern GSM_Error ATGEN_DialVoice (GSM_StateMachine *s, char *number, GSM_CallShowNumber ShowNumber);
extern GSM_Error ATGEN_AnswerCall (GSM_StateMachine *s, int ID, bool all);
extern GSM_Error ATGEN_CancelCall (GSM_StateMachine *s, int ID, bool all);
extern GSM_Error ATGEN_SetDateTime (GSM_StateMachine *s, GSM_DateTime *date_time);
extern GSM_Error ATGEN_EnterSecurityCode (GSM_StateMachine *s, GSM_SecurityCode Code);
extern GSM_Error ATGEN_GetSecurityStatus (GSM_StateMachine *s, GSM_SecurityCodeType *Status);
extern GSM_Error ATGEN_ResetPhoneSettings (GSM_StateMachine *s, GSM_ResetSettingsType Type);
extern GSM_Error ATGEN_SendDTMF (GSM_StateMachine *s, char *sequence);
extern GSM_Error ATGEN_GetSIMIMSI (GSM_StateMachine *s, char *IMSI);
extern GSM_Error ATGEN_HandleCMSError (GSM_StateMachine *s);
extern GSM_Error ATGEN_GetNetworkInfo (GSM_StateMachine *s, GSM_NetworkInfo *netinfo);
extern GSM_Error ATGEN_Reset (GSM_StateMachine *s, bool hard);
extern GSM_Error ATGEN_PressKey (GSM_StateMachine *s, GSM_KeyCode Key, bool Press);
extern GSM_Error ATGEN_GetDisplayStatus (GSM_StateMachine *s, GSM_DisplayFeatures *features);
extern GSM_Error ATGEN_SetAutoNetworkLogin (GSM_StateMachine *s);
extern GSM_Error ATGEN_DeleteAllMemory (GSM_StateMachine *s, GSM_MemoryType type);
extern GSM_Error ATGEN_DispatchMessage (GSM_StateMachine *s);
+extern GSM_Error ATGEN_SetFastSMSSending (GSM_StateMachine *s, bool enable);
extern GSM_Error ATGEN_SetIncomingCB (GSM_StateMachine *s, bool enable);
extern GSM_Error ATGEN_SetIncomingSMS (GSM_StateMachine *s, bool enable);
/**
* Alcatel uses some 8-bit characters in contacts, calendar etc.. This table
* attempts to decode it, it is probably not complete, here are just chars
* that I found...
*/
unsigned char GSM_AlcatelAlphabet[] =
{
/* in phone unicode description */
0x80, 0x00,0x20, /* empty */
0x81, 0x00,0x20, /* empty */
0x82, 0x00,0x20, /* empty */
0x83, 0x00,0x20, /* empty */
-
+
0x84, 0x00,0xe7, /* c cedilla */
0x85, 0x20,0x26, /* ... */
0x86, 0x03,0xc0, /* pi */
0x87, 0x01,0x3e, /* l caron */
0x88, 0x00,0xc0, /* A grave */
0x89, 0x00,0xc1, /* A acute */
0x8a, 0x00,0xc2, /* A circumflex */
0x8b, 0x00,0xc3, /* A tilde */
0x8c, 0x00,0xc8, /* E grave */
0x8d, 0x00,0xca, /* E circumflex */
0x8e, 0x00,0xcb, /* E diaresis */
0x8f, 0x00,0xcc, /* I grave */
0x90, 0x00,0xcd, /* I acute */
0x91, 0x00,0xd0, /* ETH */
0x92, 0x00,0xd2, /* O grave */
0x93, 0x00,0xd3, /* O acute */
0x94, 0x00,0xd4, /* O circumflex */
0x95, 0x00,0xd5, /* O tilde */
0x96, 0x00,0xd9, /* U grave */
0x97, 0x00,0xda, /* U acute */
0x98, 0x00,0xe1, /* a acute */
0x99, 0x00,0xe2, /* a circumflex */
0x9a, 0x00,0xe3, /* a tilde */
0x9b, 0x00,0xea, /* e circumflex */
0x9c, 0x00,0xeb, /* e diaresis */
0x9d, 0x00,0xed, /* i acute */
0x9e, 0x00,0xee, /* i circumflex */
0x9f, 0x00,0xef, /* i diaresis */
0xa0, 0x00,0xf3, /* o acute */
0xa1, 0x00,0xf4, /* o circumflex */
0xa2, 0x00,0xf5, /* o tilde */
0xa3, 0x00,0xfa, /* u acute */
0xa4, 0x00,0xa2, /* cent */
0xa5, 0x00,0x5b, /* [ */
0xa6, 0x01,0x59, /* r caron */
0xa7, 0x01,0x0d, /* c caron */
0xa8, 0x01,0x61, /* s caron */
0xa9, 0x01,0x1b, /* e caron */
0xaa, 0x01,0x6f, /* u ring */
0xab, 0x00,0xfd, /* y acute */
0xac, 0x00,0xf0, /* eth */
0xad, 0x01,0x07, /* c acute */
0xae, 0x01,0x19, /* e ogonek */
0xaf, 0x01,0x05, /* a ogonek */
0xb0, 0x01,0x7c, /* z dot */
0xb1, 0x01,0x7a, /* z acute */
0xb2, 0x01,0x5b, /* s acute */
0xb3, 0x01,0x44, /* n acute */
0xb4, 0x01,0x42, /* l stroke */
0xb5, 0x00,0x20, /* empty */
-
+
0xb6, 0x01,0x48, /* n caron */
0xb7, 0x01,0x65, /* t caron */
-
+
0xb8, 0x00,0x20, /* empty */
-
+
0xb9, 0x01,0x7e, /* z caron */
0xba, 0x01,0xe7, /* g caron */
-
+
0xbb, 0x00,0x20, /* empty */
0xbc, 0x00,0x20, /* empty */
-
+
0xbd, 0x1e,0x20, /* G macron */
0xbe, 0x1e,0x21, /* g macron */
0xbf, 0x01,0x5e, /* S cedilla */
0xc0, 0x01,0x5f, /* s cedilla */
0xc1, 0x01,0x2f, /* i ogonek */ /* FIXME: not sure with this, it look like normal i */
0xc2, 0x01,0x31, /* i dotless */
0xc3, 0x01,0x68, /* U tilde */
0xc4, 0x01,0x50, /* O dbl acute */
0xc5, 0x01,0x69, /* u tilde */
0xc6, 0x01,0x51, /* o dbl acute */
0xc7, 0x27,0xa9, /* => */
0xc8, 0x27,0xa8, /* filled => */
0xc9, 0x00,0xd7, /* x */
0xca, 0x00,0x5d, /* ] */
0xcb, 0x26,0x0f, /* phone */
0xcc, 0x01,0x0f, /* d caron */
-
+
0xcd, 0x00,0x20, /* empty */
0xce, 0x00,0x7e, /* ~ */
0xcf, 0x00,0x5c, /* \ */
0xd0, 0x00,0x5e, /* ^ */
-
+
0xd1, 0x00,0x20, /* empty */
-
+
0xd2, 0x00,0x7b, /* { */
0xd3, 0x00,0x7c, /* | */
0xd4, 0x00,0x7d, /* } */
-
+
0xd5, 0x00,0x20, /* empty */
-
+
0xd6, 0x01,0x63, /* t cedilla */
-
+
0xd7, 0x00,0x20, /* empty */
0xd8, 0x00,0x20, /* empty */
0xd9, 0x00,0x20, /* empty */
0xda, 0x00,0x20, /* empty */
0xdb, 0x00,0x20, /* empty */
0xdc, 0x00,0x20, /* empty */
0xdd, 0x00,0x20, /* empty */
0xde, 0x00,0x20, /* empty */
0xdf, 0x00,0x20, /* empty */
0xe0, 0x00,0x20, /* empty */
-
+
0xe1, 0x00,0x20, /* two candles */ /* FIXME */
-
+
0xe2, 0x00,0x20, /* empty */
0xe3, 0x00,0x20, /* empty */
0xe4, 0x00,0x20, /* empty */
-
+
0xe5, 0x01,0xce, /* a caron */
0xe6, 0x01,0x01, /* a macron */
0xe7, 0x01,0x13, /* e macron */
0xe8, 0x01,0x2b, /* i macron */
0xe9, 0x01,0x4d, /* o macron */
0xea, 0x01,0x6b, /* u macron */
0xeb, 0x00,0x41, /* A */
0xec, 0x00,0x40, /* @ */
0xed, 0x00,0x20, /* some strange char :-) */ /* FIXME */
-
+
0xee, 0x00,0x20, /* big key stroken */ /* FIXME */
0xef, 0x00,0x20, /* big key */ /* FIXME */
-
+
0xf0, 0x00,0x20, /* empty */
-
+
0xf1, 0x00,0x31, /* 1 */
0xf2, 0x00,0x21, /* bold ! */
0xf3, 0x26,0x0e, /* black phone */
0xf4, 0x00,0x26, /* & */
0xf5, 0x23,0x7e, /* bell */
0xf6, 0x26,0x6a, /* note */
-
+
0xf7, 0x27,0x13, /* okay inv */ /* FIXME */
0xf8, 0x27,0x13, /* okay */
-
+
0xf9, 0x00,0x20, /* empty */
-
+
0xfa, 0x00,0x20, /* key */ /* FIXME */
-
+
0xfb, 0x00,0x20, /* empty */
-
+
0xfc, 0x20,0xac, /* Euro */
0xfd, 0x21,0x97, /* NE arrow */
0xfe, 0x21,0x98, /* SE arrow */
0xff, 0x00,0x20, /* empty */
-
+
0x00, 0x00,0x00
};
/* This is being called from atgen */
GSM_Error ALCATEL_ProtocolVersionReply (GSM_Protocol_Message msg, GSM_StateMachine *s)
{
char *str, *str2;
/*
* Reply received here looks like:
* 1 "AT+CPROT=?"
* 2 "+CPROT: 0,"V1.0",1"
* 3 "+CPROT: 16,"V1.1",16"
* 4 "OK"
*/
switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
case AT_Reply_OK:
str = strstr(msg.Buffer, "\"V");
if (str == NULL) return ERR_UNKNOWNRESPONSE;
str += 2;
while((str2 = strstr(str, "\"V")) != NULL) str = str2 + 2;
if (strncmp(str, "1.0", 3) == 0) {
s->Phone.Data.Priv.ALCATEL.ProtocolVersion = V_1_0;
} else if (strncmp(str, "1.1", 3) == 0) {
s->Phone.Data.Priv.ALCATEL.ProtocolVersion = V_1_1;
} else {
smprintf(s, "Unknown protocol version. Please send debug log and phone info to author.\n");
return ERR_NOTIMPLEMENTED;
}
return ERR_NONE;
case AT_Reply_Error:
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
return ERR_UNKNOWNRESPONSE;
}
}
static GSM_Error ALCATEL_SetBinaryMode(GSM_StateMachine *s)
{
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_Error error;
if (Priv->Mode == ModeBinary) return ERR_NONE;
dbgprintf ("Changing to binary mode\n");
error=GSM_WaitFor (s, "AT+IFC=2,2\r", 11, 0x02, 4, ID_SetFlowControl);
if (error != ERR_NONE) return error;
-
+
error=GSM_WaitFor (s, "AT+CPROT=?\r", 11, 0x02, 4, ID_AlcatelProtocol);
if (error != ERR_NONE) return error;
if (Priv->ProtocolVersion == V_1_0) {
error=GSM_WaitFor (s, "AT+CPROT=16,\"V1.0\",16\r", 22, 0x00, 4, ID_AlcatelConnect);
} else {
error=GSM_WaitFor (s, "AT+CPROT=16,\"V1.1\",16\r", 22, 0x00, 4, ID_AlcatelConnect);
}
-
+
if (error == ERR_TIMEOUT && s->Speed != 19200) {
smprintf(s, "HINT: Try changing speed to 19200, it is sometimes needed for Alcatel binary mode.\n");
}
-
+
if (error != ERR_NONE) return error;
dbgprintf ("Changing protocol to Alcabus\n");
s->Protocol.Functions = &ALCABUSProtocol;
error = s->Protocol.Functions->Initialise(s);
if (error != ERR_NONE) {
s->Protocol.Functions = &ATProtocol;
return error;
}
s->Phone.Functions->ReplyFunctions = ALCATELReplyFunctions;
Priv->Mode = ModeBinary;
Priv->BinaryItem = 0;
Priv->BinaryType = 0;
Priv->BinaryState = StateAttached;
return ERR_NONE;
}
static GSM_Error ALCATEL_GoToBinaryState(GSM_StateMachine *s, GSM_Alcatel_BinaryState state, GSM_Alcatel_BinaryType type, int item) {
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_Error error;
unsigned char attach_buffer[] = {0x00, 0x00, 0x7C ,0x20};
unsigned char detach_buffer[] = {0x00, 0x01, 0x7C ,0x00};
unsigned char start_buffer[] =
{0x00, 0x04, 0x7C, 0x80, /* 4 byte database id follows */
0x12, 0x34, 0x56, 0x78};
unsigned char end_buffer[] =
{0x00, 0x04, 0x7C, 0x82,
0x00, /* type */
0x00, 0x00, 0x00, 0x00}; /* TimeStamp */
unsigned char close_buffer[] =
{0x00, 0x04,
0x00, /*type */
0x23, 0x01};
unsigned char select1_buffer[] =
{0x00, 0x00,
0x00, /*type */
0x20};
unsigned char select2_buffer[] =
{0x00, 0x04,
0x00, /*type */
0x22, 0x01, 0x00};
unsigned char begin_buffer[] =
{0x00, 0x04, 0x7C, 0x81,
0x00, /*type */
0x00, 0x85, 0x00};
unsigned char commit_buffer[] =
- {0x00, 0x04,
+ {0x00, 0x04,
0x00, /*type */
0x20, 0x01};
smprintf(s, "Alcatel state switcher: %d -> %d, %d -> %d, %d -> %d\n", Priv->BinaryState, state, Priv->BinaryType, type, Priv->BinaryItem, item);
error = ALCATEL_SetBinaryMode(s);
if (error != ERR_NONE) return error;
/* Do we need to do anything? */
if ((state == Priv->BinaryState) && (type == Priv->BinaryType) && (item == Priv->BinaryItem)) return ERR_NONE;
/* We're editing, but the next state is not the same. so commit editing */
if (Priv->BinaryState == StateEdit) {
/* Something has changed, we will have to reread fields! */
Priv->CurrentFieldsItem = -1;
switch (Priv->BinaryType) {
case TypeCalendar:
commit_buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
break;
case TypeContacts:
commit_buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
break;
case TypeToDo:
commit_buffer[2] = ALCATEL_SYNC_TYPE_TODO;
break;
}
dbgprintf ("Commiting edited record\n");
error=GSM_WaitFor (s, commit_buffer, 5, 0x02, ALCATEL_TIMEOUT, ID_AlcatelCommit);
if (error != ERR_NONE) return error;
error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelCommit2);
if (error != ERR_NONE) return error;
Priv->BinaryState = StateSession;
Priv->BinaryItem = 0;
}
/* Do we want to edit something of same type? */
if ((state == StateEdit) && (type == Priv->BinaryType)) {
/* Edit state doesn't need any switching, it is needed only for
* indication that e have to commit record before we switch to other
* mode.
*/
Priv->BinaryState = StateEdit;
Priv->BinaryItem = item;
return ERR_NONE;
}
/* Now we can be only in Attached or Session state, so if states and types matches, just keep them as they are */
if ((state == Priv->BinaryState) && (type == Priv->BinaryType)) {
return ERR_NONE;
}
/* Do we need to close session? */
if (Priv->BinaryState == StateSession) {
dbgprintf ("Ending session\n");
switch (Priv->BinaryType) {
case TypeCalendar:
end_buffer[4] = ALCATEL_BEGIN_SYNC_CALENDAR;
break;
case TypeContacts:
end_buffer[4] = ALCATEL_BEGIN_SYNC_CONTACTS;
break;
case TypeToDo:
end_buffer[4] = ALCATEL_BEGIN_SYNC_TODO;
break;
}
error=GSM_WaitFor (s, end_buffer, 9, 0x02, ALCATEL_TIMEOUT, ID_AlcatelEnd);
if (error != ERR_NONE) return error;
-
+
switch (Priv->BinaryType) {
case TypeCalendar:
close_buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
break;
case TypeContacts:
close_buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
break;
case TypeToDo:
close_buffer[2] = ALCATEL_SYNC_TYPE_TODO;
break;
}
dbgprintf ("Closing session\n");
error=GSM_WaitFor (s, close_buffer, 5, 0x02, ALCATEL_TIMEOUT, ID_AlcatelClose);
if (error != ERR_NONE) return error;
dbgprintf ("Detaching binary mode\n");
GSM_WaitFor (s, detach_buffer, 4, 0x02, ALCATEL_TIMEOUT, ID_AlcatelDetach);
Priv->BinaryState = StateAttached;
Priv->BinaryType = 0;
}
/* Do we need to open session? */
if (state == StateSession || state == StateEdit) {
dbgprintf ("Starting session for %s\n",
(type == TypeCalendar ? "Calendar" :
(type == TypeToDo ? "Todo" :
(type == TypeContacts ? "Contacts" :
"Unknown!"))));
/* Fill up buffers */
switch (type) {
case TypeCalendar:
select1_buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
select2_buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
begin_buffer[4] = ALCATEL_BEGIN_SYNC_CALENDAR;
break;
case TypeContacts:
select1_buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
select2_buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
begin_buffer[4] = ALCATEL_BEGIN_SYNC_CONTACTS;
break;
case TypeToDo:
select1_buffer[2] = ALCATEL_SYNC_TYPE_TODO;
select2_buffer[2] = ALCATEL_SYNC_TYPE_TODO;
begin_buffer[4] = ALCATEL_BEGIN_SYNC_TODO;
break;
}
dbgprintf ("Attaching in binary mode\n");
/* Communicate */
error=GSM_WaitFor (s, attach_buffer, 4, 0x02, ALCATEL_TIMEOUT, ID_AlcatelAttach);
if (error != ERR_NONE) return error;
smprintf(s,"Start session\n");
error=GSM_WaitFor (s, start_buffer, 8, 0x02, ALCATEL_TIMEOUT, ID_AlcatelStart);
if (error != ERR_NONE) return error;
smprintf(s,"Select type\n");
error=GSM_WaitFor (s, select1_buffer, 4, 0x02, ALCATEL_TIMEOUT, ID_AlcatelSelect1);
if (error != ERR_NONE) return error;
error=GSM_WaitFor (s, select2_buffer, 6, 0x02, ALCATEL_TIMEOUT, ID_AlcatelSelect2);
if (error != ERR_NONE) return error;
error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelSelect3);
if (error != ERR_NONE) return error;
smprintf(s,"Begin transfer\n");
error=GSM_WaitFor (s, begin_buffer, 8, 0x02, ALCATEL_TIMEOUT, ID_AlcatelBegin1);
if (error != ERR_NONE) return error;
error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelBegin2);
if (error != ERR_NONE) return error;
Priv->BinaryState = StateSession;
Priv->BinaryType = type;
/* Do we want to edit something of same type? */
if ((state == StateEdit) && (type == Priv->BinaryType)) {
Priv->BinaryState = StateEdit;
Priv->BinaryItem = item;
return ERR_NONE;
}
}
return ERR_NONE;
}
static GSM_Error ALCATEL_SetATMode(GSM_StateMachine *s)
{
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_Error error;
if (Priv->Mode == ModeAT) return ERR_NONE;
error = ALCATEL_GoToBinaryState(s, StateAttached, 0, 0);
if (error != ERR_NONE) return error;
error = s->Protocol.Functions->Terminate(s);
if (error != ERR_NONE) return error;
dbgprintf ("Changing protocol to AT\n");
s->Protocol.Functions = &ATProtocol;
s->Phone.Functions->ReplyFunctions = ATGENReplyFunctions;
Priv->Mode = ModeAT;
+ s->Phone.Data.Priv.ATGEN.PBKCharset = 0;
+ s->Phone.Data.Priv.ATGEN.PBKMemory = 0;
my_sleep(100);
/* In case we don't send AT command short after closing binary mode,
* phone takes VERY long to react next time. The error code in
* intetionally ignored.
*/
GSM_WaitFor (s, "AT\r", 3, 0x00, 0, ID_IncomingFrame);
return ERR_NONE;
}
static GSM_Error ALCATEL_Initialise(GSM_StateMachine *s)
{
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_Error error;
Priv->Mode = ModeAT;
Priv->CalendarItems = NULL;
Priv->ContactsItems = NULL;
Priv->ToDoItems = NULL;
Priv->CalendarItemsCount = 0;
Priv->ToDoItemsCount = 0;
Priv->ContactsItemsCount = 0;
Priv->CurrentFields[0] = 0;
Priv->CurrentFieldsCount = 0;
Priv->CurrentFieldsItem = 0;
Priv->CurrentFieldsType = 0;
Priv->ProtocolVersion = V_1_0;
Priv->CurrentFieldsItem = -1;
Priv->CurrentCategoriesCount = 0;
Priv->CurrentCategoriesType = 0;
s->Protocol.Functions = &ATProtocol;
s->Phone.Functions->ReplyFunctions = ATGENReplyFunctions;
if (ATGEN_Initialise(s) != ERR_NONE || GSM_WaitFor (s, "AT\r", 3, 0x00, 2, ID_IncomingFrame) != ERR_NONE) {
smprintf(s,"AT initialisation failed, trying to stop binary mode...\n");
s->Protocol.Functions = &ALCABUSProtocol;
error = s->Protocol.Functions->Terminate(s);
s->Protocol.Functions = &ATProtocol;
error = ATGEN_Initialise(s);
if (error != ERR_NONE) return error;
}
return ERR_NONE;
}
static GSM_Error ALCATEL_Terminate(GSM_StateMachine *s)
{
GSM_Error error;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
free(Priv->CalendarItems);
free(Priv->ContactsItems);
free(Priv->ToDoItems);
error = ALCATEL_SetATMode(s);
return ATGEN_Terminate(s);
}
/* finds whether id is set in the phone */
static GSM_Error ALCATEL_IsIdAvailable(GSM_StateMachine *s, int id) {
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int i;
if (id > ALCATEL_MAX_LOCATION) return ERR_INVALIDLOCATION;
switch (Priv->BinaryType) {
case TypeCalendar:
Priv->CurrentList = &(Priv->CalendarItems);
Priv->CurrentCount = &(Priv->CalendarItemsCount);
break;
case TypeContacts:
Priv->CurrentList = &(Priv->ContactsItems);
Priv->CurrentCount = &(Priv->ContactsItemsCount);
break;
case TypeToDo:
Priv->CurrentList = &(Priv->ToDoItems);
Priv->CurrentCount = &(Priv->ToDoItemsCount);
break;
}
-
+
for (i=0; i<*Priv->CurrentCount; i++) {
if ((*Priv->CurrentList)[i] == id) return ERR_NONE;
}
-
+
return ERR_EMPTY;
}
/* finds next id that is available in the phone */
static GSM_Error ALCATEL_GetNextId(GSM_StateMachine *s, int *id) {
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int i = 0;
int next = ALCATEL_MAX_LOCATION;
switch (Priv->BinaryType) {
case TypeCalendar:
Priv->CurrentList = &(Priv->CalendarItems);
Priv->CurrentCount = &(Priv->CalendarItemsCount);
break;
case TypeContacts:
Priv->CurrentList = &(Priv->ContactsItems);
Priv->CurrentCount = &(Priv->ContactsItemsCount);
break;
case TypeToDo:
Priv->CurrentList = &(Priv->ToDoItems);
Priv->CurrentCount = &(Priv->ToDoItemsCount);
break;
}
for (i=0; i<*Priv->CurrentCount; i++) {
if (((*Priv->CurrentList)[i] > *id) && ((*Priv->CurrentList)[i] < next )) {
next = (*Priv->CurrentList)[i];
}
}
if (next == ALCATEL_MAX_LOCATION) {
return ERR_EMPTY;
} else {
*id = next;
return ERR_NONE;
}
}
static GSM_Error ALCATEL_ReplyGetIds(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int count,i,pos;
count = msg.Buffer[10];
*Priv->CurrentCount += count;
*Priv->CurrentList = (int *)realloc(*Priv->CurrentList, (*Priv->CurrentCount + 1)* sizeof(int));
if (*Priv->CurrentList == NULL) return ERR_MOREMEMORY;
for (i = 0; i < count; i++) {
pos = 11 + (4 * i);
(*Priv->CurrentList)[*Priv->CurrentCount - count + i] = msg.Buffer[pos + 3] +
(msg.Buffer[pos + 2] << 8) +
(msg.Buffer[pos + 1] << 16) +
(msg.Buffer[pos] << 24);
}
(*Priv->CurrentList)[*Priv->CurrentCount] = 0;
/* If last byte is 0, then we transmitted all items */
Priv->TransferCompleted = msg.Buffer[4 + msg.Buffer[4]] == 0;
return ERR_NONE;
}
static GSM_Error ALCATEL_GetAvailableIds(GSM_StateMachine *s, bool refresh)
{
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_Error error;
int i;
unsigned char buffer[] =
{0x00, 0x04,
0x00, /*type */
0x2F, 0x01};
if (Priv->BinaryState != StateSession) return ERR_UNKNOWN;
switch (Priv->BinaryType) {
case TypeCalendar:
buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
Priv->CurrentList = &(Priv->CalendarItems);
Priv->CurrentCount = &(Priv->CalendarItemsCount);
break;
case TypeContacts:
buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
Priv->CurrentList = &(Priv->ContactsItems);
Priv->CurrentCount = &(Priv->ContactsItemsCount);
break;
case TypeToDo:
buffer[2] = ALCATEL_SYNC_TYPE_TODO;
Priv->CurrentList = &(Priv->ToDoItems);
Priv->CurrentCount = &(Priv->ToDoItemsCount);
break;
}
if (*Priv->CurrentList != NULL) {
if (!refresh) return ERR_NONE;
free(*Priv->CurrentList);
*Priv->CurrentList = NULL;
}
smprintf(s,"Reading items list\n");
*Priv->CurrentCount = 0;
Priv->TransferCompleted = false;
error=GSM_WaitFor (s, buffer, 5, 0x02, ALCATEL_TIMEOUT, ID_AlcatelGetIds1);
if (error != ERR_NONE) return error;
while (!Priv->TransferCompleted) {
error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelGetIds2);
if (error != ERR_NONE) return error;
}
i = 0;
smprintf(s,"Received %d ids: ", *Priv->CurrentCount);
for (i=0; i < *Priv->CurrentCount; i++) {
smprintf(s,"%x ", (*Priv->CurrentList)[i]);
}
smprintf(s,"\n");
return ERR_NONE;
}
static GSM_Error ALCATEL_ReplyGetFields(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int i;
if (msg.Buffer[14] > GSM_PHONEBOOK_ENTRIES) {
smprintf(s, "WARNING: Field list truncated, you should increase GSM_PHONEBOOK_ENTRIES to at least %d\n", msg.Buffer[14]);
Priv->CurrentFieldsCount = GSM_PHONEBOOK_ENTRIES;
} else {
Priv->CurrentFieldsCount = msg.Buffer[14];
}
Priv->CurrentFields[Priv->CurrentFieldsCount] = 0;
for (i = 0; i < Priv->CurrentFieldsCount; i++) {
Priv->CurrentFields[i] = msg.Buffer[15 + i];
}
return ERR_NONE;
}
static GSM_Error ALCATEL_GetFields(GSM_StateMachine *s, int id) {
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_Error error;
int i;
unsigned char buffer[] =
{0x00, 0x04,
0x00, /* type */
0x30, 0x01,
0x00, 0x00, 0x00, 0x00}; /* item */
if (Priv->BinaryState != StateSession) return ERR_UNKNOWN;
if ((Priv->CurrentFieldsItem == id) && (Priv->CurrentFieldsType == Priv->BinaryType)) return ERR_NONE;
smprintf(s,"Reading item fields (%d)\n", id);
buffer[5] = (id >> 24);
buffer[6] = ((id >> 16) & 0xff);
buffer[7] = ((id >> 8) & 0xff);
buffer[8] = (id & 0xff);
switch (Priv->BinaryType) {
case TypeCalendar:
buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
break;
case TypeContacts:
buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
break;
case TypeToDo:
buffer[2] = ALCATEL_SYNC_TYPE_TODO;
break;
}
Priv->CurrentFieldsItem = id;
Priv->CurrentFieldsType = Priv->BinaryType;
error=GSM_WaitFor (s, buffer, 9, 0x02, ALCATEL_TIMEOUT, ID_AlcatelGetFields1);
if (error != ERR_NONE) return error;
error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelGetFields2);
if (error != ERR_NONE) return error;
i = 0;
smprintf(s,"Received %d fields: ", Priv->CurrentFieldsCount);
for (i=0; i < Priv->CurrentFieldsCount; i++) {
smprintf(s,"%x ", Priv->CurrentFields[i]);
}
smprintf(s,"\n");
return ERR_NONE;
}
static GSM_Error ALCATEL_ReplyGetFieldValue(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
unsigned char *buffer = &(msg.Buffer[16]);
if (buffer[1] == 0x05 && buffer[2] == 0x67) {
/* date */
Priv->ReturnType = Alcatel_date;
Priv->ReturnDateTime.Day = buffer[4];
Priv->ReturnDateTime.Month = buffer[5];
Priv->ReturnDateTime.Year = buffer[7] + (buffer[6] << 8);
Priv->ReturnDateTime.Timezone = 0; /* FIXME: how to acquire this? */
Priv->ReturnDateTime.Hour = 0;
Priv->ReturnDateTime.Minute = 0;
Priv->ReturnDateTime.Second = 0;
} else if (buffer[1] == 0x06 && buffer[2] == 0x68) {
/* time */
Priv->ReturnType = Alcatel_time;
Priv->ReturnDateTime.Hour = buffer[4];
Priv->ReturnDateTime.Minute = buffer[5];
Priv->ReturnDateTime.Second = buffer[6];
-
+
Priv->ReturnDateTime.Day = 0;
Priv->ReturnDateTime.Month = 0;
Priv->ReturnDateTime.Year = 0;
Priv->ReturnDateTime.Timezone = 0;
} else if (buffer[1] == 0x08 && buffer[2] == 0x3C) {
/* string */
Priv->ReturnType = Alcatel_string;
if (GSM_PHONEBOOK_TEXT_LENGTH < buffer[3])
smprintf(s, "WARNING: Text truncated, you should increase GSM_PHONEBOOK_TEXT_LENGTH to at least %d\n", buffer[3] + 1);
if (Priv->ProtocolVersion == V_1_0) {
DecodeDefault( Priv->ReturnString, buffer + 4, MIN(GSM_PHONEBOOK_TEXT_LENGTH, buffer[3]), false, GSM_AlcatelAlphabet);
} else if(Priv->ProtocolVersion == V_1_1 && (buffer[4] & 0x80)) {
memcpy(Priv->ReturnString, buffer + 5, buffer[3]);
Priv->ReturnString[buffer[3] + 1] = 0;
Priv->ReturnString[buffer[3] + 2] = 0;
ReverseUnicodeString(Priv->ReturnString);
} else {
DecodeDefault( Priv->ReturnString, buffer + 4, MIN(GSM_PHONEBOOK_TEXT_LENGTH, buffer[3]), false, GSM_AlcatelAlphabet);
}
} else if (buffer[1] == 0x07 && buffer[2] == 0x3C) {
/* phone */
Priv->ReturnType = Alcatel_phone;
if (GSM_PHONEBOOK_TEXT_LENGTH < buffer[3])
smprintf(s, "WARNING: Text truncated, you should increase GSM_PHONEBOOK_TEXT_LENGTH to at least %d\n", buffer[3] + 1);
if (Priv->ProtocolVersion == V_1_0) {
DecodeDefault( Priv->ReturnString, buffer + 4, MIN(GSM_PHONEBOOK_TEXT_LENGTH, buffer[3]), false, GSM_AlcatelAlphabet);
} else if(Priv->ProtocolVersion == V_1_1 && (buffer[4] & 0x80)) {
memcpy(Priv->ReturnString, buffer + 5, buffer[3]);
Priv->ReturnString[buffer[3] + 1] = 0;
Priv->ReturnString[buffer[3] + 2] = 0;
ReverseUnicodeString(Priv->ReturnString);
} else {
DecodeDefault( Priv->ReturnString, buffer + 4, MIN(GSM_PHONEBOOK_TEXT_LENGTH, buffer[3]), false, GSM_AlcatelAlphabet);
}
} else if (buffer[1] == 0x03 && buffer[2] == 0x3B) {
/* boolean */
Priv->ReturnType = Alcatel_bool;
Priv->ReturnInt = buffer[3];
} else if (buffer[1] == 0x02 && buffer[2] == 0x3A) {
/* integer */
Priv->ReturnType = Alcatel_int;
Priv->ReturnInt = buffer[6] + (buffer[5] << 8) + (buffer[4] << 16) + (buffer[3] << 24);
} else if (buffer[1] == 0x04 && buffer[2] == 0x38) {
/* enumeration */
Priv->ReturnType = Alcatel_enum;
Priv->ReturnInt = buffer[3];
} else if (buffer[1] == 0x00 && buffer[2] == 0x38) {
/* byte */
Priv->ReturnType = Alcatel_byte;
Priv->ReturnInt = buffer[3];
} else {
smprintf(s, "WARNING: Uknown data type received (%02X,%02X)\n", buffer[1], buffer[2]);
return ERR_UNKNOWNRESPONSE;
}
return ERR_NONE;
}
static GSM_Error ALCATEL_GetFieldValue(GSM_StateMachine *s, int id, int field)
{
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_Error error;
unsigned char buffer[] =
{0x00, 0x04,
0x00, /* type */
0x1f, 0x01,
0x00, 0x00, 0x00, 0x00, /* here follows 4byte id */
0x00}; /* field */
smprintf(s,"Reading item value (%08x.%02x)\n", id, field);
switch (Priv->BinaryType) {
case TypeCalendar:
buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
break;
case TypeContacts:
buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
break;
case TypeToDo:
buffer[2] = ALCATEL_SYNC_TYPE_TODO;
break;
}
buffer[5] = (id >> 24);
buffer[6] = ((id >> 16) & 0xff);
buffer[7] = ((id >> 8) & 0xff);
buffer[8] = (id & 0xff);
buffer[9] = (field & 0xff);
error=GSM_WaitFor (s, buffer, 10, 0x02, ALCATEL_TIMEOUT, ID_AlcatelGetFieldValue1);
if (error != ERR_NONE) return error;
error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelGetFieldValue2);
if (error != ERR_NONE) return error;
return ERR_NONE;
}
static GSM_Error ALCATEL_ReplyGetCategories(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int i;
/* Did we get any category? */
if (msg.Buffer[4] == 6) {
Priv->CurrentCategoriesCount = 0;
return ERR_NONE;
}
if (msg.Buffer[12] > ALCATEL_MAX_CATEGORIES) {
smprintf(s, "WARNING: Field list truncated, you should increase ALCATEL_MAX_CATEGORIES to at least %d\n", msg.Buffer[12]);
Priv->CurrentCategoriesCount = ALCATEL_MAX_CATEGORIES;
} else {
Priv->CurrentCategoriesCount = msg.Buffer[12];
}
for (i = 0; i < Priv->CurrentCategoriesCount; i++) {
Priv->CurrentCategories[i] = msg.Buffer[13 + i];
Priv->CurrentCategoriesCache[i][0] = '\000';
Priv->CurrentCategoriesCache[i][1] = '\000';
}
return ERR_NONE;
}
static GSM_Error ALCATEL_GetAvailableCategoryIds(GSM_StateMachine *s) {
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_Error error;
int i;
unsigned char buffer[] =
{0x00, 0x04,
0x00 /*type */,
0x0b,
0x00 /* list */};
if (Priv->BinaryState != StateSession) return ERR_UNKNOWN;
if (Priv->CurrentCategoriesType == Priv->BinaryType) return ERR_NONE;
switch (Priv->BinaryType) {
case TypeContacts:
buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
buffer[4] = ALCATEL_LIST_CONTACTS_CAT;
break;
case TypeToDo:
buffer[2] = ALCATEL_SYNC_TYPE_TODO;
buffer[4] = ALCATEL_LIST_TODO_CAT;
break;
default:
return ERR_NOTSUPPORTED;
}
Priv->CurrentCategoriesType = Priv->BinaryType;
smprintf(s,"Reading category list\n");
error=GSM_WaitFor (s, buffer, 5, 0x02, ALCATEL_TIMEOUT, ID_AlcatelGetCategories1);
if (error != ERR_NONE) return error;
error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelGetCategories2);
if (error != ERR_NONE) return error;
i = 0;
smprintf(s,"Received %d ids: ", Priv->CurrentCategoriesCount);
for (i=0; i < Priv->CurrentCategoriesCount; i++) {
smprintf(s,"%i ", Priv->CurrentCategories[i]);
}
smprintf(s,"\n");
return ERR_NONE;
}
static GSM_Error ALCATEL_IsCategoryIdAvailable(GSM_StateMachine *s, int id) {
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int i = 0;
if (Priv->CurrentCategoriesType != Priv->BinaryType) return ERR_UNKNOWN;
for (i = 0; i< Priv->CurrentCategoriesCount; i++) {
if (Priv->CurrentCategories[i] == id) return ERR_NONE;
}
return ERR_EMPTY;
}
static GSM_Error ALCATEL_ReplyAddCategoryText(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
Priv->ReturnInt = msg.Buffer[12];
return ERR_NONE;
}
static GSM_Error ALCATEL_AddCategoryText(GSM_StateMachine *s, const unsigned char *str) {
unsigned char buffer[200] = {0x00, 0x04, 0x00 /*type*/, 0x0d, 0x00 /*list*/, 0x0b };
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_Error error;
int len;
smprintf(s,"Creating category\n");
len = UnicodeLength(str);
EncodeDefault(buffer + 8, str, &len, true, GSM_AlcatelAlphabet);
buffer[6] = len + 1;
buffer[7] = len;
switch (Priv->BinaryType) {
case TypeContacts:
buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
buffer[4] = ALCATEL_LIST_CONTACTS_CAT;
break;
case TypeToDo:
buffer[2] = ALCATEL_SYNC_TYPE_TODO;
buffer[4] = ALCATEL_LIST_TODO_CAT;
break;
default:
return ERR_NOTSUPPORTED;
}
error=GSM_WaitFor (s, buffer, 8 + len, 0x02, ALCATEL_TIMEOUT, ID_AlcatelAddCategoryText1);
if (error != ERR_NONE) return error;
error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelAddCategoryText2);
if (error != ERR_NONE) return error;
/* Refresh list */
Priv->CurrentCategoriesType = 0;
return ALCATEL_GetAvailableCategoryIds(s);
}
static GSM_Error ALCATEL_ReplyGetCategoryText(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int len;
len = msg.Buffer[14];
if (len > GSM_MAX_CATEGORY_NAME_LENGTH) {
smprintf(s, "WARNING: Category name truncated, you should increase GSM_MAX_CATEGORY_NAME_LENGTH to at least %d\n", len);
}
if (Priv->ProtocolVersion == V_1_0) {
DecodeDefault( Priv->ReturnString, msg.Buffer + 15, MIN(GSM_MAX_CATEGORY_NAME_LENGTH, len), false, GSM_AlcatelAlphabet);
} else if(Priv->ProtocolVersion == V_1_1 && (msg.Buffer[15] & 0x80)) {
memcpy(Priv->ReturnString, msg.Buffer + 16, len);
Priv->ReturnString[len + 1] = 0;
Priv->ReturnString[len + 2] = 0;
ReverseUnicodeString(Priv->ReturnString);
} else {
DecodeDefault( Priv->ReturnString, msg.Buffer + 15, MIN(GSM_MAX_CATEGORY_NAME_LENGTH, len), false, GSM_AlcatelAlphabet);
}
return ERR_NONE;
}
static GSM_Error ALCATEL_GetCategoryText(GSM_StateMachine *s, int id) {
unsigned char buffer[] = {0x00, 0x04, 0x00 /*type*/, 0x0c, 0x00 /*list*/, 0x0A, 0x01, 0x00 /*item*/ };
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_Error error;
-
+
if (Priv->CurrentCategoriesCache[id][0] != '\000' || Priv->CurrentCategoriesCache[id][1] != '\000') {
CopyUnicodeString(Priv->ReturnString, Priv->CurrentCategoriesCache[id]);
return ERR_NONE;
}
-
+
smprintf(s,"Reading category %d\n", id);
switch (Priv->BinaryType) {
case TypeContacts:
buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
buffer[4] = ALCATEL_LIST_CONTACTS_CAT;
break;
case TypeToDo:
buffer[2] = ALCATEL_SYNC_TYPE_TODO;
buffer[4] = ALCATEL_LIST_TODO_CAT;
break;
default:
return ERR_NOTSUPPORTED;
}
buffer[7] = (id & 0xff);
error=GSM_WaitFor (s, buffer, 8, 0x02, ALCATEL_TIMEOUT, ID_AlcatelGetCategoryText1);
if (error != ERR_NONE) return error;
error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelGetCategoryText2);
if (error != ERR_NONE) return error;
-
+
CopyUnicodeString(Priv->CurrentCategoriesCache[id], Priv->ReturnString);
return ERR_NONE;
}
static GSM_Error ALCATEL_DeleteField(GSM_StateMachine *s, int id, int field) {
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_Error error;
unsigned char buffer[] =
{0x00, 0x04,
0x00, /* type */
0x26, 0x01,
0x00, 0x00, 0x00, 0x00, /* here follows 4byte id */
0x65, 0x01,
0x00, /* field */
0x01};
smprintf(s,"Deleting field (%08x.%02x)\n", id, field);
switch (Priv->BinaryType) {
case TypeCalendar:
buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
break;
case TypeContacts:
buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
break;
case TypeToDo:
buffer[2] = ALCATEL_SYNC_TYPE_TODO;
break;
}
buffer[5] = (id >> 24);
buffer[6] = ((id >> 16) & 0xff);
buffer[7] = ((id >> 8) & 0xff);
buffer[8] = (id & 0xff);
buffer[11] = (field & 0xff);
error=GSM_WaitFor (s, buffer, 13, 0x02, ALCATEL_TIMEOUT, ID_AlcatelDeleteField);
if (error != ERR_NONE) return error;
return ERR_NONE;
}
static GSM_Error ALCATEL_DeleteItem(GSM_StateMachine *s, int id) {
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_Error error;
unsigned char buffer[] =
{0x00, 0x04,
0x00, /* type */
0x27, 0x01,
0x00, 0x00, 0x00, 0x00, /* here follows 4byte id */
0x42};
smprintf(s,"Deleting item (%08x)\n", id);
switch (Priv->BinaryType) {
case TypeCalendar:
buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
break;
case TypeContacts:
buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
break;
case TypeToDo:
buffer[2] = ALCATEL_SYNC_TYPE_TODO;
break;
}
buffer[5] = (id >> 24);
buffer[6] = ((id >> 16) & 0xff);
buffer[7] = ((id >> 8) & 0xff);
buffer[8] = (id & 0xff);
error=GSM_WaitFor (s, buffer, 10, 0x02, ALCATEL_TIMEOUT, ID_AlcatelDeleteItem1);
if (error != ERR_NONE) return error;
error=GSM_WaitFor (s, 0, 0, 0x0, ALCATEL_TIMEOUT, ID_AlcatelDeleteItem2);
if (error != ERR_NONE) return error;
return ERR_NONE;
}
static GSM_Error ALCATEL_ReplyDeleteItem(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
if (msg.Buffer[8] != 0x25) return ERR_UNKNOWNRESPONSE;
return ERR_NONE;
}
static GSM_Error ALCATEL_BuildWriteBuffer(unsigned char * buffer, GSM_Alcatel_FieldType type, int field, void *data) {
int len;
-
+
buffer[1] = field & 0xff;
-
+
switch(type) {
case Alcatel_date:
if (!CheckDate((GSM_DateTime *)data)) return ERR_INVALIDDATETIME;
buffer[3] = 0x05;
buffer[4] = 0x67;
buffer[0] = 0x09;
buffer[5] = 0x04;
buffer[6] = ((GSM_DateTime *)data)->Day & 0xff;
buffer[7] = ((GSM_DateTime *)data)->Month & 0xff;
buffer[8] = ((GSM_DateTime *)data)->Year >> 8;
buffer[9] = ((GSM_DateTime *)data)->Year & 0xff;
buffer[10] = 0x00;
break;
case Alcatel_time:
if (!CheckTime((GSM_DateTime *)data)) return ERR_INVALIDDATETIME;
buffer[3] = 0x06;
buffer[4] = 0x68;
buffer[0] = 0x08;
buffer[5] = 0x03;
buffer[6] = ((GSM_DateTime *)data)->Hour & 0xff;
buffer[7] = ((GSM_DateTime *)data)->Minute & 0xff;
buffer[8] = ((GSM_DateTime *)data)->Second & 0xff;
buffer[9] = 0x00;
break;
case Alcatel_string:
buffer[3] = 0x08;
buffer[4] = 0x3c;
len = MIN(UnicodeLength((char *)data),62);
EncodeDefault(buffer + 6, (char *)data, &len, true, GSM_AlcatelAlphabet);
buffer[5] = len;
buffer[0] = 5 + len;
buffer[6 + len] = 0x00;
break;
case Alcatel_phone:
buffer[3] = 0x07;
buffer[4] = 0x3c;
len = MIN(UnicodeLength((char *)data),50);
EncodeDefault(buffer + 6, (char *)data, &len, true, GSM_AlcatelAlphabet);
buffer[5] = len;
buffer[0] = 5 + len;
buffer[6 + len] = 0x00;
break;
case Alcatel_enum:
buffer[3] = 0x04;
buffer[4] = 0x38;
buffer[0] = 0x05;
buffer[5] = *(int *)data & 0xff;
buffer[6] = 0x00;
break;
case Alcatel_bool:
buffer[3] = 0x03;
buffer[4] = 0x3b;
buffer[0] = 0x05;
buffer[5] = *(int *)data & 0xff;
buffer[6] = 0x00;
break;
case Alcatel_int:
buffer[3] = 0x02;
buffer[4] = 0x3a;
buffer[0] = 0x08;
buffer[5] = *(unsigned int *)data >> 24;
buffer[6] = (*(unsigned int *)data >> 16) & 0xff;
buffer[7] = (*(unsigned int *)data >> 8) & 0xff;
buffer[8] = *(unsigned int *)data & 0xff;
buffer[9] = 0x00;
break;
case Alcatel_byte:
buffer[3] = 0x00;
buffer[4] = 0x38;
buffer[0] = 0x05;
buffer[5] = *(int *)data & 0xff;
buffer[6] = 0x00;
break;
}
return ERR_NONE;
}
static GSM_Error ALCATEL_CreateField(GSM_StateMachine *s, GSM_Alcatel_FieldType type, int field, void *data) {
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_Error error;
unsigned char buffer[200] =
{0x00, 0x04,
0x00, /* type */
0x25, 0x01, 0x65,
0x00, /* length of remaining part */
0x00, /* field */
0x37}; /* data follows here */
smprintf(s,"Creating field (%02x)\n", field);
switch (Priv->BinaryType) {
case TypeCalendar:
buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
break;
case TypeContacts:
buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
break;
case TypeToDo:
buffer[2] = ALCATEL_SYNC_TYPE_TODO;
break;
}
error = ALCATEL_BuildWriteBuffer(buffer + 6, type, field, data);
if (error != ERR_NONE) return error;
-
+
error = GSM_WaitFor (s, buffer, 8 + buffer[6], 0x02, ALCATEL_TIMEOUT, ID_AlcatelCreateField);
if (error != ERR_NONE) return error;
-
+
return ERR_NONE;
}
static GSM_Error ALCATEL_UpdateField(GSM_StateMachine *s, GSM_Alcatel_FieldType type, int id, int field, void *data) {
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_Error error;
unsigned char buffer[200] =
{0x00, 0x04,
0x00, /* type */
- 0x26, 0x01,
+ 0x26, 0x01,
0x00, 0x00, 0x00, 0x00, /* id */
0x65,
0x00, /* length of remaining part */
0x00, /* field */
0x37}; /* data follows here */
smprintf(s,"Updating field (%08x.%02x)\n", id, field);
-
+
buffer[5] = (id >> 24);
buffer[6] = ((id >> 16) & 0xff);
buffer[7] = ((id >> 8) & 0xff);
buffer[8] = (id & 0xff);
switch (Priv->BinaryType) {
case TypeCalendar:
buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
break;
case TypeContacts:
buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
break;
case TypeToDo:
buffer[2] = ALCATEL_SYNC_TYPE_TODO;
break;
}
error = ALCATEL_BuildWriteBuffer(buffer + 10, type, field, data);
if (error != ERR_NONE) return error;
-
+
error = GSM_WaitFor (s, buffer, 12 + buffer[10], 0x02, ALCATEL_TIMEOUT, ID_AlcatelUpdateField);
if (error != ERR_NONE) return error;
-
+
return ERR_NONE;
}
static GSM_Error ALCATEL_GetManufacturer(GSM_StateMachine *s)
{
strcpy(s->Phone.Data.Manufacturer, "Alcatel");
return ERR_NONE;
}
static GSM_Error ALCATEL_GetIMEI (GSM_StateMachine *s)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetIMEI(s);
}
static GSM_Error ALCATEL_GetFirmware(GSM_StateMachine *s)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetFirmware(s);
}
static GSM_Error ALCATEL_GetModel(GSM_StateMachine *s)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetModel(s);
}
static GSM_Error ALCATEL_GetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetDateTime(s, date_time);
}
static GSM_Error ALCATEL_GetMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
GSM_Error error;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int i;
int j = 0;
if (entry->MemoryType == MEM_ME) {
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
if ((error = ALCATEL_IsIdAvailable(s, entry->Location))!= ERR_NONE) {
entry->EntriesNum = 0;
return error;
}
if ((error = ALCATEL_GetFields(s, entry->Location))!= ERR_NONE) return error;
entry->EntriesNum = Priv->CurrentFieldsCount;
for (i=0; i<Priv->CurrentFieldsCount; i++) {
if ((error = ALCATEL_GetFieldValue(s, entry->Location, Priv->CurrentFields[i]))!= ERR_NONE) return error;
entry->Entries[i].VoiceTag = 0;
entry->Entries[i].SMSList[0] = 0;
switch (Priv->CurrentFields[i]) {
case 0:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 0, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_LastName;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 1:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 1, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_FirstName;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 2:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 2, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_Company;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 3:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 3, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_JobTitle;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 4:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 4, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_Note;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 5:
if (Priv->ReturnType != Alcatel_byte) {
smprintf(s,"WARNING: Received unexpected type %02X for field 5, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Category;
entry->Entries[i - j].Number = Priv->ReturnInt;
break;
case 6:
if (Priv->ReturnType != Alcatel_bool) {
smprintf(s,"WARNING: Received unexpected type %02X for field 6, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Private;
entry->Entries[i - j].Number = Priv->ReturnInt;
break;
case 7:
if (Priv->ReturnType != Alcatel_phone) {
smprintf(s,"WARNING: Received unexpected type %02X for field 7, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Number_Work;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 8:
if (Priv->ReturnType != Alcatel_phone) {
smprintf(s,"WARNING: Received unexpected type %02X for field 8, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Number_General;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 9:
if (Priv->ReturnType != Alcatel_phone) {
smprintf(s,"WARNING: Received unexpected type %02X for field 9, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Number_Fax;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 10:
if (Priv->ReturnType != Alcatel_phone) {
smprintf(s,"WARNING: Received unexpected type %02X for field 10, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Number_Other;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 11:
if (Priv->ReturnType != Alcatel_phone) {
smprintf(s,"WARNING: Received unexpected type %02X for field 11, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Number_Pager;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 12:
if (Priv->ReturnType != Alcatel_phone) {
smprintf(s,"WARNING: Received unexpected type %02X for field 12, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Number_Mobile;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 13:
if (Priv->ReturnType != Alcatel_phone) {
smprintf(s,"WARNING: Received unexpected type %02X for field 13, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Number_Home;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 14:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 14, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_Email;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 15:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 15, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_Email2;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 16:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 16, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_StreetAddress;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 17:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 17, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_City;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 18:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 18, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_State;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 19:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 19, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_Zip;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 20:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 20, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_Country;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 21:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 21, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_Custom1;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 22:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 22, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_Custom2;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 23:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 23, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_Custom3;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 24:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X for field 24, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
entry->Entries[i - j].EntryType = PBK_Text_Custom4;
CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
break;
case 25:
if (Priv->ReturnType != Alcatel_int) {
smprintf(s,"WARNING: Received unexpected type %02X for field 25, ignoring\n", Priv->ReturnType);
entry->EntriesNum--;
j++;
break;
}
if (Priv->ReturnInt != 0) {
entry->Entries[i - j].EntryType = PBK_PictureID;
entry->Entries[i - j].Number = Priv->ReturnInt;
} else {
entry->EntriesNum--;
j++;
}
break;
default:
entry->EntriesNum--;
j++;
smprintf(s,"WARNING: Received unknown field %02X, ignoring. Type = %02X. Value = ", Priv->CurrentFields[i], Priv->ReturnType);
switch (Priv->ReturnType) {
case Alcatel_date:
smprintf(s, "%d.%d.%d", Priv->ReturnDateTime.Day, Priv->ReturnDateTime.Month, Priv->ReturnDateTime.Year);
break;
case Alcatel_time:
smprintf(s, "%d:%d:%d", Priv->ReturnDateTime.Hour, Priv->ReturnDateTime.Minute, Priv->ReturnDateTime.Second);
break;
case Alcatel_string:
case Alcatel_phone:
smprintf(s, "\"%s\"",DecodeUnicodeString(Priv->ReturnString));
break;
case Alcatel_enum:
case Alcatel_bool:
case Alcatel_int:
case Alcatel_byte:
smprintf(s, "%d", Priv->ReturnInt);
break;
}
smprintf(s,"\n");
}
}
return ERR_NONE;
} else {
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetMemory(s, entry);
}
}
static GSM_Error ALCATEL_GetNextMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry, bool start)
{
GSM_Error error;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
if (entry->MemoryType == MEM_ME) {
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
if (Priv->ContactsItemsCount == 0) return ERR_EMPTY;
-
+
if (start) entry->Location = 0;
if ((error = ALCATEL_GetNextId(s, &(entry->Location))) != ERR_NONE) return error;
return ALCATEL_GetMemory(s, entry);
} else {
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetNextMemory(s, entry, start);
}
}
static GSM_Error ALCATEL_AddMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
GSM_Error error;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int NamePosition = -1;
bool NameSet = false;
int i;
if (entry->MemoryType == MEM_ME) {
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GoToBinaryState(s, StateEdit, TypeContacts, 0))!= ERR_NONE) return error;
for (i = 0; i < entry->EntriesNum; i++) {
switch (entry->Entries[i].EntryType) {
- case PBK_Number_General:
+ case PBK_Number_General:
if ((error = ALCATEL_CreateField(s, Alcatel_phone, 8, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Number_Mobile:
if ((error = ALCATEL_CreateField(s, Alcatel_phone, 12, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Number_Work:
if ((error = ALCATEL_CreateField(s, Alcatel_phone, 7, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Number_Fax:
+ case PBK_Number_Fax:
if ((error = ALCATEL_CreateField(s, Alcatel_phone, 9, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Number_Home:
if ((error = ALCATEL_CreateField(s, Alcatel_phone, 13, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Number_Pager:
if ((error = ALCATEL_CreateField(s, Alcatel_phone, 11, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Number_Other:
if ((error = ALCATEL_CreateField(s, Alcatel_phone, 10, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_Note:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 4, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_Email:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 14, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_Email2:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 15, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_LastName:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 0, entry->Entries[i].Text)) != ERR_NONE) return error;
NameSet = true;
break;
case PBK_Text_FirstName:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 1, entry->Entries[i].Text)) != ERR_NONE) return error;
NameSet = true;
break;
case PBK_Text_Company:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 2, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Text_JobTitle:
+ case PBK_Text_JobTitle:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 3, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Category:
+ case PBK_Category:
if ((error = ALCATEL_CreateField(s, Alcatel_byte, 5, &(entry->Entries[i].Number))) != ERR_NONE) return error;
break;
- case PBK_Private:
+ case PBK_Private:
if ((error = ALCATEL_CreateField(s, Alcatel_bool, 6, &(entry->Entries[i].Number))) != ERR_NONE) return error;
break;
case PBK_Text_StreetAddress:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 16, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_City:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 17, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_State:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 18, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_Zip:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 19, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_Country:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 20, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_Custom1:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 21, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_Custom2:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 22, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_Custom3:
- if ((error = ALCATEL_CreateField(s, Alcatel_string, 23, entry->Entries[i].Text)) != ERR_NONE) return error;
+ if ((error = ALCATEL_CreateField(s, Alcatel_string, 23, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_Custom4:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 24, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_PictureID:
+ case PBK_PictureID:
if (s->Phone.Data.Priv.ALCATEL.ProtocolVersion == V_1_1) {
if ((error = ALCATEL_CreateField(s, Alcatel_int, 25, &(entry->Entries[i].Number))) != ERR_NONE) return error;
} else {
smprintf(s,"WARNING: Ignoring entry %d, not supported by phone\n", entry->Entries[i].EntryType);
}
break;
case PBK_Text_Name: NamePosition = i; break;
/* Following fields are not supported: */
case PBK_Text_UserID:
case PBK_SMSListID:
case PBK_RingtoneFileSystemID:
case PBK_Date:
case PBK_Caller_Group:
case PBK_RingtoneID:
case PBK_Text_Postal:
case PBK_Text_URL:
smprintf(s,"WARNING: Ignoring entry %d, not supported by phone\n", entry->Entries[i].EntryType);
break;
}
}
if (NamePosition != -1) {
if (NameSet) {
smprintf(s,"WARNING: Ignoring name, not supported by phone\n");
} else {
if ((error = ALCATEL_CreateField(s, Alcatel_string, 1, entry->Entries[i].Text)) != ERR_NONE) return error;
}
}
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
entry->Location = Priv->CommitedRecord;
/* Refresh list */
if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
return ERR_NONE;
} else {
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_AddMemory(s, entry);
}
}
static GSM_Error ALCATEL_SetMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
GSM_Error error;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int NamePosition = -1;
bool NameSet = false;
int i;
bool UpdatedFields[26];
if (entry->Location == 0) return ERR_INVALIDLOCATION;
if (entry->MemoryType == MEM_ME) {
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
/* Save modified entry */
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
if ((error = ALCATEL_IsIdAvailable(s, entry->Location))!= ERR_NONE) {
/* Entry doesn't exist, we will create new one */
return ALCATEL_AddMemory(s, entry);
}
/* Get fields for current item */
if ((error = ALCATEL_GetFields(s, entry->Location))!= ERR_NONE) return error;
-
+
for (i = 0; i < 26; i++) { UpdatedFields[i] = false; }
-
+
if ((error = ALCATEL_GoToBinaryState(s, StateEdit, TypeContacts, entry->Location))!= ERR_NONE) return error;
for (i = 0; i < entry->EntriesNum; i++) {
switch (entry->Entries[i].EntryType) {
- case PBK_Number_General:
- UpdatedFields[8] = true;
- if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 8, entry->Entries[i].Text)) != ERR_NONE) return error;
+ case PBK_Number_General:
+ UpdatedFields[8] = true;
+ if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 8, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Number_Mobile:
- UpdatedFields[12] = true;
- if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 12, entry->Entries[i].Text)) != ERR_NONE) return error;
+ case PBK_Number_Mobile:
+ UpdatedFields[12] = true;
+ if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 12, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Number_Work:
- UpdatedFields[7] = true;
- if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 7, entry->Entries[i].Text)) != ERR_NONE) return error;
+ case PBK_Number_Work:
+ UpdatedFields[7] = true;
+ if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 7, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Number_Fax:
- UpdatedFields[9] = true;
- if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 9, entry->Entries[i].Text)) != ERR_NONE) return error;
+ case PBK_Number_Fax:
+ UpdatedFields[9] = true;
+ if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 9, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Number_Home:
- UpdatedFields[13] = true;
- if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 13, entry->Entries[i].Text)) != ERR_NONE) return error;
+ case PBK_Number_Home:
+ UpdatedFields[13] = true;
+ if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 13, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Number_Pager:
- UpdatedFields[11] = true;
+ case PBK_Number_Pager:
+ UpdatedFields[11] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 11, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Number_Other:
UpdatedFields[10] = true;
- if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 10, entry->Entries[i].Text)) != ERR_NONE) return error;
+ if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 10, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Text_Note:
+ case PBK_Text_Note:
UpdatedFields[4] = true;
- if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 4, entry->Entries[i].Text)) != ERR_NONE) return error;
+ if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 4, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Text_Email:
- UpdatedFields[14] = true;
+ case PBK_Text_Email:
+ UpdatedFields[14] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 14, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Text_Email2:
- UpdatedFields[15] = true;
- if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 15, entry->Entries[i].Text)) != ERR_NONE) return error;
+ case PBK_Text_Email2:
+ UpdatedFields[15] = true;
+ if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 15, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Text_LastName:
- UpdatedFields[0] = true;
- if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 0, entry->Entries[i].Text)) != ERR_NONE) return error; NameSet = true;
+ case PBK_Text_LastName:
+ UpdatedFields[0] = true;
+ if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 0, entry->Entries[i].Text)) != ERR_NONE) return error; NameSet = true;
break;
- case PBK_Text_FirstName:
- UpdatedFields[1] = true;
- if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 1, entry->Entries[i].Text)) != ERR_NONE) return error; NameSet = true;
+ case PBK_Text_FirstName:
+ UpdatedFields[1] = true;
+ if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 1, entry->Entries[i].Text)) != ERR_NONE) return error; NameSet = true;
break;
case PBK_Text_Company:
- UpdatedFields[2] = true;
- if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 2, entry->Entries[i].Text)) != ERR_NONE) return error;
+ UpdatedFields[2] = true;
+ if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 2, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Text_JobTitle:
+ case PBK_Text_JobTitle:
UpdatedFields[3] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 3, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Category:
- UpdatedFields[5] = true;
+ UpdatedFields[5] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_byte, entry->Location, 5, &(entry->Entries[i].Number))) != ERR_NONE) return error;
break;
case PBK_Private:
UpdatedFields[6] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_bool, entry->Location, 6, &(entry->Entries[i].Number))) != ERR_NONE) return error;
break;
- case PBK_Text_StreetAddress:
+ case PBK_Text_StreetAddress:
UpdatedFields[16] = true;
- if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 16, entry->Entries[i].Text)) != ERR_NONE) return error;
+ if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 16, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Text_City:
- UpdatedFields[17] = true;
- if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 17, entry->Entries[i].Text)) != ERR_NONE) return error;
+ case PBK_Text_City:
+ UpdatedFields[17] = true;
+ if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 17, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Text_State:
- UpdatedFields[18] = true;
- if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 18, entry->Entries[i].Text)) != ERR_NONE) return error;
+ case PBK_Text_State:
+ UpdatedFields[18] = true;
+ if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 18, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Text_Zip:
- UpdatedFields[19] = true;
- if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 19, entry->Entries[i].Text)) != ERR_NONE) return error;
+ case PBK_Text_Zip:
+ UpdatedFields[19] = true;
+ if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 19, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_Country:
UpdatedFields[20] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 20, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_Custom1:
UpdatedFields[21] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 21, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
- case PBK_Text_Custom2:
+ case PBK_Text_Custom2:
UpdatedFields[22] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 22, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_Custom3:
UpdatedFields[23] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 23, entry->Entries[i].Text)) != ERR_NONE) return error;
break;
case PBK_Text_Custom4:
- UpdatedFields[24] = true;
+ UpdatedFields[24] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 24, entry->Entries[i].Text)) != ERR_NONE) return error
; break;
- case PBK_PictureID:
+ case PBK_PictureID:
if (s->Phone.Data.Priv.ALCATEL.ProtocolVersion == V_1_1) {
UpdatedFields[25] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_int, entry->Location, 25, &(entry->Entries[i].Number))) != ERR_NONE) return error;
} else {
smprintf(s,"WARNING: Ignoring entry %d, not supported by phone\n", entry->Entries[i].EntryType);
}
break;
case PBK_Text_Name: NamePosition = i; break;
/* Following fields are not supported: */
case PBK_SMSListID:
case PBK_Text_UserID:
case PBK_RingtoneFileSystemID:
case PBK_Date:
case PBK_Caller_Group:
case PBK_RingtoneID:
case PBK_Text_Postal:
case PBK_Text_URL:
smprintf(s,"WARNING: Ignoring entry %d, not supported by phone\n", entry->Entries[i].EntryType);
break;
}
}
if (NamePosition != -1) {
if (NameSet) {
smprintf(s,"WARNING: Ignoring name, not supported by phone\n");
} else {
UpdatedFields[1] = true; if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 1, entry->Entries[i].Text)) != ERR_NONE) return error;
}
}
/* If we didn't update some field, we have to delete it... */
for (i=0; i<Priv->CurrentFieldsCount; i++) {
if (!UpdatedFields[Priv->CurrentFields[i]]) if ((error = ALCATEL_DeleteField(s, entry->Location, Priv->CurrentFields[i])) != ERR_NONE) return error;
}
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
entry->Location = Priv->CommitedRecord;
return ERR_NONE;
} else {
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_SetMemory(s, entry);
}
}
static GSM_Error ALCATEL_DeleteMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
GSM_Error error;
if (entry->MemoryType == MEM_ME) {
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
if ((error = ALCATEL_IsIdAvailable(s, entry->Location))!= ERR_NONE) {
/* Entry was empty => no error */
return ERR_NONE;
}
/* Do real delete */
error = ALCATEL_DeleteItem(s, entry->Location);
if (error != ERR_NONE) return error;
-
+
/* Refresh list */
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
-
+
return ERR_NONE;
} else {
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_DeleteMemory(s, entry);
}
}
static GSM_Error ALCATEL_DeleteAllMemory(GSM_StateMachine *s, GSM_MemoryType type)
{
GSM_Error error;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int i;
if (type == MEM_ME) {
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
for (i=0; i<Priv->ContactsItemsCount; i++) {
error = ALCATEL_DeleteItem(s, Priv->ContactsItems[i]);
if (error != ERR_NONE) return error;
}
/* Refresh list */
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
return ERR_NONE;
} else {
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_DeleteAllMemory(s, type);
}
}
static GSM_Error ALCATEL_GetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetSMSC(s, smsc);
}
static GSM_Error ALCATEL_GetMemoryStatus(GSM_StateMachine *s, GSM_MemoryStatus *Status)
{
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_Error error;
if (Status->MemoryType == MEM_ME) {
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
Status->MemoryUsed = Priv->ContactsItemsCount;
Status->MemoryFree = ALCATEL_FREE_MEMORY;
return ERR_NONE;
} else {
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetMemoryStatus(s, Status);
}
}
static GSM_Error ALCATEL_GetSMS(GSM_StateMachine *s, GSM_MultiSMSMessage *sms)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetSMS(s, sms);
}
static GSM_Error ALCATEL_DeleteSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_DeleteSMS(s, sms);
}
static GSM_Error ALCATEL_AddSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_AddSMS(s, sms);
}
static GSM_Error ALCATEL_GetBatteryCharge(GSM_StateMachine *s, GSM_BatteryCharge *bat)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetBatteryCharge(s, bat);
}
static GSM_Error ALCATEL_GetSignalStrength(GSM_StateMachine *s, GSM_SignalQuality *sig)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetSignalQuality(s, sig);
}
static GSM_Error ALCATEL_GetSMSFolders(GSM_StateMachine *s, GSM_SMSFolders *folders)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetSMSFolders(s, folders);
}
static GSM_Error ALCATEL_GetNextSMS(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, bool start)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetNextSMS(s, sms, start);
}
static GSM_Error ALCATEL_GetSMSStatus(GSM_StateMachine *s, GSM_SMSMemoryStatus *status)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetSMSStatus(s, status);
}
static GSM_Error ALCATEL_DialVoice(GSM_StateMachine *s, char *number, GSM_CallShowNumber ShowNumber)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_DialVoice(s, number, ShowNumber);
}
static GSM_Error ALCATEL_AnswerCall(GSM_StateMachine *s, int ID, bool all)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_AnswerCall(s,ID,all);
}
static GSM_Error ALCATEL_GetNetworkInfo(GSM_StateMachine *s, GSM_NetworkInfo *netinfo)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetNetworkInfo(s, netinfo);
}
static GSM_Error ALCATEL_GetDisplayStatus(GSM_StateMachine *s, GSM_DisplayFeatures *features)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetDisplayStatus(s, features);
}
-
+
static GSM_Error ALCATEL_SetAutoNetworkLogin(GSM_StateMachine *s)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_SetAutoNetworkLogin(s);
}
static GSM_Error ALCATEL_PressKey(GSM_StateMachine *s, GSM_KeyCode Key, bool Press)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_PressKey(s, Key, Press);
}
static GSM_Error ALCATEL_Reset(GSM_StateMachine *s, bool hard)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_Reset(s, hard);
}
static GSM_Error ALCATEL_CancelCall(GSM_StateMachine *s, int ID, bool all)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_CancelCall(s,ID,all);
}
static GSM_Error ALCATEL_SendSavedSMS(GSM_StateMachine *s, int Folder, int Location)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_SendSavedSMS(s, Folder, Location);
}
static GSM_Error ALCATEL_SendSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_SendSMS(s, sms);
}
static GSM_Error ALCATEL_SetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_SetDateTime(s, date_time);
}
static GSM_Error ALCATEL_SetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_SetSMSC(s, smsc);
}
static GSM_Error ALCATEL_EnterSecurityCode(GSM_StateMachine *s, GSM_SecurityCode Code)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_EnterSecurityCode(s, Code);
}
static GSM_Error ALCATEL_GetSecurityStatus(GSM_StateMachine *s, GSM_SecurityCodeType *Status)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetSecurityStatus(s, Status);
}
static GSM_Error ALCATEL_ResetPhoneSettings(GSM_StateMachine *s, GSM_ResetSettingsType Type)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_ResetPhoneSettings(s, Type);
}
static GSM_Error ALCATEL_SendDTMF(GSM_StateMachine *s, char *sequence)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_SendDTMF(s, sequence);
}
static GSM_Error ALCATEL_GetSIMIMSI(GSM_StateMachine *s, char *IMSI)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_GetSIMIMSI(s, IMSI);
}
static GSM_Error ALCATEL_GetCalendarStatus(GSM_StateMachine *s, GSM_CalendarStatus *status)
{
GSM_Error error;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
-
+
status->Used = 0;
-
+
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
status->Used = Priv->CalendarItemsCount;
return ERR_NONE;
}
static GSM_Error ALCATEL_GetCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
{
GSM_Error error;
GSM_DateTime *dt = NULL;
GSM_DateTime evdate;
bool evdateused = true;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int i;
int j=0;
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
if ((error = ALCATEL_IsIdAvailable(s, Note->Location))!= ERR_NONE) {
Note->EntriesNum = 0;
return error;
}
if ((error = ALCATEL_GetFields(s, Note->Location))!= ERR_NONE) return error;
Note->EntriesNum = Priv->CurrentFieldsCount;
for (i=0; i < Priv->CurrentFieldsCount; i++) {
if ((error = ALCATEL_GetFieldValue(s, Note->Location, Priv->CurrentFields[i]))!= ERR_NONE) return error;
switch (Priv->CurrentFields[i]) {
case 0:
if (Priv->ReturnType != Alcatel_date) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
if (!CheckDate(&(Priv->ReturnDateTime))) {
smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
Note->EntriesNum--;
j++;
break;
}
j++;
Note->EntriesNum--;
evdate = Priv->ReturnDateTime;
evdateused = false;
break;
case 1:
if (Priv->ReturnType != Alcatel_time) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
if (!CheckTime(&(Priv->ReturnDateTime))) {
smprintf(s,"WARNING: Invalid time in phone, ignoring\n");
Note->EntriesNum--;
j++;
break;
}
Note->Entries[i-j].EntryType = CAL_START_DATETIME;
Note->Entries[i-j].Date = Priv->ReturnDateTime;
Note->Entries[i-j].Date.Day = evdate.Day;
Note->Entries[i-j].Date.Month = evdate.Month;
Note->Entries[i-j].Date.Year = evdate.Year;
Note->Entries[i-j].Date.Timezone = evdate.Timezone;
evdateused = true;
break;
case 2:
if (Priv->ReturnType != Alcatel_time) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
if (!CheckTime(&(Priv->ReturnDateTime))) {
smprintf(s,"WARNING: Invalid time in phone, ignoring\n");
Note->EntriesNum--;
j++;
break;
}
Note->Entries[i-j].EntryType = CAL_END_DATETIME;
Note->Entries[i-j].Date = Priv->ReturnDateTime;
Note->Entries[i-j].Date.Day = evdate.Day;
Note->Entries[i-j].Date.Month = evdate.Month;
Note->Entries[i-j].Date.Year = evdate.Year;
Note->Entries[i-j].Date.Timezone = evdate.Timezone;
evdateused = true;
break;
case 3:
if (Priv->ReturnType != Alcatel_date) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
if (!CheckDate(&(Priv->ReturnDateTime))) {
smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
Note->EntriesNum--;
j++;
break;
}
if (dt == NULL) {
Note->Entries[i-j].EntryType = CAL_ALARM_DATETIME;
Note->Entries[i-j].Date = Priv->ReturnDateTime;
dt = &(Note->Entries[i-j].Date);
} else {
j++;
Note->EntriesNum--;
dt->Day = Priv->ReturnDateTime.Day;
dt->Month = Priv->ReturnDateTime.Month;
dt->Year = Priv->ReturnDateTime.Year;
dt->Timezone = Priv->ReturnDateTime.Timezone;
dt = NULL;
}
break;
case 4:
if (Priv->ReturnType != Alcatel_time) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
if (!CheckTime(&(Priv->ReturnDateTime))) {
smprintf(s,"WARNING: Invalid time in phone, ignoring\n");
Note->EntriesNum--;
j++;
break;
}
if (dt == NULL) {
Note->Entries[i-j].EntryType = CAL_ALARM_DATETIME;
Note->Entries[i-j].Date = Priv->ReturnDateTime;
dt = &(Note->Entries[i-j].Date);
} else {
j++;
Note->EntriesNum--;
dt->Hour = Priv->ReturnDateTime.Hour;
dt->Minute = Priv->ReturnDateTime.Minute;
dt->Second = Priv->ReturnDateTime.Second;
dt = NULL;
}
break;
case 5:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
Note->Entries[i-j].EntryType = CAL_TEXT;
CopyUnicodeString(Note->Entries[i-j].Text, Priv->ReturnString);
break;
case 6:
if (Priv->ReturnType != Alcatel_bool) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
Note->Entries[i-j].EntryType = CAL_PRIVATE;
Note->Entries[i-j].Number = Priv->ReturnInt;
break;
case 7:
if (Priv->ReturnType != Alcatel_enum) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
switch (Priv->ReturnInt) {
case 0:
Note->Type = GSM_CAL_MEETING;
break;
case 2:
Note->Type = GSM_CAL_BIRTHDAY;
break;
case 3:
Note->Type = GSM_CAL_CALL;
break;
case 4:
Note->Type = GSM_CAL_ALARM;
break;
case 5:
Note->Type = GSM_CAL_DAILY_ALARM;
break;
case 9:
/* I'd call this repeating event, but it makes no sense creating one more type ... */
Note->Type = GSM_CAL_MEETING;
break;
default:
smprintf(s,"WARNING: Received unknown event type %02X!\n", Priv->ReturnInt);
@@ -2538,1454 +2541,1463 @@ static GSM_Error ALCATEL_GetCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Not
Note->EntriesNum--;
break;
case 8:
if (Priv->ReturnType != Alcatel_int) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
/* 0xffffffff indicates that there is phone (BF5), 0 means none (BF5, BE5)*/
if (Priv->ReturnInt == 0xffffffff || Priv->ReturnInt == 0) {
j++;
Note->EntriesNum--;
} else {
Note->Entries[i-j].EntryType = CAL_CONTACTID;
Note->Entries[i-j].Number = Priv->ReturnInt;
}
break;
case 9:
if (Priv->ReturnType != Alcatel_phone) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
Note->Entries[i-j].EntryType = CAL_PHONE;
CopyUnicodeString(Note->Entries[i-j].Text, Priv->ReturnString);
break;
case 10:
if (Priv->ReturnType != Alcatel_byte) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
Note->Entries[i-j].EntryType = CAL_REPEAT_DAYOFWEEK;
Note->Entries[i-j].Number = Priv->ReturnInt;
break;
case 11:
if (Priv->ReturnType != Alcatel_byte) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
Note->Entries[i-j].EntryType = CAL_REPEAT_DAY;
Note->Entries[i-j].Number = Priv->ReturnInt;
break;
case 12:
if (Priv->ReturnType != Alcatel_byte) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
Note->Entries[i-j].EntryType = CAL_REPEAT_WEEKOFMONTH;
Note->Entries[i-j].Number = Priv->ReturnInt;
break;
case 13:
if (Priv->ReturnType != Alcatel_byte) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
Note->Entries[i-j].EntryType = CAL_REPEAT_MONTH;
Note->Entries[i-j].Number = Priv->ReturnInt;
break;
case 17:
if (Priv->ReturnType != Alcatel_byte) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
/* In BF5 birthday has frequency = 1 */
if (Note->Type == GSM_CAL_BIRTHDAY) {
Note->EntriesNum--;
j++;
} else {
Note->Entries[i-j].EntryType = CAL_REPEAT_FREQUENCY;
Note->Entries[i-j].Number = Priv->ReturnInt;
}
break;
case 18:
if (Priv->ReturnType != Alcatel_date) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
if (!CheckDate(&(Priv->ReturnDateTime))) {
smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
Note->EntriesNum--;
j++;
break;
}
Note->Entries[i-j].EntryType = CAL_REPEAT_STARTDATE;
Note->Entries[i-j].Date = Priv->ReturnDateTime;
break;
case 19:
if (Priv->ReturnType != Alcatel_date) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
if (!CheckDate(&(Priv->ReturnDateTime))) {
smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
Note->EntriesNum--;
j++;
break;
}
Note->Entries[i-j].EntryType = CAL_REPEAT_STOPDATE;
Note->Entries[i-j].Date = Priv->ReturnDateTime;
break;
case 20:
if (Priv->ReturnType != Alcatel_date) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
if (!CheckDate(&(Priv->ReturnDateTime))) {
smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
Note->EntriesNum--;
j++;
break;
}
/* This entry had always same value as the 3rd (alarm date) */
j++;
Note->EntriesNum--;
break;
case 21:
if (Priv->ReturnType != Alcatel_time) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
Note->EntriesNum--;
j++;
break;
}
if (!CheckTime(&(Priv->ReturnDateTime))) {
smprintf(s,"WARNING: Invalid time in phone, ignoring\n");
Note->EntriesNum--;
j++;
break;
}
/* This entry had always same value as the 4th (alarm time) */
j++;
Note->EntriesNum--;
break;
default:
Note->EntriesNum--;
j++;
smprintf(s,"WARNING: Received unknown field %02X, ignoring. Type = %02X. Value = ", Priv->CurrentFields[i], Priv->ReturnType);
switch (Priv->ReturnType) {
case Alcatel_date:
smprintf(s, "%d.%d.%d", Priv->ReturnDateTime.Day, Priv->ReturnDateTime.Month, Priv->ReturnDateTime.Year);
break;
case Alcatel_time:
smprintf(s, "%d:%d:%d", Priv->ReturnDateTime.Hour, Priv->ReturnDateTime.Minute, Priv->ReturnDateTime.Second);
break;
case Alcatel_string:
case Alcatel_phone:
smprintf(s, "\"%s\"",DecodeUnicodeString(Priv->ReturnString));
break;
case Alcatel_enum:
case Alcatel_bool:
case Alcatel_int:
case Alcatel_byte:
smprintf(s, "%d", Priv->ReturnInt);
break;
}
smprintf(s,"\n");
}
}
/* The event didn't have start/stop time -> we need only date */
if (!evdateused) {
Note->EntriesNum++;
Note->Entries[i-j].EntryType = CAL_START_DATETIME;
Note->Entries[i-j].Date = evdate;
}
return ERR_NONE;
}
static GSM_Error ALCATEL_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
{
GSM_Error error;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
if (Priv->CalendarItemsCount == 0) return ERR_EMPTY;
-
+
if (start) Note->Location = 0;
if ((error = ALCATEL_GetNextId(s, &(Note->Location))) != ERR_NONE) return error;
return ALCATEL_GetCalendar(s, Note);
}
static GSM_Error ALCATEL_DeleteCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
{
GSM_Error error;
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
/* Delete Calendar */
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
if ((error = ALCATEL_IsIdAvailable(s, Note->Location))!= ERR_NONE) {
/* Entry was empty => no error */
return ERR_NONE;
}
error = ALCATEL_DeleteItem(s, Note->Location);
if (error != ERR_NONE) return error;
/* Refresh list */
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
return ERR_NONE;
}
static GSM_Error ALCATEL_AddCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
{
GSM_Error error;
unsigned int val;
bool contact_set = false;
bool phone_set = false;
bool date_set = false;
bool repeating = false;
int i;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GoToBinaryState(s, StateEdit, TypeCalendar, 0))!= ERR_NONE) return error;
-
+
for (i = 0; i < Note->EntriesNum; i++) {
switch (Note->Entries[i].EntryType) {
case CAL_START_DATETIME:
if (!date_set) {
if ((error = ALCATEL_CreateField(s, Alcatel_date, 0, &(Note->Entries[i].Date))) != ERR_NONE) return error;
date_set = true;
}
if ((error = ALCATEL_CreateField(s, Alcatel_time, 1, &(Note->Entries[i].Date))) != ERR_NONE) return error;
break;
case CAL_END_DATETIME:
if (!date_set) {
if ((error = ALCATEL_CreateField(s, Alcatel_date, 0, &(Note->Entries[i].Date))) != ERR_NONE) return error;
date_set = true;
}
if ((error = ALCATEL_CreateField(s, Alcatel_time, 2, &(Note->Entries[i].Date))) != ERR_NONE) return error;
break;
case CAL_ALARM_DATETIME:
if ((error = ALCATEL_CreateField(s, Alcatel_date, 3, &(Note->Entries[i].Date))) != ERR_NONE) return error;
if ((error = ALCATEL_CreateField(s, Alcatel_time, 4, &(Note->Entries[i].Date))) != ERR_NONE) return error;
if (Note->Type == GSM_CAL_ALARM || Note->Type == GSM_CAL_DAILY_ALARM) {
if ((error = ALCATEL_CreateField(s, Alcatel_date, 20, &(Note->Entries[i].Date))) != ERR_NONE) return error;
if ((error = ALCATEL_CreateField(s, Alcatel_time, 21, &(Note->Entries[i].Date))) != ERR_NONE) return error;
}
break;
case CAL_TEXT:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 5, Note->Entries[i].Text)) != ERR_NONE) return error;
break;
case CAL_PRIVATE:
if ((error = ALCATEL_CreateField(s, Alcatel_bool, 6, &(Note->Entries[i].Number))) != ERR_NONE) return error;
break;
case CAL_CONTACTID:
if ((error = ALCATEL_CreateField(s, Alcatel_int, 8, &(Note->Entries[i].Number))) != ERR_NONE) return error;
contact_set = true;
break;
case CAL_PHONE:
if ((error = ALCATEL_CreateField(s, Alcatel_phone, 9, Note->Entries[i].Text)) != ERR_NONE) return error;
phone_set = true;
- break;
+ break;
case CAL_REPEAT_DAYOFWEEK:
if ((error = ALCATEL_CreateField(s, Alcatel_byte, 10, &(Note->Entries[i].Number))) != ERR_NONE) return error;
repeating = true;
break;
case CAL_REPEAT_DAY:
if ((error = ALCATEL_CreateField(s, Alcatel_byte, 11, &(Note->Entries[i].Number))) != ERR_NONE) return error;
repeating = true;
break;
case CAL_REPEAT_WEEKOFMONTH:
if ((error = ALCATEL_CreateField(s, Alcatel_byte, 12, &(Note->Entries[i].Number))) != ERR_NONE) return error;
repeating = true;
break;
case CAL_REPEAT_MONTH:
if ((error = ALCATEL_CreateField(s, Alcatel_byte, 13, &(Note->Entries[i].Number))) != ERR_NONE) return error;
repeating = true;
break;
case CAL_REPEAT_FREQUENCY:
if ((error = ALCATEL_CreateField(s, Alcatel_byte, 17, &(Note->Entries[i].Number))) != ERR_NONE) return error;
repeating = true;
break;
case CAL_REPEAT_STARTDATE:
if ((error = ALCATEL_CreateField(s, Alcatel_date, 18, &(Note->Entries[i].Date))) != ERR_NONE) return error;
repeating = true;
break;
case CAL_REPEAT_STOPDATE:
if ((error = ALCATEL_CreateField(s, Alcatel_date, 19, &(Note->Entries[i].Date))) != ERR_NONE) return error;
repeating = true;
break;
case CAL_SILENT_ALARM_DATETIME:
case CAL_RECURRANCE:
case CAL_LOCATION:
smprintf(s,"WARNING: Ignoring entry %d, not supported by phone\n", Note->Entries[i].EntryType);
break;
}
}
-
+
switch (Note->Type) {
case GSM_CAL_CALL:
val = 3;
break;
case GSM_CAL_BIRTHDAY:
val = 2;
break;
case GSM_CAL_ALARM:
val = 4;
break;
case GSM_CAL_DAILY_ALARM:
val = 5;
break;
default:
if (repeating) {
val = 9;
} else {
val = 0;
}
}
if ((error = ALCATEL_CreateField(s, Alcatel_enum, 7, &val)) != ERR_NONE) return error;
if (!contact_set) {
if (phone_set) {
val = 0xffffffff;
} else {
val = 0;
}
if ((error = ALCATEL_CreateField(s, Alcatel_int, 8, &val)) != ERR_NONE) return error;
}
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
Note->Location = Priv->CommitedRecord;
/* Refresh list */
if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
return ERR_NONE;
}
static GSM_Error ALCATEL_SetCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
{
GSM_Error error;
unsigned int val;
bool contact_set = false;
bool phone_set = false;
bool date_set = false;
bool repeating = false;
int i;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
bool UpdatedFields[22];
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
if ((error = ALCATEL_IsIdAvailable(s, Note->Location))!= ERR_NONE) {
/* Entry doesn't exist, we will create new one */
return ALCATEL_AddCalendar(s, Note);
}
/* Get fields for current item */
if ((error = ALCATEL_GetFields(s, Note->Location))!= ERR_NONE) return error;
-
+
for (i = 0; i < 22; i++) { UpdatedFields[i] = false; }
if ((error = ALCATEL_GoToBinaryState(s, StateEdit, TypeCalendar, Note->Location))!= ERR_NONE) return error;
-
+
for (i = 0; i < Note->EntriesNum; i++) {
switch (Note->Entries[i].EntryType) {
case CAL_START_DATETIME:
if (!date_set) {
- UpdatedFields[0] = true;
+ UpdatedFields[0] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_date, Note->Location, 0, &(Note->Entries[i].Date))) != ERR_NONE) return error;
date_set = true;
}
UpdatedFields[1] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_time, Note->Location, 1, &(Note->Entries[i].Date))) != ERR_NONE) return error;
break;
case CAL_END_DATETIME:
if (!date_set) {
UpdatedFields[0] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_date, Note->Location, 0, &(Note->Entries[i].Date))) != ERR_NONE) return error;
date_set = true;
}
UpdatedFields[2] = true; if ((error = ALCATEL_UpdateField(s, Alcatel_time, Note->Location, 2, &(Note->Entries[i].Date))) != ERR_NONE) return error;
break;
case CAL_ALARM_DATETIME:
UpdatedFields[3] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_date, Note->Location, 3, &(Note->Entries[i].Date))) != ERR_NONE) return error;
UpdatedFields[4] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_time, Note->Location, 4, &(Note->Entries[i].Date))) != ERR_NONE) return error;
if (Note->Type == GSM_CAL_ALARM || Note->Type == GSM_CAL_DAILY_ALARM) {
UpdatedFields[20] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_date, Note->Location, 20, &(Note->Entries[i].Date))) != ERR_NONE) return error;
UpdatedFields[21] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_time, Note->Location, 21, &(Note->Entries[i].Date))) != ERR_NONE) return error;
}
break;
case CAL_TEXT:
UpdatedFields[5] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_string, Note->Location, 5, Note->Entries[i].Text)) != ERR_NONE) return error;
break;
case CAL_PRIVATE:
UpdatedFields[6] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_bool, Note->Location, 6, &(Note->Entries[i].Number))) != ERR_NONE) return error;
break;
case CAL_CONTACTID:
UpdatedFields[8] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_int, Note->Location, 8, &(Note->Entries[i].Number))) != ERR_NONE) return error;
contact_set = true;
break;
case CAL_PHONE:
UpdatedFields[9] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_phone, Note->Location, 9, Note->Entries[i].Text)) != ERR_NONE) return error;
phone_set = true;
- break;
+ break;
case CAL_REPEAT_DAYOFWEEK:
UpdatedFields[10] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_byte, Note->Location, 10, &(Note->Entries[i].Number))) != ERR_NONE) return error;
repeating = true;
break;
case CAL_REPEAT_DAY:
UpdatedFields[11] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_byte, Note->Location, 11, &(Note->Entries[i].Number))) != ERR_NONE) return error;
repeating = true;
break;
case CAL_REPEAT_WEEKOFMONTH:
UpdatedFields[12] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_byte, Note->Location, 12, &(Note->Entries[i].Number))) != ERR_NONE) return error;
repeating = true;
break;
case CAL_REPEAT_MONTH:
UpdatedFields[13] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_byte, Note->Location, 13, &(Note->Entries[i].Number))) != ERR_NONE) return error;
repeating = true;
break;
case CAL_REPEAT_FREQUENCY:
UpdatedFields[17] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_byte, Note->Location, 17, &(Note->Entries[i].Number))) != ERR_NONE) return error;
repeating = true;
break;
case CAL_REPEAT_STARTDATE:
UpdatedFields[18] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_date, Note->Location, 18, &(Note->Entries[i].Date))) != ERR_NONE) return error;
repeating = true;
break;
case CAL_REPEAT_STOPDATE:
UpdatedFields[19] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_date, Note->Location, 19, &(Note->Entries[i].Date))) != ERR_NONE) return error;
repeating = true;
break;
case CAL_SILENT_ALARM_DATETIME:
case CAL_RECURRANCE:
case CAL_LOCATION:
smprintf(s,"WARNING: Ignoring entry %d, not supported by phone\n", Note->Entries[i].EntryType);
break;
}
}
-
+
switch (Note->Type) {
case GSM_CAL_CALL:
val = 3;
break;
case GSM_CAL_BIRTHDAY:
val = 2;
break;
case GSM_CAL_ALARM:
val = 4;
break;
case GSM_CAL_DAILY_ALARM:
val = 5;
break;
default:
if (repeating) {
val = 9;
} else {
val = 0;
}
}
UpdatedFields[7] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_enum, Note->Location, 7, &val)) != ERR_NONE) return error;
if (!contact_set) {
if (phone_set) {
val = 0xffffffff;
} else {
val = 0;
}
UpdatedFields[8] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_int, Note->Location, 8, &val)) != ERR_NONE) return error;
}
/* If we didn't update some field, we have to delete it... */
for (i=0; i<Priv->CurrentFieldsCount; i++) {
if (!UpdatedFields[Priv->CurrentFields[i]]) if ((error = ALCATEL_DeleteField(s, Note->Location, Priv->CurrentFields[i])) != ERR_NONE) return error;
}
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
return ERR_NONE;
}
static GSM_Error ALCATEL_DeleteAllCalendar (GSM_StateMachine *s)
{
GSM_Error error;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int i;
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
for (i=0; i<Priv->CalendarItemsCount; i++) {
error = ALCATEL_DeleteItem(s, Priv->CalendarItems[i]);
if (error != ERR_NONE) return error;
}
/* Refresh list */
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
return ERR_NONE;
}
static GSM_Error ALCATEL_GetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
{
GSM_Error error;
GSM_CalendarEntry Note;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int i;
bool Found = false;
bool DateSet = false;
int alarm_number = alarm->Location;
static GSM_DateTime nulldt = {0,0,0,0,0,0,0};
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
-
+
for (i=0; i<Priv->CalendarItemsCount; i++) {
if ((error = ALCATEL_GetFieldValue(s, Priv->CalendarItems[i], 7))!= ERR_NONE) return error;
if (Priv->ReturnType != Alcatel_enum) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
continue;
}
if (Priv->ReturnInt == 4 || Priv->ReturnInt == 5) {
alarm_number--;
if (alarm_number == 0) {
Found = true;
break;
}
}
}
if (!Found) return ERR_EMPTY;
Note.Location = Priv->CalendarItems[i];
-
+
if ((error = ALCATEL_GetCalendar(s, &Note))!= ERR_NONE) return error;
if (Note.Type == GSM_CAL_ALARM) {
alarm->Repeating = false;
} else {
alarm->Repeating = true;
}
-
+
alarm->Text[0] = 0; alarm->Text[1] = 0;
for (i = 0; i < Note.EntriesNum; i++) {
if (Note.Entries[i].EntryType == CAL_TEXT) {
CopyUnicodeString(alarm->Text, Note.Entries[i].Text);
} else if (Note.Entries[i].EntryType == CAL_ALARM_DATETIME) {
alarm->DateTime = Note.Entries[i].Date;
DateSet = false;
}
}
if (!DateSet) {
alarm->DateTime = nulldt;
}
return ERR_NONE;
}
static GSM_Error ALCATEL_SetAlarm (GSM_StateMachine *s, GSM_Alarm *alarm)
{
GSM_Error error;
GSM_CalendarEntry Note;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
GSM_DateTime dt;
int i;
bool Found = false;
int alarm_number = alarm->Location;
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
for (i=0; i<Priv->CalendarItemsCount; i++) {
if ((error = ALCATEL_GetFieldValue(s, Priv->CalendarItems[i], 7))!= ERR_NONE) return error;
if (Priv->ReturnType != Alcatel_enum) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
continue;
}
if (Priv->ReturnInt == 4 || Priv->ReturnInt == 5) {
alarm_number--;
if (alarm_number == 0) {
Found = true;
break;
}
}
}
-
+
if (Found) {
Note.Location = Priv->CalendarItems[i];
}
Note.EntriesNum = 1;
Note.Entries[0].EntryType = CAL_ALARM_DATETIME;
Note.Entries[0].Date = alarm->DateTime;
if (alarm->Repeating) {
Note.Type = GSM_CAL_DAILY_ALARM;
GSM_GetCurrentDateTime(&dt);
Note.Entries[0].Date.Day = dt.Day;
Note.Entries[0].Date.Month = dt.Month;
Note.Entries[0].Date.Year = dt.Year;
} else {
Note.Type = GSM_CAL_ALARM;
}
if (alarm->Text[0] != 0 || alarm->Text[1] != 0) {
Note.EntriesNum++;
Note.Entries[1].EntryType = CAL_TEXT;
CopyUnicodeString(Note.Entries[1].Text, alarm->Text);
}
if (Found) {
return ALCATEL_SetCalendar(s, &Note);
} else {
return ALCATEL_AddCalendar(s, &Note);
}
}
static GSM_Error ALCATEL_GetToDoStatus(GSM_StateMachine *s, GSM_ToDoStatus *status)
{
GSM_Error error;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
-
+
status->Used = 0;
-
+
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
status->Used = Priv->ToDoItemsCount;
return ERR_NONE;
}
static GSM_Error ALCATEL_GetToDo (GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
{
GSM_Error error;
GSM_DateTime *dt = NULL;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int i;
int j=0;
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
if ((error = ALCATEL_IsIdAvailable(s, ToDo->Location))!= ERR_NONE) {
ToDo->EntriesNum = 0;
return error;
}
if ((error = ALCATEL_GetFields(s, ToDo->Location))!= ERR_NONE) return error;
ToDo->EntriesNum = Priv->CurrentFieldsCount;
for (i=0; i < Priv->CurrentFieldsCount; i++) {
if ((error = ALCATEL_GetFieldValue(s, ToDo->Location, Priv->CurrentFields[i]))!= ERR_NONE) return error;
switch (Priv->CurrentFields[i]) {
case 0:
if (Priv->ReturnType != Alcatel_date) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
ToDo->EntriesNum--;
j++;
break;
}
if (!CheckDate(&(Priv->ReturnDateTime))) {
smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
ToDo->EntriesNum--;
j++;
break;
}
ToDo->Entries[i-j].EntryType = TODO_END_DATETIME;
ToDo->Entries[i-j].Date = Priv->ReturnDateTime;
break;
case 1:
if (Priv->ReturnType != Alcatel_bool) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
ToDo->EntriesNum--;
j++;
break;
}
ToDo->Entries[i-j].EntryType = TODO_COMPLETED;
ToDo->Entries[i-j].Number = Priv->ReturnInt;
break;
case 2:
if (Priv->ReturnType != Alcatel_date) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
ToDo->EntriesNum--;
j++;
break;
}
if (!CheckDate(&(Priv->ReturnDateTime))) {
smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
ToDo->EntriesNum--;
j++;
break;
}
if (dt == NULL) {
ToDo->Entries[i-j].EntryType = TODO_ALARM_DATETIME;
ToDo->Entries[i-j].Date = Priv->ReturnDateTime;
dt = &(ToDo->Entries[i-j].Date);
} else {
j++;
ToDo->EntriesNum--;
dt->Day = Priv->ReturnDateTime.Day;
dt->Month = Priv->ReturnDateTime.Month;
dt->Year = Priv->ReturnDateTime.Year;
dt->Timezone = Priv->ReturnDateTime.Timezone;
dt = NULL;
}
break;
case 3:
if (Priv->ReturnType != Alcatel_time) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
ToDo->EntriesNum--;
j++;
break;
}
if (!CheckTime(&(Priv->ReturnDateTime))) {
smprintf(s,"WARNING: Invalid time in phone, ignoring\n");
ToDo->EntriesNum--;
j++;
break;
}
if (dt == NULL) {
ToDo->Entries[i-j].EntryType = TODO_ALARM_DATETIME;
ToDo->Entries[i-j].Date = Priv->ReturnDateTime;
dt = &(ToDo->Entries[i-j].Date);
} else {
j++;
ToDo->EntriesNum--;
dt->Hour = Priv->ReturnDateTime.Hour;
dt->Minute = Priv->ReturnDateTime.Minute;
dt->Second = Priv->ReturnDateTime.Second;
dt = NULL;
}
break;
case 4:
if (Priv->ReturnType != Alcatel_string) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
ToDo->EntriesNum--;
j++;
break;
}
ToDo->Entries[i-j].EntryType = TODO_TEXT;
CopyUnicodeString(ToDo->Entries[i-j].Text, Priv->ReturnString);
break;
case 5:
if (Priv->ReturnType != Alcatel_bool) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
ToDo->EntriesNum--;
j++;
break;
}
ToDo->Entries[i-j].EntryType = TODO_PRIVATE;
ToDo->Entries[i-j].Number = Priv->ReturnInt;
break;
case 6:
if (Priv->ReturnType != Alcatel_byte) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
ToDo->EntriesNum--;
j++;
break;
}
if (Priv->ReturnInt == 255) {
/* 255 means no category */
j++;
ToDo->EntriesNum--;
} else {
ToDo->Entries[i-j].EntryType = TODO_CATEGORY;
ToDo->Entries[i-j].Number = Priv->ReturnInt;
}
break;
case 7:
/* This one seems to be byte for BF5 and enum for BE5 */
if (Priv->ReturnType != Alcatel_enum && Priv->ReturnType != Alcatel_byte) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
ToDo->EntriesNum--;
j++;
break;
}
switch (Priv->ReturnInt) {
case 0:
ToDo->Priority = GSM_Priority_High;
break;
case 1:
ToDo->Priority = GSM_Priority_Medium;
break;
case 2:
ToDo->Priority = GSM_Priority_Low;
break;
default:
ToDo->Priority = 0;
smprintf(s,"WARNING: Received unexpected priority %02X, ignoring\n", Priv->ReturnInt);
}
j++;
ToDo->EntriesNum--;
break;
case 8:
if (Priv->ReturnType != Alcatel_int) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
ToDo->EntriesNum--;
j++;
break;
}
/* 0xffffffff indicates that there is phone, 0 means none */
if (Priv->ReturnInt == 0xffffffff || Priv->ReturnInt == 0) {
j++;
ToDo->EntriesNum--;
} else {
ToDo->Entries[i-j].EntryType = TODO_CONTACTID;
ToDo->Entries[i-j].Number = Priv->ReturnInt;
}
break;
case 9:
if (Priv->ReturnType != Alcatel_phone) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
ToDo->EntriesNum--;
j++;
break;
}
ToDo->Entries[i-j].EntryType = TODO_PHONE;
CopyUnicodeString(ToDo->Entries[i-j].Text, Priv->ReturnString);
break;
case 10:
if (Priv->ReturnType != Alcatel_date) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
ToDo->EntriesNum--;
j++;
break;
}
if (!CheckDate(&(Priv->ReturnDateTime))) {
smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
ToDo->EntriesNum--;
j++;
break;
}
/* This entry had always same value as the 2nd (alarm date) */
j++;
ToDo->EntriesNum--;
break;
case 11:
if (Priv->ReturnType != Alcatel_time) {
smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
ToDo->EntriesNum--;
j++;
break;
}
if (!CheckTime(&(Priv->ReturnDateTime))) {
smprintf(s,"WARNING: Invalid time in phone, ignoring\n");
ToDo->EntriesNum--;
j++;
break;
}
/* This entry had always same value as the 3rd (alarm time) */
j++;
ToDo->EntriesNum--;
break;
default:
ToDo->EntriesNum--;
j++;
smprintf(s,"WARNING: Received unknown field %02X, ignoring. Type = %02X. Value = ", Priv->CurrentFields[i], Priv->ReturnType);
switch (Priv->ReturnType) {
case Alcatel_date:
smprintf(s, "%d.%d.%d", Priv->ReturnDateTime.Day, Priv->ReturnDateTime.Month, Priv->ReturnDateTime.Year);
break;
case Alcatel_time:
smprintf(s, "%d:%d:%d", Priv->ReturnDateTime.Hour, Priv->ReturnDateTime.Minute, Priv->ReturnDateTime.Second);
break;
case Alcatel_string:
case Alcatel_phone:
smprintf(s, "\"%s\"",DecodeUnicodeString(Priv->ReturnString));
break;
case Alcatel_enum:
case Alcatel_bool:
case Alcatel_int:
case Alcatel_byte:
smprintf(s, "%d", Priv->ReturnInt);
break;
}
smprintf(s,"\n");
}
}
return ERR_NONE;
}
static GSM_Error ALCATEL_GetNextToDo(GSM_StateMachine *s, GSM_ToDoEntry *ToDo, bool start)
{
GSM_Error error;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
if (Priv->ToDoItemsCount == 0) return ERR_EMPTY;
-
+
if (start) ToDo->Location = 0;
if ((error = ALCATEL_GetNextId(s, &(ToDo->Location))) != ERR_NONE) return error;
return ALCATEL_GetToDo(s, ToDo);
}
static GSM_Error ALCATEL_DeleteAllToDo (GSM_StateMachine *s)
{
GSM_Error error;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
int i;
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
for (i=0; i<Priv->ToDoItemsCount; i++) {
error = ALCATEL_DeleteItem(s, Priv->ToDoItems[i]);
if (error != ERR_NONE) return error;
}
/* Refresh list */
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
return ERR_NONE;
}
static GSM_Error ALCATEL_AddToDo (GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
{
GSM_Error error;
unsigned int val;
bool contact_set = false;
bool phone_set = false;
int i;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GoToBinaryState(s, StateEdit, TypeToDo, 0))!= ERR_NONE) return error;
-
+
switch (ToDo->Priority) {
case GSM_Priority_High:
val = 0;
break;
case GSM_Priority_Low:
val = 2;
break;
case GSM_Priority_Medium:
default:
val = 1;
break;
}
/* This one seems to be byte for BF5 and enum for BE5 */
if (s->Phone.Data.Priv.ALCATEL.ProtocolVersion == V_1_1) {
if ((error = ALCATEL_CreateField(s, Alcatel_byte, 7, &val)) != ERR_NONE) return error;
} else {
if ((error = ALCATEL_CreateField(s, Alcatel_enum, 7, &val)) != ERR_NONE) return error;
}
for (i = 0; i < ToDo->EntriesNum; i++) {
switch (ToDo->Entries[i].EntryType) {
case TODO_END_DATETIME:
if ((error = ALCATEL_CreateField(s, Alcatel_date, 0, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
break;
case TODO_COMPLETED:
if ((error = ALCATEL_CreateField(s, Alcatel_bool, 1, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
break;
- case TODO_ALARM_DATETIME:
+ case TODO_ALARM_DATETIME:
if ((error = ALCATEL_CreateField(s, Alcatel_date, 2, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
if ((error = ALCATEL_CreateField(s, Alcatel_time, 3, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
if ((error = ALCATEL_CreateField(s, Alcatel_date, 10, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
if ((error = ALCATEL_CreateField(s, Alcatel_time, 11, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
break;
case TODO_TEXT:
if ((error = ALCATEL_CreateField(s, Alcatel_string, 4, ToDo->Entries[i].Text)) != ERR_NONE) return error;
break;
case TODO_PRIVATE:
if ((error = ALCATEL_CreateField(s, Alcatel_bool, 5, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
break;
case TODO_CATEGORY:
if ((error = ALCATEL_CreateField(s, Alcatel_byte, 6, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
break;
case TODO_CONTACTID:
if ((error = ALCATEL_CreateField(s, Alcatel_int, 8, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
contact_set = true;
break;
case TODO_PHONE:
if ((error = ALCATEL_CreateField(s, Alcatel_phone, 9, ToDo->Entries[i].Text)) != ERR_NONE) return error;
phone_set = true;
break;
default:
break;
}
}
if (!contact_set) {
if (phone_set) {
val = 0xffffffff;
} else {
val = 0;
}
if ((error = ALCATEL_CreateField(s, Alcatel_int, 8, &val)) != ERR_NONE) return error;
}
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
ToDo->Location = Priv->CommitedRecord;
/* Refresh list */
if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
return ERR_NONE;
}
static GSM_Error ALCATEL_SetToDo (GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
{
GSM_Error error;
unsigned int val;
bool contact_set = false;
bool phone_set = false;
bool UpdatedFields[12];
int i;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
/* Save modified ToDo */
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
if ((error = ALCATEL_IsIdAvailable(s, ToDo->Location))!= ERR_NONE) {
/* Entry doesn't exist, we will create new one */
return ALCATEL_AddToDo(s, ToDo);
}
/* Get fields for current item */
if ((error = ALCATEL_GetFields(s, ToDo->Location))!= ERR_NONE) return error;
-
+
for (i = 0; i < 12; i++) { UpdatedFields[i] = false; }
-
+
if ((error = ALCATEL_GoToBinaryState(s, StateEdit, TypeToDo, ToDo->Location))!= ERR_NONE) return error;
switch (ToDo->Priority) {
case GSM_Priority_High:
val = 0;
break;
case GSM_Priority_Low:
val = 2;
break;
case GSM_Priority_Medium:
default:
val = 1;
break;
}
/* This one seems to be byte for BF5 and enum for BE5 */
if (s->Phone.Data.Priv.ALCATEL.ProtocolVersion == V_1_1) {
if ((error = ALCATEL_UpdateField(s, Alcatel_byte, ToDo->Location, 7, &val)) != ERR_NONE) return error;
} else {
if ((error = ALCATEL_UpdateField(s, Alcatel_enum, ToDo->Location, 7, &val)) != ERR_NONE) return error;
}
UpdatedFields[7] = true;
for (i = 0; i < ToDo->EntriesNum; i++) {
switch (ToDo->Entries[i].EntryType) {
case TODO_END_DATETIME:
if ((error = ALCATEL_UpdateField(s, Alcatel_date, ToDo->Location, 0, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
- UpdatedFields[0] = true;
+ UpdatedFields[0] = true;
break;
case TODO_COMPLETED:
if ((error = ALCATEL_UpdateField(s, Alcatel_bool, ToDo->Location, 1, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
- UpdatedFields[1] = true;
+ UpdatedFields[1] = true;
break;
- case TODO_ALARM_DATETIME:
+ case TODO_ALARM_DATETIME:
if ((error = ALCATEL_UpdateField(s, Alcatel_date, ToDo->Location, 2, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
- UpdatedFields[2] = true;
+ UpdatedFields[2] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_time, ToDo->Location, 3, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
- UpdatedFields[3] = true;
+ UpdatedFields[3] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_date, ToDo->Location, 10, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
- UpdatedFields[10] = true;
+ UpdatedFields[10] = true;
if ((error = ALCATEL_UpdateField(s, Alcatel_time, ToDo->Location, 11, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
- UpdatedFields[11] = true;
+ UpdatedFields[11] = true;
break;
case TODO_TEXT:
if ((error = ALCATEL_UpdateField(s, Alcatel_string, ToDo->Location, 4, ToDo->Entries[i].Text)) != ERR_NONE) return error;
- UpdatedFields[4] = true;
+ UpdatedFields[4] = true;
break;
case TODO_PRIVATE:
if ((error = ALCATEL_UpdateField(s, Alcatel_bool, ToDo->Location, 5, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
- UpdatedFields[5] = true;
+ UpdatedFields[5] = true;
break;
case TODO_CATEGORY:
if ((error = ALCATEL_UpdateField(s, Alcatel_byte, ToDo->Location, 6, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
- UpdatedFields[6] = true;
+ UpdatedFields[6] = true;
break;
case TODO_CONTACTID:
if ((error = ALCATEL_UpdateField(s, Alcatel_int, ToDo->Location, 8, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
- UpdatedFields[8] = true;
+ UpdatedFields[8] = true;
contact_set = true;
break;
case TODO_PHONE:
if ((error = ALCATEL_UpdateField(s, Alcatel_phone, ToDo->Location, 9, ToDo->Entries[i].Text)) != ERR_NONE) return error;
- UpdatedFields[9] = true;
+ UpdatedFields[9] = true;
phone_set = true;
break;
default:
break;
}
}
if (!contact_set) {
if (phone_set) {
val = 0xffffffff;
} else {
val = 0;
}
if ((error = ALCATEL_UpdateField(s, Alcatel_int, ToDo->Location, 8, &val)) != ERR_NONE) return error;
UpdatedFields[8] = true;
}
/* If we didn't update some field, we have to delete it... */
for (i=0; i<Priv->CurrentFieldsCount; i++) {
if (!UpdatedFields[Priv->CurrentFields[i]]) if ((error = ALCATEL_DeleteField(s, ToDo->Location, Priv->CurrentFields[i])) != ERR_NONE) return error;
}
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
return ERR_NONE;
}
static GSM_Error ALCATEL_DeleteToDo (GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
{
GSM_Error error;
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
/* Delete ToDo */
if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
if ((error = ALCATEL_IsIdAvailable(s, ToDo->Location))!= ERR_NONE) {
/* Entry was empty => no error */
return ERR_NONE;
}
error = ALCATEL_DeleteItem(s, ToDo->Location);
if (error != ERR_NONE) return error;
/* Refresh list */
if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
return ERR_NONE;
}
static GSM_Error ALCATEL_GetCategoryStatus(GSM_StateMachine *s, GSM_CategoryStatus *Status)
{
GSM_Alcatel_BinaryType type;
GSM_Error error;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
switch (Status->Type) {
case Category_ToDo: type = TypeToDo; break;
case Category_Phonebook: type = TypeContacts; break;
default: return ERR_NOTSUPPORTED;
}
if ((error = ALCATEL_GoToBinaryState(s, StateSession, type, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableCategoryIds(s))!= ERR_NONE) return error;
Status->Used = Priv->CurrentCategoriesCount;
return ERR_NONE;
}
static GSM_Error ALCATEL_GetCategory(GSM_StateMachine *s, GSM_Category *Category)
{
GSM_Alcatel_BinaryType type;
GSM_Error error;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
switch (Category->Type) {
case Category_ToDo: type = TypeToDo; break;
case Category_Phonebook: type = TypeContacts; break;
default: return ERR_NOTSUPPORTED;
}
if ((error = ALCATEL_GoToBinaryState(s, StateSession, type, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_GetAvailableCategoryIds(s))!= ERR_NONE) return error;
if ((error = ALCATEL_IsCategoryIdAvailable(s, Category->Location))!= ERR_NONE) return error;
if ((error = ALCATEL_GetCategoryText(s, Category->Location))!= ERR_NONE) return error;
CopyUnicodeString(Category->Name, Priv->ReturnString);
return ERR_NONE;
}
static GSM_Error ALCATEL_AddCategory(GSM_StateMachine *s, GSM_Category *Category)
{
GSM_Alcatel_BinaryType type;
GSM_Error error;
GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
switch (Category->Type) {
case Category_ToDo: type = TypeToDo; break;
case Category_Phonebook: type = TypeContacts; break;
default: return ERR_NOTSUPPORTED;
}
if ((error = ALCATEL_GoToBinaryState(s, StateSession, type, 0))!= ERR_NONE) return error;
if ((error = ALCATEL_AddCategoryText(s, Category->Name))!= ERR_NONE) return error;
Category->Location = Priv->ReturnInt;
return ERR_NONE;
}
static GSM_Error ALCATEL_GetProductCode(GSM_StateMachine *s, char *value)
{
strcpy(value, s->Phone.Data.ModelInfo->model);
return ERR_NONE;
}
static GSM_Error ALCATEL_DispatchMessage(GSM_StateMachine *s)
{
if (s->Phone.Data.Priv.ALCATEL.Mode == ModeBinary) {
return GSM_DispatchMessage(s);
} else {
return ATGEN_DispatchMessage(s);
}
}
static GSM_Error ALCATEL_ReplyGeneric(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
/* All error values are just VERY wild guesses, but these seems to work
* almost as expected ...
*/
switch (msg.Buffer[8]) {
case 0x00: /* no error */
return ERR_NONE;
case 0x10: /* same thing opened in phone menus */
return ERR_INSIDEPHONEMENU;
case 0x13:
/* This appears in more cases:
* - phone needs PIN code
* - we want to close not opened session
* For normal users the second case shouldn't occur...
*/
return ERR_SECURITYERROR;
case 0x14: /* Bad data */
case 0x2f: /* Closing session when not opened */
case 0x1f: /* Bad in/out counter in packet/ack */
case 0x0e: /* Openning session when not closed */
case 0x0C: /* Bad id (item/database) */
case 0x11: /* Bad list id */
case 0x2A: /* Nonexistant field/item id */
case 0x35: /* Too long text */
return ERR_BUG;
case 0x23: /* Session opened */
case 0x80: /* Transfer started */
return ERR_NONE;
case 0x82: /* Transfer canceled */
return ERR_CANCELED;
default:
smprintf(s, "WARNING: Packet seems to indicate some status by %02X, ignoring!\n", msg.Buffer[8]);
return ERR_NONE;
}
}
static GSM_Error ALCATEL_ReplyCommit(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
s->Phone.Data.Priv.ALCATEL.CommitedRecord = msg.Buffer[12] + (msg.Buffer[11] << 8) + (msg.Buffer[10] << 16) + (msg.Buffer[9] << 24);
smprintf(s, "Created record %08x\n", s->Phone.Data.Priv.ALCATEL.CommitedRecord);
return ERR_NONE;
}
static GSM_Error ALCATEL_SetIncomingCB (GSM_StateMachine *s, bool enable)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_SetIncomingCB(s, enable);
}
static GSM_Error ALCATEL_SetIncomingSMS (GSM_StateMachine *s, bool enable)
{
GSM_Error error;
if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
return ATGEN_SetIncomingSMS(s, enable);
}
+static GSM_Error ALCATEL_SetFastSMSSending(GSM_StateMachine *s, bool enable)
+{
+ GSM_Error error;
+
+ if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
+ return ATGEN_SetFastSMSSending(s, enable);
+}
+
static GSM_Reply_Function ALCATELReplyFunctions[] = {
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelAttach },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelDetach },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelCommit },
{ALCATEL_ReplyCommit, "\x02",0x00,0x00, ID_AlcatelCommit2 },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelEnd },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelClose },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelStart },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelSelect1 },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelSelect2 },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelSelect3 },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelBegin1 },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelBegin2 },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelGetIds1 },
{ALCATEL_ReplyGetIds, "\x02",0x00,0x00, ID_AlcatelGetIds2 },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelGetCategories1 },
{ALCATEL_ReplyGetCategories, "\x02",0x00,0x00, ID_AlcatelGetCategories2 },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelGetCategoryText1 },
{ALCATEL_ReplyGetCategoryText, "\x02",0x00,0x00, ID_AlcatelGetCategoryText2 },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelAddCategoryText1 },
{ALCATEL_ReplyAddCategoryText, "\x02",0x00,0x00, ID_AlcatelAddCategoryText2 },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelGetFields1 },
{ALCATEL_ReplyGetFields, "\x02",0x00,0x00, ID_AlcatelGetFields2 },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelGetFieldValue1 },
{ALCATEL_ReplyGetFieldValue, "\x02",0x00,0x00, ID_AlcatelGetFieldValue2 },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelDeleteField },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelDeleteItem1 },
{ALCATEL_ReplyDeleteItem, "\x02",0x00,0x00, ID_AlcatelDeleteItem2 },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelCreateField },
{ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelUpdateField },
{NULL, "\x00",0x00,0x00, ID_None }
};
GSM_Phone_Functions ALCATELPhone = {
/* AFAIK, any 50[0123] phone should work, but I'm not sure whether all
* they were ever really released, if yes add them here also.
*/
"alcatel|OT501|OT701|OT715|OT535|OT735|BE5|BF5|BH4",
ALCATELReplyFunctions,
ALCATEL_Initialise,
ALCATEL_Terminate,
ALCATEL_DispatchMessage,
NOTSUPPORTED, /* ShowStartInfo */
ALCATEL_GetManufacturer,
ALCATEL_GetModel,
ALCATEL_GetFirmware,
ALCATEL_GetIMEI,
NOTSUPPORTED, /* GetOriginalIMEI */
NOTSUPPORTED, /* GetManufactureMonth */
ALCATEL_GetProductCode,
NOTSUPPORTED, /* GetHardware */
NOTSUPPORTED, /* GetPPM */
ALCATEL_GetSIMIMSI,
ALCATEL_GetDateTime,
ALCATEL_SetDateTime,
ALCATEL_GetAlarm,
ALCATEL_SetAlarm,
NOTSUPPORTED, /* GetLocale */
NOTSUPPORTED, /* SetLocale */
ALCATEL_PressKey,
ALCATEL_Reset,
ALCATEL_ResetPhoneSettings,
ALCATEL_EnterSecurityCode,
ALCATEL_GetSecurityStatus,
ALCATEL_GetDisplayStatus,
ALCATEL_SetAutoNetworkLogin,
ALCATEL_GetBatteryCharge,
ALCATEL_GetSignalStrength,
ALCATEL_GetNetworkInfo,
ALCATEL_GetCategory,
ALCATEL_AddCategory,
ALCATEL_GetCategoryStatus,
ALCATEL_GetMemoryStatus,
ALCATEL_GetMemory,
ALCATEL_GetNextMemory,
ALCATEL_SetMemory,
ALCATEL_AddMemory,
ALCATEL_DeleteMemory,
ALCATEL_DeleteAllMemory,
NOTSUPPORTED, /* GetSpeedDial */
NOTSUPPORTED, /* SetSpeedDial */
ALCATEL_GetSMSC,
ALCATEL_SetSMSC,
ALCATEL_GetSMSStatus,
ALCATEL_GetSMS,
ALCATEL_GetNextSMS,
NOTSUPPORTED, /* SetSMS */
ALCATEL_AddSMS,
ALCATEL_DeleteSMS,
ALCATEL_SendSMS,
ALCATEL_SendSavedSMS,
+ ALCATEL_SetFastSMSSending,
ALCATEL_SetIncomingSMS,
ALCATEL_SetIncomingCB,
ALCATEL_GetSMSFolders,
NOTSUPPORTED, /* AddSMSFolder */
NOTSUPPORTED, /* DeleteSMSFolder */
ALCATEL_DialVoice,
ALCATEL_AnswerCall,
ALCATEL_CancelCall,
NOTSUPPORTED, /* HoldCall */
NOTSUPPORTED, /* UnholdCall */
NOTSUPPORTED, /* ConferenceCall */
NOTSUPPORTED, /* SplitCall */
NOTSUPPORTED, /* TransferCall */
NOTSUPPORTED, /* SwitchCall */
NOTSUPPORTED, /* GetCallDivert */
NOTSUPPORTED, /* SetCallDivert */
NOTSUPPORTED, /* CancelAllDiverts */
NONEFUNCTION, /* SetIncomingCall */
NOTSUPPORTED, /* SetIncomingUSSD */
ALCATEL_SendDTMF,
NOTSUPPORTED, /* GetRingtone */
NOTSUPPORTED, /* SetRingtone */
NOTSUPPORTED, /* GetRingtonesInfo */
NOTSUPPORTED, /* DeleteUserRingtones */
NOTSUPPORTED, /* PlayTone */
NOTSUPPORTED, /* GetWAPBookmark */
NOTSUPPORTED, /* SetWAPBookmark */
NOTSUPPORTED, /* DeleteWAPBookmark */
NOTSUPPORTED, /* GetWAPSettings */
NOTSUPPORTED, /* SetWAPSettings */
NOTSUPPORTED, /* GetMMSSettings */
NOTSUPPORTED, /* SetMMSSettings */
NOTSUPPORTED, /* GetSyncMLSettings */
NOTSUPPORTED, /* SetSyncMLSettings */
NOTSUPPORTED, /* GetChatSettings */
NOTSUPPORTED, /* SetChatSettings */
NOTSUPPORTED, /* GetBitmap */
NOTSUPPORTED, /* SetBitmap */
ALCATEL_GetToDoStatus,
ALCATEL_GetToDo,
ALCATEL_GetNextToDo,
ALCATEL_SetToDo,
ALCATEL_AddToDo,
ALCATEL_DeleteToDo,
ALCATEL_DeleteAllToDo,
ALCATEL_GetCalendarStatus,
ALCATEL_GetCalendar,
ALCATEL_GetNextCalendar,
ALCATEL_SetCalendar,
ALCATEL_AddCalendar,
ALCATEL_DeleteCalendar,
ALCATEL_DeleteAllCalendar,
NOTSUPPORTED, /* GetCalendarSettings */
NOTSUPPORTED, /* SetCalendarSettings */
- NOTSUPPORTED, /* GetNote */
+ NOTSUPPORTED, /* GetNextNote */
NOTSUPPORTED, /* GetProfile */
NOTSUPPORTED, /* SetProfile */
NOTSUPPORTED, /* GetFMStation */
NOTSUPPORTED, /* SetFMStation */
NOTSUPPORTED, /* ClearFMStations */
NOTSUPPORTED, /* GetNextFileFolder */
NOTSUPPORTED, /* GetFilePart */
NOTSUPPORTED, /* AddFilePart */
NOTSUPPORTED, /* GetFileSystemStatus */
NOTSUPPORTED, /* DeleteFile */
NOTSUPPORTED, /* AddFolder */
NOTSUPPORTED, /* GetGPRSAccessPoint */
NOTSUPPORTED /* SetGPRSAccessPoint */
};
#endif
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/at/atgen.c b/gammu/emb/common/phone/at/atgen.c
index 1834f15..ba23eb2 100644
--- a/gammu/emb/common/phone/at/atgen.c
+++ b/gammu/emb/common/phone/at/atgen.c
@@ -1,1144 +1,1200 @@
/* (c) 2002-2004 by Marcin Wiacek and Michal Cihar */
#include "../../gsmstate.h"
#ifdef GSM_ENABLE_ATGEN
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "../../gsmcomon.h"
#include "../../misc/coding/coding.h"
#include "../../service/sms/gsmsms.h"
#include "../pfunc.h"
+
#include "atgen.h"
+#include "samsung.h"
+#include "siemens.h"
+#include "sonyeric.h"
+
#ifdef GSM_ENABLE_ALCATEL
-extern GSM_Error ALCATEL_ProtocolVersionReply (GSM_Protocol_Message msg, GSM_StateMachine *s);
+GSM_Error ALCATEL_ProtocolVersionReply (GSM_Protocol_Message, GSM_StateMachine *);
#endif
-extern GSM_Error ATGEN_CMS35ReplyGetBitmap (GSM_Protocol_Message msg, GSM_StateMachine *s);
-extern GSM_Error ATGEN_CMS35ReplySetBitmap (GSM_Protocol_Message msg, GSM_StateMachine *s);
-extern GSM_Error ATGEN_CMS35ReplyGetRingtone (GSM_Protocol_Message msg, GSM_StateMachine *s);
-extern GSM_Error ATGEN_CMS35ReplySetRingtone (GSM_Protocol_Message msg, GSM_StateMachine *s);
-extern GSM_Error ATGEN_CMS35ReplyGetNextCal (GSM_Protocol_Message msg, GSM_StateMachine *s);
-extern GSM_Error ATGEN_CMS35ReplySetCalendar (GSM_Protocol_Message msg, GSM_StateMachine *s);
-extern GSM_Error ATGEN_CMS35ReplyDeleteCalendar (GSM_Protocol_Message msg, GSM_StateMachine *s);
-extern GSM_Error ATGEN_SL45ReplyGetMemory (GSM_Protocol_Message msg, GSM_StateMachine *s);
-
-extern GSM_Error ATGEN_GetRingtone (GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone);
-extern GSM_Error ATGEN_SetRingtone (GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength);
-extern GSM_Error ATGEN_GetBitmap (GSM_StateMachine *s, GSM_Bitmap *Bitmap);
-extern GSM_Error ATGEN_SetBitmap (GSM_StateMachine *s, GSM_Bitmap *Bitmap);
-extern GSM_Error SIEMENS_GetNextCalendar (GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start);
-extern GSM_Error SIEMENS_AddCalendarNote (GSM_StateMachine *s, GSM_CalendarEntry *Note);
-extern GSM_Error SIEMENS_DelCalendarNote (GSM_StateMachine *s, GSM_CalendarEntry *Note);
-
-extern GSM_Error SONYERIC_GetNextCalendar (GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start);
-extern GSM_Error SONYERIC_GetNextToDo (GSM_StateMachine *s, GSM_ToDoEntry *ToDo, bool start);
-extern GSM_Error SONYERIC_GetToDoStatus (GSM_StateMachine *s, GSM_ToDoStatus *status);
-extern GSM_Error SONYERIC_AddCalendarNote (GSM_StateMachine *s, GSM_CalendarEntry *Note);
-extern GSM_Error SONYERIC_AddToDo (GSM_StateMachine *s, GSM_ToDoEntry *ToDo);
-extern GSM_Error SONYERIC_DeleteAllToDo (GSM_StateMachine *s);
-extern GSM_Error SONYERIC_DelCalendarNote (GSM_StateMachine *s, GSM_CalendarEntry *Note);
-extern GSM_Error SONYERIC_GetCalendarStatus (GSM_StateMachine *s, GSM_CalendarStatus *Status);
typedef struct {
int Number;
char Text[60];
} ATErrorCode;
static ATErrorCode CMSErrorCodes[] = {
/*
* Error codes not specified here were either undefined or reserved in my
* copy of specifications, if you have newer one, please fill in the gaps.
*/
/* 0...127 from GSM 04.11 Annex E-2 */
{1, "Unassigned (unallocated) number"},
{8, "Operator determined barring"},
{10, "Call barred"},
{21, "Short message transfer rejected"},
{27, "Destination out of service"},
{28, "Unidentified subscriber"},
{29, "Facility rejected"},
{30, "Unknown subscriber"},
{38, "Network out of order"},
{41, "Temporary failure"},
{42, "Congestion"},
{47, "Resources unavailable, unspecified"},
{50, "Requested facility not subscribed"},
{69, "Requested facility not implemented"},
{81, "Invalid short message transfer reference value"},
{95, "Invalid message, unspecified"},
{96, "Invalid mandatory information"},
{97, "Message type non-existent or not implemented"},
{98, "Message not compatible with short message protocol state"},
{99, "Information element non-existent or not implemented"},
{111, "Protocol error, unspecified"},
{127, "Interworking, unspecified"},
/* 128...255 from GSM 03.40 subclause 9.2.3.22 */
{0x80, "Telematic interworking not supported"},
{0x81, "Short message Type 0 not supported"},
{0x82, "Cannot replace short message"},
{0x8F, "Unspecified TP-PID error"},
{0x90, "Data coding scheme (alphabet) not supported"},
{0x91, "Message class not supported"},
{0x9F, "Unspecified TP-DCS error"},
{0xA0, "Command cannot be actioned"},
{0xA1, "Command unsupported"},
{0xAF, "Unspecified TP-Command error"},
{0xB0, "TPDU not supported"},
{0xC0, "SC busy"},
{0xC1, "No SC subscription"},
{0xC2, "SC system failure"},
{0xC3, "Invalid SME address"},
{0xC4, "Destination SME barred"},
{0xC5, "SM Rejected-Duplicate SM"},
{0xC6, "TP-VPF not supported"},
{0xC7, "TP-VP not supported"},
{0xD0, "SIM SMS storage full"},
{0xD1, "No SMS storage capability in SIM"},
{0xD2, "Error in MS"},
{0xD3, "Memory Capacity Exceede"},
{0xD4, "SIM Application Toolkit Busy"},
{0xFF, "Unspecified error cause"},
/* 300...511 from GSM 07.05 subclause 3.2.5 */
{300, "ME failure"},
{301, "SMS service of ME reserved"},
{302, "operation not allowed"},
{303, "operation not supported"},
{304, "invalid PDU mode parameter"},
{305, "invalid text mode parameter"},
{310, "SIM not inserted"},
{311, "SIM PIN required"},
{312, "PH-SIM PIN required"},
{313, "SIM failure"},
{314, "SIM busy"},
{315, "SIM wrong"},
{316, "SIM PUK required"},
{317, "SIM PIN2 required"},
{318, "SIM PUK2 required"},
{320, "memory failure"},
{321, "invalid memory index"},
{322, "memory full"},
{330, "SMSC address unknown"},
{331, "no network service"},
{332, "network timeout"},
{340, "no CNMA acknowledgement expected"},
{500, "unknown error"},
/* > 512 are manufacturer specific according to GSM 07.05 subclause 3.2.5 */
{-1, ""}
};
static ATErrorCode CMEErrorCodes[] = {
/* CME Error codes from GSM 07.07 section 9.2 */
{0, "phone failure"},
{1, "no connection to phone"},
{2, "phone-adaptor link reserved"},
{3, "operation not allowed"},
{4, "operation not supported"},
{5, "PH-SIM PIN required"},
{10, "SIM not inserted"},
{11, "SIM PIN required"},
{12, "SIM PUK required"},
{13, "SIM failure"},
{14, "SIM busy"},
{15, "SIM wrong"},
{16, "incorrect password"},
{17, "SIM PIN2 required"},
{18, "SIM PUK2 required"},
{20, "memory full"},
{21, "invalid index"},
{22, "not found"},
{23, "memory failure"},
{24, "text string too long"},
{25, "invalid characters in text string"},
{26, "dial string too long"},
{27, "invalid characters in dial string"},
{30, "no network service"},
{31, "network timeout"},
{100, "unknown"},
};
GSM_Error ATGEN_HandleCMEError(GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
if (Priv->ErrorCode == 0) {
smprintf(s, "CME Error occured, but it's type not detected\n");
} else if (Priv->ErrorText == NULL) {
smprintf(s, "CME Error %i, no description available\n", Priv->ErrorCode);
} else {
smprintf(s, "CME Error %i: \"%s\"\n", Priv->ErrorCode, Priv->ErrorText);
}
/* For error codes descriptions see table a bit above */
switch (Priv->ErrorCode) {
+ case -1:
+ return ERR_EMPTY;
case 3:
return ERR_PERMISSION;
case 4:
return ERR_NOTSUPPORTED;
case 5:
case 11:
case 12:
case 16:
case 17:
case 18:
return ERR_SECURITYERROR;
case 20:
return ERR_FULL;
case 21:
return ERR_INVALIDLOCATION;
case 22:
return ERR_EMPTY;
case 23:
return ERR_MEMORY;
case 24:
case 25:
case 26:
case 27:
return ERR_INVALIDDATA;
default:
return ERR_UNKNOWN;
}
}
GSM_Error ATGEN_HandleCMSError(GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
if (Priv->ErrorCode == 0) {
smprintf(s, "CMS Error occured, but it's type not detected\n");
} else if (Priv->ErrorText == NULL) {
smprintf(s, "CMS Error %i, no description available\n", Priv->ErrorCode);
} else {
smprintf(s, "CMS Error %i: \"%s\"\n", Priv->ErrorCode, Priv->ErrorText);
}
/* For error codes descriptions see table a bit above */
switch (Priv->ErrorCode) {
case 304:
return ERR_NOTSUPPORTED;
case 305:
return ERR_BUG;
case 311:
case 312:
case 316:
case 317:
case 318:
return ERR_SECURITYERROR;
case 322:
return ERR_FULL;
case 321:
return ERR_INVALIDLOCATION;
default:
return ERR_UNKNOWN;
}
}
/* FIXME: Function doesn't respect quoting of parameters and thus +FOO:
* "ab","cd,ef" will consider as three arguments: "ab" >> "cd >> ef"
*/
int ATGEN_ExtractOneParameter(unsigned char *input, unsigned char *output)
{
int position=0;
while (*input!=',' && *input!=0x0d && *input!=0x00) {
*output=*input;
input ++;
output ++;
position++;
}
*output=0;
position++;
return position;
}
void ATGEN_DecodeDateTime(GSM_DateTime *dt, unsigned char *input)
{
- dt->Year=2000+(*input-'0')*10; input++;
+ /* Samsung phones report year as %d instead of %02d */
+ if (input[2] == '/') {
+ dt->Year=(*input-'0')*10;
+ input++;
+ } else {
+ dt->Year=0;
+ }
+
dt->Year=dt->Year+(*input-'0'); input++;
+ dt->Year+=2000;
input++;
dt->Month=(*input-'0')*10; input++;
dt->Month=dt->Month+(*input-'0'); input++;
input++;
dt->Day=(*input-'0')*10; input++;
dt->Day=dt->Day+(*input-'0'); input++;
input++;
dt->Hour=(*input-'0')*10; input++;
dt->Hour=dt->Hour+(*input-'0'); input++;
input++;
dt->Minute=(*input-'0')*10; input++;
dt->Minute=dt->Minute+(*input-'0');input++;
input++;
dt->Second=(*input-'0')*10; input++;
dt->Second=dt->Second+(*input-'0');input++;
if (input!=NULL) {
input++;
dt->Timezone=(*input-'0')*10; input++;
dt->Timezone=dt->Timezone+(*input-'0');input++;
input=input-2;
if (*input=='-') dt->Timezone=-dt->Timezone;
}
}
GSM_Error ATGEN_DispatchMessage(GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_Protocol_Message *msg = s->Phone.Data.RequestMsg;
int i = 0, j, k;
char *err, *line;
ATErrorCode *ErrorCodes = NULL;
SplitLines(msg->Buffer, msg->Length, &Priv->Lines, "\x0D\x0A", 2, true);
/* Find number of lines */
while (Priv->Lines.numbers[i*2+1] != 0) {
/* FIXME: handle special chars correctly */
smprintf(s, "%i \"%s\"\n",i+1,GetLineString(msg->Buffer,Priv->Lines,i+1));
i++;
}
Priv->ReplyState = AT_Reply_Unknown;
Priv->ErrorText = NULL;
Priv->ErrorCode = 0;
line = GetLineString(msg->Buffer,Priv->Lines,i);
if (!strcmp(line,"OK")) Priv->ReplyState = AT_Reply_OK;
if (!strcmp(line,"> ")) Priv->ReplyState = AT_Reply_SMSEdit;
if (!strcmp(line,"CONNECT")) Priv->ReplyState = AT_Reply_Connect;
if (!strcmp(line,"ERROR" )) Priv->ReplyState = AT_Reply_Error;
if (!strncmp(line,"+CME ERROR:",11)) {
Priv->ReplyState = AT_Reply_CMEError;
ErrorCodes = CMEErrorCodes;
}
if (!strncmp(line,"+CMS ERROR:",11)) {
Priv->ReplyState = AT_Reply_CMSError;
ErrorCodes = CMSErrorCodes;
}
+
+ /* FIXME: Samsung phones can answer +CME ERROR:-1 meaning empty location */
+ if (Priv->ReplyState == AT_Reply_CMEError && Priv->Manufacturer == AT_Samsung) {
+ err = line + 11;
+ Priv->ErrorCode = atoi(err);
+
+ if (Priv->ErrorCode == -1) {
+ Priv->ErrorText = "[Samsung] Empty location";
+ return GSM_DispatchMessage(s);
+ }
+ }
+
if (Priv->ReplyState == AT_Reply_CMEError || Priv->ReplyState == AT_Reply_CMSError) {
j = 0;
/* One char behind +CM[SE] ERROR */
err = line + 12;
while (err[j] && !isalnum(err[j])) j++;
if (isdigit(err[j])) {
Priv->ErrorCode = atoi(&(err[j]));
k = 0;
while (ErrorCodes[k].Number != -1) {
if (ErrorCodes[k].Number == Priv->ErrorCode) {
Priv->ErrorText = (char *)&(ErrorCodes[k].Text);
break;
}
k++;
}
} else if (isalpha(err[j])) {
k = 0;
while (ErrorCodes[k].Number != -1) {
if (!strncmp(err + j, ErrorCodes[k].Text, strlen(ErrorCodes[k].Text))) {
Priv->ErrorCode = ErrorCodes[k].Number;
Priv->ErrorText = (char *)&(ErrorCodes[k].Text);
break;
}
k++;
}
}
}
return GSM_DispatchMessage(s);
}
GSM_Error ATGEN_GenericReply(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
case AT_Reply_OK:
case AT_Reply_Connect:
return ERR_NONE;
case AT_Reply_Error:
return ERR_UNKNOWN;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
case AT_Reply_CMEError:
return ATGEN_HandleCMEError(s);
default:
break;
}
return ERR_UNKNOWNRESPONSE;
}
+GSM_Error ATGEN_ReplyGetUSSD(GSM_Protocol_Message msg, GSM_StateMachine *s)
+{
+ unsigned char buffer[2000],buffer2[4000];
+ int i = 10;
+
+ /* Ugly hack */
+ while (msg.Buffer[i]!=13) i++;
+ i = i - 6;
+ memcpy(buffer,msg.Buffer+10,i-11);
+ buffer[i-11] = 0x00;
+
+ smprintf(s, "USSD reply: \"%s\"\n",buffer);
+
+ if (s->Phone.Data.EnableIncomingUSSD && s->User.IncomingUSSD!=NULL) {
+ EncodeUnicode(buffer2,buffer,strlen(buffer));
+ s->User.IncomingUSSD(s->CurrentConfig->Device, buffer2);
+ }
+
+ return ERR_NONE;
+}
+
+GSM_Error ATGEN_SetIncomingUSSD(GSM_StateMachine *s, bool enable)
+{
+ GSM_Error error;
+
+ if (enable) {
+ smprintf(s, "Enabling incoming USSD\n");
+ error=GSM_WaitFor (s, "AT+CUSD=1\r", 10, 0x00, 3, ID_SetUSSD);
+ } else {
+ smprintf(s, "Disabling incoming USSD\n");
+ error=GSM_WaitFor (s, "AT+CUSD=0\r", 10, 0x00, 3, ID_SetUSSD);
+ }
+ if (error==ERR_NONE) s->Phone.Data.EnableIncomingUSSD = enable;
+ return error;
+}
+
GSM_Error ATGEN_ReplyGetModel(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_Phone_Data *Data = &s->Phone.Data;
if (s->Phone.Data.Priv.ATGEN.ReplyState != AT_Reply_OK) return ERR_NOTSUPPORTED;
if (strlen(GetLineString(msg.Buffer, Priv->Lines, 2)) <= MAX_MODEL_LENGTH) {
CopyLineString(Data->Model, msg.Buffer, Priv->Lines, 2);
/* Sometimes phone adds this before manufacturer (Sagem) */
if (strncmp("+CGMM: ", Data->Model, 7) == 0) {
memmove(Data->Model, Data->Model + 7, strlen(Data->Model + 7) + 1);
}
Data->ModelInfo = GetModelData(NULL,Data->Model,NULL);
if (Data->ModelInfo->number[0] == 0) Data->ModelInfo = GetModelData(NULL,NULL,Data->Model);
if (Data->ModelInfo->number[0] == 0) Data->ModelInfo = GetModelData(Data->Model,NULL,NULL);
if (Data->ModelInfo->number[0] != 0) strcpy(Data->Model,Data->ModelInfo->number);
if (strstr(msg.Buffer,"Nokia")) Priv->Manufacturer = AT_Nokia;
else if (strstr(msg.Buffer,"M20")) Priv->Manufacturer = AT_Siemens;
else if (strstr(msg.Buffer,"MC35")) Priv->Manufacturer = AT_Siemens;
+ else if (strstr(msg.Buffer,"TC35")) Priv->Manufacturer = AT_Siemens;
else if (strstr(msg.Buffer, "iPAQ")) Priv->Manufacturer = AT_HP;
if (strstr(msg.Buffer,"M20")) strcpy(Data->Model,"M20");
else if (strstr(msg.Buffer,"MC35")) strcpy(Data->Model,"MC35");
+ else if (strstr(msg.Buffer,"TC35")) strcpy(Data->Model,"TC35");
else if (strstr(msg.Buffer, "iPAQ")) strcpy(Data->Model,"iPAQ");
} else {
smprintf(s, "WARNING: Model name too long, increase MAX_MODEL_LENGTH to at least %zd\n", strlen(GetLineString(msg.Buffer, Priv->Lines, 2)));
}
return ERR_NONE;
}
GSM_Error ATGEN_GetModel(GSM_StateMachine *s)
{
GSM_Error error;
if (s->Phone.Data.Model[0] != 0) return ERR_NONE;
smprintf(s, "Getting model\n");
error=GSM_WaitFor (s, "AT+CGMM\r", 8, 0x00, 3, ID_GetModel);
if (error==ERR_NONE) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
smprintf(s, "[Connected model - \"%s\"]\n",s->Phone.Data.Model);
}
}
return error;
}
GSM_Error ATGEN_ReplyGetManufacturer(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
switch (Priv->ReplyState) {
case AT_Reply_OK:
smprintf(s, "Manufacturer info received\n");
Priv->Manufacturer = AT_Unknown;
if (strlen(GetLineString(msg.Buffer, Priv->Lines, 2)) <= MAX_MANUFACTURER_LENGTH) {
CopyLineString(s->Phone.Data.Manufacturer, msg.Buffer, Priv->Lines, 2);
} else {
smprintf(s, "WARNING: Manufacturer name too long, increase MAX_MANUFACTURER_LENGTH to at least %zd\n", strlen(GetLineString(msg.Buffer, Priv->Lines, 2)));
s->Phone.Data.Manufacturer[0] = 0;
}
/* Sometimes phone adds this before manufacturer (Sagem) */
if (strncmp("+CGMI: ", s->Phone.Data.Manufacturer, 7) == 0) {
memmove(s->Phone.Data.Manufacturer, s->Phone.Data.Manufacturer + 7, strlen(s->Phone.Data.Manufacturer + 7) + 1);
}
if (strstr(msg.Buffer,"Falcom")) {
smprintf(s, "Falcom\n");
strcpy(s->Phone.Data.Manufacturer,"Falcom");
Priv->Manufacturer = AT_Falcom;
if (strstr(msg.Buffer,"A2D")) {
strcpy(s->Phone.Data.Model,"A2D");
s->Phone.Data.ModelInfo = GetModelData(NULL,s->Phone.Data.Model,NULL);
smprintf(s, "Model A2D\n");
}
}
if (strstr(msg.Buffer,"Nokia")) {
smprintf(s, "Nokia\n");
strcpy(s->Phone.Data.Manufacturer,"Nokia");
Priv->Manufacturer = AT_Nokia;
}
if (strstr(msg.Buffer,"SIEMENS")) {
smprintf(s, "Siemens\n");
strcpy(s->Phone.Data.Manufacturer,"Siemens");
Priv->Manufacturer = AT_Siemens;
}
if (strstr(msg.Buffer,"ERICSSON")) {
smprintf(s, "Ericsson\n");
strcpy(s->Phone.Data.Manufacturer,"Ericsson");
Priv->Manufacturer = AT_Ericsson;
}
if (strstr(msg.Buffer,"iPAQ")) {
smprintf(s, "iPAQ\n");
strcpy(s->Phone.Data.Manufacturer,"HP");
Priv->Manufacturer = AT_HP;
}
if (strstr(msg.Buffer,"ALCATEL")) {
smprintf(s, "Alcatel\n");
strcpy(s->Phone.Data.Manufacturer,"Alcatel");
Priv->Manufacturer = AT_Alcatel;
}
if (strstr(msg.Buffer,"SAGEM")) {
smprintf(s, "Sagem\n");
strcpy(s->Phone.Data.Manufacturer,"Sagem");
Priv->Manufacturer = AT_Sagem;
}
+ if (strstr(msg.Buffer,"Samsung")) {
+ smprintf(s, "Samsung\n");
+ strcpy(s->Phone.Data.Manufacturer,"Samsung");
+ Priv->Manufacturer = AT_Samsung;
+ }
return ERR_NONE;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
break;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error ATGEN_GetManufacturer(GSM_StateMachine *s)
{
if (s->Phone.Data.Manufacturer[0] != 0) return ERR_NONE;
return GSM_WaitFor (s, "AT+CGMI\r", 8, 0x00, 4, ID_GetManufacturer);
}
GSM_Error ATGEN_ReplyGetFirmwareCGMR(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
unsigned int i = 0;
strcpy(s->Phone.Data.Version,"unknown");
s->Phone.Data.VerNum = 0;
if (Priv->ReplyState == AT_Reply_OK) {
CopyLineString(s->Phone.Data.Version, msg.Buffer, Priv->Lines, 2);
/* Sometimes phone adds this before manufacturer (Sagem) */
if (strncmp("+CGMR: ", s->Phone.Data.Version, 7) == 0) {
memmove(s->Phone.Data.Version, s->Phone.Data.Version + 7, strlen(s->Phone.Data.Version + 7) + 1);
}
}
if (Priv->Manufacturer == AT_Ericsson) {
while (1) {
if (s->Phone.Data.Version[i] == 0x20) {
s->Phone.Data.Version[i] = 0x00;
break;
}
if (i == strlen(s->Phone.Data.Version)) break;
i++;
}
}
smprintf(s, "Received firmware version: \"%s\"\n",s->Phone.Data.Version);
GSM_CreateFirmwareNumber(s);
return ERR_NONE;
}
GSM_Error ATGEN_ReplyGetFirmwareATI(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
switch (Priv->ReplyState) {
case AT_Reply_OK:
// strcpy(Data->Version,"0.00");
// *Data->VersionNum=0;
// if (Data->Priv.ATGEN.ReplyState==AT_Reply_OK) {
// CopyLineString(Data->Version, msg.Buffer, Priv->Lines, 2);
// }
// smprintf(s, "Received firmware version: \"%s\"\n",Data->Version);
// GSM_CreateFirmwareNumber(Data);
// return ERR_NONE;
case AT_Reply_Error:
return ERR_NOTSUPPORTED;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
break;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error ATGEN_GetFirmware(GSM_StateMachine *s)
{
GSM_Error error;
if (s->Phone.Data.Version[0] != 0) return ERR_NONE;
error=ATGEN_GetManufacturer(s);
if (error != ERR_NONE) return error;
// smprintf(s, "Getting firmware - method 1\n");
// error=GSM_WaitFor (s, "ATI\r", 4, 0x00, 3, ID_GetFirmware);
// if (error != ERR_NONE) {
smprintf(s, "Getting firmware - method 2\n");
error=GSM_WaitFor (s, "AT+CGMR\r", 8, 0x00, 3, ID_GetFirmware);
// }
if (error==ERR_NONE) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
smprintf(s, "[Firmware version - \"%s\"]\n",s->Phone.Data.Version);
}
}
return error;
}
GSM_Error ATGEN_Initialise(GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_Error error;
char buff[2];
Priv->SMSMode = 0;
Priv->Manufacturer = 0;
Priv->PhoneSMSMemory = 0;
Priv->CanSaveSMS = false;
Priv->SIMSMSMemory = 0;
Priv->SMSMemory = 0;
Priv->PBKMemory = 0;
Priv->PBKSBNR = 0;
Priv->PBKCharset = 0;
Priv->UCS2CharsetFailed = false;
Priv->NonUCS2CharsetFailed = false;
Priv->PBKMemories[0] = 0;
Priv->FirstCalendarPos = 0;
Priv->NextMemoryEntry = 0;
Priv->FirstMemoryEntry = 0;
Priv->file.Used = 0;
Priv->file.Buffer = NULL;
Priv->OBEX = false;
Priv->MemorySize = 0;
Priv->TextLength = 0;
Priv->NumberLength = 0;
Priv->ErrorText = NULL;
if (s->ConnectionType != GCT_IRDAAT && s->ConnectionType != GCT_BLUEAT) {
/* We try to escape AT+CMGS mode, at least Siemens M20
* then needs to get some rest
*/
smprintf(s, "Escaping SMS mode\n");
error = s->Protocol.Functions->WriteMessage(s, "\x1B\r", 2, 0x00);
if (error!=ERR_NONE) return error;
/* Grab any possible garbage */
while (s->Device.Functions->ReadDevice(s, buff, 2) > 0) my_sleep(10);
}
/* When some phones (Alcatel BE5) is first time connected, it needs extra
* time to react, sending just AT wakes up the phone and it then can react
* to ATE1. We don't need to check whether this fails as it is just to
* wake up the phone and does nothing.
*/
smprintf(s, "Sending simple AT command to wake up some devices\n");
GSM_WaitFor (s, "AT\r", 3, 0x00, 2, ID_IncomingFrame);
smprintf(s, "Enabling echo\n");
error = GSM_WaitFor (s, "ATE1\r", 5, 0x00, 3, ID_EnableEcho);
if (error != ERR_NONE) return error;
smprintf(s, "Enabling CME errors\n");
/* Try numeric errors */
if (GSM_WaitFor (s, "AT+CMEE=1\r", 10, 0x00, 3, ID_EnableErrorInfo) != ERR_NONE) {
/* Try textual errors */
if (GSM_WaitFor (s, "AT+CMEE=2\r", 10, 0x00, 3, ID_EnableErrorInfo) != ERR_NONE) {
smprintf(s, "CME errors could not be enabled, some error types won't be detected.\n");
}
}
error = ATGEN_GetModel(s);
if (error != ERR_NONE) return error;
if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SLOWWRITE)) {
s->Protocol.Data.AT.FastWrite = true;
}
return error;
}
GSM_Error ATGEN_SetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
{
unsigned char req[50];
if (smsc->Location!=1) return ERR_NOTSUPPORTED;
sprintf(req, "AT+CSCA=\"%s\"\r",DecodeUnicodeString(smsc->Number));
smprintf(s, "Setting SMSC\n");
return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_SetSMSC);
}
GSM_Error ATGEN_ReplyGetSMSMemories(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
case AT_Reply_OK:
/* Reply here is:
* (memories for reading)[, (memories for writing)[, (memories for storing received messages)]]
* each memory is in quotes,
* Example: ("SM"), ("SM"), ("SM")
*
* We need to get from this supported memories. For this case
* we assume, that just appearence of memory makes it
* available for everything. Then we need to find out whether
* phone supports writing to memory. This is done by searching
* for "), (", which will appear between lists.
*/
- s->Phone.Data.Priv.ATGEN.CanSaveSMS = (strstr(msg.Buffer, "), (") != NULL);
+ s->Phone.Data.Priv.ATGEN.CanSaveSMS = false;
+ if (strstr(msg.Buffer, "), (") != NULL || strstr(msg.Buffer, "),(") != NULL) {
+ s->Phone.Data.Priv.ATGEN.CanSaveSMS = true;
+ }
+
if (strstr(msg.Buffer, "\"SM\"") != NULL) s->Phone.Data.Priv.ATGEN.SIMSMSMemory = AT_AVAILABLE;
else s->Phone.Data.Priv.ATGEN.SIMSMSMemory = AT_NOTAVAILABLE;
+
if (strstr(msg.Buffer, "\"ME\"") != NULL) s->Phone.Data.Priv.ATGEN.PhoneSMSMemory = AT_AVAILABLE;
else s->Phone.Data.Priv.ATGEN.PhoneSMSMemory = AT_NOTAVAILABLE;
- smprintf(s, "Available SMS memories received, ME = %d, SM = %d\n", s->Phone.Data.Priv.ATGEN.PhoneSMSMemory, s->Phone.Data.Priv.ATGEN.SIMSMSMemory);
+
+ smprintf(s, "Available SMS memories received, ME = %d, SM = %d, cansavesms =", s->Phone.Data.Priv.ATGEN.PhoneSMSMemory, s->Phone.Data.Priv.ATGEN.SIMSMSMemory);
+ if (s->Phone.Data.Priv.ATGEN.CanSaveSMS) smprintf(s, "true");
+ smprintf(s, "\n");
return ERR_NONE;
case AT_Reply_Error:
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
+ case AT_Reply_CMEError:
+ return ATGEN_HandleCMEError(s);
default:
return ERR_UNKNOWNRESPONSE;
}
}
GSM_Error ATGEN_GetSMSMemories(GSM_StateMachine *s)
{
smprintf(s, "Getting available SMS memories\n");
return GSM_WaitFor (s, "AT+CPMS=?\r", 10, 0x00, 4, ID_GetSMSMemories);
}
GSM_Error ATGEN_SetSMSMemory(GSM_StateMachine *s, bool SIM)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
char req[] = "AT+CPMS=\"XX\",\"XX\"\r";
int reqlen = 18;
GSM_Error error;
if ((SIM && Priv->SIMSMSMemory == 0) || (!SIM && Priv->PhoneSMSMemory == 0)) {
/* We silently ignore error here, because when this fails, we can try to setmemory anyway */
ATGEN_GetSMSMemories(s);
}
/* If phone can not save SMS, don't try to set memory for saving */
if (!Priv->CanSaveSMS) {
req[12] = '\r';
reqlen = 13;
}
if (SIM) {
if (Priv->SMSMemory == MEM_SM) return ERR_NONE;
if (Priv->SIMSMSMemory == AT_NOTAVAILABLE) return ERR_NOTSUPPORTED;
req[9] = 'S'; req[10] = 'M';
req[14] = 'S'; req[15] = 'M';
smprintf(s, "Setting SMS memory type to SM\n");
error=GSM_WaitFor (s, req, reqlen, 0x00, 3, ID_SetMemoryType);
if (Priv->SIMSMSMemory == 0 && error == ERR_NONE) {
Priv->SIMSMSMemory = AT_AVAILABLE;
}
if (error == ERR_NOTSUPPORTED) {
smprintf(s, "Can't access SIM card?\n");
return ERR_SECURITYERROR;
}
if (error != ERR_NONE) return error;
Priv->SMSMemory = MEM_SM;
} else {
if (Priv->SMSMemory == MEM_ME) return ERR_NONE;
if (Priv->PhoneSMSMemory == AT_NOTAVAILABLE) return ERR_NOTSUPPORTED;
req[9] = 'M'; req[10] = 'E';
req[14] = 'M'; req[15] = 'E';
smprintf(s, "Setting SMS memory type to ME\n");
error=GSM_WaitFor (s, req, reqlen, 0x00, 3, ID_SetMemoryType);
if (Priv->PhoneSMSMemory == 0 && error == ERR_NONE) {
Priv->PhoneSMSMemory = AT_AVAILABLE;
}
if (error == ERR_NONE) Priv->SMSMemory = MEM_ME;
}
return error;
}
GSM_Error ATGEN_GetSMSMode(GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_Error error;
if (Priv->SMSMode != 0) return ERR_NONE;
smprintf(s, "Trying SMS PDU mode\n");
error=GSM_WaitFor (s, "AT+CMGF=0\r", 10, 0x00, 3, ID_GetSMSMode);
if (error==ERR_NONE) {
Priv->SMSMode = SMS_AT_PDU;
return ERR_NONE;
}
smprintf(s, "Trying SMS text mode\n");
error=GSM_WaitFor (s, "AT+CMGF=1\r", 10, 0x00, 3, ID_GetSMSMode);
if (error==ERR_NONE) {
smprintf(s, "Enabling displaying all parameters in text mode\n");
error=GSM_WaitFor (s, "AT+CSDH=1\r", 10, 0x00, 3, ID_GetSMSMode);
if (error == ERR_NONE) Priv->SMSMode = SMS_AT_TXT;
}
return error;
}
GSM_Error ATGEN_GetSMSLocation(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char *folderid, int *location)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
int ifolderid, maxfolder;
GSM_Error error;
if (Priv->PhoneSMSMemory == 0) {
error = ATGEN_SetSMSMemory(s, false);
if (error != ERR_NONE && error != ERR_NOTSUPPORTED) return error;
}
if (Priv->SIMSMSMemory == 0) {
error = ATGEN_SetSMSMemory(s, true);
if (error != ERR_NONE && error != ERR_NOTSUPPORTED) return error;
}
if (Priv->SIMSMSMemory != AT_AVAILABLE && Priv->PhoneSMSMemory != AT_AVAILABLE) {
/* No SMS memory at all */
return ERR_NOTSUPPORTED;
}
if (Priv->SIMSMSMemory == AT_AVAILABLE && Priv->PhoneSMSMemory == AT_AVAILABLE) {
/* Both available */
maxfolder = 2;
} else {
/* One available */
maxfolder = 1;
}
/* simulate flat SMS memory */
if (sms->Folder == 0x00) {
ifolderid = sms->Location / PHONE_MAXSMSINFOLDER;
if (ifolderid + 1 > maxfolder) return ERR_NOTSUPPORTED;
*folderid = ifolderid + 1;
*location = sms->Location - ifolderid * PHONE_MAXSMSINFOLDER;
} else {
if (sms->Folder > 2 * maxfolder) return ERR_NOTSUPPORTED;
*folderid = sms->Folder <= 2 ? 1 : 2;
*location = sms->Location;
}
smprintf(s, "SMS folder %i & location %i -> ATGEN folder %i & location %i\n",
sms->Folder,sms->Location,*folderid,*location);
if (Priv->SIMSMSMemory == AT_AVAILABLE && *folderid == 1) {
return ATGEN_SetSMSMemory(s, true);
} else {
return ATGEN_SetSMSMemory(s, false);
}
}
void ATGEN_SetSMSLocation(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char folderid, int location)
{
sms->Folder = 0;
sms->Location = (folderid - 1) * PHONE_MAXSMSINFOLDER + location;
smprintf(s, "ATGEN folder %i & location %i -> SMS folder %i & location %i\n",
folderid,location,sms->Folder,sms->Location);
}
GSM_Error ATGEN_ReplyGetSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_SMSMessage *sms = &s->Phone.Data.GetSMSMessage->SMS[0];
int current = 0, current2, i;
unsigned char buffer[300],smsframe[800];
unsigned char firstbyte, TPDCS, TPUDL, TPStatus;
GSM_Error error;
switch (Priv->ReplyState) {
case AT_Reply_OK:
if (Priv->Lines.numbers[4] == 0x00) return ERR_EMPTY;
s->Phone.Data.GetSMSMessage->Number = 1;
s->Phone.Data.GetSMSMessage->SMS[0].Name[0] = 0;
s->Phone.Data.GetSMSMessage->SMS[0].Name[1] = 0;
switch (Priv->SMSMode) {
case SMS_AT_PDU:
CopyLineString(buffer, msg.Buffer, Priv->Lines, 2);
switch (buffer[7]) {
case '0': sms->State = SMS_UnRead; break;
case '1': sms->State = SMS_Read; break;
case '2': sms->State = SMS_UnSent; break;
default : sms->State = SMS_Sent; break;//case '3'
}
DecodeHexBin (buffer, GetLineString(msg.Buffer,Priv->Lines,3), strlen(GetLineString(msg.Buffer,Priv->Lines,3)));
/* Siemens MC35 (only ?) */
if (strstr(msg.Buffer,"+CMGR: 0,,0")!=NULL) return ERR_EMPTY;
/* Siemens M20 */
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_M20SMS)) {
- if (buffer[1]!=NUMBER_UNKNOWN && buffer[1]!=NUMBER_INTERNATIONAL &&
- buffer[1]!=NUMBER_ALPHANUMERIC) {
+ /* we check for the most often visible */
+ if (buffer[1]!=NUMBER_UNKNOWN_NUMBERING_PLAN_ISDN && buffer[1]!=NUMBER_INTERNATIONAL_NUMBERING_PLAN_ISDN &&
+ buffer[1]!=NUMBER_ALPHANUMERIC_NUMBERING_PLAN_UNKNOWN) {
/* Seems to be Delivery Report */
smprintf(s, "SMS type - status report (M20 style)\n");
sms->PDU = SMS_Status_Report;
sms->Folder = 1; /*INBOX SIM*/
sms->InboxFolder = true;
smsframe[12]=buffer[current++];
smsframe[PHONE_SMSStatusReport.TPMR]=buffer[current++];
current2=((buffer[current])+1)/2+1;
for(i=0;i<current2+1;i++) smsframe[PHONE_SMSStatusReport.Number+i]=buffer[current++];
for(i=0;i<7;i++) smsframe[PHONE_SMSStatusReport.DateTime+i]=buffer[current++];
smsframe[0] = 0;
for(i=0;i<7;i++) smsframe[PHONE_SMSStatusReport.SMSCTime+i]=buffer[current++];
smsframe[PHONE_SMSStatusReport.TPStatus]=buffer[current];
GSM_DecodeSMSFrame(sms,smsframe,PHONE_SMSStatusReport);
return ERR_NONE;
}
}
/* We use locations from SMS layouts like in ../phone2.c(h) */
for(i=0;i<buffer[0]+1;i++) smsframe[i]=buffer[current++];
smsframe[12]=buffer[current++];
/* See GSM 03.40 section 9.2.3.1 */
switch (smsframe[12] & 0x03) {
case 0x00:
smprintf(s, "SMS type - deliver\n");
sms->PDU = SMS_Deliver;
if (Priv->SMSMemory == MEM_SM) {
sms->Folder = 1; /*INBOX SIM*/
} else {
sms->Folder = 3; /*INBOX ME*/
}
sms->InboxFolder = true;
current2=((buffer[current])+1)/2+1;
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_M20SMS)) {
- if (buffer[current+1]==NUMBER_ALPHANUMERIC) {
+ if (buffer[current+1]==NUMBER_ALPHANUMERIC_NUMBERING_PLAN_UNKNOWN) {
smprintf(s, "Trying to read alphanumeric number\n");
for(i=0;i<4;i++) smsframe[PHONE_SMSDeliver.Number+i]=buffer[current++];
current+=6;
for(i=0;i<current2-3;i++) smsframe[PHONE_SMSDeliver.Number+i+4]=buffer[current++];
} else {
for(i=0;i<current2+1;i++) smsframe[PHONE_SMSDeliver.Number+i]=buffer[current++];
}
} else {
for(i=0;i<current2+1;i++) smsframe[PHONE_SMSDeliver.Number+i]=buffer[current++];
}
smsframe[PHONE_SMSDeliver.TPPID] = buffer[current++];
smsframe[PHONE_SMSDeliver.TPDCS] = buffer[current++];
for(i=0;i<7;i++) smsframe[PHONE_SMSDeliver.DateTime+i]=buffer[current++];
smsframe[PHONE_SMSDeliver.TPUDL] = buffer[current++];
for(i=0;i<smsframe[PHONE_SMSDeliver.TPUDL];i++) smsframe[i+PHONE_SMSDeliver.Text]=buffer[current++];
GSM_DecodeSMSFrame(sms,smsframe,PHONE_SMSDeliver);
return ERR_NONE;
case 0x01:
smprintf(s, "SMS type - submit\n");
sms->PDU = SMS_Submit;
if (Priv->SMSMemory == MEM_SM) {
sms->Folder = 2; /*OUTBOX SIM*/
smprintf(s, "Outbox SIM\n");
} else {
sms->Folder = 4; /*OUTBOX ME*/
}
sms->InboxFolder = false;
smsframe[PHONE_SMSSubmit.TPMR] = buffer[current++];
current2=((buffer[current])+1)/2+1;
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_M20SMS)) {
- if (buffer[current+1]==NUMBER_ALPHANUMERIC) {
+ if (buffer[current+1]==NUMBER_ALPHANUMERIC_NUMBERING_PLAN_UNKNOWN) {
smprintf(s, "Trying to read alphanumeric number\n");
for(i=0;i<4;i++) smsframe[PHONE_SMSSubmit.Number+i]=buffer[current++];
current+=6;
for(i=0;i<current2-3;i++) smsframe[PHONE_SMSSubmit.Number+i+4]=buffer[current++];
} else {
for(i=0;i<current2+1;i++) smsframe[PHONE_SMSSubmit.Number+i]=buffer[current++];
}
} else {
for(i=0;i<current2+1;i++) smsframe[PHONE_SMSSubmit.Number+i]=buffer[current++];
}
smsframe[PHONE_SMSSubmit.TPPID] = buffer[current++];
smsframe[PHONE_SMSSubmit.TPDCS] = buffer[current++];
/* See GSM 03.40 9.2.3.3 - TPVP can not exist in frame */
if ((smsframe[12] & 0x18)!=0) current++; //TPVP is ignored now
smsframe[PHONE_SMSSubmit.TPUDL] = buffer[current++];
for(i=0;i<smsframe[PHONE_SMSSubmit.TPUDL];i++) smsframe[i+PHONE_SMSSubmit.Text]=buffer[current++];
GSM_DecodeSMSFrame(sms,smsframe,PHONE_SMSSubmit);
return ERR_NONE;
case 0x02:
smprintf(s, "SMS type - status report\n");
sms->PDU = SMS_Status_Report;
sms->Folder = 1; /*INBOX SIM*/
sms->InboxFolder = true;
- smprintf(s, "TPMR is %02x\n",buffer[current]);
+ smprintf(s, "TPMR is %d\n",buffer[current]);
smsframe[PHONE_SMSStatusReport.TPMR] = buffer[current++];
current2=((buffer[current])+1)/2+1;
for(i=0;i<current2+1;i++) smsframe[PHONE_SMSStatusReport.Number+i]=buffer[current++];
for(i=0;i<7;i++) smsframe[PHONE_SMSStatusReport.DateTime+i]=buffer[current++];
for(i=0;i<7;i++) smsframe[PHONE_SMSStatusReport.SMSCTime+i]=buffer[current++];
smsframe[PHONE_SMSStatusReport.TPStatus]=buffer[current];
GSM_DecodeSMSFrame(sms,smsframe,PHONE_SMSStatusReport);
return ERR_NONE;
}
break;
case SMS_AT_TXT:
current = 0;
while (msg.Buffer[current]!='"') current++;
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
if (!strcmp(buffer,"\"0\"") || !strcmp(buffer,"\"REC UNREAD\"")) {
smprintf(s, "SMS type - deliver\n");
sms->State = SMS_UnRead;
sms->PDU = SMS_Deliver;
if (Priv->SMSMemory == MEM_SM) {
sms->Folder = 1; /*INBOX SIM*/
} else {
sms->Folder = 3; /*INBOX ME*/
}
sms->InboxFolder = true;
} else if (!strcmp(buffer,"\"1\"") || !strcmp(buffer,"\"REC READ\"")) {
smprintf(s, "SMS type - deliver\n");
sms->State = SMS_Read;
sms->PDU = SMS_Deliver;
if (Priv->SMSMemory == MEM_SM) {
sms->Folder = 1; /*INBOX SIM*/
} else {
sms->Folder = 3; /*INBOX ME*/
}
sms->InboxFolder = true;
} else if (!strcmp(buffer,"\"2\"") || !strcmp(buffer,"\"STO UNSENT\"")) {
smprintf(s, "SMS type - submit\n");
sms->State = SMS_UnSent;
sms->PDU = SMS_Submit;
if (Priv->SMSMemory == MEM_SM) {
sms->Folder = 2; /*OUTBOX SIM*/
} else {
sms->Folder = 4; /*OUTBOX ME*/
}
sms->InboxFolder = false;
} else if (!strcmp(buffer,"\"3\"") || !strcmp(buffer,"\"STO SENT\"")) {
smprintf(s, "SMS type - submit\n");
sms->State = SMS_Sent;
sms->PDU = SMS_Submit;
if (Priv->SMSMemory == MEM_SM) {
sms->Folder = 2; /*OUTBOX SIM*/
} else {
sms->Folder = 4; /*OUTBOX ME*/
}
sms->InboxFolder = false;
}
current += ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
/* It's delivery report according to Nokia AT standards */
if (sms->Folder==1 && buffer[0]!=0 && buffer[0]!='"') {
/* ??? */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
/* format of sender number */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
/* Sender number */
/* FIXME: support for all formats */
EncodeUnicode(sms->Number,buffer+1,strlen(buffer)-2);
smprintf(s, "Sender \"%s\"\n",DecodeUnicodeString(sms->Number));
/* ??? */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
/* Sending datetime */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
i = strlen(buffer);
buffer[i] = ',';
i++;
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer+i);
smprintf(s, "\"%s\"\n",buffer);
ATGEN_DecodeDateTime(&sms->DateTime, buffer+1);
/* Date of SMSC response */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
i = strlen(buffer);
buffer[i] = ',';
i++;
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer+i);
smprintf(s, "\"%s\"\n",buffer);
ATGEN_DecodeDateTime(&sms->SMSCTime, buffer+1);
/* TPStatus */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
TPStatus=atoi(buffer);
buffer[PHONE_SMSStatusReport.TPStatus] = TPStatus;
error=GSM_DecodeSMSFrameStatusReportData(sms, buffer, PHONE_SMSStatusReport);
if (error!=ERR_NONE) return error;
/* NO SMSC number */
sms->SMSC.Number[0]=0;
sms->SMSC.Number[1]=0;
sms->PDU = SMS_Status_Report;
sms->ReplyViaSameSMSC=false;
} else {
/* Sender number */
/* FIXME: support for all formats */
EncodeUnicode(sms->Number,buffer+1,strlen(buffer)-2);
/* Sender number in alphanumeric format ? */
current += ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
if (strlen(buffer)!=0) EncodeUnicode(sms->Number,buffer+1,strlen(buffer)-2);
smprintf(s, "Sender \"%s\"\n",DecodeUnicodeString(sms->Number));
/* Sending datetime */
if (sms->Folder==1 || sms->Folder==3) {
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
/* FIXME: ATGEN_ExtractOneParameter() is broken as it doesn't respect
* quoting of parameters and thus +FOO: "ab","cd,ef" will consider
* as three arguments: "ab" >> "cd >> ef"
*/
if (*buffer=='"') {
i = strlen(buffer);
buffer[i] = ',';
i++;
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer+i);
}
smprintf(s, "\"%s\"\n",buffer);
if (*buffer)
ATGEN_DecodeDateTime(&sms->DateTime, buffer+1);
else {
/* FIXME: What is the proper undefined GSM_DateTime ? */
memset(&sms->DateTime, 0, sizeof(sms->DateTime));
}
ATGEN_DecodeDateTime(&sms->DateTime, buffer+1);
}
/* Sender number format */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
/* First byte */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
firstbyte=atoi(buffer);
sms->ReplyViaSameSMSC=false;
/* GSM 03.40 section 9.2.3.17 (TP-Reply-Path) */
if ((firstbyte & 128)==128) sms->ReplyViaSameSMSC=true;
/* TP PID */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
sms->ReplaceMessage = 0;
if (atoi(buffer) > 0x40 && atoi(buffer) < 0x48) {
sms->ReplaceMessage = atoi(buffer) - 0x40;
}
smprintf(s, "TPPID: %02x %i\n",atoi(buffer),atoi(buffer));
/* TP DCS */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
TPDCS=atoi(buffer);
if (sms->Folder==2 || sms->Folder==4) {
/*TP VP */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
}
/* SMSC number */
/* FIXME: support for all formats */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
EncodeUnicode(sms->SMSC.Number,buffer+1,strlen(buffer)-2);
/* Format of SMSC number */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
/* TPUDL */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
TPUDL=atoi(buffer);
current++;
sms->Coding = SMS_Coding_Default;
/* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme)
* and GSM 03.38 section 4
*/
if ((TPDCS & 0xf4) == 0xf4) sms->Coding=SMS_Coding_8bit;
if ((TPDCS & 0x08) == 0x08) sms->Coding=SMS_Coding_Unicode;
sms->Class = -1;
if ((TPDCS & 0xF3)==0xF0) sms->Class = 0;
if ((TPDCS & 0xF3)==0xF1) sms->Class = 1;
if ((TPDCS & 0xF3)==0xF2) sms->Class = 2;
if ((TPDCS & 0xF3)==0xF3) sms->Class = 3;
smprintf(s, "SMS class: %i\n",sms->Class);
switch (sms->Coding) {
case SMS_Coding_Default:
/* GSM 03.40 section 9.2.3.23 (TP-User-Data-Header-Indicator) */
/* If not SMS with UDH, it's coded normal */
/* If UDH available, treat it as Unicode or 8 bit */
if ((firstbyte & 0x40)!=0x40) {
sms->UDH.Type = UDH_NoUDH;
sms->Length = TPUDL;
EncodeUnicode(sms->Text,msg.Buffer+Priv->Lines.numbers[2*2],TPUDL);
break;
}
case SMS_Coding_Unicode:
case SMS_Coding_8bit:
DecodeHexBin(buffer+PHONE_SMSDeliver.Text, msg.Buffer+current, TPUDL*2);
buffer[PHONE_SMSDeliver.firstbyte] = firstbyte;
buffer[PHONE_SMSDeliver.TPDCS] = TPDCS;
buffer[PHONE_SMSDeliver.TPUDL] = TPUDL;
return GSM_DecodeSMSFrameText(sms, buffer, PHONE_SMSDeliver);
}
}
return ERR_NONE;
default:
break;
@@ -1451,531 +1507,544 @@ GSM_Error ATGEN_MakeSMSFrame(GSM_StateMachine *s, GSM_SMSMessage *message, unsig
for(i=0;i<length;i++) req[(*current)++]=buffer[PHONE_SMSSubmit.Text+i];
EncodeHexBin(hexreq, req, *current);
*length2 = *current * 2;
*current = *current - (req[PHONE_SMSSubmit.SMSCNumber]+1);
}
break;
case SMS_AT_TXT:
if (Priv->Manufacturer == 0) {
error=ATGEN_GetManufacturer(s);
if (error != ERR_NONE) return error;
}
if (Priv->Manufacturer != AT_Nokia) {
if (message->Coding != SMS_Coding_Default) return ERR_NOTSUPPORTED;
}
error=PHONE_EncodeSMSFrame(s,message,req,PHONE_SMSDeliver,&i,true);
if (error != ERR_NONE) return error;
CopyUnicodeString(SMSC.Number,message->SMSC.Number);
SMSC.Location=1;
error=ATGEN_SetSMSC(s,&SMSC);
if (error!=ERR_NONE) return error;
sprintf(buffer, "AT+CSMP=%i,%i,%i,%i\r",
req[PHONE_SMSDeliver.firstbyte],
req[PHONE_SMSDeliver.TPVP],
req[PHONE_SMSDeliver.TPPID],
req[PHONE_SMSDeliver.TPDCS]);
error=GSM_WaitFor (s, buffer, strlen(buffer), 0x00, 4, ID_SetSMSParameters);
if (error==ERR_NOTSUPPORTED) {
/* Nokia Communicator 9000i doesn't support <vp> parameter */
sprintf(buffer, "AT+CSMP=%i,,%i,%i\r",
req[PHONE_SMSDeliver.firstbyte],
req[PHONE_SMSDeliver.TPPID],
req[PHONE_SMSDeliver.TPDCS]);
error=GSM_WaitFor (s, buffer, strlen(buffer), 0x00, 4, ID_SetSMSParameters);
}
if (error!=ERR_NONE) return error;
switch (message->Coding) {
case SMS_Coding_Default:
/* If not SMS with UDH, it's as normal text */
if (message->UDH.Type==UDH_NoUDH) {
strcpy(hexreq,DecodeUnicodeString(message->Text));
*length2 = UnicodeLength(message->Text);
break;
}
case SMS_Coding_Unicode:
case SMS_Coding_8bit:
error=PHONE_EncodeSMSFrame(s,message,buffer,PHONE_SMSDeliver,current,true);
if (error != ERR_NONE) return error;
EncodeHexBin (hexreq, buffer+PHONE_SMSDeliver.Text, buffer[PHONE_SMSDeliver.TPUDL]);
*length2 = buffer[PHONE_SMSDeliver.TPUDL] * 2;
break;
}
break;
}
return ERR_NONE;
}
GSM_Error ATGEN_AddSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
{
GSM_Error error, error2;
int state,Replies,reply, current, current2;
unsigned char buffer[1000], hexreq[1000];
GSM_Phone_Data *Phone = &s->Phone.Data;
unsigned char *statetxt;
/* This phone supports only sent/unsent messages on SIM */
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SMSONLYSENT)) {
if (sms->Folder != 2) {
smprintf(s, "This phone supports only folder = 2!\n");
return ERR_NOTSUPPORTED;
}
}
sms->PDU = SMS_Submit;
switch (sms->Folder) {
case 1: sms->PDU = SMS_Deliver; /* Inbox SIM */
error=ATGEN_SetSMSMemory(s, true);
break;
case 2: error=ATGEN_SetSMSMemory(s, true); /* Outbox SIM */
break;
case 3: sms->PDU = SMS_Deliver;
error=ATGEN_SetSMSMemory(s, false); /* Inbox phone */
break;
case 4: error=ATGEN_SetSMSMemory(s, false); /* Outbox phone */
break;
default: return ERR_NOTSUPPORTED;
}
if (error!=ERR_NONE) return error;
error = ATGEN_MakeSMSFrame(s, sms, hexreq, &current, &current2);
if (error != ERR_NONE) return error;
switch (Phone->Priv.ATGEN.SMSMode) {
case SMS_AT_PDU:
if (sms->PDU == SMS_Deliver) {
state = 0;
if (sms->State == SMS_Read || sms->State == SMS_Sent) state = 1;
} else {
state = 2;
if (sms->State == SMS_Read || sms->State == SMS_Sent) state = 3;
}
/* Siemens M20 */
if (IsPhoneFeatureAvailable(Phone->ModelInfo, F_M20SMS)) {
/* No (good and 100% working) support for alphanumeric numbers */
if (sms->Number[1]!='+' && (sms->Number[1]<'0' || sms->Number[1]>'9')) {
EncodeUnicode(sms->Number,"123",3);
error = ATGEN_MakeSMSFrame(s, sms, hexreq, &current, &current2);
if (error != ERR_NONE) return error;
}
}
sprintf(buffer, "AT+CMGW=%i,%i\r",current,state);
break;
case SMS_AT_TXT:
if (sms->PDU == SMS_Deliver) {
statetxt = "REC UNREAD";
if (sms->State == SMS_Read || sms->State == SMS_Sent) statetxt = "REC READ";
} else {
statetxt = "STO UNSENT";
if (sms->State == SMS_Read || sms->State == SMS_Sent) statetxt = "STO SENT";
}
/* Siemens M20 */
if (IsPhoneFeatureAvailable(Phone->ModelInfo, F_M20SMS)) {
/* No (good and 100% working) support for alphanumeric numbers */
/* FIXME: Try to autodetect support for <stat> (statetxt) parameter although:
* Siemens M20 supports +CMGW <stat> specification but on my model it just
* reports ERROR (and <stat> is not respected).
* Fortunately it will write "+CMGW: <index>\n" before and the message gets written
*/
if (sms->Number[1]!='+' && (sms->Number[1]<'0' || sms->Number[1]>'9')) {
sprintf(buffer, "AT+CMGW=\"123\",,\"%s\"\r",statetxt);
} else {
sprintf(buffer, "AT+CMGW=\"%s\",,\"%s\"\r",DecodeUnicodeString(sms->Number),statetxt);
}
} else {
sprintf(buffer, "AT+CMGW=\"%s\",,\"%s\"\r",DecodeUnicodeString(sms->Number),statetxt);
}
}
Phone->SaveSMSMessage = sms;
for (reply=0;reply<s->ReplyNum;reply++) {
if (reply!=0) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
smprintf(s, "[Retrying %i]\n", reply+1);
}
}
s->Protocol.Data.AT.EditMode = true;
Replies = s->ReplyNum;
s->ReplyNum = 1;
smprintf(s,"Waiting for modem prompt\n");
error=GSM_WaitFor (s, buffer, strlen(buffer), 0x00, 3, ID_SaveSMSMessage);
s->ReplyNum = Replies;
if (error == ERR_NONE) {
Phone->DispatchError = ERR_TIMEOUT;
Phone->RequestID = ID_SaveSMSMessage;
smprintf(s, "Saving SMS\n");
error = s->Protocol.Functions->WriteMessage(s, hexreq, current2, 0x00);
if (error!=ERR_NONE) return error;
my_sleep(500);
/* CTRL+Z ends entering */
error = s->Protocol.Functions->WriteMessage(s, "\x1A", 1, 0x00);
if (error!=ERR_NONE) return error;
error = GSM_WaitForOnce(s, NULL, 0x00, 0x00, 4);
if (error != ERR_TIMEOUT) return error;
} else {
smprintf(s, "Escaping SMS mode\n");
error2 = s->Protocol.Functions->WriteMessage(s, "\x1B\r", 2, 0x00);
if (error2 != ERR_NONE) return error2;
return error;
}
}
return Phone->DispatchError;
}
GSM_Error ATGEN_ReplySendSMS(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
char *start;
if (s->Protocol.Data.AT.EditMode) {
if (s->Phone.Data.Priv.ATGEN.ReplyState != AT_Reply_SMSEdit) {
return ERR_UNKNOWN;
}
s->Protocol.Data.AT.EditMode = false;
return ERR_NONE;
}
switch (Priv->ReplyState) {
case AT_Reply_OK:
smprintf(s, "SMS sent OK\n");
if (s->User.SendSMSStatus!=NULL) {
- start = strstr(msg.Buffer, "+CMGW: ");
+ start = strstr(msg.Buffer, "+CMGS: ");
if (start != NULL) {
s->User.SendSMSStatus(s->CurrentConfig->Device,0,atoi(start+7));
} else {
- s->User.SendSMSStatus(s->CurrentConfig->Device,0,0);
+ s->User.SendSMSStatus(s->CurrentConfig->Device,0,-1);
}
}
return ERR_NONE;
case AT_Reply_CMSError:
smprintf(s, "Error %i\n",Priv->ErrorCode);
- if (s->User.SendSMSStatus!=NULL) s->User.SendSMSStatus(s->CurrentConfig->Device,Priv->ErrorCode,0);
+ if (s->User.SendSMSStatus!=NULL) s->User.SendSMSStatus(s->CurrentConfig->Device,Priv->ErrorCode,-1);
return ATGEN_HandleCMSError(s);
case AT_Reply_Error:
return ERR_UNKNOWN;
default:
return ERR_UNKNOWNRESPONSE;
}
}
GSM_Error ATGEN_SendSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
{
GSM_Error error,error2;
int current, current2, Replies;
unsigned char buffer[1000], hexreq[1000];
GSM_Phone_Data *Phone = &s->Phone.Data;
if (sms->PDU == SMS_Deliver) sms->PDU = SMS_Submit;
error = ATGEN_MakeSMSFrame(s, sms, hexreq, &current, &current2);
if (error != ERR_NONE) return error;
switch (Phone->Priv.ATGEN.SMSMode) {
case SMS_AT_PDU:
sprintf(buffer, "AT+CMGS=%i\r",current);
break;
case SMS_AT_TXT:
sprintf(buffer, "AT+CMGS=\"%s\"\r",DecodeUnicodeString(sms->Number));
}
s->Protocol.Data.AT.EditMode = true;
Replies = s->ReplyNum;
s->ReplyNum = 1;
smprintf(s,"Waiting for modem prompt\n");
error=GSM_WaitFor (s, buffer, strlen(buffer), 0x00, 3, ID_IncomingFrame);
s->ReplyNum = Replies;
if (error == ERR_NONE) {
smprintf(s, "Sending SMS\n");
error = s->Protocol.Functions->WriteMessage(s, hexreq, current2, 0x00);
if (error!=ERR_NONE) return error;
my_sleep(500);
/* CTRL+Z ends entering */
error=s->Protocol.Functions->WriteMessage(s, "\x1A", 1, 0x00);
my_sleep(100);
return error;
} else {
smprintf(s, "Escaping SMS mode\n");
error2=s->Protocol.Functions->WriteMessage(s, "\x1B\r", 2, 0x00);
if (error2 != ERR_NONE) return error2;
}
return error;
}
GSM_Error ATGEN_SendSavedSMS(GSM_StateMachine *s, int Folder, int Location)
{
GSM_Error error;
int location;
unsigned char smsfolder;
unsigned char req[100];
GSM_MultiSMSMessage msms;
msms.Number = 0;
msms.SMS[0].Folder = Folder;
msms.SMS[0].Location = Location;
/* By reading SMS we check if it is really inbox/outbox */
error = ATGEN_GetSMS(s, &msms);
if (error != ERR_NONE) return error;
/* Can not send from other folder that outbox */
if (msms.SMS[0].Folder != 2 && msms.SMS[0].Folder != 4) return ERR_NOTSUPPORTED;
error=ATGEN_GetSMSLocation(s, &msms.SMS[0], &smsfolder, &location);
if (error != ERR_NONE) return error;
sprintf(req, "AT+CMSS=%i\r",location);
return s->Protocol.Functions->WriteMessage(s, req, strlen(req), 0x00);
}
GSM_Error ATGEN_ReplyGetDateTime_Alarm(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int current = 19;
GSM_Phone_Data *Data = &s->Phone.Data;
switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
case AT_Reply_OK:
if (msg.Buffer[current]==0x0d || msg.Buffer[current-1]==0x0d) {
smprintf(s, "Not set in phone\n");
return ERR_EMPTY;
} else {
if (Data->RequestID == ID_GetDateTime) {
ATGEN_DecodeDateTime(Data->DateTime, msg.Buffer+current);
} else {
ATGEN_DecodeDateTime(&(Data->Alarm->DateTime), msg.Buffer+current);
}
return ERR_NONE;
}
case AT_Reply_Error:
return ERR_NOTSUPPORTED;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
break;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error ATGEN_GetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
{
s->Phone.Data.DateTime=date_time;
smprintf(s, "Getting date & time\n");
return GSM_WaitFor (s, "AT+CCLK?\r", 9, 0x00, 4, ID_GetDateTime);
}
GSM_Error ATGEN_SetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
{
char req[128];
sprintf(req, "AT+CCLK=\"%02i/%02i/%02i,%02i:%02i:%02i+00\"\r",
date_time->Year-2000,date_time->Month,date_time->Day,
date_time->Hour,date_time->Minute,date_time->Second);
smprintf(s, "Setting date & time\n");
return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_SetDateTime);
}
GSM_Error ATGEN_GetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
{
if (alarm->Location != 1) return ERR_NOTSUPPORTED;
alarm->Repeating = true;
alarm->Text[0] = 0; alarm->Text[1] = 0;
s->Phone.Data.Alarm = alarm;
smprintf(s, "Getting alarm\n");
return GSM_WaitFor (s, "AT+CALA?\r", 9, 0x00, 4, ID_GetAlarm);
}
+/* R320 only takes HH:MM. Do other phones understand full date? */
+GSM_Error ATGEN_SetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
+{
+ char req[20];
+
+ if (alarm->Location != 1) return ERR_INVALIDLOCATION;
+
+ sprintf(req, "AT+CALA=\"%02i:%02i\"\r",alarm->DateTime.Hour,alarm->DateTime.Minute);
+
+ smprintf(s, "Setting Alarm\n");
+ return GSM_WaitFor (s, req, strlen(req), 0x00, 3, ID_SetAlarm);
+}
+
GSM_Error ATGEN_ReplyGetSMSC(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_SMSC *SMSC = s->Phone.Data.SMSC;
int current;
int len;
unsigned char buffer[100];
switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
case AT_Reply_OK:
smprintf(s, "SMSC info received\n");
current = 0;
while (msg.Buffer[current]!='"') current++;
/* SMSC number */
/* FIXME: support for all formats */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
/*
* Some phones return this as unicode encoded when they are
* switched to UCS2 mode, so we try to solve this correctly.
*/
len = strlen(buffer + 1) - 1;
buffer[len + 1] = 0;
if ((len > 20) && (len % 4 == 0) && (strchr(buffer + 1, '+') == NULL)) {
/* This is probably unicode encoded number */
DecodeHexUnicode(SMSC->Number,buffer + 1,len);
} else {
EncodeUnicode(SMSC->Number,buffer + 1,len);
}
smprintf(s, "Number: \"%s\"\n",DecodeUnicodeString(SMSC->Number));
/* Format of SMSC number */
current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
smprintf(s, "Format %s\n",buffer);
/* International number */
if (!strcmp(buffer,"145")) {
sprintf(buffer+1,"%s",DecodeUnicodeString(SMSC->Number));
if (strlen(buffer+1)!=0 && buffer[1] != '+') {
/* Sony Ericsson issue */
/* International number is without + */
buffer[0] = '+';
EncodeUnicode(SMSC->Number,buffer,strlen(buffer));
}
}
SMSC->Format = SMS_FORMAT_Text;
SMSC->Validity.Format = SMS_Validity_RelativeFormat;
SMSC->Validity.Relative = SMS_VALID_Max_Time;
SMSC->Name[0] = 0;
SMSC->Name[1] = 0;
SMSC->DefaultNumber[0] = 0;
SMSC->DefaultNumber[1] = 0;
return ERR_NONE;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
break;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error ATGEN_GetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
{
if (smsc->Location==0x00 || smsc->Location!=0x01) return ERR_INVALIDLOCATION;
s->Phone.Data.SMSC=smsc;
smprintf(s, "Getting SMSC\n");
return GSM_WaitFor (s, "AT+CSCA?\r", 9, 0x00, 4, ID_GetSMSC);
}
GSM_Error ATGEN_ReplyGetNetworkLAC_CID(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_NetworkInfo *NetworkInfo = s->Phone.Data.NetworkInfo;
GSM_Lines Lines;
int i=0;
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
char *answer;
if (s->Phone.Data.RequestID == ID_IncomingFrame) {
smprintf(s, "Incoming LAC & CID info\n");
return ERR_NONE;
}
switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
case AT_Reply_OK:
break;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
return ERR_UNKNOWNRESPONSE;
}
SplitLines(GetLineString(msg.Buffer,Priv->Lines,2),
strlen(GetLineString(msg.Buffer,Priv->Lines,2)),
&Lines, ",", 1, true);
/* Find number of lines */
while (Lines.numbers[i*2+1] != 0) {
/* FIXME: handle special chars correctly */
smprintf(s, "%i \"%s\"\n",i+1,GetLineString(GetLineString(msg.Buffer,Priv->Lines,2),Lines,i+1));
i++;
}
smprintf(s, "Network LAC & CID & state received\n");
answer = GetLineString(GetLineString(msg.Buffer,Priv->Lines,2),Lines,2);
while (*answer == 0x20) answer++;
#ifdef DEBUG
switch (answer[0]) {
case '0': smprintf(s, "Not registered into any network. Not searching for network\n"); break;
case '1': smprintf(s, "Home network\n"); break;
case '2': smprintf(s, "Not registered into any network. Searching for network\n"); break;
case '3': smprintf(s, "Registration denied\n"); break;
case '4': smprintf(s, "Unknown\n"); break;
case '5': smprintf(s, "Registered in roaming network\n"); break;
default : smprintf(s, "Unknown\n");
}
#endif
switch (answer[0]) {
case '0': NetworkInfo->State = GSM_NoNetwork; break;
case '1': NetworkInfo->State = GSM_HomeNetwork; break;
case '2': NetworkInfo->State = GSM_RequestingNetwork; break;
case '3': NetworkInfo->State = GSM_RegistrationDenied; break;
case '4': NetworkInfo->State = GSM_NetworkStatusUnknown;break;
case '5': NetworkInfo->State = GSM_RoamingNetwork; break;
default : NetworkInfo->State = GSM_NetworkStatusUnknown;break;
}
if (NetworkInfo->State == GSM_HomeNetwork ||
NetworkInfo->State == GSM_RoamingNetwork) {
memset(NetworkInfo->CID,0,4);
memset(NetworkInfo->LAC,0,4);
if (Lines.numbers[3*2+1]==0) return ERR_NONE;
answer = GetLineString(GetLineString(msg.Buffer,Priv->Lines,2),Lines,3);
while (*answer == 0x20) answer++;
sprintf(NetworkInfo->CID, "%c%c%c%c", answer[1], answer[2], answer[3], answer[4]);
answer = GetLineString(GetLineString(msg.Buffer,Priv->Lines,2),Lines,4);
while (*answer == 0x20) answer++;
sprintf(NetworkInfo->LAC, "%c%c%c%c", answer[1], answer[2], answer[3], answer[4]);
smprintf(s, "CID : %s\n",NetworkInfo->CID);
smprintf(s, "LAC : %s\n",NetworkInfo->LAC);
}
return ERR_NONE;
}
GSM_Error ATGEN_ReplyGetNetworkCode(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_NetworkInfo *NetworkInfo = s->Phone.Data.NetworkInfo;
switch (Priv->ReplyState) {
case AT_Reply_OK:
smprintf(s, "Network code received\n");
if (Priv->Manufacturer == AT_Falcom) {
NetworkInfo->NetworkCode[0] = msg.Buffer[22];
NetworkInfo->NetworkCode[1] = msg.Buffer[23];
NetworkInfo->NetworkCode[2] = msg.Buffer[24];
NetworkInfo->NetworkCode[3] = ' ';
NetworkInfo->NetworkCode[4] = msg.Buffer[25];
NetworkInfo->NetworkCode[5] = msg.Buffer[26];
} else {
NetworkInfo->NetworkCode[0] = msg.Buffer[23];
NetworkInfo->NetworkCode[1] = msg.Buffer[24];
NetworkInfo->NetworkCode[2] = msg.Buffer[25];
NetworkInfo->NetworkCode[3] = ' ';
NetworkInfo->NetworkCode[4] = msg.Buffer[26];
NetworkInfo->NetworkCode[5] = msg.Buffer[27];
}
NetworkInfo->NetworkCode[6] = 0;
smprintf(s, " Network code : %s\n", NetworkInfo->NetworkCode);
smprintf(s, " Network name for Gammu : %s ",
DecodeUnicodeString(GSM_GetNetworkName(NetworkInfo->NetworkCode)));
smprintf(s, "(%s)\n",DecodeUnicodeString(GSM_GetCountryName(NetworkInfo->NetworkCode)));
return ERR_NONE;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
break;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error ATGEN_GetNetworkInfo(GSM_StateMachine *s, GSM_NetworkInfo *netinfo)
{
GSM_Error error;
s->Phone.Data.NetworkInfo=netinfo;
netinfo->NetworkName[0] = 0;
netinfo->NetworkName[1] = 0;
@@ -2013,1657 +2082,1781 @@ GSM_Error ATGEN_ReplyGetPBKMemories(GSM_Protocol_Message msg, GSM_StateMachine *
}
memcpy(s->Phone.Data.Priv.ATGEN.PBKMemories,msg.Buffer,strlen(msg.Buffer));
return ERR_NONE;
}
GSM_Error ATGEN_SetPBKMemory(GSM_StateMachine *s, GSM_MemoryType MemType)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
char req[] = "AT+CPBS=\"XX\"\r";
GSM_Error error;
if (Priv->PBKMemory == MemType) return ERR_NONE;
/* Zero values that are for actual memory */
Priv->MemorySize = 0;
Priv->FirstMemoryEntry = 0;
Priv->NextMemoryEntry = 0;
Priv->TextLength = 0;
Priv->NumberLength = 0;
if (Priv->PBKMemories[0] == 0) {
error=GSM_WaitFor (s, "AT+CPBS=?\r", 10, 0x00, 3, ID_SetMemoryType);
if (error != ERR_NONE) return error;
}
switch (MemType) {
case MEM_SM:
req[9] = 'S'; req[10] = 'M';
break;
case MEM_ME:
if (strstr(Priv->PBKMemories,"ME")==NULL) return ERR_NOTSUPPORTED;
req[9] = 'M'; req[10] = 'E';
break;
case MEM_RC:
if (strstr(Priv->PBKMemories,"RC")==NULL) return ERR_NOTSUPPORTED;
req[9] = 'R'; req[10] = 'C';
break;
case MEM_MC:
if (strstr(Priv->PBKMemories,"MC")==NULL) return ERR_NOTSUPPORTED;
req[9] = 'M'; req[10] = 'C';
break;
case MEM_ON:
if (strstr(Priv->PBKMemories,"ON")==NULL) return ERR_NOTSUPPORTED;
req[9] = 'O'; req[10] = 'N';
break;
case MEM_FD:
if (strstr(Priv->PBKMemories,"FD")==NULL) return ERR_NOTSUPPORTED;
req[9] = 'F'; req[10] = 'D';
break;
case MEM_DC:
if (strstr(Priv->PBKMemories,"DC")!=NULL) {
req[9] = 'D'; req[10] = 'C';
break;
}
if (strstr(Priv->PBKMemories,"LD")!=NULL) {
req[9] = 'L'; req[10] = 'D';
break;
}
return ERR_NOTSUPPORTED;
break;
default:
return ERR_NOTSUPPORTED;
}
smprintf(s, "Setting memory type\n");
error=GSM_WaitFor (s, req, 13, 0x00, 3, ID_SetMemoryType);
if (error == ERR_NONE) Priv->PBKMemory = MemType;
return error;
}
GSM_Error ATGEN_ReplyGetCPBSMemoryStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_MemoryStatus *MemoryStatus = s->Phone.Data.MemoryStatus;
char *start;
switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
case AT_Reply_OK:
smprintf(s, "Memory status received\n");
MemoryStatus->MemoryUsed = 0;
MemoryStatus->MemoryFree = 0;
start = strchr(msg.Buffer, ',');
if (start) {
start++;
MemoryStatus->MemoryUsed = atoi(start);
start = strchr(start, ',');
if (start) {
start++;
MemoryStatus->MemoryFree = atoi(start) - MemoryStatus->MemoryUsed;
return ERR_NONE;
} else return ERR_UNKNOWN;
} else return ERR_UNKNOWN;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
break;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error ATGEN_ReplyGetCPBRMemoryInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
char *pos;
switch (Priv->ReplyState) {
case AT_Reply_OK:
smprintf(s, "Memory info received\n");
/* Parse +CPBR: (first-last),max_number_len,max_name_len */
/* Parse first location */
pos = strchr(msg.Buffer, '(');
if (!pos) return ERR_UNKNOWN;
pos++;
Priv->FirstMemoryEntry = atoi(pos);
/* Parse last location*/
pos = strchr(pos, '-');
if (!pos) return ERR_UNKNOWN;
pos++;
Priv->MemorySize = atoi(pos) + 1 - Priv->FirstMemoryEntry;
/* Parse number length*/
pos = strchr(pos, ',');
if (!pos) return ERR_UNKNOWN;
pos++;
Priv->NumberLength = atoi(pos);
/* Parse text length*/
pos = strchr(pos, ',');
if (!pos) return ERR_UNKNOWN;
pos++;
Priv->TextLength = atoi(pos);
return ERR_NONE;
case AT_Reply_Error:
return ERR_UNKNOWN;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
return ERR_UNKNOWNRESPONSE;
}
}
GSM_Error ATGEN_ReplyGetCPBRMemoryStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_MemoryStatus *MemoryStatus = s->Phone.Data.MemoryStatus;
int line=0;
char *str;
int cur;
switch (Priv->ReplyState) {
case AT_Reply_OK:
smprintf(s, "Memory entries received\n");
/* Walk through lines with +CPBR: */
while (Priv->Lines.numbers[line*2+1]!=0) {
str = GetLineString(msg.Buffer,Priv->Lines,line+1);
if (strncmp(str, "+CPBR: ", 7) == 0) {
MemoryStatus->MemoryUsed++;
if (sscanf(str, "+CPBR: %d,", &cur) == 1) {
cur -= Priv->FirstMemoryEntry - 1;
if (cur == Priv->NextMemoryEntry || Priv->NextMemoryEntry == 0)
Priv->NextMemoryEntry = cur + 1;
}
}
line++;
}
return ERR_NONE;
case AT_Reply_Error:
return ERR_UNKNOWN;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
return ERR_UNKNOWNRESPONSE;
}
}
GSM_Error ATGEN_GetMemoryInfo(GSM_StateMachine *s, GSM_MemoryStatus *Status, GSM_AT_NeededMemoryInfo NeededInfo)
{
GSM_Error error;
char req[20];
int start;
int end;
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
smprintf(s, "Getting memory information\n");
Priv->MemorySize = 0;
Priv->TextLength = 0;
Priv->NumberLength = 0;
error = GSM_WaitFor (s, "AT+CPBR=?\r", 10, 0x00, 4, ID_GetMemoryStatus);
+ if (Priv->Manufacturer == AT_Samsung)
+ error = GSM_WaitFor (s, "", 0, 0x00, 4, ID_GetMemoryStatus);
if (error != ERR_NONE) return error;
if (NeededInfo == AT_Total || NeededInfo == AT_Sizes || NeededInfo == AT_First) return ERR_NONE;
smprintf(s, "Getting memory status by reading values\n");
s->Phone.Data.MemoryStatus = Status;
Status->MemoryUsed = 0;
Status->MemoryFree = 0;
start = Priv->FirstMemoryEntry;
Priv->NextMemoryEntry = 0;
while (1) {
end = start + 20;
if (end > Priv->MemorySize) end = Priv->MemorySize;
sprintf(req, "AT+CPBR=%i,%i\r", start, end);
error = GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetMemoryStatus);
if (error != ERR_NONE) return error;
if (NeededInfo == AT_NextEmpty && Priv->NextMemoryEntry != 0 && Priv->NextMemoryEntry != end + 1) return ERR_NONE;
if (end == Priv->MemorySize) {
Status->MemoryFree = Priv->MemorySize - Status->MemoryUsed;
return ERR_NONE;
}
start = end + 1;
}
}
GSM_Error ATGEN_GetMemoryStatus(GSM_StateMachine *s, GSM_MemoryStatus *Status)
{
GSM_Error error;
error = ATGEN_SetPBKMemory(s, Status->MemoryType);
if (error != ERR_NONE) return error;
s->Phone.Data.MemoryStatus=Status;
/* in some phones doesn't work or doesn't return memory status inside */
/* Some workaround for buggy mobile, that hangs after "AT+CPBS?" for other
* memory than SM.
*/
if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_BROKENCPBS) || (Status->MemoryType == MEM_SM)) {
smprintf(s, "Getting memory status\n");
error=GSM_WaitFor (s, "AT+CPBS?\r", 9, 0x00, 4, ID_GetMemoryStatus);
if (error == ERR_NONE) return ERR_NONE;
}
return ATGEN_GetMemoryInfo(s, Status, AT_Status);
}
GSM_Error ATGEN_SetPBKCharset(GSM_StateMachine *s, bool PreferUnicode)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_Error error;
/* Have we already selected something? */
if (Priv->PBKCharset!=0) {
/* If we want unicode charset and we have it already or setting of it
* failed, we have nothing to do. */
if (PreferUnicode && (Priv->PBKCharset==AT_PBK_UCS2 || Priv->UCS2CharsetFailed)) return ERR_NONE;
/* If we don't need unicode charset and we have some (or have unicode
* charset when other failed), we have nothing to do. */
if (!PreferUnicode && (Priv->PBKCharset!=AT_PBK_UCS2 || Priv->NonUCS2CharsetFailed)) return ERR_NONE;
}
error=ATGEN_GetManufacturer(s);
if (error != ERR_NONE) return error;
+ /* Samsung (and Sagem?) phones use only PCCP437? */
+ if (Priv->Manufacturer == AT_Samsung) {
+ Priv->PBKCharset = AT_PBK_PCCP437;
+ return ERR_NONE;
+ }
+
if (PreferUnicode && !Priv->UCS2CharsetFailed) {
smprintf(s, "Setting charset to UCS2\n");
error=GSM_WaitFor (s, "AT+CSCS=\"UCS2\"\r", 15, 0x00, 3, ID_SetMemoryCharset);
if (error == ERR_NONE) {
Priv->PBKCharset = AT_PBK_UCS2;
return ERR_NONE;
} else {
Priv->UCS2CharsetFailed = true;
}
}
smprintf(s, "Setting charset to HEX\n");
error=GSM_WaitFor (s, "AT+CSCS=\"HEX\"\r", 14, 0x00, 3, ID_SetMemoryCharset);
/* Falcom replies OK for HEX mode and send everything
* in normal format */
if (error == ERR_NONE && Priv->Manufacturer != AT_Falcom) {
Priv->PBKCharset = AT_PBK_HEX;
return ERR_NONE;
}
smprintf(s, "Setting charset to GSM\n");
error=GSM_WaitFor (s, "AT+CSCS=\"GSM\"\r", 14, 0x00, 3, ID_SetMemoryCharset);
if (error == ERR_NONE) {
Priv->PBKCharset = AT_PBK_GSM;
return ERR_NONE;
}
if (!Priv->UCS2CharsetFailed) {
Priv->NonUCS2CharsetFailed = true;
smprintf(s, "Setting charset to UCS2\n");
error=GSM_WaitFor (s, "AT+CSCS=\"UCS2\"\r", 15, 0x00, 3, ID_SetMemoryCharset);
if (error == ERR_NONE) {
Priv->PBKCharset = AT_PBK_UCS2;
return ERR_NONE;
} else {
Priv->UCS2CharsetFailed = true;
}
}
return error;
}
GSM_Error ATGEN_ReplyGetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_MemoryEntry *Memory = s->Phone.Data.Memory;
char *pos;
unsigned char buffer[500],buffer2[500];
int len;
switch (Priv->ReplyState) {
case AT_Reply_OK:
smprintf(s, "Phonebook entry received\n");
Memory->EntriesNum = 0;
if (Priv->Lines.numbers[4]==0) return ERR_EMPTY;
pos = strstr(msg.Buffer, "+CPBR:");
if (pos == NULL) return ERR_UNKNOWN;
/* Go after +CPBR: */
pos += 6;
/* Location */
while (*pos && !isdigit(*pos)) pos++;
Memory->Location = atoi(pos) + 1 - Priv->FirstMemoryEntry;
smprintf(s, "Location: %d\n", Memory->Location);
/* Number */
while (*pos != '"') pos++;
pos += ATGEN_ExtractOneParameter(pos, buffer);
smprintf(s, "Number: %s\n",buffer);
Memory->EntriesNum++;
Memory->Entries[0].EntryType = PBK_Number_General;
Memory->Entries[0].VoiceTag = 0;
Memory->Entries[0].SMSList[0] = 0;
len = strlen(buffer + 1) - 1;
if (Priv->PBKCharset == AT_PBK_HEX && (len > 10) && (len % 2 == 0) && (strchr(buffer + 1, '+') == NULL)) {
/* This is probably hex encoded number */
DecodeHexBin(buffer2, buffer+1, len);
DecodeDefault(Memory->Entries[0].Text ,buffer2, strlen(buffer2), false, NULL);
} else if (Priv->PBKCharset == AT_PBK_UCS2 && (len > 20) && (len % 4 == 0) && (strchr(buffer + 1, '+') == NULL)) {
/* This is probably unicode encoded number */
DecodeHexUnicode(Memory->Entries[0].Text, buffer + 1,len);
} else {
EncodeUnicode(Memory->Entries[0].Text, buffer + 1, len);
}
/* Number format */
pos += ATGEN_ExtractOneParameter(pos, buffer);
smprintf(s, "Number format: %s\n",buffer);
/* International number */
if (!strcmp(buffer,"145")) {
sprintf(buffer+1,"%s",DecodeUnicodeString(Memory->Entries[0].Text));
if (strlen(buffer+1)!=0 && buffer[1] != '+') {
/* Sony Ericsson issue */
/* International number is without + */
buffer[0] = '+';
EncodeUnicode(Memory->Entries[0].Text,buffer,strlen(buffer));
}
}
/* Name */
pos += ATGEN_ExtractOneParameter(pos, buffer);
smprintf(s, "Name text: %s\n",buffer);
Memory->EntriesNum++;
Memory->Entries[1].EntryType=PBK_Text_Name;
switch (Priv->PBKCharset) {
case AT_PBK_HEX:
DecodeHexBin(buffer2,buffer+1,strlen(buffer)-2);
DecodeDefault(Memory->Entries[1].Text,buffer2,strlen(buffer2),false,NULL);
break;
case AT_PBK_GSM:
DecodeDefault(Memory->Entries[1].Text,buffer+1,strlen(buffer)-2,false,NULL);
break;
case AT_PBK_UCS2:
DecodeHexUnicode(Memory->Entries[1].Text,buffer+1,strlen(buffer+1) - 1);
break;
+ case AT_PBK_PCCP437:
+ /* FIXME: correctly decode PCCP437 */
+ DecodeDefault(Memory->Entries[1].Text,buffer+1,strlen(buffer)-2,false,NULL);
+ break;
+ }
+
+ /* Samsung number type */
+ if (Priv->Manufacturer == AT_Samsung) {
+ int type;
+
+ pos += ATGEN_ExtractOneParameter(pos, buffer);
+ smprintf(s, "Number type: %s\n",buffer);
+ type = strtoul(buffer, NULL, 0);
+ switch (type) {
+ case 0:
+ Memory->Entries[0].EntryType = PBK_Number_Mobile;
+ break;
+ case 1:
+ Memory->Entries[0].EntryType = PBK_Number_Work;
+ break;
+ case 2:
+ Memory->Entries[0].EntryType = PBK_Number_Home;
+ break;
+ case 3:
+ Memory->Entries[0].EntryType = PBK_Text_Email;
+ break;
+ default:
+ Memory->Entries[0].EntryType = PBK_Number_General;
+ }
}
+
return ERR_NONE;
case AT_Reply_CMEError:
return ATGEN_HandleCMEError(s);
case AT_Reply_Error:
smprintf(s, "Error - too high location ?\n");
return ERR_INVALIDLOCATION;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
break;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error ATGEN_PrivGetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry, int endlocation)
{
GSM_Error error;
unsigned char req[20];
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
if (entry->Location==0x00) return ERR_INVALIDLOCATION;
if (entry->MemoryType == MEM_ME) {
if (Priv->PBKSBNR == 0) {
sprintf(req, "AT^SBNR=?\r");
smprintf(s, "Checking availablity of SBNR\n");
error=GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetMemory);
switch (error) {
case ERR_NONE:
Priv->PBKSBNR = AT_SBNR_AVAILABLE;
break;
case ERR_UNKNOWN:
case ERR_NOTSUPPORTED:
Priv->PBKSBNR = AT_SBNR_NOTAVAILABLE;
break;
default:
return error;
}
}
if (Priv->PBKSBNR == AT_SBNR_AVAILABLE) {
sprintf(req, "AT^SBNR=vcf,%i\r",entry->Location-1);
s->Phone.Data.Memory=entry;
smprintf(s, "Getting phonebook entry\n");
return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetMemory);
}
}
error=ATGEN_GetManufacturer(s);
if (error != ERR_NONE) return error;
error=ATGEN_SetPBKMemory(s, entry->MemoryType);
if (error != ERR_NONE) return error;
if (Priv->FirstMemoryEntry == 0) {
error = ATGEN_GetMemoryInfo(s, NULL, AT_First);
if (error != ERR_NONE) return error;
}
error=ATGEN_SetPBKCharset(s, true); /* For reading we prefer unicode */
if (error != ERR_NONE) return error;
if (endlocation == 0) {
sprintf(req, "AT+CPBR=%i\r", entry->Location + Priv->FirstMemoryEntry - 1);
} else {
sprintf(req, "AT+CPBR=%i,%i\r", entry->Location + Priv->FirstMemoryEntry - 1, endlocation + Priv->FirstMemoryEntry - 1);
}
s->Phone.Data.Memory=entry;
smprintf(s, "Getting phonebook entry\n");
return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetMemory);
}
GSM_Error ATGEN_GetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
return ATGEN_PrivGetMemory(s, entry, 0);
}
GSM_Error ATGEN_GetNextMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry, bool start)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_Error error;
int step = 0;
if (Priv->MemorySize == 0) {
error = ATGEN_GetMemoryInfo(s, NULL, AT_Total);
if (error != ERR_NONE) return error;
}
if (start) {
entry->Location = 1;
} else {
entry->Location++;
}
while ((error = ATGEN_PrivGetMemory(s, entry, step == 0 ? 0 : MIN(Priv->MemorySize, entry->Location + step))) == ERR_EMPTY) {
entry->Location += step + 1;
if (entry->Location > Priv->MemorySize) break;
/* SNBR works only for one location */
if (entry->MemoryType != MEM_ME || Priv->PBKSBNR != AT_SBNR_AVAILABLE) step = MIN(step + 2, 20);
}
if (error == ERR_INVALIDLOCATION) return ERR_EMPTY;
return error;
}
GSM_Error ATGEN_DeleteAllMemory(GSM_StateMachine *s, GSM_MemoryType type)
{
GSM_Error error;
unsigned char req[100];
int i;
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
error = ATGEN_SetPBKMemory(s, type);
if (error != ERR_NONE) return error;
if (Priv->MemorySize == 0) {
error = ATGEN_GetMemoryInfo(s, NULL, AT_Total);
if (error != ERR_NONE) return error;
}
if (Priv->FirstMemoryEntry == 0) {
error = ATGEN_GetMemoryInfo(s, NULL, AT_First);
if (error != ERR_NONE) return error;
}
smprintf(s, "Deleting all phonebook entries\n");
for (i = Priv->FirstMemoryEntry; i < Priv->FirstMemoryEntry + Priv->MemorySize; i++) {
sprintf(req, "AT+CPBW=%d\r",i);
error = GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_SetMemory);
if (error != ERR_NONE) return error;
}
return ERR_NONE;
}
GSM_Error ATGEN_ReplyDialVoice(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
case AT_Reply_OK:
smprintf(s, "Dial voice OK\n");
return ERR_NONE;
case AT_Reply_Error:
smprintf(s, "Dial voice error\n");
return ERR_UNKNOWN;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
break;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error ATGEN_DialVoice(GSM_StateMachine *s, char *number, GSM_CallShowNumber ShowNumber)
{
char req[39] = "ATDT";
if (ShowNumber != GSM_CALL_DefaultNumberPresence) return ERR_NOTSUPPORTED;
if (strlen(number) > 32) return (ERR_UNKNOWN);
strcat(req, number);
strcat(req, ";\r");
smprintf(s, "Making voice call\n");
return GSM_WaitFor (s, req, 4+2+strlen(number), 0x00, 5, ID_DialVoice);
}
GSM_Error ATGEN_ReplyEnterSecurityCode(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
case AT_Reply_OK:
smprintf(s, "Security code was OK\n");
return ERR_NONE;
case AT_Reply_Error:
smprintf(s, "Incorrect security code\n");
return ERR_SECURITYERROR;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
+ case AT_Reply_CMEError:
+ return ATGEN_HandleCMEError(s);
default:
break;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error ATGEN_EnterSecurityCode(GSM_StateMachine *s, GSM_SecurityCode Code)
{
unsigned char req[50];
switch (Code.Type) {
case SEC_Pin :
sprintf(req, "AT+CPIN=\"%s\"\r" , Code.Code);
break;
case SEC_Pin2 :
if (s->Phone.Data.Priv.ATGEN.Manufacturer == AT_Siemens) {
sprintf(req, "AT+CPIN2=\"%s\"\r", Code.Code);
} else {
sprintf(req, "AT+CPIN=\"%s\"\r" , Code.Code);
}
break;
default : return ERR_NOTIMPLEMENTED;
}
smprintf(s, "Entering security code\n");
return GSM_WaitFor (s, req, strlen(req), 0x00, 6, ID_EnterSecurityCode);
}
GSM_Error ATGEN_ReplyGetSecurityStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_SecurityCodeType *Status = s->Phone.Data.SecurityStatus;
smprintf(s, "Security status received - ");
if (strstr(msg.Buffer,"READY")) {
*Status = SEC_None;
smprintf(s, "nothing to enter\n");
return ERR_NONE;
}
if (strstr(msg.Buffer,"PH_SIM PIN")) {
smprintf(s, "no SIM inside or other error\n");
return ERR_UNKNOWN;
}
if (strstr(msg.Buffer,"SIM PIN2")) {
*Status = SEC_Pin2;
smprintf(s, "waiting for PIN2\n");
return ERR_NONE;
}
if (strstr(msg.Buffer,"SIM PUK2")) {
*Status = SEC_Puk2;
smprintf(s, "waiting for PUK2\n");
return ERR_NONE;
}
if (strstr(msg.Buffer,"SIM PIN")) {
*Status = SEC_Pin;
smprintf(s, "waiting for PIN\n");
return ERR_NONE;
}
if (strstr(msg.Buffer,"SIM PUK")) {
*Status = SEC_Puk;
smprintf(s, "waiting for PUK\n");
return ERR_NONE;
}
smprintf(s, "unknown\n");
return ERR_UNKNOWNRESPONSE;
}
GSM_Error ATGEN_GetSecurityStatus(GSM_StateMachine *s, GSM_SecurityCodeType *Status)
{
s->Phone.Data.SecurityStatus=Status;
smprintf(s, "Getting security code status\n");
/* Please note, that A2D doesn't return OK on the end.
* Because of it ReplyGetSecurityStatus is called after receiving line
* with +CPIN:
*/
return GSM_WaitFor (s, "AT+CPIN?\r", 9, 0x00, 4, ID_GetSecurityStatus);
}
GSM_Error ATGEN_AnswerCall(GSM_StateMachine *s, int ID, bool all)
{
if (all) {
smprintf(s, "Answering all calls\n");
return GSM_WaitFor (s, "ATA\r", 4, 0x00, 4, ID_AnswerCall);
}
return ERR_NOTSUPPORTED;
}
GSM_Error ATGEN_ReplyCancelCall(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Call call;
switch(s->Phone.Data.Priv.ATGEN.ReplyState) {
case AT_Reply_OK:
smprintf(s, "Calls canceled\n");
call.CallIDAvailable = false;
call.Status = GSM_CALL_CallLocalEnd;
if (s->User.IncomingCall) s->User.IncomingCall(s->CurrentConfig->Device, call);
return ERR_NONE;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
return ERR_UNKNOWN;
}
}
GSM_Error ATGEN_CancelCall(GSM_StateMachine *s, int ID, bool all)
{
GSM_Error error;
if (all) {
smprintf(s, "Dropping all calls\n");
error = GSM_WaitFor (s, "ATH\r", 4, 0x00, 4, ID_CancelCall);
if (error == ERR_UNKNOWN) {
return GSM_WaitFor (s, "AT+CHUP\r", 8, 0x00, 4, ID_CancelCall);
}
return error;
}
return ERR_NOTSUPPORTED;
}
GSM_Error ATGEN_ReplyReset(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Reset done\n");
return ERR_NONE;
}
GSM_Error ATGEN_Reset(GSM_StateMachine *s, bool hard)
{
GSM_Error error;
if (!hard) return ERR_NOTSUPPORTED;
smprintf(s, "Resetting device\n");
/* Siemens 35 */
error=GSM_WaitFor (s, "AT+CFUN=1,1\r", 12, 0x00, 8, ID_Reset);
if (error != ERR_NONE) {
/* Siemens M20 */
error=GSM_WaitFor (s, "AT^SRESET\r", 10, 0x00, 8, ID_Reset);
}
return error;
}
GSM_Error ATGEN_ReplyResetPhoneSettings(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Reset done\n");
return ERR_NONE;
}
GSM_Error ATGEN_ResetPhoneSettings(GSM_StateMachine *s, GSM_ResetSettingsType Type)
{
smprintf(s, "Resetting settings to default\n");
return GSM_WaitFor (s, "AT&F\r", 5, 0x00, 4, ID_ResetPhoneSettings);
}
GSM_Error ATGEN_SetAutoNetworkLogin(GSM_StateMachine *s)
{
smprintf(s, "Enabling automatic network login\n");
return GSM_WaitFor (s, "AT+COPS=0\r", 10, 0x00, 4, ID_SetAutoNetworkLogin);
}
GSM_Error ATGEN_SendDTMF(GSM_StateMachine *s, char *sequence)
{
unsigned char req[80] = "AT+VTS=";
int n;
for (n = 0; n < 32; n++) {
if (sequence[n] == '\0') break;
if (n != 0) req[6 + 2 * n] = ',';
req[7 + 2 * n] = sequence[n];
}
strcat(req, ";\r");
smprintf(s, "Sending DTMF\n");
return GSM_WaitFor (s, req, 7+2+2*strlen(sequence), 0x00, 4, ID_SendDTMF);
}
GSM_Error ATGEN_ReplyDeleteSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
case AT_Reply_OK:
smprintf(s, "SMS deleted OK\n");
return ERR_NONE;
case AT_Reply_Error:
smprintf(s, "Invalid location\n");
return ERR_INVALIDLOCATION;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
break;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error ATGEN_DeleteSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
{
unsigned char req[20], folderid;
GSM_Error error;
int location;
GSM_MultiSMSMessage msms;
msms.Number = 0;
msms.SMS[0] = *sms;
/* By reading SMS we check if it is really inbox/outbox */
error = ATGEN_GetSMS(s, &msms);
if (error != ERR_NONE) return error;
error = ATGEN_GetSMSLocation(s, sms, &folderid, &location);
if (error != ERR_NONE) return error;
sprintf(req, "AT+CMGD=%i\r",location);
smprintf(s, "Deleting SMS\n");
return GSM_WaitFor (s, req, strlen(req), 0x00, 5, ID_DeleteSMSMessage);
}
GSM_Error ATGEN_GetSMSFolders(GSM_StateMachine *s, GSM_SMSFolders *folders)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_Error error;
int used = 0;
if (Priv->PhoneSMSMemory == 0) {
error = ATGEN_SetSMSMemory(s, false);
if (error != ERR_NONE && error != ERR_NOTSUPPORTED) return error;
}
if (Priv->SIMSMSMemory == 0) {
error = ATGEN_SetSMSMemory(s, true);
if (error != ERR_NONE && error != ERR_NOTSUPPORTED) return error;
}
folders->Number = 0;
if (Priv->PhoneSMSMemory == AT_NOTAVAILABLE && Priv->SIMSMSMemory == AT_NOTAVAILABLE) {
return ERR_NONE;
}
PHONE_GetSMSFolders(s,folders);
if (Priv->SIMSMSMemory == AT_AVAILABLE) {
used = 2;
}
if (Priv->PhoneSMSMemory == AT_AVAILABLE) {
if (used != 0) {
CopyUnicodeString(folders->Folder[used ].Name,folders->Folder[0].Name);
CopyUnicodeString(folders->Folder[used + 1].Name,folders->Folder[1].Name);
folders->Folder[used ].InboxFolder = true;
folders->Folder[used + 1].InboxFolder = false;
}
folders->Folder[used ].Memory = MEM_ME;
folders->Folder[used + 1].Memory = MEM_ME;
folders->Number += 2;
used += 2;
}
return ERR_NONE;
}
GSM_Error ATGEN_ReplySetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
case AT_Reply_OK:
smprintf(s, "Phonebook entry written OK\n");
return ERR_NONE;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
case AT_Reply_CMEError:
return ATGEN_HandleCMEError(s);
case AT_Reply_Error:
return ERR_INVALIDDATA;
default:
return ERR_UNKNOWNRESPONSE;
}
}
GSM_Error ATGEN_DeleteMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
GSM_Error error;
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
unsigned char req[100];
if (entry->Location < 1) return ERR_INVALIDLOCATION;
error = ATGEN_SetPBKMemory(s, entry->MemoryType);
if (error != ERR_NONE) return error;
if (Priv->FirstMemoryEntry == 0) {
error = ATGEN_GetMemoryInfo(s, NULL, AT_First);
if (error != ERR_NONE) return error;
}
sprintf(req, "AT+CPBW=%d\r",entry->Location + Priv->FirstMemoryEntry - 1);
smprintf(s, "Deleting phonebook entry\n");
return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_SetMemory);
}
GSM_Error ATGEN_PrivSetMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
/* REQUEST_SIZE should be big enough to handle all possibl cases
* correctly, especially with unicode entries */
#define REQUEST_SIZE ((4 * GSM_PHONEBOOK_TEXT_LENGTH) + 30)
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
int Group, Name, Number,NumberType=0, len;
GSM_Error error;
unsigned char req[REQUEST_SIZE + 1];
unsigned char name[2*(GSM_PHONEBOOK_TEXT_LENGTH + 1)];
unsigned char uname[2*(GSM_PHONEBOOK_TEXT_LENGTH + 1)];
unsigned char number[GSM_PHONEBOOK_TEXT_LENGTH + 1];
int reqlen;
bool PreferUnicode = false;
if (entry->Location == 0) return ERR_INVALIDLOCATION;
error = ATGEN_SetPBKMemory(s, entry->MemoryType);
if (error != ERR_NONE) return error;
GSM_PhonebookFindDefaultNameNumberGroup(entry, &Name, &Number, &Group);
name[0] = 0;
if (Name != -1) {
len = UnicodeLength(entry->Entries[Name].Text);
/* Compare if we would loose some information when not using
* unicode */
EncodeDefault(name, entry->Entries[Name].Text, &len, true, NULL);
DecodeDefault(uname, name, len, true, NULL);
if (!mywstrncmp(uname, entry->Entries[Name].Text, len)) {
/* Get maximal text length */
if (Priv->TextLength == 0) {
ATGEN_GetMemoryInfo(s, NULL, AT_Sizes);
}
/* I char stored in GSM alphabet takes 7 bits, one
* unicode 16, if storing in unicode would truncate
* text, do not use it, otherwise we will use it */
if ((Priv->TextLength != 0) && ((Priv->TextLength * 7 / 16) <= len)) {
PreferUnicode = false;
} else {
PreferUnicode = true;
}
}
error = ATGEN_SetPBKCharset(s, PreferUnicode);
if (error != ERR_NONE) return error;
switch (Priv->PBKCharset) {
case AT_PBK_HEX:
EncodeHexBin(name, DecodeUnicodeString(entry->Entries[Name].Text), UnicodeLength(entry->Entries[Name].Text));
len = strlen(name);
break;
case AT_PBK_GSM:
smprintf(s, "str: %s\n", DecodeUnicodeString(entry->Entries[Name].Text));
len = UnicodeLength(entry->Entries[Name].Text);
EncodeDefault(name, entry->Entries[Name].Text, &len, true, NULL);
break;
case AT_PBK_UCS2:
EncodeHexUnicode(name, entry->Entries[Name].Text, UnicodeLength(entry->Entries[Name].Text));
len = strlen(name);
break;
+ case AT_PBK_PCCP437:
+ /* FIXME: correctly decode PCCP437 */
+ smprintf(s, "str: %s\n", DecodeUnicodeString(entry->Entries[Name].Text));
+ len = UnicodeLength(entry->Entries[Name].Text);
+ EncodeDefault(name, entry->Entries[Name].Text, &len, true, NULL);
+ break;
}
} else {
smprintf(s, "WARNING: No usable name found!\n");
len = 0;
}
if (Number != -1) {
GSM_PackSemiOctetNumber(entry->Entries[Number].Text, number, false);
NumberType = number[0];
sprintf(number,"%s",DecodeUnicodeString(entry->Entries[Number].Text));
} else {
smprintf(s, "WARNING: No usable number found!\n");
number[0] = 0;
}
if (Priv->FirstMemoryEntry == 0) {
error = ATGEN_GetMemoryInfo(s, NULL, AT_First);
if (error != ERR_NONE) return error;
}
/* We can't use here:
* sprintf(req, "AT+CPBW=%d, \"%s\", %i, \"%s\"\r",
* entry->Location, number, NumberType, name);
* because name can contain 0 when using GSM alphabet.
*/
sprintf(req, "AT+CPBW=%d, \"%s\", %i, \"", entry->Location + Priv->FirstMemoryEntry - 1, number, NumberType);
reqlen = strlen(req);
if (reqlen + len > REQUEST_SIZE - 2) {
smprintf(s, "WARNING: Text truncated to fit in buffer!\n");
len = REQUEST_SIZE - 2 - reqlen;
}
memcpy(req + reqlen, name, len);
reqlen += len;
memcpy(req + reqlen, "\"\r", 2);
reqlen += 2;
smprintf(s, "Writing phonebook entry\n");
return GSM_WaitFor (s, req, reqlen, 0x00, 4, ID_SetMemory);
#undef REQUEST_SIZE
}
GSM_Error ATGEN_SetMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
if (entry->Location == 0) return ERR_INVALIDLOCATION;
return ATGEN_PrivSetMemory(s, entry);
}
GSM_Error ATGEN_AddMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
GSM_Error error;
GSM_MemoryStatus Status;
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
/* Find out empty location */
error = ATGEN_GetMemoryInfo(s, &Status, AT_NextEmpty);
if (error != ERR_NONE) return error;
if (Priv->NextMemoryEntry == 0) return ERR_FULL;
entry->Location = Priv->NextMemoryEntry;
return ATGEN_PrivSetMemory(s, entry);
}
/* Use ATGEN_ExtractOneParameter ?? */
void Extract_CLIP_number(char *dest, char *buf)
{
char *start, *stop;
int i = 0;
stop = strstr(buf, ",");
if (stop != NULL) {
start = strstr(buf, ":");
if (start != NULL) {
for (start = start + 2; start + i < stop; i++)
dest[i] = start[i];
}
}
dest[i] = 0; /* end the number */
return;
}
GSM_Error ATGEN_ReplyIncomingCallInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
char num[128];
GSM_Call call;
smprintf(s, "Incoming call info\n");
if (s->Phone.Data.EnableIncomingCall && s->User.IncomingCall!=NULL) {
call.CallIDAvailable = false;
num[0] = 0;
if (strstr(msg.Buffer, "RING")) {
call.Status = GSM_CALL_IncomingCall;
Extract_CLIP_number(num, msg.Buffer);
} else if (strstr(msg.Buffer, "NO CARRIER")) {
call.Status = GSM_CALL_CallEnd;
} else if (strstr(msg.Buffer, "COLP:")) {
call.Status = GSM_CALL_CallStart;
Extract_CLIP_number(num, msg.Buffer);
} else {
smprintf(s, "CLIP: error\n");
return ERR_NONE;
}
EncodeUnicode(call.PhoneNumber, num, strlen(num));
s->User.IncomingCall(s->CurrentConfig->Device, call);
}
return ERR_NONE;
}
GSM_Error ATGEN_IncomingGPRS(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
/* "+CGREG: 1,1" */
smprintf(s, "GPRS change\n");
return ERR_NONE;
}
GSM_Error ATGEN_IncomingBattery(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int level = 0;
char *p;
/* "_OBS: 92,1" */
p = strstr(msg.Buffer, "_OBS:");
if (p) level = atoi(p + 5);
smprintf(s, "Battery level changed to %d\n", level);
return ERR_NONE;
}
GSM_Error ATGEN_IncomingNetworkLevel(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int level = 0;
char *p;
/* "_OSIGQ: 12,0" */
p = strstr(msg.Buffer, "_OSIGQ: ");
if (p) level = atoi(p + 7);
smprintf(s, "Network level changed to %d\n", level);
return ERR_NONE;
}
GSM_Error ATGEN_ReplyGetSIMIMSI(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_Phone_Data *Data = &s->Phone.Data;
char *c;
switch (Priv->ReplyState) {
case AT_Reply_OK:
CopyLineString(Data->PhoneString, msg.Buffer, Priv->Lines, 2);
/* Read just IMSI also on phones that prepend it by "<IMSI>:" (Alcatel BE5) */
c = strstr(Data->PhoneString, "<IMSI>:");
if (c != NULL) {
c += 7;
memmove(Data->PhoneString, c, strlen(c) + 1);
}
smprintf(s, "Received IMSI %s\n",Data->PhoneString);
return ERR_NONE;
case AT_Reply_Error:
smprintf(s, "No access to SIM card or not supported by device\n");
return ERR_SECURITYERROR;
case AT_Reply_CMEError:
return ATGEN_HandleCMEError(s);
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
break;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error ATGEN_GetSIMIMSI(GSM_StateMachine *s, char *IMSI)
{
s->Phone.Data.PhoneString = IMSI;
smprintf(s, "Getting SIM IMSI\n");
return GSM_WaitFor (s, "AT+CIMI\r", 8, 0x00, 4, ID_GetSIMIMSI);
}
GSM_Error ATGEN_GetDisplayStatus(GSM_StateMachine *s, GSM_DisplayFeatures *features)
{
return ERR_NOTSUPPORTED;
s->Phone.Data.DisplayFeatures = features;
smprintf(s, "Getting display status\n");
return GSM_WaitFor (s, "AT+CIND?\r",9, 0x00, 4, ID_GetDisplayStatus);
}
GSM_Error ATGEN_IncomingSMSCInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
return ERR_NONE;
}
GSM_Error ATGEN_ReplyGetBatteryCharge(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
int i;
Data->BatteryCharge->BatteryPercent = -1;
Data->BatteryCharge->ChargeState = 0;
switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
case AT_Reply_OK:
smprintf(s, "Battery level received\n");
Data->BatteryCharge->BatteryPercent = atoi(msg.Buffer+17);
i = atoi(msg.Buffer+14);
if (i >= 0 && i <= 3) {
Data->BatteryCharge->ChargeState = i + 1;
}
return ERR_NONE;
case AT_Reply_Error:
smprintf(s, "Can't get battery level\n");
return ERR_UNKNOWN;
case AT_Reply_CMSError:
smprintf(s, "Can't get battery level\n");
return ATGEN_HandleCMSError(s);
default:
break;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error ATGEN_GetBatteryCharge(GSM_StateMachine *s, GSM_BatteryCharge *bat)
{
s->Phone.Data.BatteryCharge = bat;
smprintf(s, "Getting battery charge\n");
return GSM_WaitFor (s, "AT+CBC\r", 7, 0x00, 4, ID_GetBatteryCharge);
}
GSM_Error ATGEN_ReplyGetSignalQuality(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_SignalQuality *Signal = s->Phone.Data.SignalQuality;
int i;
char *pos;
Signal->SignalStrength = -1;
Signal->SignalPercent = -1;
Signal->BitErrorRate = -1;
switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
case AT_Reply_OK:
smprintf(s, "Signal quality info received\n");
i = atoi(msg.Buffer+15);
if (i != 99) {
/* from GSM 07.07 section 8.5 */
Signal->SignalStrength = 2 * i - 113;
/* FIXME: this is wild guess and probably will be phone dependant */
Signal->SignalPercent = 15 * i;
if (Signal->SignalPercent > 100) Signal->SignalPercent = 100;
}
pos = strchr(msg.Buffer + 15, ',');
if (pos != NULL) {
i = atoi(pos + 1);
/* from GSM 05.08 section 8.2.4 */
switch (i) {
case 0: Signal->BitErrorRate = 0; break; /* 0.14 */
case 1: Signal->BitErrorRate = 0; break; /* 0.28 */
case 2: Signal->BitErrorRate = 1; break; /* 0.57 */
case 3: Signal->BitErrorRate = 1; break; /* 1.13 */
case 4: Signal->BitErrorRate = 2; break; /* 2.26 */
case 5: Signal->BitErrorRate = 5; break; /* 4.53 */
case 6: Signal->BitErrorRate = 9; break; /* 9.05 */
case 7: Signal->BitErrorRate = 18; break; /* 18.10 */
}
}
return ERR_NONE;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
break;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error ATGEN_GetSignalQuality(GSM_StateMachine *s, GSM_SignalQuality *sig)
{
s->Phone.Data.SignalQuality = sig;
smprintf(s, "Getting signal quality info\n");
return GSM_WaitFor (s, "AT+CSQ\r", 7, 0x00, 4, ID_GetSignalQuality);
}
/* When use AT+CPIN?, A2D returns it without OK and because of it Gammu
parses answer without it.
MC35 and other return OK after answer for AT+CPIN?. Here we handle it.
Any better idea ?
*/
GSM_Error ATGEN_ReplyOK(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
return ERR_NONE;
}
static GSM_Error ATGEN_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
if (Priv->Manufacturer==AT_Siemens ) return SIEMENS_GetNextCalendar(s,Note,start);
if (Priv->Manufacturer==AT_Ericsson) return SONYERIC_GetNextCalendar(s,Note,start);
return ERR_NOTSUPPORTED;
}
GSM_Error ATGEN_Terminate(GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
free(Priv->file.Buffer);
return ERR_NONE;
}
GSM_Error ATGEN_AddCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
if (Priv->Manufacturer==AT_Siemens) return SIEMENS_AddCalendarNote(s, Note);
if (Priv->Manufacturer==AT_Ericsson) return SONYERIC_AddCalendarNote(s, Note);
return ERR_NOTSUPPORTED;
}
GSM_Error ATGEN_DelCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
if (Priv->Manufacturer==AT_Siemens) return SIEMENS_DelCalendarNote(s, Note);
if (Priv->Manufacturer==AT_Ericsson) return SONYERIC_DelCalendarNote(s, Note);
return ERR_NOTSUPPORTED;
}
+
+GSM_Error ATGEN_GetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
+{
+ GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
+
+ if (Priv->Manufacturer==AT_Siemens) return SIEMENS_GetBitmap(s, Bitmap);
+ if (Priv->Manufacturer==AT_Samsung) return SAMSUNG_GetBitmap(s, Bitmap);
+ return ERR_NOTSUPPORTED;
+}
+
+GSM_Error ATGEN_SetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
+{
+ GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
+
+ if (Priv->Manufacturer==AT_Siemens) return SIEMENS_SetBitmap(s, Bitmap);
+ if (Priv->Manufacturer==AT_Samsung) return SAMSUNG_SetBitmap(s, Bitmap);
+ return ERR_NOTSUPPORTED;
+}
+
+GSM_Error ATGEN_GetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone)
+{
+ GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
+
+ if (Priv->Manufacturer==AT_Siemens) return SIEMENS_GetRingtone(s, Ringtone, PhoneRingtone);
+ if (Priv->Manufacturer==AT_Samsung) return SAMSUNG_GetRingtone(s, Ringtone, PhoneRingtone);
+ return ERR_NOTSUPPORTED;
+}
+
+GSM_Error ATGEN_SetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength)
+{
+ GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
+
+ if (Priv->Manufacturer==AT_Siemens) return SIEMENS_SetRingtone(s, Ringtone, maxlength);
+ if (Priv->Manufacturer==AT_Samsung) return SAMSUNG_SetRingtone(s, Ringtone, maxlength);
+ return ERR_NOTSUPPORTED;
+}
+
GSM_Error ATGEN_PressKey(GSM_StateMachine *s, GSM_KeyCode Key, bool Press)
{
GSM_Error error;
unsigned char Frame[] = "AT+CKPD=\"?\"\r";
if (Press) {
switch (Key) {
case GSM_KEY_1 : Frame[9] = '1'; break;
case GSM_KEY_2 : Frame[9] = '2'; break;
case GSM_KEY_3 : Frame[9] = '3'; break;
case GSM_KEY_4 : Frame[9] = '4'; break;
case GSM_KEY_5 : Frame[9] = '5'; break;
case GSM_KEY_6 : Frame[9] = '6'; break;
case GSM_KEY_7 : Frame[9] = '7'; break;
case GSM_KEY_8 : Frame[9] = '8'; break;
case GSM_KEY_9 : Frame[9] = '9'; break;
case GSM_KEY_0 : Frame[9] = '0'; break;
case GSM_KEY_HASH : Frame[9] = '#'; break;
case GSM_KEY_ASTERISK : Frame[9] = '*'; break;
case GSM_KEY_POWER : return ERR_NOTSUPPORTED;
case GSM_KEY_GREEN : Frame[9] = 'S'; break;
case GSM_KEY_RED : Frame[9] = 'E'; break;
case GSM_KEY_INCREASEVOLUME : Frame[9] = 'U'; break;
case GSM_KEY_DECREASEVOLUME : Frame[9] = 'D'; break;
case GSM_KEY_UP : Frame[9] = '^'; break;
case GSM_KEY_DOWN : Frame[9] = 'V'; break;
case GSM_KEY_MENU : Frame[9] = 'F'; break;
case GSM_KEY_NAMES : Frame[9] = 'C'; break;
default : return ERR_NOTSUPPORTED;
}
smprintf(s, "Pressing key\n");
error = GSM_WaitFor (s, Frame, 12, 0x00, 4, ID_PressKey);
if (error != ERR_NONE) return error;
/* Strange. My T310 needs it */
return GSM_WaitFor (s, "ATE1\r", 5, 0x00, 4, ID_EnableEcho);
} else {
return ERR_NONE;
}
}
#ifdef GSM_ENABLE_CELLBROADCAST
GSM_Error ATGEN_ReplyIncomingCB(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_CBMessage CB;
int i,j;
char Buffer[300],Buffer2[300];
smprintf(s, "CB received\n");
return ERR_NONE;
DecodeHexBin (Buffer,msg.Buffer+6,msg.Length-6);
DumpMessage(stdout, di.dl ,Buffer,msg.Length-6);
CB.Channel = Buffer[4];
for (j=0;j<msg.Length;j++) {
smprintf(s, "j=%i\n",j);
i=GSM_UnpackEightBitsToSeven(0, msg.Buffer[6], msg.Buffer[6], msg.Buffer+j, Buffer2);
// i = msg.Buffer[6] - 1;
// while (i!=0) {
// if (Buffer[i] == 13) i = i - 1; else break;
// }
DecodeDefault(CB.Text, Buffer2, msg.Buffer[6], false, NULL);
smprintf(s, "Channel %i, text \"%s\"\n",CB.Channel,DecodeUnicodeString(CB.Text));
}
if (s->Phone.Data.EnableIncomingCB && s->User.IncomingCB!=NULL) {
s->User.IncomingCB(s->CurrentConfig->Device,CB);
}
return ERR_NONE;
}
#endif
GSM_Error ATGEN_SetIncomingCB(GSM_StateMachine *s, bool enable)
{
#ifdef GSM_ENABLE_CELLBROADCAST
if (s->Phone.Data.EnableIncomingCB!=enable) {
s->Phone.Data.EnableIncomingCB = enable;
if (enable) {
smprintf(s, "Enabling incoming CB\n");
return GSM_WaitFor(s, "AT+CNMI=3,,2\r", 13, 0x00, 4, ID_SetIncomingCB);
} else {
smprintf(s, "Disabling incoming CB\n");
return GSM_WaitFor(s, "AT+CNMI=3,,0\r", 13, 0x00, 4, ID_SetIncomingCB);
}
}
return ERR_NONE;
#else
return ERR_SOURCENOTAVAILABLE;
#endif
}
+GSM_Error ATGEN_SetFastSMSSending(GSM_StateMachine *s, bool enable)
+{
+ if (enable) {
+ smprintf(s, "Enabling fast SMS sending\n");
+ return GSM_WaitFor(s, "AT+CMMS=2\r", 10, 0x00, 4, ID_SetFastSMSSending);
+ } else {
+ smprintf(s, "Disabling fast SMS sending\n");
+ return GSM_WaitFor(s, "AT+CMMS=0\r", 10, 0x00, 4, ID_SetFastSMSSending);
+ }
+}
+
GSM_Error ATGEN_IncomingSMSInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Incoming SMS\n");
return ERR_NONE;
}
GSM_Error ATGEN_IncomingSMSDeliver(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
GSM_SMSMessage sms;
int current = 0, current2, i=0;
unsigned char buffer[300],smsframe[800];
smprintf(s, "Incoming SMS received (Deliver)\n");
if (Data->EnableIncomingSMS && s->User.IncomingSMS!=NULL) {
sms.State = SMS_UnRead;
sms.InboxFolder = true;
sms.PDU = SMS_Deliver;
/* T310 with larger SMS goes crazy and mix this incoming
* frame with normal answers. PDU is always last frame
* We find its' number and parse it */
while (Data->Priv.ATGEN.Lines.numbers[i*2+1] != 0) {
/* FIXME: handle special chars correctly */
i++;
}
DecodeHexBin (buffer,
GetLineString(msg.Buffer,Data->Priv.ATGEN.Lines,i),
strlen(GetLineString(msg.Buffer,Data->Priv.ATGEN.Lines,i)));
/* We use locations from SMS layouts like in ../phone2.c(h) */
for(i=0;i<buffer[0]+1;i++) smsframe[i]=buffer[current++];
smsframe[12]=buffer[current++];
current2=((buffer[current])+1)/2+1;
for(i=0;i<current2+1;i++) smsframe[PHONE_SMSDeliver.Number+i]=buffer[current++];
smsframe[PHONE_SMSDeliver.TPPID] = buffer[current++];
smsframe[PHONE_SMSDeliver.TPDCS] = buffer[current++];
for(i=0;i<7;i++) smsframe[PHONE_SMSDeliver.DateTime+i]=buffer[current++];
smsframe[PHONE_SMSDeliver.TPUDL] = buffer[current++];
for(i=0;i<smsframe[PHONE_SMSDeliver.TPUDL];i++) smsframe[i+PHONE_SMSDeliver.Text]=buffer[current++];
GSM_DecodeSMSFrame(&sms,smsframe,PHONE_SMSDeliver);
s->User.IncomingSMS(s->CurrentConfig->Device,sms);
}
return ERR_NONE;
}
/* I don't have phone able to do it and can't fill it */
GSM_Error ATGEN_IncomingSMSReport(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Incoming SMS received (Report)\n");
return ERR_NONE;
}
GSM_Error ATGEN_SetIncomingSMS(GSM_StateMachine *s, bool enable)
{
/* Nokia returns OK, but doesn't return anything */
if (s->Phone.Data.Priv.ATGEN.Manufacturer == AT_Nokia) return ERR_NOTSUPPORTED;
if (s->Phone.Data.EnableIncomingSMS!=enable) {
s->Phone.Data.EnableIncomingSMS = enable;
if (enable) {
smprintf(s, "Enabling incoming SMS\n");
/* Delivery reports */
GSM_WaitFor(s, "AT+CNMI=3,,,1\r", 14, 0x00, 4, ID_SetIncomingSMS);
/* SMS deliver */
return GSM_WaitFor(s, "AT+CNMI=3,3\r", 12, 0x00, 4, ID_SetIncomingSMS);
} else {
smprintf(s, "Disabling incoming SMS\n");
return GSM_WaitFor(s, "AT+CNMI=3,0\r", 12, 0x00, 4, ID_SetIncomingSMS);
}
}
return ERR_NONE;
}
+GSM_Error ATGEN_GetLocale(GSM_StateMachine *s, GSM_Locale *locale)
+{
+ if (s->Phone.Data.Priv.ATGEN.Manufacturer==AT_Ericsson) return ERICSSON_GetLocale(s,locale);
+ return ERR_NOTSUPPORTED;
+}
+
+GSM_Error ATGEN_SetLocale(GSM_StateMachine *s, GSM_Locale *locale)
+{
+ if (s->Phone.Data.Priv.ATGEN.Manufacturer==AT_Ericsson) return ERICSSON_SetLocale(s,locale);
+ return ERR_NOTSUPPORTED;
+}
+
GSM_Reply_Function ATGENReplyFunctions[] = {
{ATGEN_GenericReply, "AT\r" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_GenericReply, "ATE1" ,0x00,0x00,ID_EnableEcho },
{ATGEN_GenericReply, "AT+CMEE=" ,0x00,0x00,ID_EnableErrorInfo },
{ATGEN_GenericReply, "AT+CKPD=" ,0x00,0x00,ID_PressKey },
{ATGEN_ReplyGetSIMIMSI, "AT+CIMI" ,0x00,0x00,ID_GetSIMIMSI },
{ATGEN_GenericReply, "AT*EOBEX" ,0x00,0x00,ID_SetOBEX },
+{ERICSSON_ReplyGetDateLocale, "*ESDF:" ,0x00,0x00,ID_GetLocale },
+{ERICSSON_ReplyGetTimeLocale, "*ESTF:" ,0x00,0x00,ID_GetLocale },
+{ATGEN_GenericReply, "AT*ESDF=" ,0x00,0x00,ID_SetLocale },
+{ATGEN_GenericReply, "AT*ESTF=" ,0x00,0x00,ID_SetLocale },
+
#ifdef GSM_ENABLE_CELLBROADCAST
{ATGEN_ReplyIncomingCB, "+CBM:" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_GenericReply, "AT+CNMI" ,0x00,0x00,ID_SetIncomingCB },
#endif
{ATGEN_IncomingBattery, "_OBS:" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_ReplyGetBatteryCharge, "AT+CBC" ,0x00,0x00,ID_GetBatteryCharge },
{ATGEN_ReplyGetModel, "AT+CGMM" ,0x00,0x00,ID_GetModel },
{ATGEN_ReplyGetManufacturer, "AT+CGMI" ,0x00,0x00,ID_GetManufacturer },
{ATGEN_ReplyGetFirmwareCGMR, "AT+CGMR" ,0x00,0x00,ID_GetFirmware },
{ATGEN_ReplyGetFirmwareATI, "ATI" ,0x00,0x00,ID_GetFirmware },
{ATGEN_ReplyGetIMEI, "AT+CGSN" ,0x00,0x00,ID_GetIMEI },
{ATGEN_ReplySendSMS, "AT+CMGS" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_ReplySendSMS, "AT+CMSS" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_GenericReply, "AT+CNMI" ,0x00,0x00,ID_SetIncomingSMS },
{ATGEN_GenericReply, "AT+CMGF" ,0x00,0x00,ID_GetSMSMode },
{ATGEN_GenericReply, "AT+CSDH" ,0x00,0x00,ID_GetSMSMode },
{ATGEN_ReplyGetSMSMessage, "AT+CMGR" ,0x00,0x00,ID_GetSMSMessage },
{ATGEN_GenericReply, "AT+CPMS" ,0x00,0x00,ID_SetMemoryType },
{ATGEN_ReplyGetSMSStatus, "AT+CPMS" ,0x00,0x00,ID_GetSMSStatus },
{ATGEN_ReplyGetSMSMemories, "AT+CPMS=?" ,0x00,0x00,ID_GetSMSMemories },
{ATGEN_ReplyAddSMSMessage, "AT+CMGW" ,0x00,0x00,ID_SaveSMSMessage },
{ATGEN_GenericReply, "AT+CSMP" ,0x00,0x00,ID_SetSMSParameters },
{ATGEN_GenericReply, "AT+CSCA" ,0x00,0x00,ID_SetSMSC },
{ATGEN_ReplyGetSMSC, "AT+CSCA?" ,0x00,0x00,ID_GetSMSC },
{ATGEN_ReplyDeleteSMSMessage, "AT+CMGD" ,0x00,0x00,ID_DeleteSMSMessage },
{ATGEN_GenericReply, "ATE1" ,0x00,0x00,ID_SetSMSParameters },
{ATGEN_GenericReply, "\x1b\x0D" ,0x00,0x00,ID_SetSMSParameters },
+{ATGEN_GenericReply, "AT+CMMS" ,0x00,0x00,ID_SetFastSMSSending },
{ATGEN_IncomingSMSInfo, "+CMTI:" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_IncomingSMSDeliver, "+CMT:" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_IncomingSMSReport, "+CDS:" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_IncomingSMSCInfo, "^SCN:" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_ReplyGetDateTime_Alarm, "AT+CCLK?" ,0x00,0x00,ID_GetDateTime },
{ATGEN_GenericReply, "AT+CCLK=" ,0x00,0x00,ID_SetDateTime },
+{ATGEN_GenericReply, "AT+CALA=" ,0x00,0x00,ID_SetAlarm },
{ATGEN_ReplyGetDateTime_Alarm, "AT+CALA?" ,0x00,0x00,ID_GetAlarm },
{ATGEN_ReplyGetNetworkLAC_CID, "AT+CREG?" ,0x00,0x00,ID_GetNetworkInfo },
{ATGEN_GenericReply, "AT+CREG=2" ,0x00,0x00,ID_GetNetworkInfo },
{ATGEN_GenericReply, "AT+COPS=" ,0x00,0x00,ID_GetNetworkInfo },
{ATGEN_GenericReply, "AT+COPS=" ,0x00,0x00,ID_SetAutoNetworkLogin},
{ATGEN_ReplyGetNetworkCode, "AT+COPS" ,0x00,0x00,ID_GetNetworkInfo },
{ATGEN_ReplyGetSignalQuality, "AT+CSQ" ,0x00,0x00,ID_GetSignalQuality },
{ATGEN_IncomingNetworkLevel, "_OSIGQ:" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_IncomingGPRS, "+CGREG:" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_ReplyGetNetworkLAC_CID, "+CREG:" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_ReplyGetPBKMemories, "AT+CPBS=?" ,0x00,0x00,ID_SetMemoryType },
{ATGEN_GenericReply, "AT+CPBS=" ,0x00,0x00,ID_SetMemoryType },
{ATGEN_ReplyGetCPBSMemoryStatus,"AT+CPBS?" ,0x00,0x00,ID_GetMemoryStatus },
+// /* Samsung phones reply +CPBR: after OK --claudio*/
{ATGEN_ReplyGetCPBRMemoryInfo, "AT+CPBR=?" ,0x00,0x00,ID_GetMemoryStatus },
+{ATGEN_ReplyGetCPBRMemoryInfo, "+CPBR:" ,0x00,0x00,ID_GetMemoryStatus },
{ATGEN_ReplyGetCPBRMemoryStatus,"AT+CPBR=" ,0x00,0x00,ID_GetMemoryStatus },
{ATGEN_GenericReply, "AT+CSCS=" ,0x00,0x00,ID_SetMemoryCharset },
{ATGEN_ReplyGetMemory, "AT+CPBR=" ,0x00,0x00,ID_GetMemory },
{ATGEN_GenericReply, "AT^SBNR=?" ,0x00,0x00,ID_GetMemory },
-{ATGEN_SL45ReplyGetMemory, "AT^SBNR" ,0x00,0x00,ID_GetMemory },
+{SIEMENS_ReplyGetMemory, "AT^SBNR" ,0x00,0x00,ID_GetMemory },
{ATGEN_ReplySetMemory, "AT+CPBW" ,0x00,0x00,ID_SetMemory },
-{ATGEN_CMS35ReplyGetBitmap, "AT^SBNR=\"bmp\"" ,0x00,0x00,ID_GetBitmap },
-{ATGEN_CMS35ReplySetBitmap, "AT^SBNW=\"bmp\"" ,0x00,0x00,ID_SetBitmap },
+{SIEMENS_ReplyGetBitmap, "AT^SBNR=\"bmp\"" ,0x00,0x00,ID_GetBitmap },
+{SIEMENS_ReplySetBitmap, "AT^SBNW=\"bmp\"" ,0x00,0x00,ID_SetBitmap },
-{ATGEN_CMS35ReplyGetRingtone, "AT^SBNR=\"mid\"" ,0x00,0x00,ID_GetRingtone },
-{ATGEN_CMS35ReplySetRingtone, "AT^SBNW=\"mid\"" ,0x00,0x00,ID_SetRingtone },
+{SIEMENS_ReplyGetRingtone, "AT^SBNR=\"mid\"" ,0x00,0x00,ID_GetRingtone },
+{SIEMENS_ReplySetRingtone, "AT^SBNW=\"mid\"" ,0x00,0x00,ID_SetRingtone },
-{ATGEN_CMS35ReplyGetNextCal, "AT^SBNR=\"vcs\"" ,0x00,0x00,ID_GetCalendarNote },
-{ATGEN_CMS35ReplySetCalendar, "AT^SBNW=\"vcs\"" ,0x00,0x00,ID_SetCalendarNote },
-{ATGEN_CMS35ReplyDeleteCalendar,"AT^SBNW=\"vcs\"" ,0x00,0x00,ID_DeleteCalendarNote },
+{SIEMENS_ReplyGetNextCalendar, "AT^SBNR=\"vcs\"" ,0x00,0x00,ID_GetCalendarNote },
+{SIEMENS_ReplyAddCalendarNote, "AT^SBNW=\"vcs\"" ,0x00,0x00,ID_SetCalendarNote },
+{SIEMENS_ReplyDelCalendarNote, "AT^SBNW=\"vcs\"" ,0x00,0x00,ID_DeleteCalendarNote },
{ATGEN_ReplyEnterSecurityCode, "AT+CPIN=" ,0x00,0x00,ID_EnterSecurityCode },
{ATGEN_ReplyEnterSecurityCode, "AT+CPIN2=" ,0x00,0x00,ID_EnterSecurityCode },
{ATGEN_ReplyGetSecurityStatus, "AT+CPIN?" ,0x00,0x00,ID_GetSecurityStatus },
{ATGEN_ReplyOK, "OK" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_GenericReply, "AT+VTS" ,0x00,0x00,ID_SendDTMF },
{ATGEN_ReplyCancelCall, "AT+CHUP" ,0x00,0x00,ID_CancelCall },
{ATGEN_ReplyDialVoice, "ATDT" ,0x00,0x00,ID_DialVoice },
{ATGEN_ReplyCancelCall, "ATH" ,0x00,0x00,ID_CancelCall },
+{ATGEN_GenericReply, "AT+CUSD" ,0x00,0x00,ID_SetUSSD },
+{ATGEN_ReplyGetUSSD, "+CUSD" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_GenericReply, "AT+CLIP=1" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_ReplyIncomingCallInfo, "+CLIP" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_ReplyIncomingCallInfo, "+COLP" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_ReplyIncomingCallInfo, "RING" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_ReplyIncomingCallInfo, "NO CARRIER" ,0x00,0x00,ID_IncomingFrame },
{ATGEN_ReplyReset, "AT^SRESET" ,0x00,0x00,ID_Reset },
{ATGEN_ReplyReset, "AT+CFUN=1,1" ,0x00,0x00,ID_Reset },
{ATGEN_ReplyResetPhoneSettings, "AT&F" ,0x00,0x00,ID_ResetPhoneSettings },
+{SAMSUNG_ReplyGetBitmap, "AT+IMGR=" ,0x00,0x00,ID_GetBitmap },
+{SAMSUNG_ReplySetBitmap, "SDNDCRC =" ,0x00,0x00,ID_SetBitmap },
+
+{SAMSUNG_ReplyGetRingtone, "AT+MELR=" ,0x00,0x00,ID_GetRingtone },
+{SAMSUNG_ReplySetRingtone, "SDNDCRC =" ,0x00,0x00,ID_SetRingtone },
+
#ifdef GSM_ENABLE_ALCATEL
/* Why do I give Alcatel specific things here? It's simple, Alcatel needs
* some AT commands to start it's binary mode, so this needs to be in AT
* related stuff.
*
* XXX: AT+IFC could later move outside this ifdef, because it is not Alcatel
* specific and it's part of ETSI specifications
*/
{ATGEN_GenericReply, "AT+IFC" ,0x00,0x00,ID_SetFlowControl },
{ALCATEL_ProtocolVersionReply, "AT+CPROT=?" ,0x00,0x00,ID_AlcatelProtocol },
{ATGEN_GenericReply, "AT+CPROT" ,0x00,0x00,ID_AlcatelConnect },
#endif
{NULL, "\x00" ,0x00,0x00,ID_None }
};
GSM_Phone_Functions ATGENPhone = {
- "A2D|iPAQ|at|M20|S25|MC35|C35i|5110|5130|5190|5210|6110|6130|6150|6190|6210|6250|6310|6310i|6510|7110|8210|8250|8290|8310|8390|8850|8855|8890|8910|9110|9210",
+ "A2D|iPAQ|at|M20|S25|MC35|TC35|C35i|S300|5110|5130|5190|5210|6110|6130|6150|6190|6210|6250|6310|6310i|6510|7110|8210|8250|8290|8310|8390|8850|8855|8890|8910|9110|9210",
ATGENReplyFunctions,
ATGEN_Initialise,
ATGEN_Terminate,
ATGEN_DispatchMessage,
NOTSUPPORTED, /* ShowStartInfo */
ATGEN_GetManufacturer,
ATGEN_GetModel,
ATGEN_GetFirmware,
ATGEN_GetIMEI,
NOTSUPPORTED, /* GetOriginalIMEI */
NOTSUPPORTED, /* GetManufactureMonth */
NOTSUPPORTED, /* GetProductCode */
NOTSUPPORTED, /* GetHardware */
NOTSUPPORTED, /* GetPPM */
ATGEN_GetSIMIMSI,
ATGEN_GetDateTime,
ATGEN_SetDateTime,
ATGEN_GetAlarm,
- NOTIMPLEMENTED, /* SetAlarm */
- NOTSUPPORTED, /* GetLocale */
- NOTSUPPORTED, /* SetLocale */
+ ATGEN_SetAlarm,
+ ATGEN_GetLocale,
+ ATGEN_SetLocale,
ATGEN_PressKey,
ATGEN_Reset,
ATGEN_ResetPhoneSettings,
ATGEN_EnterSecurityCode,
ATGEN_GetSecurityStatus,
ATGEN_GetDisplayStatus,
ATGEN_SetAutoNetworkLogin,
ATGEN_GetBatteryCharge,
ATGEN_GetSignalQuality,
ATGEN_GetNetworkInfo,
NOTSUPPORTED, /* GetCategory */
NOTSUPPORTED, /* AddCategory */
NOTSUPPORTED, /* GetCategoryStatus */
ATGEN_GetMemoryStatus,
ATGEN_GetMemory,
ATGEN_GetNextMemory,
ATGEN_SetMemory,
ATGEN_AddMemory,
ATGEN_DeleteMemory,
ATGEN_DeleteAllMemory,
NOTSUPPORTED, /* GetSpeedDial */
NOTSUPPORTED, /* SetSpeedDial */
ATGEN_GetSMSC,
ATGEN_SetSMSC,
ATGEN_GetSMSStatus,
ATGEN_GetSMS,
ATGEN_GetNextSMS,
NOTSUPPORTED, /* SetSMS */
ATGEN_AddSMS,
ATGEN_DeleteSMS,
ATGEN_SendSMS,
ATGEN_SendSavedSMS,
+ ATGEN_SetFastSMSSending,
ATGEN_SetIncomingSMS,
ATGEN_SetIncomingCB,
ATGEN_GetSMSFolders,
NOTSUPPORTED, /* AddSMSFolder */
NOTSUPPORTED, /* DeleteSMSFolder */
ATGEN_DialVoice,
ATGEN_AnswerCall,
ATGEN_CancelCall,
NOTSUPPORTED, /* HoldCall */
NOTSUPPORTED, /* UnholdCall */
NOTSUPPORTED, /* ConferenceCall */
NOTSUPPORTED, /* SplitCall */
NOTSUPPORTED, /* TransferCall */
NOTSUPPORTED, /* SwitchCall */
NOTSUPPORTED, /* GetCallDivert */
NOTSUPPORTED, /* SetCallDivert */
NOTSUPPORTED, /* CancelAllDiverts */
NONEFUNCTION, /* SetIncomingCall */
- NOTSUPPORTED, /* SetIncomingUSSD */
+ ATGEN_SetIncomingUSSD,
ATGEN_SendDTMF,
ATGEN_GetRingtone,
ATGEN_SetRingtone,
NOTSUPPORTED, /* GetRingtonesInfo */
NOTSUPPORTED, /* DeleteUserRingtones */
NOTSUPPORTED, /* PlayTone */
NOTSUPPORTED, /* GetWAPBookmark */
NOTSUPPORTED, /* SetWAPBookmark */
NOTSUPPORTED, /* DeleteWAPBookmark */
NOTSUPPORTED, /* GetWAPSettings */
NOTSUPPORTED, /* SetWAPSettings */
NOTSUPPORTED, /* GetMMSSettings */
NOTSUPPORTED, /* SetMMSSettings */
NOTSUPPORTED, /* GetSyncMLSettings */
NOTSUPPORTED, /* SetSyncMLSettings */
NOTSUPPORTED, /* GetChatSettings */
NOTSUPPORTED, /* SetChatSettings */
ATGEN_GetBitmap, /* GetBitmap */
ATGEN_SetBitmap, /* SetBitmap */
SONYERIC_GetToDoStatus,
NOTSUPPORTED, /* GetToDo */
SONYERIC_GetNextToDo,
NOTSUPPORTED, /* SetToDo */
SONYERIC_AddToDo,
NOTSUPPORTED, /* DeleteToDo */
SONYERIC_DeleteAllToDo,
SONYERIC_GetCalendarStatus,
NOTIMPLEMENTED, /* GetCalendar */
ATGEN_GetNextCalendar,
NOTIMPLEMENTED, /* SetCalendar */
ATGEN_AddCalendarNote,
ATGEN_DelCalendarNote,
NOTIMPLEMENTED, /* DeleteAllCalendar */
NOTSUPPORTED, /* GetCalendarSettings */
NOTSUPPORTED, /* SetCalendarSettings */
- NOTSUPPORTED, /* GetNote */
+ NOTSUPPORTED, /* GetNextNote */
NOTSUPPORTED, /* GetProfile */
NOTSUPPORTED, /* SetProfile */
NOTSUPPORTED, /* GetFMStation */
NOTSUPPORTED, /* SetFMStation */
NOTSUPPORTED, /* ClearFMStations */
NOTSUPPORTED, /* GetNextFileFolder */
NOTSUPPORTED, /* GetFilePart */
NOTSUPPORTED, /* AddFile */
NOTSUPPORTED, /* GetFileSystemStatus */
NOTSUPPORTED, /* DeleteFile */
NOTSUPPORTED, /* AddFolder */
NOTSUPPORTED, /* GetGPRSAccessPoint */
NOTSUPPORTED /* SetGPRSAccessPoint */
};
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/at/atgen.h b/gammu/emb/common/phone/at/atgen.h
index 0e08ee4..bb5c559 100644
--- a/gammu/emb/common/phone/at/atgen.h
+++ b/gammu/emb/common/phone/at/atgen.h
@@ -1,110 +1,116 @@
/* (c) 2002-2004 by Marcin Wiacek and Michal Cihar */
#ifndef atgen_h
#define atgen_h
#include "../../gsmcomon.h"
#include "../../gsmstate.h"
#include "../../service/sms/gsmsms.h"
#ifndef GSM_USED_AT
# define GSM_USED_AT
#endif
#ifndef GSM_USED_BLUEAT
# define GSM_USED_BLUEAT
#endif
#ifndef GSM_USED_IRDAAT
# define GSM_USED_IRDAAT
#endif
#define MAX_VCALENDAR_LOCATION 50
typedef enum {
SMS_AT_PDU = 1,
SMS_AT_TXT
} GSM_AT_SMS_Modes;
typedef enum {
AT_Reply_OK = 1,
AT_Reply_Connect,
AT_Reply_Error,
AT_Reply_Unknown,
AT_Reply_CMSError,
AT_Reply_CMEError,
AT_Reply_SMSEdit
} GSM_AT_Reply_State;
typedef enum {
AT_Nokia = 1,
AT_Alcatel,
AT_Siemens,
AT_HP,
AT_Falcom,
AT_Ericsson,
AT_Sagem,
+ AT_Samsung,
AT_Unknown
} GSM_AT_Manufacturer;
typedef enum {
AT_PBK_HEX = 1,
AT_PBK_GSM,
- AT_PBK_UCS2
+ AT_PBK_UCS2,
+ AT_PBK_PCCP437
} GSM_AT_PBK_Charset;
typedef enum {
AT_AVAILABLE = 1,
AT_NOTAVAILABLE
} GSM_AT_SMSMemory;
typedef enum {
AT_SBNR_AVAILABLE = 1,
AT_SBNR_NOTAVAILABLE
} GSM_AT_SBNR;
typedef enum {
AT_Status,
AT_NextEmpty,
AT_Total,
AT_First,
AT_Sizes
} GSM_AT_NeededMemoryInfo;
#define AT_PBK_MAX_MEMORIES 200
typedef struct {
GSM_AT_Manufacturer Manufacturer; /* Who is manufacturer */
GSM_Lines Lines; /* Allow to simply get each line in response */
GSM_AT_Reply_State ReplyState; /* What response type - error, OK, etc. */
int ErrorCode; /* Error codes from responses */
char *ErrorText; /* Error description */
GSM_MemoryType PBKMemory; /* Last read PBK memory */
char PBKMemories[AT_PBK_MAX_MEMORIES + 1]; /* Supported by phone PBK memories */
int NextMemoryEntry; /* Next empty memory entry */
int FirstMemoryEntry; /* First memory entry to be read */
GSM_AT_PBK_Charset PBKCharset; /* Last read PBK charset */
bool UCS2CharsetFailed; /* Whether setting of UCS2 charset has already failed */
bool NonUCS2CharsetFailed; /* Whether setting of non-UCS2 charset has already failed */
GSM_AT_SBNR PBKSBNR;
int NumberLength;
int TextLength;
int MemorySize;
GSM_SMSMemoryStatus LastSMSStatus;
int LastSMSRead;
int FirstCalendarPos;
bool CanSaveSMS;
GSM_AT_SMSMemory PhoneSMSMemory; /* Is phone SMS memory available ? */
GSM_AT_SMSMemory SIMSMSMemory; /* Is SIM SMS memory available ? */
GSM_MemoryType SMSMemory; /* Last read SMS memory */
GSM_AT_SMS_Modes SMSMode; /* PDU or TEXT mode for SMS ? */
bool OBEX;
GSM_File file;
} GSM_Phone_ATGENData;
+GSM_Error ATGEN_HandleCMSError (GSM_StateMachine *);
+GSM_Error ATGEN_HandleCMEError (GSM_StateMachine *);
+GSM_Error ATGEN_DispatchMessage (GSM_StateMachine *);
+
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/at/samsung.c b/gammu/emb/common/phone/at/samsung.c
new file mode 100644
index 0000000..55a42e5
--- a/dev/null
+++ b/gammu/emb/common/phone/at/samsung.c
@@ -0,0 +1,447 @@
+/* Samsung-specific functions
+ * Copyright (C) 2004 Claudio Matsuoka <cmatsuoka@gmail.com>
+ * Tested with S300 only!
+ */
+
+#include "../../gsmstate.h"
+
+#ifdef GSM_ENABLE_ATGEN
+
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+#include "../../misc/coding/coding.h"
+#include "../../gsmcomon.h"
+#include "../../service/sms/gsmsms.h"
+#include "../pfunc.h"
+
+#include "atgen.h"
+#include "samsung.h"
+
+/* Binary frame size */
+#define BLKSZ 1024
+
+struct ModelRes {
+ char *model;
+ int width;
+ int height;
+};
+
+static struct ModelRes modres[] = {
+ { "S100", 128, 128 },
+ { "S200", 128, 113 },
+ { "S300", 128, 97 },
+ { "S500", 128, 128 },
+ { "T100", 128, 128 },
+ { "E700", 128, 128 },
+ { NULL, 0, 0 }
+};
+
+/*
+ * CRC functions from the Granch SBNI12 Linux driver by
+ * Denis I. Timofeev <timofeev@granch.ru>
+ */
+static unsigned int crc32tab[] = {
+ 0xD202EF8D, 0xA505DF1B, 0x3C0C8EA1, 0x4B0BBE37,
+ 0xD56F2B94, 0xA2681B02, 0x3B614AB8, 0x4C667A2E,
+ 0xDCD967BF, 0xABDE5729, 0x32D70693, 0x45D03605,
+ 0xDBB4A3A6, 0xACB39330, 0x35BAC28A, 0x42BDF21C,
+ 0xCFB5FFE9, 0xB8B2CF7F, 0x21BB9EC5, 0x56BCAE53,
+ 0xC8D83BF0, 0xBFDF0B66, 0x26D65ADC, 0x51D16A4A,
+ 0xC16E77DB, 0xB669474D, 0x2F6016F7, 0x58672661,
+ 0xC603B3C2, 0xB1048354, 0x280DD2EE, 0x5F0AE278,
+ 0xE96CCF45, 0x9E6BFFD3, 0x0762AE69, 0x70659EFF,
+ 0xEE010B5C, 0x99063BCA, 0x000F6A70, 0x77085AE6,
+ 0xE7B74777, 0x90B077E1, 0x09B9265B, 0x7EBE16CD,
+ 0xE0DA836E, 0x97DDB3F8, 0x0ED4E242, 0x79D3D2D4,
+ 0xF4DBDF21, 0x83DCEFB7, 0x1AD5BE0D, 0x6DD28E9B,
+ 0xF3B61B38, 0x84B12BAE, 0x1DB87A14, 0x6ABF4A82,
+ 0xFA005713, 0x8D076785, 0x140E363F, 0x630906A9,
+ 0xFD6D930A, 0x8A6AA39C, 0x1363F226, 0x6464C2B0,
+ 0xA4DEAE1D, 0xD3D99E8B, 0x4AD0CF31, 0x3DD7FFA7,
+ 0xA3B36A04, 0xD4B45A92, 0x4DBD0B28, 0x3ABA3BBE,
+ 0xAA05262F, 0xDD0216B9, 0x440B4703, 0x330C7795,
+ 0xAD68E236, 0xDA6FD2A0, 0x4366831A, 0x3461B38C,
+ 0xB969BE79, 0xCE6E8EEF, 0x5767DF55, 0x2060EFC3,
+ 0xBE047A60, 0xC9034AF6, 0x500A1B4C, 0x270D2BDA,
+ 0xB7B2364B, 0xC0B506DD, 0x59BC5767, 0x2EBB67F1,
+ 0xB0DFF252, 0xC7D8C2C4, 0x5ED1937E, 0x29D6A3E8,
+ 0x9FB08ED5, 0xE8B7BE43, 0x71BEEFF9, 0x06B9DF6F,
+ 0x98DD4ACC, 0xEFDA7A5A, 0x76D32BE0, 0x01D41B76,
+ 0x916B06E7, 0xE66C3671, 0x7F6567CB, 0x0862575D,
+ 0x9606C2FE, 0xE101F268, 0x7808A3D2, 0x0F0F9344,
+ 0x82079EB1, 0xF500AE27, 0x6C09FF9D, 0x1B0ECF0B,
+ 0x856A5AA8, 0xF26D6A3E, 0x6B643B84, 0x1C630B12,
+ 0x8CDC1683, 0xFBDB2615, 0x62D277AF, 0x15D54739,
+ 0x8BB1D29A, 0xFCB6E20C, 0x65BFB3B6, 0x12B88320,
+ 0x3FBA6CAD, 0x48BD5C3B, 0xD1B40D81, 0xA6B33D17,
+ 0x38D7A8B4, 0x4FD09822, 0xD6D9C998, 0xA1DEF90E,
+ 0x3161E49F, 0x4666D409, 0xDF6F85B3, 0xA868B525,
+ 0x360C2086, 0x410B1010, 0xD80241AA, 0xAF05713C,
+ 0x220D7CC9, 0x550A4C5F, 0xCC031DE5, 0xBB042D73,
+ 0x2560B8D0, 0x52678846, 0xCB6ED9FC, 0xBC69E96A,
+ 0x2CD6F4FB, 0x5BD1C46D, 0xC2D895D7, 0xB5DFA541,
+ 0x2BBB30E2, 0x5CBC0074, 0xC5B551CE, 0xB2B26158,
+ 0x04D44C65, 0x73D37CF3, 0xEADA2D49, 0x9DDD1DDF,
+ 0x03B9887C, 0x74BEB8EA, 0xEDB7E950, 0x9AB0D9C6,
+ 0x0A0FC457, 0x7D08F4C1, 0xE401A57B, 0x930695ED,
+ 0x0D62004E, 0x7A6530D8, 0xE36C6162, 0x946B51F4,
+ 0x19635C01, 0x6E646C97, 0xF76D3D2D, 0x806A0DBB,
+ 0x1E0E9818, 0x6909A88E, 0xF000F934, 0x8707C9A2,
+ 0x17B8D433, 0x60BFE4A5, 0xF9B6B51F, 0x8EB18589,
+ 0x10D5102A, 0x67D220BC, 0xFEDB7106, 0x89DC4190,
+ 0x49662D3D, 0x3E611DAB, 0xA7684C11, 0xD06F7C87,
+ 0x4E0BE924, 0x390CD9B2, 0xA0058808, 0xD702B89E,
+ 0x47BDA50F, 0x30BA9599, 0xA9B3C423, 0xDEB4F4B5,
+ 0x40D06116, 0x37D75180, 0xAEDE003A, 0xD9D930AC,
+ 0x54D13D59, 0x23D60DCF, 0xBADF5C75, 0xCDD86CE3,
+ 0x53BCF940, 0x24BBC9D6, 0xBDB2986C, 0xCAB5A8FA,
+ 0x5A0AB56B, 0x2D0D85FD, 0xB404D447, 0xC303E4D1,
+ 0x5D677172, 0x2A6041E4, 0xB369105E, 0xC46E20C8,
+ 0x72080DF5, 0x050F3D63, 0x9C066CD9, 0xEB015C4F,
+ 0x7565C9EC, 0x0262F97A, 0x9B6BA8C0, 0xEC6C9856,
+ 0x7CD385C7, 0x0BD4B551, 0x92DDE4EB, 0xE5DAD47D,
+ 0x7BBE41DE, 0x0CB97148, 0x95B020F2, 0xE2B71064,
+ 0x6FBF1D91, 0x18B82D07, 0x81B17CBD, 0xF6B64C2B,
+ 0x68D2D988, 0x1FD5E91E, 0x86DCB8A4, 0xF1DB8832,
+ 0x616495A3, 0x1663A535, 0x8F6AF48F, 0xF86DC419,
+ 0x660951BA, 0x110E612C, 0x88073096, 0xFF000000
+};
+
+static unsigned int GetCRC(char *data, int size)
+{
+ unsigned int crc = 0;
+
+ while (size--)
+ crc = crc32tab[(crc ^ *data++) & 0xff] ^ ((crc >> 8) & 0x00FFFFFF);
+
+ return crc;
+}
+
+/*
+ * Frame transfer
+ */
+
+static GSM_Error WaitFor(GSM_StateMachine *s, char *t, int ttl)
+{
+ char readbuf[100];
+ int n;
+ unsigned int sec;
+ GSM_DateTime Date;
+
+ GSM_GetCurrentDateTime (&Date);
+ sec = Date.Second;
+
+ n = s->Device.Functions->ReadDevice(s, readbuf, 80);
+ readbuf[n] = 0;
+ while (strstr(readbuf, t) == NULL && (sec + ttl) >= Date.Second) {
+ my_sleep(5000);
+ n = s->Device.Functions->ReadDevice(s, readbuf, 80);
+ readbuf[n] = 0;
+ GSM_GetCurrentDateTime (&Date);
+ }
+
+ return (sec + ttl) >= Date.Second ? ERR_NONE : ERR_TIMEOUT;
+}
+
+static GSM_Error SetSamsungFrame(GSM_StateMachine *s, unsigned char *buff, int size, GSM_Phone_RequestID id)
+{
+ GSM_Phone_Data *Phone = &s->Phone.Data;
+ GSM_Error error;
+ int i, count;
+
+ count = size / BLKSZ;
+
+ for (i = 0; i < count; i++) {
+ error = WaitFor(s, ">", 4);
+ if (error!=ERR_NONE) return error;
+
+ error = s->Protocol.Functions->WriteMessage(s,
+ buff + i * BLKSZ, BLKSZ, 0x00);
+ if (error!=ERR_NONE) return error;
+ }
+
+ error = WaitFor(s, ">", 4);
+ if (error!=ERR_NONE) return error;
+ error = s->Protocol.Functions->WriteMessage(s,
+ buff + i * BLKSZ, size%BLKSZ, 0x00);
+ if (error!=ERR_NONE) return error;
+
+ error = GSM_WaitFor(s, "", 0, 0x00, 4, id);
+ if (error!=ERR_NONE) return error;
+
+ return Phone->DispatchError;
+}
+
+/* Answer format for binary data transfer
+ *
+ * SDNDCRC = 0xa : RECEIVECRC = 0xcbf53a1c : BINSIZE = 5
+ * CRCERR
+ */
+static GSM_Error ReplySetSamsungFrame(GSM_Protocol_Message msg, GSM_StateMachine *s)
+{
+ unsigned long txcrc, rxcrc;
+ int binsize;
+ char *pos;
+
+ /* Parse SDNDCRC */
+ pos = strchr(msg.Buffer, '=');
+ if (!pos) return ERR_UNKNOWN;
+ pos++;
+ txcrc = strtoul(pos, NULL, 0);
+ smprintf(s, "Sent CRC : 0x%lx\n", txcrc);
+
+ /* Parse RECEIVECRC */
+ pos = strchr(pos, '=');
+ if (!pos) return ERR_UNKNOWN;
+ pos++;
+ rxcrc = strtoul(pos, NULL, 0);
+ smprintf(s, "Reveived CRC : 0x%lx\n", rxcrc);
+
+ /* Parse BINSIZE */
+ pos = strchr(pos, '=');
+ if (!pos) return ERR_UNKNOWN;
+ pos++;
+ binsize = strtoul(pos, NULL, 0);
+ smprintf(s, "Binary size : %d\n", binsize);
+
+ return txcrc == rxcrc ? ERR_NONE : ERR_WRONGCRC;
+}
+
+/*
+ * Bitmaps
+ */
+
+GSM_Error SAMSUNG_ReplyGetBitmap(GSM_Protocol_Message msg, GSM_StateMachine *s)
+{
+ GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
+ unsigned char buffer[32];
+ char *pos;
+ int location, count;
+
+ switch (Priv->ReplyState) {
+ case AT_Reply_OK:
+ smprintf(s, "Bitmap info received\n");
+ /* Parse +IMGR:location,name,0,0,0,0 */
+
+ /* Parse location */
+ pos = strchr(msg.Buffer, ':');
+ if (!pos) return ERR_UNKNOWN;
+ pos++;
+ location = atoi(pos);
+ smprintf(s, "Location : %d\n", location);
+
+ /* Parse name */
+ pos = strchr(pos, '"');
+ if (!pos) return ERR_UNKNOWN;
+ pos++;
+ for (count = 0; count < 31; count++) {
+ if (pos[count] == '"')
+ break;
+ buffer[count] = pos[count];
+ }
+ buffer[count] = 0;
+ smprintf(s, "Name : %s\n", buffer);
+ s->Phone.Data.Bitmap->Name = malloc((strlen(buffer) + 1) * 2);
+ if (s->Phone.Data.Bitmap->Name == NULL)
+ return ERR_MOREMEMORY;
+ EncodeUnicode(s->Phone.Data.Bitmap->Name, buffer, strlen(buffer));
+
+ s->Phone.Data.Bitmap->Location = location;
+
+ return ERR_NONE;
+ case AT_Reply_Error:
+ return ERR_UNKNOWN;
+ case AT_Reply_CMSError:
+ return ATGEN_HandleCMSError(s);
+ case AT_Reply_CMEError:
+ return ATGEN_HandleCMEError(s);
+ default:
+ return ERR_UNKNOWNRESPONSE;
+ }
+}
+
+GSM_Error SAMSUNG_ReplySetBitmap(GSM_Protocol_Message msg, GSM_StateMachine *s)
+{
+ smprintf(s, "Bitmap sent\n");
+ return ReplySetSamsungFrame(msg, s);
+}
+
+GSM_Error SAMSUNG_GetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
+{
+ unsigned char req[100];
+
+ s->Phone.Data.Bitmap=Bitmap;
+ smprintf(s, "Getting bitmap\n");
+ sprintf(req, "AT+IMGR=%d\r", Bitmap->Location-1);
+ return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetBitmap);
+}
+
+GSM_Error SAMSUNG_SetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
+{
+ unsigned char req[100];
+ unsigned long crc;
+ GSM_Error error;
+ char name[50], *dot, *model;
+ GSM_Phone_Data *Data = &s->Phone.Data;
+ int i;
+
+ s->Phone.Data.Bitmap = Bitmap;
+ smprintf(s, "Setting bitmap\n");
+
+ if (Bitmap->Type != GSM_PictureBinary) {
+ smprintf(s, "Invalid picture type\n");
+ return ERR_INVALIDDATA;
+ }
+
+ if (Bitmap->BinaryPic.Type != PICTURE_GIF) {
+ smprintf(s, "Invalid binary picture type\n");
+ return ERR_INVALIDDATA;
+ }
+
+ /* Check if picture size matches phone model */
+ model = GetModelData(NULL,Data->Model,NULL)->model;
+ smprintf(s, "Checking picture size for %s\n", model);
+ for (i = 0; modres[i].model; i++) {
+ if (!strcmp(model, modres[i].model)) {
+ if (Bitmap->BitmapWidth != modres[i].width ||
+ Bitmap->BitmapHeight != modres[i].height) {
+ smprintf(s, "Model %s must use %d x %d picture size\n",
+ modres[i].model, modres[i].width,
+ modres[i].height);
+ return ERR_INVALIDDATA;
+ }
+ break;
+ }
+ }
+ if (modres[i].model == NULL) {
+ smprintf(s, "Model \"%s\" is not supported.\n", Data->Model);
+ return ERR_NOTSUPPORTED;
+ }
+
+ crc = GetCRC(Bitmap->BinaryPic.Buffer, Bitmap->BinaryPic.Length);
+
+ /* Remove extension from file name */
+ strncpy(name, DecodeUnicodeString(Bitmap->Name), 50);
+ if ((dot = strrchr(name, '.')) != NULL)
+ *dot = 0;
+
+ sprintf(req, "AT+IMGW=0,\"%s\",2,0,0,0,0,100,%d,%u\r", name,
+ Bitmap->BinaryPic.Length, (unsigned int)crc);
+
+ error = s->Protocol.Functions->WriteMessage(s, req, strlen(req), 0x00);
+ if (error!=ERR_NONE) return error;
+
+ return SetSamsungFrame(s, Bitmap->BinaryPic.Buffer,
+ Bitmap->BinaryPic.Length, ID_SetBitmap);
+}
+
+/*
+ * Ringtones
+ */
+
+GSM_Error SAMSUNG_ReplyGetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
+{
+ GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
+ unsigned char buffer[32];
+ char *pos;
+ int location, length, count;
+
+ switch (Priv->ReplyState) {
+ case AT_Reply_OK:
+ smprintf(s, "Ringtone info received\n");
+ /* Parse +MELR:location,name,size */
+
+ /* Parse location */
+ pos = strchr(msg.Buffer, ':');
+ if (!pos) return ERR_UNKNOWN;
+ pos++;
+ location = atoi(pos);
+ smprintf(s, "Location : %d\n", location);
+
+ /* Parse name */
+ pos = strchr(pos, '"');
+ if (!pos) return ERR_UNKNOWN;
+ pos++;
+ /* Ringtone.Name size is 20 chars */
+ for (count = 0; count < 19; count++) {
+ if (pos[count] == '"')
+ break;
+ buffer[count] = pos[count];
+ }
+ buffer[count] = 0;
+ smprintf(s, "Name : %s\n", buffer);
+ EncodeUnicode(s->Phone.Data.Ringtone->Name,buffer,strlen(buffer));
+
+ /* Parse ringtone length */
+ pos = strchr(pos, ',');
+ if (!pos) return ERR_UNKNOWN;
+ pos++;
+ length = atoi(pos);
+ smprintf(s, "Length : %d\n", length);
+
+ /* S300 ringtones are always MMF */
+ s->Phone.Data.Ringtone->Format = RING_MMF;
+ s->Phone.Data.Ringtone->Location = location;
+ s->Phone.Data.Ringtone->BinaryTone.Length = length;
+
+ return ERR_NONE;
+ case AT_Reply_Error:
+ return ERR_UNKNOWN;
+ case AT_Reply_CMSError:
+ return ATGEN_HandleCMSError(s);
+ case AT_Reply_CMEError:
+ return ATGEN_HandleCMEError(s);
+ default:
+ return ERR_UNKNOWNRESPONSE;
+ }
+}
+
+GSM_Error SAMSUNG_GetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone)
+{
+ unsigned char req[100];
+
+ s->Phone.Data.Ringtone = Ringtone;
+ smprintf(s, "Getting ringtone\n");
+ sprintf(req, "AT+MELR=%d\r", Ringtone->Location-1);
+ return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetRingtone);
+}
+
+GSM_Error SAMSUNG_ReplySetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
+{
+ smprintf(s, "Ringtone sent\n");
+ return ReplySetSamsungFrame(msg, s);
+}
+
+GSM_Error SAMSUNG_SetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength)
+{
+ unsigned char req[100];
+ unsigned long crc;
+ GSM_Error error;
+ char name[50], *dot;
+
+ s->Phone.Data.Ringtone = Ringtone;
+ smprintf(s, "Setting ringtone\n");
+
+ if (Ringtone->Format != RING_MMF) {
+ smprintf(s, "Not MMF ringtone\n");
+ return ERR_INVALIDDATA;
+ }
+
+ /* Remove extension from file name */
+ strncpy(name, DecodeUnicodeString(Ringtone->Name), 50);
+ if ((dot = strrchr(name, '.')) != NULL) *dot = 0;
+
+ crc = GetCRC(Ringtone->BinaryTone.Buffer, Ringtone->BinaryTone.Length);
+ sprintf(req, "AT+MELW=0,\"%s\",4,%d,%u\r", name,
+ Ringtone->BinaryTone.Length, (unsigned int)crc);
+
+ error = s->Protocol.Functions->WriteMessage(s, req, strlen(req), 0x00);
+ if (error!=ERR_NONE) return error;
+
+ return SetSamsungFrame(s, Ringtone->BinaryTone.Buffer,
+ Ringtone->BinaryTone.Length, ID_SetRingtone);
+}
+
+#endif
diff --git a/gammu/emb/common/phone/at/samsung.h b/gammu/emb/common/phone/at/samsung.h
new file mode 100644
index 0000000..3b2947c
--- a/dev/null
+++ b/gammu/emb/common/phone/at/samsung.h
@@ -0,0 +1,16 @@
+#ifndef samsung_h
+#define samsung_h
+
+#include "../../gsmstate.h"
+
+GSM_Error SAMSUNG_ReplyGetRingtone (GSM_Protocol_Message, GSM_StateMachine *);
+GSM_Error SAMSUNG_ReplySetRingtone (GSM_Protocol_Message, GSM_StateMachine *);
+GSM_Error SAMSUNG_ReplyGetBitmap (GSM_Protocol_Message, GSM_StateMachine *);
+GSM_Error SAMSUNG_ReplySetBitmap (GSM_Protocol_Message, GSM_StateMachine *);
+GSM_Error SAMSUNG_GetRingtone (GSM_StateMachine *, GSM_Ringtone *, bool);
+GSM_Error SAMSUNG_SetRingtone (GSM_StateMachine *, GSM_Ringtone *, int *);
+GSM_Error SAMSUNG_GetBitmap (GSM_StateMachine *, GSM_Bitmap *);
+GSM_Error SAMSUNG_SetBitmap (GSM_StateMachine *, GSM_Bitmap *);
+GSM_Error SAMSUNG_GetCallLogs (GSM_StateMachine *, GSM_MemoryEntry *, int);
+
+#endif
diff --git a/gammu/emb/common/phone/at/siemens.c b/gammu/emb/common/phone/at/siemens.c
index ab7dd2c..7f66cf8 100644
--- a/gammu/emb/common/phone/at/siemens.c
+++ b/gammu/emb/common/phone/at/siemens.c
@@ -1,320 +1,316 @@
/* (c) 2002-2003 by Walek */
#include "../../gsmstate.h"
#ifdef GSM_ENABLE_ATGEN
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "../../misc/coding/coding.h"
#include "../../gsmcomon.h"
#include "../../service/sms/gsmsms.h"
#include "../pfunc.h"
-extern GSM_Error ATGEN_HandleCMSError(GSM_StateMachine *s);
+#include "atgen.h"
+#include "siemens.h"
-GSM_Error ATGEN_CMS35ReplySetFunction (GSM_Protocol_Message msg, GSM_StateMachine *s,char *function)
-{
- if (s->Protocol.Data.AT.EditMode) {
- s->Protocol.Data.AT.EditMode = false;
- return ERR_NONE;
- }
- dbgprintf ("Written %s",function);
- if (s->Phone.Data.Priv.ATGEN.ReplyState == AT_Reply_OK){
- dbgprintf (" - OK\n");
- return ERR_NONE;
- } else {
- dbgprintf (" - error\n");
- return ERR_UNKNOWN;
- }
-}
-GSM_Error GetSiemensFrame(GSM_Protocol_Message msg, GSM_StateMachine *s, char *templ,
+static GSM_Error GetSiemensFrame(GSM_Protocol_Message msg, GSM_StateMachine *s, char *templ,
unsigned char *buffer, int *len)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
int i=2, pos=0, length=0;
unsigned char buf[512];
if (strstr(GetLineString(msg.Buffer,Priv->Lines,2),"OK")) return ERR_EMPTY;
if (!strstr(GetLineString(msg.Buffer,Priv->Lines,2),templ)) return ERR_UNKNOWN;
while (1) {
if (Priv->Lines.numbers[i*2+1]==0) break;
if ((!strstr(GetLineString(msg.Buffer,Priv->Lines,i+1),templ)) &&
(strstr(GetLineString(msg.Buffer,Priv->Lines,i),templ))){
length = strlen(GetLineString(msg.Buffer,Priv->Lines,i+1));
DecodeHexBin(buf, GetLineString(msg.Buffer,Priv->Lines,i+1),length);
length = length/2;
memcpy (buffer+pos,buf,length);
pos+=length;
}
i++;
}
*len = pos;
return ERR_NONE;
}
-GSM_Error SetSiemensFrame (GSM_StateMachine *s, unsigned char *buff, char *templ,
+static GSM_Error SetSiemensFrame (GSM_StateMachine *s, unsigned char *buff, char *templ,
int Location, GSM_Phone_RequestID RequestID, int len)
{
GSM_Phone_Data *Phone = &s->Phone.Data;
GSM_Error error;
unsigned char req[20],req1[512],hexreq[2096];
int MaxFrame,CurrentFrame,size,sz,pos=0;
EncodeHexBin(hexreq,buff,len);
size = len * 2;
MaxFrame = size / 352;
if (size % 352) MaxFrame++;
for (CurrentFrame=0;CurrentFrame<MaxFrame;CurrentFrame++) {
pos=CurrentFrame*352;
if (pos+352 < size) sz = 352; else sz = size - pos;
sprintf(req, "AT^SBNW=\"%s\",%i,%i,%i\r",templ,Location,CurrentFrame+1,MaxFrame);
s->Protocol.Data.AT.EditMode = true;
error = GSM_WaitFor (s, req, strlen(req), 0x00, 3, RequestID);
s->Phone.Data.DispatchError=ERR_TIMEOUT;
s->Phone.Data.RequestID=RequestID;
if (error!=ERR_NONE) return error;
memcpy (req1,hexreq+pos,sz);
error = s->Protocol.Functions->WriteMessage(s, req1, sz, 0x00);
if (error!=ERR_NONE) return error;
error = s->Protocol.Functions->WriteMessage(s,"\x1A", 1, 0x00);
if (error!=ERR_NONE) return error;
error = GSM_WaitForOnce(s, NULL, 0x00, 0x00, 4);
if (error == ERR_TIMEOUT) return error;
}
return Phone->DispatchError;
}
-GSM_Error ATGEN_CMS35ReplyGetBitmap(GSM_Protocol_Message msg, GSM_StateMachine *s)
+GSM_Error SIEMENS_ReplyGetBitmap(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
unsigned char buffer[4096];
int length;
GSM_Error error;
error = GetSiemensFrame(msg,s,"bmp",buffer,&length);
if (error!=ERR_NONE) return error;
dbgprintf ("Operator logo received lenght=%i\n",length);
error = BMP2Bitmap (buffer,NULL,s->Phone.Data.Bitmap);
if (error==ERR_NONE) return error;
else return ERR_UNKNOWN;
}
-GSM_Error ATGEN_CMS35ReplySetBitmap(GSM_Protocol_Message msg, GSM_StateMachine *s)
+GSM_Error SIEMENS_ReplySetFunction (GSM_Protocol_Message msg, GSM_StateMachine *s,char *function)
{
- return ATGEN_CMS35ReplySetFunction (msg, s, "Operator Logo");
+ if (s->Protocol.Data.AT.EditMode) {
+ s->Protocol.Data.AT.EditMode = false;
+ return ERR_NONE;
+ }
+ dbgprintf ("Written %s",function);
+ if (s->Phone.Data.Priv.ATGEN.ReplyState == AT_Reply_OK){
+ dbgprintf (" - OK\n");
+ return ERR_NONE;
+ } else {
+ dbgprintf (" - error\n");
+ return ERR_UNKNOWN;
+ }
}
-GSM_Error ATGEN_GetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
+GSM_Error SIEMENS_ReplySetBitmap(GSM_Protocol_Message msg, GSM_StateMachine *s)
+{
+ return SIEMENS_ReplySetFunction (msg, s, "Operator Logo");
+}
+
+GSM_Error SIEMENS_GetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
{
unsigned char req[32];
- if (s->Phone.Data.Priv.ATGEN.Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
if (Bitmap->Type!=GSM_OperatorLogo) return ERR_NOTSUPPORTED;
if (Bitmap->Location-1 < 0) Bitmap->Location++;
s->Phone.Data.Bitmap=Bitmap;
sprintf(req, "AT^SBNR=\"bmp\",%i\r", Bitmap->Location-1);
smprintf(s, "Getting Bitmap\n");
return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetBitmap);
}
-GSM_Error ATGEN_SetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
+GSM_Error SIEMENS_SetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
{
unsigned char buffer[4096];
int length;
GSM_Error error;
- if (s->Phone.Data.Priv.ATGEN.Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
if (Bitmap->Type!=GSM_OperatorLogo) return ERR_NOTSUPPORTED;
error = Bitmap2BMP (buffer,NULL,Bitmap);
if (error!=ERR_NONE) return error;
length = 0x100 * buffer[3] + buffer[2];
buffer[58]=0xff; buffer[59]=0xff; buffer[60]=0xff;
if (Bitmap->Location-1 < 0) Bitmap->Location++;
s->Phone.Data.Bitmap=Bitmap;
return SetSiemensFrame(s, buffer,"bmp",Bitmap->Location-1,
ID_SetBitmap,length);
}
-GSM_Error ATGEN_CMS35ReplyGetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
+GSM_Error SIEMENS_ReplyGetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
unsigned char buffer[32];
int length;
GSM_Error error;
error = GetSiemensFrame(msg,s,"mid",s->Phone.Data.Ringtone->NokiaBinary.Frame,&length);
if (error!=ERR_NONE) return error;
dbgprintf ("Midi ringtone received\n");
s->Phone.Data.Ringtone->Format = RING_MIDI;
s->Phone.Data.Ringtone->NokiaBinary.Length = length;
sprintf(buffer,"Individual");
EncodeUnicode (s->Phone.Data.Ringtone->Name,buffer,strlen(buffer));
return ERR_NONE;
}
-GSM_Error ATGEN_GetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone)
+GSM_Error SIEMENS_GetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone)
{
unsigned char req[32];
- if (s->Phone.Data.Priv.ATGEN.Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
-
s->Phone.Data.Ringtone=Ringtone;
sprintf(req, "AT^SBNR=\"mid\",%i\r", Ringtone->Location-1);
smprintf(s, "Getting RingTone\n");
return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetRingtone);
}
-GSM_Error ATGEN_CMS35ReplySetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
+GSM_Error SIEMENS_ReplySetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
- return ATGEN_CMS35ReplySetFunction (msg, s, "Ringtone");
+ return SIEMENS_ReplySetFunction (msg, s, "Ringtone");
}
-GSM_Error ATGEN_SetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength)
+GSM_Error SIEMENS_SetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength)
{
GSM_Phone_Data *Phone = &s->Phone.Data;
- if (s->Phone.Data.Priv.ATGEN.Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
-
if (Ringtone->Location==255) Ringtone->Location=1;
if (Ringtone->Location-1 > 1) return ERR_INVALIDLOCATION;
s->Phone.Data.Ringtone = Ringtone;
Phone->Ringtone = Ringtone;
return SetSiemensFrame(s, Ringtone->NokiaBinary.Frame,"mid",Ringtone->Location-1,
ID_SetRingtone,Ringtone->NokiaBinary.Length);
}
-GSM_Error ATGEN_CMS35ReplyGetNextCal(GSM_Protocol_Message msg, GSM_StateMachine *s)
+GSM_Error SIEMENS_ReplyGetNextCalendar(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
GSM_CalendarEntry *Calendar = Data->Cal;
GSM_ToDoEntry ToDo;
GSM_Error error;
unsigned char buffer[354];
int len, pos=0;
if (Data->Priv.ATGEN.ReplyState != AT_Reply_OK) return ERR_UNKNOWN;
error = GetSiemensFrame(msg,s,"vcs",buffer,&len);
if (error!=ERR_NONE) return error;
error=GSM_DecodeVCALENDAR_VTODO(buffer,&pos,Calendar,&ToDo,Siemens_VCalendar,0);
return error;
}
GSM_Error SIEMENS_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_Error error;
unsigned char req[32];
int Location;
if (Priv->Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
if (start) Note->Location=Priv->FirstCalendarPos;
s->Phone.Data.Cal = Note;
Note->EntriesNum = 0;
smprintf(s, "Getting VCALENDAR\n");
Location = Note->Location;
while (1){
Location++;
sprintf(req, "AT^SBNR=\"vcs\",%i\r",Location);
error = GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetCalendarNote);
if ((error!=ERR_NONE) && (error!=ERR_EMPTY)) return ERR_INVALIDLOCATION;
Note->Location = Location;
Priv->FirstCalendarPos = Location;
if (Location > MAX_VCALENDAR_LOCATION) return ERR_EMPTY;
if (error==ERR_NONE) return error;
}
return error;
}
-GSM_Error ATGEN_CMS35ReplySetCalendar(GSM_Protocol_Message msg, GSM_StateMachine *s)
+GSM_Error SIEMENS_ReplyAddCalendarNote(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
- return ATGEN_CMS35ReplySetFunction (msg, s, "Calendar Note");
+ return SIEMENS_ReplySetFunction (msg, s, "Calendar Note");
}
-GSM_Error ATGEN_CMS35ReplyDeleteCalendar(GSM_Protocol_Message msg, GSM_StateMachine *s)
+GSM_Error SIEMENS_ReplyDelCalendarNote(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
if (Data->Cal->Location > MAX_VCALENDAR_LOCATION) return ERR_UNKNOWN;
if (Data->Priv.ATGEN.ReplyState== AT_Reply_OK) {
smprintf(s, "Calendar note deleted\n");
return ERR_NONE;
} else {
smprintf(s, "Can't delete calendar note\n");
return ERR_UNKNOWN;
}
}
GSM_Error SIEMENS_DelCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
{
unsigned char req[32];
if (s->Phone.Data.Priv.ATGEN.Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
s->Phone.Data.Cal = Note;
sprintf(req, "AT^SBNW=\"vcs\",%i,0\r",Note->Location);
smprintf(s, "Deleting calendar note\n");
return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_DeleteCalendarNote);
}
GSM_Error SIEMENS_AddCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_Error error;
unsigned char req[500];
int size=0;
if (Priv->Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
// if (Note->Location==0x00) return ERR_INVALIDLOCATION;
s->Phone.Data.Cal = Note;
error=GSM_EncodeVCALENDAR(req,&size,Note,true,Siemens_VCalendar);
return SetSiemensFrame (s,req,"vcs",Note->Location,ID_SetCalendarNote,size);
}
/* (c) by Timo Teras */
-GSM_Error ATGEN_SL45ReplyGetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
+GSM_Error SIEMENS_ReplyGetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
#ifndef ENABLE_LGPL
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_MemoryEntry *Memory = s->Phone.Data.Memory;
unsigned char buffer[500],buffer2[500];
switch (Priv->ReplyState) {
case AT_Reply_OK:
smprintf(s, "Phonebook entry received\n");
CopyLineString(buffer, msg.Buffer, Priv->Lines, 3);
DecodeHexBin(buffer2,buffer,strlen(buffer));
Memory->EntriesNum = 0;
DecodeVCARD21Text(buffer2, Memory);
if (Memory->EntriesNum == 0) return ERR_EMPTY;
return ERR_NONE;
case AT_Reply_Error:
smprintf(s, "Error - too high location ?\n");
return ERR_INVALIDLOCATION;
case AT_Reply_CMSError:
return ATGEN_HandleCMSError(s);
default:
break;
}
return ERR_UNKNOWNRESPONSE;
#else
return ERR_NOTIMPLEMENTED;
#endif
}
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/at/sonyeric.c b/gammu/emb/common/phone/at/sonyeric.c
index 4b2670a..8eeb39b 100644
--- a/gammu/emb/common/phone/at/sonyeric.c
+++ b/gammu/emb/common/phone/at/sonyeric.c
@@ -1,411 +1,520 @@
/* (c) 2003 by Marcin Wiacek */
#include "../../gsmstate.h"
#ifdef GSM_ENABLE_ATGEN
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "../../gsmcomon.h"
#include "../../misc/coding/coding.h"
-extern GSM_Reply_Function ATGENReplyFunctions[];
-extern GSM_Error ATGEN_DispatchMessage (GSM_StateMachine *s);
+#include "atgen.h"
+#include "sonyeric.h"
#ifdef GSM_ENABLE_OBEXGEN
-extern GSM_Reply_Function OBEXGENReplyFunctions[];
-extern GSM_Error OBEXGEN_GetFilePart (GSM_StateMachine *s, GSM_File *File);
-extern GSM_Error OBEXGEN_AddFilePart (GSM_StateMachine *s, GSM_File *File, int *Pos);
-extern GSM_Error OBEXGEN_Disconnect (GSM_StateMachine *s);
+#include "../obex/obexgen.h"
-#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
+extern GSM_Reply_Function OBEXGENReplyFunctions[];
+extern GSM_Reply_Function ATGENReplyFunctions[];
static GSM_Error SONYERIC_SetOBEXMode(GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_Error error;
if (Priv->OBEX) return ERR_NONE;
dbgprintf ("Changing to OBEX\n");
error=GSM_WaitFor (s, "AT*EOBEX\r", 9, 0x00, 4, ID_SetOBEX);
if (error != ERR_NONE) return error;
error = s->Protocol.Functions->Terminate(s);
if (error != ERR_NONE) return error;
s->Protocol.Functions = &OBEXProtocol;
error = s->Protocol.Functions->Initialise(s);
if (error != ERR_NONE) {
s->Protocol.Functions = &ATProtocol;
return error;
}
strcpy(s->CurrentConfig->Model,"seobex");
s->Phone.Data.Priv.OBEXGEN.Service = 0;
s->Phone.Functions->DispatchMessage = GSM_DispatchMessage;
s->Phone.Functions->ReplyFunctions = OBEXGENReplyFunctions;
Priv->OBEX = true;
return ERR_NONE;
}
static GSM_Error SONYERIC_SetATMode(GSM_StateMachine *s)
{
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
GSM_Error error;
if (!Priv->OBEX) return ERR_NONE;
dbgprintf ("Changing to AT\n");
error = OBEXGEN_Disconnect(s);
if (error != ERR_NONE) return error;
error = s->Protocol.Functions->Terminate(s);
if (error != ERR_NONE) return error;
s->Protocol.Functions = &ATProtocol;
error = s->Protocol.Functions->Initialise(s);
if (error != ERR_NONE) {
s->Protocol.Functions = &OBEXProtocol;
return error;
}
strcpy(s->CurrentConfig->Model,"at");
s->Phone.Functions->DispatchMessage = ATGEN_DispatchMessage;
s->Phone.Functions->ReplyFunctions = ATGENReplyFunctions;
Priv->OBEX = false;
return ERR_NONE;
}
static GSM_Error SONYERIC_GetFile(GSM_StateMachine *s, GSM_File *File, unsigned char *FileName)
{
GSM_Error error;
strcpy(File->ID_FullName,FileName);
File->Used = 0;
if (File->Buffer != NULL) free(File->Buffer);
File->Buffer = NULL;
error = SONYERIC_SetOBEXMode(s);
if (error != ERR_NONE) return error;
error = ERR_NONE;
while (error == ERR_NONE) error = OBEXGEN_GetFilePart(s,File);
if (error != ERR_EMPTY) return error;
return SONYERIC_SetATMode(s);
}
static GSM_Error SONYERIC_SetFile(GSM_StateMachine *s, unsigned char *FileName, unsigned char *Buffer, int Length)
{
GSM_Error error;
GSM_File File;
int Pos = 0;
error = SONYERIC_SetOBEXMode(s);
if (error != ERR_NONE) return error;
strcpy(File.ID_FullName,FileName);
EncodeUnicode(File.Name,FileName,strlen(FileName));
File.Used = Length;
File.Buffer = malloc(Length);
memcpy(File.Buffer,Buffer,Length);
error = ERR_NONE;
while (error == ERR_NONE) error = OBEXGEN_AddFilePart(s,&File,&Pos);
free(File.Buffer);
if (error != ERR_EMPTY) return error;
return SONYERIC_SetATMode(s);
}
#endif
GSM_Error SONYERIC_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
{
-#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
+#ifdef GSM_ENABLE_OBEXGEN
GSM_Error error;
GSM_ToDoEntry ToDo;
int Pos, num, Loc;
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
if (start) {
error = SONYERIC_GetFile(s, &Priv->file, "telecom/cal.vcs");
if (error != ERR_NONE) return error;
Note->Location = 1;
} else {
Note->Location++;
}
smprintf(s, "Getting calendar note %i\n",Note->Location);
Loc = Note->Location;
Pos = 0;
num = 0;
while (1) {
error = GSM_DecodeVCALENDAR_VTODO(Priv->file.Buffer, &Pos, Note, &ToDo, SonyEricsson_VCalendar, SonyEricsson_VToDo);
if (error == ERR_EMPTY) break;
if (error != ERR_NONE) return error;
if (Note->EntriesNum != 0) {
num++;
if (num == Loc) return ERR_NONE;
}
}
return ERR_EMPTY;
#else
return ERR_SOURCENOTAVAILABLE;
#endif
}
GSM_Error SONYERIC_GetNextToDo(GSM_StateMachine *s, GSM_ToDoEntry *ToDo, bool start)
{
-#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
+#ifdef GSM_ENABLE_OBEXGEN
GSM_Error error;
GSM_CalendarEntry Calendar;
int Pos, num, Loc;
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
if (Priv->Manufacturer!=AT_Ericsson) return ERR_NOTSUPPORTED;
if (start) {
error = SONYERIC_GetFile(s, &Priv->file, "telecom/cal.vcs");
if (error != ERR_NONE) return error;
ToDo->Location = 1;
} else {
ToDo->Location++;
}
smprintf(s,"Getting ToDo %i\n",ToDo->Location);
Loc = ToDo->Location;
Pos = 0;
num = 0;
while (1) {
error = GSM_DecodeVCALENDAR_VTODO(Priv->file.Buffer, &Pos, &Calendar, ToDo, SonyEricsson_VCalendar, SonyEricsson_VToDo);
if (error == ERR_EMPTY) break;
if (error != ERR_NONE) return error;
if (ToDo->EntriesNum != 0) {
num++;
if (num == Loc) return ERR_NONE;
}
}
return ERR_EMPTY;
#else
return ERR_SOURCENOTAVAILABLE;
#endif
}
GSM_Error SONYERIC_GetToDoStatus(GSM_StateMachine *s, GSM_ToDoStatus *status)
{
-#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
+#ifdef GSM_ENABLE_OBEXGEN
GSM_Error error;
GSM_ToDoEntry ToDo;
GSM_CalendarEntry Calendar;
int Pos;
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
if (Priv->Manufacturer!=AT_Ericsson) return ERR_NOTSUPPORTED;
smprintf(s,"Getting ToDo status\n");
error = SONYERIC_GetFile(s, &Priv->file, "telecom/cal.vcs");
if (error != ERR_NONE) return error;
status->Used = 0;
Pos = 0;
while (1) {
error = GSM_DecodeVCALENDAR_VTODO(Priv->file.Buffer, &Pos, &Calendar, &ToDo, SonyEricsson_VCalendar, SonyEricsson_VToDo);
if (error == ERR_EMPTY) break;
if (error != ERR_NONE) return error;
if (ToDo.EntriesNum != 0) status->Used++;
}
return ERR_NONE;
#else
return ERR_SOURCENOTAVAILABLE;
#endif
}
GSM_Error SONYERIC_AddCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
{
-#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
+#ifdef GSM_ENABLE_OBEXGEN
unsigned char req[5000];
int size=0;
smprintf(s,"Adding calendar note\n");
GSM_EncodeVCALENDAR(req,&size,Note,true,SonyEricsson_VCalendar);
return SONYERIC_SetFile(s, "telecom/cal/luid/.vcs", req, size);
#else
return ERR_SOURCENOTAVAILABLE;
#endif
}
GSM_Error SONYERIC_AddToDo(GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
{
-#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
+#ifdef GSM_ENABLE_OBEXGEN
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
unsigned char req[5000];
int size=0;
if (Priv->Manufacturer!=AT_Ericsson) return ERR_NOTSUPPORTED;
smprintf(s,"Adding ToDo\n");
GSM_EncodeVTODO(req,&size,ToDo,true,SonyEricsson_VToDo);
return SONYERIC_SetFile(s, "telecom/cal/luid/.vcs", req, size);
#else
return ERR_SOURCENOTAVAILABLE;
#endif
}
GSM_Error SONYERIC_DeleteAllToDo(GSM_StateMachine *s)
{
-#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
+#ifdef GSM_ENABLE_OBEXGEN
GSM_Error error;
int Pos,Level = 0,Used;
unsigned char *Buf;
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
unsigned char Line[2000];
if (Priv->Manufacturer!=AT_Ericsson) return ERR_NOTSUPPORTED;
smprintf(s,"Deleting all ToDo\n");
error = SONYERIC_GetFile(s, &Priv->file, "telecom/cal.vcs");
if (error != ERR_NONE) return error;
Pos = 0;
Buf = NULL;
Used = 0;
while (1) {
MyGetLine(Priv->file.Buffer, &Pos, Line, Priv->file.Used);
if (strlen(Line) == 0) break;
dbgprintf("Line is %s,%i,%i\n",Line,Priv->file.Used,Pos);
switch (Level) {
case 0:
if (strstr(Line,"BEGIN:VTODO")) {
Level = 2;
break;
}
Buf=(unsigned char *)realloc(Buf,Used+strlen(Line)+3);
strcpy(Buf+Used,Line);
Used=Used+strlen(Line)+3;
Buf[Used-3] = 13;
Buf[Used-2] = 10;
Buf[Used-1] = 0x00;
break;
case 2: /* ToDo note */
if (strstr(Line,"END:VTODO")) {
Level = 0;
}
break;
}
}
error = SONYERIC_SetFile(s, "telecom/cal.vcs", Buf, Used);
// if (Buf != NULL) free(Buf);
return error;
#else
return ERR_SOURCENOTAVAILABLE;
#endif
}
GSM_Error SONYERIC_DelCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
{
-#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
+#ifdef GSM_ENABLE_OBEXGEN
GSM_Error error;
int Pos,Level = 0,Loc=0,Used;
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
unsigned char Line[2000];
unsigned char *Buf;
smprintf(s, "Deleting calendar note %i\n",Note->Location);
error = SONYERIC_GetFile(s, &Priv->file, "telecom/cal.vcs");
if (error != ERR_NONE) return error;
Pos = 0;
Buf = NULL;
Used = 0;
while (1) {
MyGetLine(Priv->file.Buffer, &Pos, Line, Priv->file.Used);
if (strlen(Line) == 0) break;
dbgprintf("Line is %s,%i,%i\n",Line,Priv->file.Used,Pos);
switch (Level) {
case 0:
if (strstr(Line,"BEGIN:VEVENT")) {
Loc++;
if (Loc == Note->Location) {
Level = 1;
break;
}
}
Buf=(unsigned char *)realloc(Buf,Used+strlen(Line)+3);
strcpy(Buf+Used,Line);
Used=Used+strlen(Line)+3;
Buf[Used-3] = 13;
Buf[Used-2] = 10;
Buf[Used-1] = 0x00;
break;
case 1: /* Calendar note */
if (strstr(Line,"END:VEVENT")) {
Level = 0;
}
break;
}
}
DumpMessage(s->di.df, s->di.dl, Buf, Used);
error = SONYERIC_SetFile(s, "telecom/cal.vcs", Buf, Used);
if (Buf != NULL) free(Buf);
return error;
#else
return ERR_SOURCENOTAVAILABLE;
#endif
}
GSM_Error SONYERIC_GetCalendarStatus(GSM_StateMachine *s, GSM_CalendarStatus *Status)
{
-#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
+#ifdef GSM_ENABLE_OBEXGEN
GSM_Error error;
GSM_ToDoEntry ToDo;
GSM_CalendarEntry Calendar;
int Pos;
GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
if (Priv->Manufacturer!=AT_Ericsson) return ERR_NOTSUPPORTED;
smprintf(s, "Getting calendar status\n");
error = SONYERIC_GetFile(s, &Priv->file, "telecom/cal.vcs");
if (error != ERR_NONE) return error;
Status->Used = 0;
Pos = 0;
while (1) {
error = GSM_DecodeVCALENDAR_VTODO(Priv->file.Buffer, &Pos, &Calendar, &ToDo, SonyEricsson_VCalendar, SonyEricsson_VToDo);
if (error == ERR_EMPTY) break;
if (error != ERR_NONE) return error;
if (Calendar.EntriesNum != 0) Status->Used++;
}
return ERR_NONE;
#else
return ERR_SOURCENOTAVAILABLE;
#endif
}
-#endif
+GSM_Error ERICSSON_ReplyGetDateLocale(GSM_Protocol_Message msg, GSM_StateMachine *s)
+{ /* Author: Peter Ondraska, based on code by Marcin Wiacek and Michal Cihar
+ License: Whatever the current maintainer of gammulib chooses, as long as there
+ is an easy way to obtain the source under GPL, otherwise the author's parts
+ of this function are GPL 2.0.
+ */
+ GSM_Locale *locale = s->Phone.Data.Locale;
+ char format;
+
+ switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
+ case AT_Reply_OK:
+ smprintf(s, "Date settings received\n");
+ format=atoi(msg.Buffer);
+ switch (format) {
+ case 0: locale->DateFormat = GSM_Date_OFF;
+ locale->DateSeparator = 0;
+ break;
+ case 1: locale->DateFormat = GSM_Date_DDMMMYY;
+ locale->DateSeparator = '-';
+ break;
+ case 2: locale->DateFormat = GSM_Date_DDMMYY;
+ locale->DateSeparator = '-';
+ break;
+ case 3: locale->DateFormat = GSM_Date_MMDDYY;
+ locale->DateSeparator = '/';
+ break;
+ case 4: locale->DateFormat = GSM_Date_DDMMYY;
+ locale->DateSeparator = '/';
+ break;
+ case 5: locale->DateFormat = GSM_Date_DDMMYY;
+ locale->DateSeparator = '.';
+ break;
+ case 6: locale->DateFormat = GSM_Date_YYMMDD;
+ locale->DateSeparator = 0;
+ break;
+ case 7: locale->DateFormat = GSM_Date_YYMMDD;
+ locale->DateSeparator = '-';
+ break;
+ default:return ERR_UNKNOWNRESPONSE;
+ }
+ default:
+ return ERR_NOTSUPPORTED;
+ }
+}
+
+GSM_Error ERICSSON_ReplyGetTimeLocale(GSM_Protocol_Message msg, GSM_StateMachine *s)
+{ /* Author: Peter Ondraska
+ License: Whatever the current maintainer of gammulib chooses, as long as there
+ is an easy way to obtain the source under GPL, otherwise the author's parts
+ of this function are GPL 2.0.
+ */
+ char format;
+
+ switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
+ case AT_Reply_OK:
+ smprintf(s, "Time settings received\n");
+ format=atoi(msg.Buffer);
+ switch (format) {
+ case 1:
+ case 2: s->Phone.Data.Locale->AMPMTime=(format==2);
+ return ERR_NONE;
+ default:return ERR_UNKNOWNRESPONSE;
+ }
+ default: return ERR_NOTSUPPORTED;
+ }
+}
+
+GSM_Error ERICSSON_GetLocale(GSM_StateMachine *s, GSM_Locale *locale)
+{
+ GSM_Error error;
+
+ s->Phone.Data.Locale = locale;
+
+ smprintf(s, "Getting date format\n");
+ error=GSM_WaitFor (s, "AT+ESDF?\r", 9, 0x00, 3, ID_GetLocale);
+ if (error!=ERR_NONE) return error;
+
+ smprintf(s, "Getting time format\n");
+ return GSM_WaitFor (s, "AT+ESTF?\r", 9, 0x00, 3, ID_GetLocale);
+}
+
+
+GSM_Error ERICSSON_SetLocale(GSM_StateMachine *s, GSM_Locale *locale)
+{ /* Author: Peter Ondraska
+ License: Whatever the current maintainer of gammulib chooses, as long as there
+ is an easy way to obtain the source under GPL, otherwise the author's parts
+ of this function are GPL 2.0.
+ */
+ /* this is not yet supported by gammu.c */
+ int format=0;
+ char req[12];
+
+ if (locale->DateFormat==GSM_Date_OFF) { format=0; } else
+ if ((locale->DateFormat==GSM_Date_DDMMMYY)&&(locale->DateSeparator=='-')) { format=1; } else
+ if ((locale->DateFormat==GSM_Date_DDMMYY)&&(locale->DateSeparator=='-')) { format=2; } else
+ if ((locale->DateFormat==GSM_Date_MMDDYY)&&(locale->DateSeparator=='/')) { format=3; } else
+ if ((locale->DateFormat==GSM_Date_DDMMYY)&&(locale->DateSeparator=='/')) { format=4; } else
+ if ((locale->DateFormat==GSM_Date_DDMMYY)&&(locale->DateSeparator=='.')) { format=5; } else
+ if ((locale->DateFormat==GSM_Date_YYMMDD)&&(locale->DateSeparator==0)) { format=6; } else
+ if ((locale->DateFormat==GSM_Date_YYMMDD)&&(locale->DateSeparator=='-')) { format=7; }
+ else { return ERR_NOTSUPPORTED; } /* ERR_WRONGINPUT */
+
+ sprintf(req,"AT+ESDF=%i\r",format);
+ smprintf(s, "Setting date format\n");
+ return GSM_WaitFor (s, req, strlen(req), 0x00, 3, ID_SetLocale);
+
+ if (locale->AMPMTime) { format=2; } else { format=1; }
+ sprintf(req,"AT+ESTF=%i\r",format);
+ smprintf(s, "Setting time format\n");
+ return GSM_WaitFor (s, req, strlen(req), 0x00, 3, ID_SetLocale);
+}
+
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/nokia/dct3/dct3func.c b/gammu/emb/common/phone/nokia/dct3/dct3func.c
index beef33c..17cd0a4 100644
--- a/gammu/emb/common/phone/nokia/dct3/dct3func.c
+++ b/gammu/emb/common/phone/nokia/dct3/dct3func.c
@@ -1,195 +1,198 @@
/* (c) 2001-2004 by Marcin Wiacek */
-/* based on some work from Markus Plail, Pavel Janik, others and Gnokii */
/* resetting DCT4 phones settings (c) by Walek */
+/* based on some Markus Plail, Pavel Janik & others work from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
#include <string.h> /* memcpy only */
#include <stdio.h>
#include <ctype.h>
#include "../../../gsmstate.h"
#include "../../../misc/coding/coding.h"
#include "../../../service/sms/gsmsms.h"
#include "../../pfunc.h"
#include "../nfunc.h"
#include "dct3func.h"
#ifdef GSM_ENABLE_NOKIA_DCT3
GSM_Error DCT3_DeleteWAPBookmark(GSM_StateMachine *s, GSM_WAPBookmark *bookmark)
{
GSM_Error error;
/* We have to enable WAP frames in phone */
error=DCT3DCT4_EnableWAPFunctions(s);
if (error!=ERR_NONE) return error;
return DCT3DCT4_DeleteWAPBookmarkPart(s,bookmark);
}
GSM_Error DCT3_GetWAPBookmark(GSM_StateMachine *s, GSM_WAPBookmark *bookmark)
{
GSM_Error error;
/* We have to enable WAP frames in phone */
error=DCT3DCT4_EnableWAPFunctions(s);
if (error!=ERR_NONE) return error;
return DCT3DCT4_GetWAPBookmarkPart(s,bookmark);
}
GSM_Error DCT3_ReplyPressKey(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
switch (msg.Buffer[2]) {
case 0x46:
smprintf(s, "Pressing key OK\n");
if (Data->PressKey) return ERR_NONE;
break;
case 0x47:
smprintf(s, "Releasing key OK\n");
if (!Data->PressKey) return ERR_NONE;
break;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error DCT3_PressKey(GSM_StateMachine *s, GSM_KeyCode Key, bool Press)
{
unsigned char PressReq[] = {0x00, 0x01, 0x46, 0x00, 0x01,
0x0a}; /* Key code */
unsigned char ReleaseReq[] = {0x00, 0x01, 0x47, 0x00, 0x01, 0x0c};
if (Press) {
PressReq[5] = Key;
s->Phone.Data.PressKey = true;
smprintf(s, "Pressing key\n");
return GSM_WaitFor (s, PressReq, 6, 0xd1, 4, ID_PressKey);
} else {
s->Phone.Data.PressKey = false;
smprintf(s, "Releasing key\n");
return GSM_WaitFor (s, ReleaseReq, 6, 0xd1, 4, ID_PressKey);
}
}
GSM_Error DCT3_ReplyPlayTone(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Tone played\n");
return ERR_NONE;
}
GSM_Error DCT3_PlayTone(GSM_StateMachine *s, int Herz, unsigned char Volume, bool start)
{
GSM_Error error;
unsigned char req[] = {0x00,0x01,0x8f,
0x00, /* Volume */
0x00, /* HerzLo */
0x00}; /* HerzHi */
if (start) {
error=DCT3_EnableSecurity (s, 0x01);
if (error!=ERR_NONE) return error;
}
/* For Herz==255*255 we have silent */
if (Herz!=255*255) {
req[3]=Volume;
req[5]=Herz%256;
req[4]=Herz/256;
} else {
req[3]=0;
req[5]=0;
req[4]=0;
}
return GSM_WaitFor (s, req, 6, 0x40, 4, ID_PlayTone);
}
#ifdef GSM_ENABLE_CELLBROADCAST
GSM_Error DCT3_ReplyIncomingCB(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_CBMessage CB;
int i;
char Buffer[300];
smprintf(s, "CB received\n");
CB.Channel = msg.Buffer[7];
i = GSM_UnpackEightBitsToSeven(0, msg.Buffer[9], msg.Buffer[9], msg.Buffer+10, Buffer);
i = msg.Buffer[9] - 1;
while (i!=0) {
if (Buffer[i] == 13) i = i - 1; else break;
}
DecodeDefault(CB.Text, Buffer, i + 1, false, NULL);
smprintf(s, "Channel %i, text \"%s\"\n",CB.Channel,DecodeUnicodeString(CB.Text));
if (s->Phone.Data.EnableIncomingCB && s->User.IncomingCB!=NULL) {
s->User.IncomingCB(s->CurrentConfig->Device,CB);
}
return ERR_NONE;
}
GSM_Error DCT3_ReplySetIncomingCB(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[3]) {
case 0x21:
smprintf(s, "CB set\n");
return ERR_NONE;
case 0x22:
smprintf(s, "CB not set\n");
return ERR_UNKNOWN;
case 0xCA:
smprintf(s, "No network and no CB\n");
return ERR_SECURITYERROR;
}
return ERR_UNKNOWNRESPONSE;
}
#endif
GSM_Error DCT3_SetIncomingCB(GSM_StateMachine *s, bool enable)
{
#ifdef GSM_ENABLE_CELLBROADCAST
unsigned char reqOn[] = {N6110_FRAME_HEADER, 0x20, 0x01,
0x01, 0x00, 0x00, 0x01, 0x01};
unsigned char reqOff[] = {N6110_FRAME_HEADER, 0x20, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00};
if (s->Phone.Data.EnableIncomingCB!=enable) {
s->Phone.Data.EnableIncomingCB = enable;
if (enable) {
smprintf(s, "Enabling incoming CB\n");
return GSM_WaitFor(s, reqOn, 10, 0x02, 4, ID_SetIncomingCB);
} else {
smprintf(s, "Disabling incoming CB\n");
return GSM_WaitFor(s, reqOff, 10, 0x02, 4, ID_SetIncomingCB);
}
}
return ERR_NONE;
#else
return ERR_SOURCENOTAVAILABLE;
#endif
}
GSM_Error DCT3_ReplySetSMSC(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "SMSC set\n");
return ERR_NONE;
}
GSM_Error DCT3_SetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
{
unsigned char req[100] = {N6110_FRAME_HEADER, 0x30, 0x64};
memset(req+6,100-6,0);
/* SMSC location */
req[5] = smsc->Location;
/* SMSC format */
switch (smsc->Format) {
case SMS_FORMAT_Text : req[7] = 0x00; break;
case SMS_FORMAT_Fax : req[7] = 0x22; break;
case SMS_FORMAT_Pager : req[7] = 0x26; break;
case SMS_FORMAT_Email : req[7] = 0x32; break;
}
@@ -205,451 +208,452 @@ GSM_Error DCT3_SetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
/* SMSC name */
memcpy(req + 34, DecodeUnicodeString(smsc->Name),UnicodeLength(smsc->Name));
smprintf(s, "Setting SMSC\n");
return GSM_WaitFor (s, req, 35+UnicodeLength(smsc->Name), 0x02, 4, ID_SetSMSC);
}
GSM_Error DCT3_ReplyEnableSecurity(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "State of security commands set\n");
return ERR_NONE;
}
/* If you set make some things (for example, change Security Code from
* phone's menu, disable and enable phone), it won't answer for 0x40 frames
* and you won't be able to play tones, get netmonitor, etc.
* This function do thing called "Enabling extended security commands"
* and it enables 0x40 frame functions.
* This frame can also some other things - see below
*/
GSM_Error DCT3_EnableSecurity (GSM_StateMachine *s, unsigned char status)
{
unsigned char req[] = {0x00, 0x01, 0x64,
0x01}; /* 0x00/0x01 - off/on,
* 0x03/0x04 - soft/hard reset,
* 0x06 - CONTACT SERVICE
*/
/* 0x06 MAKES CONTACT SERVICE! BE CAREFULL! */
/* When use 0x03 and had during session changed time & date
* some phones (like 6150 or 6210) can ask for time & date after reset
* or disable clock on the screen
*/
if (status!=0x06) req[3] = status;
smprintf(s, "Setting state of security commands\n");
return GSM_WaitFor (s, req, 4, 0x40, 4, ID_EnableSecurity);
}
GSM_Error DCT3_ReplyGetIMEI(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
memcpy(s->Phone.Data.IMEI,msg.Buffer + 4, 16);
smprintf(s, "Received IMEI %s\n",s->Phone.Data.IMEI);
return ERR_NONE;
}
GSM_Error DCT3_GetIMEI (GSM_StateMachine *s)
{
unsigned char req[] = {0x00, 0x01, 0x66, 0x00};
GSM_Error error;
if (strlen(s->Phone.Data.IMEI)!=0) return ERR_NONE;
error=DCT3_EnableSecurity (s, 0x01);
if (error!=ERR_NONE) return error;
smprintf(s, "Getting IMEI\n");
return GSM_WaitFor (s, req, 4, 0x40, 2, ID_GetIMEI);
}
GSM_Error DCT3_ReplySIMLogin(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Login for SIM card\n");
return ERR_NONE;
}
GSM_Error DCT3_ReplySIMLogout(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Logout for SIM card\n");
return ERR_NONE;
}
GSM_Error DCT3_ReplyGetDateTime(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Date & time received\n");
if (msg.Buffer[4]==0x01) {
NOKIA_DecodeDateTime(s, msg.Buffer+8, s->Phone.Data.DateTime);
return ERR_NONE;
}
smprintf(s, "Not set in phone\n");
return ERR_EMPTY;
}
GSM_Error DCT3_GetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time, unsigned char msgtype)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x62};
s->Phone.Data.DateTime=date_time;
smprintf(s, "Getting date & time\n");
return GSM_WaitFor (s, req, 4, msgtype, 4, ID_GetDateTime);
}
GSM_Error DCT3_ReplyGetAlarm(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Alarm: ");
if (msg.Buffer[8]==0x02) {
smprintf(s, "set to %02i:%02i\n", msg.Buffer[9], msg.Buffer[10]);
Data->Alarm->Repeating = true;
Data->Alarm->Text[0] = 0;
Data->Alarm->Text[1] = 0;
Data->Alarm->DateTime.Hour = msg.Buffer[9];
Data->Alarm->DateTime.Minute = msg.Buffer[10];
Data->Alarm->DateTime.Second = 0;
return ERR_NONE;
}
smprintf(s, "not set\n");
return ERR_EMPTY;
}
GSM_Error DCT3_GetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm, unsigned char msgtype)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x6d};
if (alarm->Location!=1) return ERR_NOTSUPPORTED;
s->Phone.Data.Alarm=alarm;
smprintf(s, "Getting alarm\n");
return GSM_WaitFor (s, req, 4, msgtype, 4, ID_GetAlarm);
}
GSM_Error DCT3_ReplySetDateTime(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Date & time: ");
if (msg.Buffer[4]==0x01) {
smprintf(s, "set OK\n");
return ERR_NONE;
}
smprintf(s, "error setting\n");
return ERR_UNKNOWN;
}
GSM_Error DCT3_SetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time, unsigned char msgtype)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x60, 0x01, 0x01, 0x07,
0x00, 0x00, /* Year */
0x00, /* Month */
0x00, /* Day */
0x00, /* Hour */
0x00, /* Minute */
0x00}; /* Unknown. Not seconds */
NOKIA_EncodeDateTime(s, req+7, date_time);
smprintf(s, "Setting date & time\n");
return GSM_WaitFor (s, req, 14, msgtype, 4, ID_SetDateTime);
}
GSM_Error DCT3_ReplySetAlarm(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Alarm: ");
if (msg.Buffer[4]==0x01) {
smprintf(s, "set OK\n");
return ERR_NONE;
}
smprintf(s, "error setting\n");
return ERR_UNKNOWN;
}
GSM_Error DCT3_SetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm, unsigned char msgtype)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x6b, 0x01, 0x20, 0x03,
0x02, /* Unknown. Not for enabling/disabling */
0x00, /* Hour */
0x00, /* Minute */
0x00}; /* Unknown. Not seconds */
if (alarm->Location != 1) return ERR_NOTSUPPORTED;
req[8] = alarm->DateTime.Hour;
req[9] = alarm->DateTime.Minute;
smprintf(s, "Setting alarm\n");
return GSM_WaitFor (s, req, 11, msgtype, 4, ID_SetAlarm);
}
GSM_Error DCT3_ReplyGetSMSC(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int i;
GSM_Phone_Data *Data = &s->Phone.Data;
switch (msg.Buffer[3]) {
case 0x34:
smprintf(s, "SMSC received\n");
Data->SMSC->Format = SMS_FORMAT_Text;
switch (msg.Buffer[6]) {
case 0x00: Data->SMSC->Format = SMS_FORMAT_Text; break;
case 0x22: Data->SMSC->Format = SMS_FORMAT_Fax; break;
case 0x26: Data->SMSC->Format = SMS_FORMAT_Pager; break;
case 0x32: Data->SMSC->Format = SMS_FORMAT_Email; break;
}
Data->SMSC->Validity.Format = SMS_Validity_RelativeFormat;
Data->SMSC->Validity.Relative = msg.Buffer[8];
+ if (msg.Buffer[8] == 0x00) Data->SMSC->Validity.Relative = SMS_VALID_Max_Time;
i=33;
while (msg.Buffer[i]!=0) {i++;}
i=i-33;
if (i>GSM_MAX_SMSC_NAME_LENGTH) {
smprintf(s, "Too long name\n");
return ERR_UNKNOWNRESPONSE;
}
EncodeUnicode(Data->SMSC->Name,msg.Buffer+33,i);
smprintf(s, "Name \"%s\"\n", DecodeUnicodeString(Data->SMSC->Name));
GSM_UnpackSemiOctetNumber(Data->SMSC->DefaultNumber,msg.Buffer+9,true);
smprintf(s, "Default number \"%s\"\n", DecodeUnicodeString(Data->SMSC->DefaultNumber));
GSM_UnpackSemiOctetNumber(Data->SMSC->Number,msg.Buffer+21,false);
smprintf(s, "Number \"%s\"\n", DecodeUnicodeString(Data->SMSC->Number));
return ERR_NONE;
case 0x35:
smprintf(s, "Getting SMSC failed\n");
return ERR_INVALIDLOCATION;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error DCT3_GetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x33, 0x64,
0x00}; /* Location */
if (smsc->Location==0x00) return ERR_INVALIDLOCATION;
req[5]=smsc->Location;
s->Phone.Data.SMSC=smsc;
smprintf(s, "Getting SMSC\n");
return GSM_WaitFor (s, req, 6, 0x02, 4, ID_GetSMSC);
}
GSM_Error DCT3_ReplyGetNetworkInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int count;
GSM_Phone_Data *Data = &s->Phone.Data;
#ifdef DEBUG
GSM_NetworkInfo NetInfo;
char name[100];
smprintf(s, "Network info received\n");
- smprintf(s, " Status : ");
+ smprintf(s, "Status : ");
switch (msg.Buffer[8]) {
case 0x01: smprintf(s, "home network"); break;
case 0x02: smprintf(s, "roaming network"); break;
case 0x03: smprintf(s, "requesting network"); break;
case 0x04: smprintf(s, "not registered in the network"); break;
default : smprintf(s, "unknown");
}
smprintf(s, "\n");
- smprintf(s, "Network selection : %s\n", msg.Buffer[9]==1?"manual":"automatic");
+ smprintf(s, "Network selection : %s\n", msg.Buffer[9]==1?"manual":"automatic");
if (msg.Buffer[8]<0x03) {
sprintf(NetInfo.CID, "%02x%02x", msg.Buffer[10], msg.Buffer[11]);
smprintf(s, "CID : %s\n", NetInfo.CID);
sprintf(NetInfo.LAC, "%02x%02x", msg.Buffer[12], msg.Buffer[13]);
smprintf(s, "LAC : %s\n", NetInfo.LAC);
- smprintf(s, "Network code : %s\n", NetInfo.NetworkCode);
NOKIA_DecodeNetworkCode(msg.Buffer+14,NetInfo.NetworkCode);
+ smprintf(s, "Network code : %s\n", NetInfo.NetworkCode);
smprintf(s, "Network name for Gammu : %s ",
DecodeUnicodeString(GSM_GetNetworkName(NetInfo.NetworkCode)));
smprintf(s, "(%s)\n",DecodeUnicodeString(GSM_GetCountryName(NetInfo.NetworkCode)));
if (msg.Length>18) {
if (msg.Buffer[18]==0x00) {
/* In 6210 name is in "normal" Unicode */
memcpy(name,msg.Buffer+18,msg.Buffer[17]*2);
name[msg.Buffer[17]*2] =0x00;
name[msg.Buffer[17]*2+1]=0x00;
smprintf(s, "Network name for phone : %s\n",DecodeUnicodeString(name));
} else {
/* In 9210 first 0x00 is cut from Unicode string */
name[0] = 0;
memcpy(name+1,msg.Buffer+18,msg.Buffer[17]*2);
name[msg.Buffer[17]*2+1]=0x00;
name[msg.Buffer[17]*2+2]=0x00;
smprintf(s, "Network name for phone : %s\n",DecodeUnicodeString(name));
}
}
}
#endif
if (Data->RequestID==ID_GetNetworkInfo) {
Data->NetworkInfo->NetworkName[0] = 0x00;
Data->NetworkInfo->NetworkName[1] = 0x00;
Data->NetworkInfo->State = 0;
switch (msg.Buffer[8]) {
case 0x01: Data->NetworkInfo->State = GSM_HomeNetwork; break;
case 0x02: Data->NetworkInfo->State = GSM_RoamingNetwork; break;
case 0x03: Data->NetworkInfo->State = GSM_RequestingNetwork; break;
case 0x04: Data->NetworkInfo->State = GSM_NoNetwork; break;
}
if (Data->NetworkInfo->State == GSM_HomeNetwork || Data->NetworkInfo->State == GSM_RoamingNetwork) {
if (msg.Buffer[18]==0x00) {
/* In 6210 name is in "normal" Unicode */
memcpy(Data->NetworkInfo->NetworkName,msg.Buffer+18,msg.Buffer[17]*2);
Data->NetworkInfo->NetworkName[msg.Buffer[17]*2] = 0x00;
Data->NetworkInfo->NetworkName[msg.Buffer[17]*2+1] = 0x00;
} else {
/* In 9210 first 0x00 is cut from Unicode string */
Data->NetworkInfo->NetworkName[0] = 0;
memcpy(Data->NetworkInfo->NetworkName+1,msg.Buffer+18,msg.Buffer[17]*2);
Data->NetworkInfo->NetworkName[msg.Buffer[17]*2+1]=0x00;
Data->NetworkInfo->NetworkName[msg.Buffer[17]*2+2]=0x00;
}
NOKIA_DecodeNetworkCode(msg.Buffer+14,Data->NetworkInfo->NetworkCode);
sprintf(Data->NetworkInfo->CID, "%02x%02x", msg.Buffer[10], msg.Buffer[11]);
sprintf(Data->NetworkInfo->LAC, "%02x%02x", msg.Buffer[12], msg.Buffer[13]);
}
}
/* 6210/6250/7110 */
if (Data->RequestID==ID_GetBitmap) {
if (msg.Buffer[4]==0x02) {
smprintf(s, "Operator logo available\n");
count = 7;
/* skip network info */
count += msg.Buffer[count];
count ++;
Data->Bitmap->BitmapWidth = msg.Buffer[count++];
Data->Bitmap->BitmapHeight = msg.Buffer[count++];
count+=4;
PHONE_DecodeBitmap(GSM_Nokia7110OperatorLogo,msg.Buffer+count,Data->Bitmap);
NOKIA_DecodeNetworkCode(msg.Buffer+14,Data->Bitmap->NetworkCode);
} else {
Data->Bitmap->BitmapWidth = 78;
Data->Bitmap->BitmapHeight = 21;
GSM_ClearBitmap(Data->Bitmap);
strcpy(Data->Bitmap->NetworkCode,"000 00");
}
}
return ERR_NONE;
}
GSM_Error DCT3_GetNetworkInfo(GSM_StateMachine *s, GSM_NetworkInfo *netinfo)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x70};
s->Phone.Data.NetworkInfo=netinfo;
smprintf(s, "Getting network info\n");
return GSM_WaitFor (s, req, 4, 0x0a, 4, ID_GetNetworkInfo);
}
GSM_Error DCT3_ReplyDialCommand(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Answer for call commands\n");
return ERR_NONE;
}
GSM_Error DCT3_DialVoice(GSM_StateMachine *s, char *number, GSM_CallShowNumber ShowNumber)
{
unsigned int i = 0;
GSM_Error error;
unsigned char req[100] = {0x00, 0x01, 0x7c,
0x01}; /* call command */
if (ShowNumber != GSM_CALL_DefaultNumberPresence) return ERR_NOTSUPPORTED;
error=DCT3_EnableSecurity (s, 0x01);
if (error!=ERR_NONE) return error;
for (i=0; i < strlen(number); i++) req[4+i]=number[i];
req[4+i+1]=0;
smprintf(s, "Making voice call\n");
return GSM_WaitFor (s, req, 4+strlen(number)+1, 0x40, 4, ID_DialVoice);
}
static GSM_Error DCT3_CancelAllCalls(GSM_StateMachine *s)
{
GSM_Error error;
unsigned char req[] = {0x00, 0x01, 0x7c,
0x03}; /* call command */
error=DCT3_EnableSecurity (s, 0x01);
if (error!=ERR_NONE) return error;
smprintf(s, "Canceling calls\n");
return GSM_WaitFor (s, req, 4, 0x40, 4, ID_CancelCall);
}
GSM_Error DCT3_CancelCall(GSM_StateMachine *s, int ID, bool all)
{
if (!all) return DCT3DCT4_CancelCall(s,ID);
return DCT3_CancelAllCalls(s);
}
GSM_Error DCT3_AnswerAllCalls(GSM_StateMachine *s)
{
GSM_Error error;
unsigned char req[] = {0x00, 0x01, 0x7c,
0x02}; /* call command */
error=DCT3_EnableSecurity (s, 0x01);
if (error!=ERR_NONE) return error;
smprintf(s, "Answering calls\n");
return GSM_WaitFor (s, req, 4, 0x40, 4, ID_AnswerCall);
}
GSM_Error DCT3_Reset(GSM_StateMachine *s, bool hard)
{
GSM_Error error;
if (hard) {
error=DCT3_EnableSecurity(s, 0x04);
} else {
error=DCT3_EnableSecurity(s, 0x03);
}
if (error == ERR_NONE) {
s->Phone.Data.EnableIncomingSMS = false;
s->Phone.Data.EnableIncomingCB = false;
}
return error;
}
GSM_Error DCT3_ReplyGetWAPBookmark(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
return DCT3DCT4_ReplyGetWAPBookmark (msg,s,false);
}
GSM_Error DCT3_SetWAPBookmark(GSM_StateMachine *s, GSM_WAPBookmark *bookmark)
{
GSM_Error error;
int count = 4, location;
unsigned char req[600] = {N6110_FRAME_HEADER, 0x09};
/* We have to enable WAP frames in phone */
error=DCT3DCT4_EnableWAPFunctions(s);
if (error!=ERR_NONE) return error;
location = bookmark->Location - 1;
if (bookmark->Location == 0) location = 0xffff;
req[count++] = (location & 0xff00) >> 8;
req[count++] = location & 0x00ff;
count += NOKIA_SetUnicodeString(s, req+count, bookmark->Title, false);
count += NOKIA_SetUnicodeString(s, req+count, bookmark->Address, false);
/* unknown */
req[count++] = 0x01; req[count++] = 0x80; req[count++] = 0x00;
req[count++] = 0x00; req[count++] = 0x00; req[count++] = 0x00;
req[count++] = 0x00; req[count++] = 0x00; req[count++] = 0x00;
smprintf(s, "Setting WAP bookmark\n");
error = GSM_WaitFor (s, req, count, 0x3f, 4, ID_SetWAPBookmark);
if (error != ERR_NONE) {
if (error == ERR_INSIDEPHONEMENU || error == ERR_EMPTY || error == ERR_FULL) {
DCT3DCT4_DisableConnectionFunctions(s);
}
return error;
}
@@ -1019,389 +1023,389 @@ GSM_Error DCT3_SetWAPSettings(GSM_StateMachine *s, GSM_MultiWAPSettings *setting
if (settings->Settings[i].Bearer == WAPSETTINGS_BEARER_USSD) {
if (phone3 != -1) loc3=i;
}
}
pos = 5;
memset(SetReq + pos, 0, 200 - pos);
SetReq[4] = settings->Location - 1;
if (loc1 != -1) {
/* Name */
pos += NOKIA_SetUnicodeString(s, SetReq + pos, settings->Settings[loc1].Title, false);
/* HomePage */
pos += NOKIA_SetUnicodeString(s, SetReq + pos, settings->Settings[loc1].HomePage, false);
if (settings->Settings[loc1].IsContinuous) SetReq[pos] = 0x01;
pos++;
SetReq[pos++] = ID;
SetReq[pos] = phone1; /* bearer */
switch (settings->ActiveBearer) {
case WAPSETTINGS_BEARER_DATA:
if (loc1 != -1) SetReq[pos] = phone1;
break;
case WAPSETTINGS_BEARER_SMS:
if (loc2 != -1) SetReq[pos] = phone2;
break;
case WAPSETTINGS_BEARER_USSD:
if (loc3 != -1) SetReq[pos] = phone3;
break;
default: break;
}
pos++;
if (settings->Settings[loc1].IsSecurity) SetReq[pos] = 0x01;
pos++;
} else if (loc2 != -1) {
/* Name */
pos += NOKIA_SetUnicodeString(s, SetReq + pos, settings->Settings[loc2].Title, false);
/* HomePage */
pos += NOKIA_SetUnicodeString(s, SetReq + pos, settings->Settings[loc2].HomePage, false);
if (settings->Settings[loc2].IsContinuous) SetReq[pos] = 0x01;
pos++;
SetReq[pos++] = ID;
SetReq[pos] = phone2; /* bearer */
switch (settings->ActiveBearer) {
case WAPSETTINGS_BEARER_DATA:
if (loc1 != -1) SetReq[pos] = phone1;
break;
case WAPSETTINGS_BEARER_SMS:
if (loc2 != -1) SetReq[pos] = phone2;
break;
case WAPSETTINGS_BEARER_USSD:
if (loc3 != -1) SetReq[pos] = phone3;
break;
default: break;
}
pos++;
if (settings->Settings[loc2].IsSecurity) SetReq[pos] = 0x01;
pos++;
} else if (loc3 != -1) {
/* Name */
pos += NOKIA_SetUnicodeString(s, SetReq + pos, settings->Settings[loc3].Title, false);
/* HomePage */
pos += NOKIA_SetUnicodeString(s, SetReq + pos, settings->Settings[loc3].HomePage, false);
if (settings->Settings[loc3].IsContinuous) SetReq[pos] = 0x01;
pos++;
SetReq[pos++] = ID;
SetReq[pos] = phone3; /* bearer */
switch (settings->ActiveBearer) {
case WAPSETTINGS_BEARER_DATA:
if (loc1 != -1) SetReq[pos] = phone1;
break;
case WAPSETTINGS_BEARER_SMS:
if (loc2 != -1) SetReq[pos] = phone2;
break;
case WAPSETTINGS_BEARER_USSD:
if (loc3 != -1) SetReq[pos] = phone3;
break;
default: break;
}
pos++;
if (settings->Settings[loc3].IsSecurity) SetReq[pos] = 0x01;
pos++;
} else {
return ERR_UNKNOWN; /* We have to have write something known */
}
memcpy(SetReq + pos, "\x01\x80\x00\x00\x00\x00\x00\x00\x00", 9);
pos += 9;
smprintf(s, "Writing WAP settings part 1\n");
error=GSM_WaitFor (s, SetReq, pos, 0x3f, 4, ID_SetConnectSet);
if (error != ERR_NONE) return error;
/* Data */
if (phone1 != -1) {
pos = 4;
memset(SetReq2 + pos, 0, 200 - pos);
SetReq2[pos++] = phone1;
SetReq2[pos++] = 0x02;
SetReq2[pos++] = 0x01; /* GSMdata */
if (loc1 != -1) {
if (!settings->Settings[loc1].IsNormalAuthentication) SetReq2[pos] = 0x01;
}
pos++;
if (loc1 != -1) {
if (settings->Settings[loc1].IsISDNCall) SetReq2[pos] = 0x01;
}
pos++;
if (loc1 != -1) {
switch (settings->Settings[loc1].Speed) {
case WAPSETTINGS_SPEED_9600 : SetReq2[pos++] = 0x01; break;
case WAPSETTINGS_SPEED_14400 : SetReq2[pos++] = 0x02; break;
default : SetReq2[pos++] = 0x02; break;
}
switch (settings->Settings[loc1].Speed) {
case WAPSETTINGS_SPEED_9600 : SetReq2[pos++] = 0x01; break;
case WAPSETTINGS_SPEED_14400 : SetReq2[pos++] = 0x02; break;
default : SetReq2[pos++] = 0x02; break;
}
} else pos+=2;
if (loc1 != -1) {
/* IP */
pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc1].IPAddress, false);
/* Number */
pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc1].DialUp, false);
/* Username */
pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc1].User, false);
/* Password */
pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc1].Password, false);
} else pos+=5;
memcpy(SetReq2 + pos, "\x80\x00\x00\x00\x00\x00\x00\x00", 8);
pos += 8;
smprintf(s, "Writing WAP settings part 2 (Data bearer)\n");
error=GSM_WaitFor (s, SetReq2, pos, 0x3f, 4, ID_SetConnectSet);
if (error != ERR_NONE) return error;
}
/* SMS */
if (phone2 != -1) {
pos = 4;
memset(SetReq2 + pos, 0, 200 - pos);
SetReq2[pos++] = phone2;
SetReq2[pos++] = 0x02;
SetReq2[pos++] = 0x00; /* SMS */
if (loc2 != -1) {
/* Service number */
pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc2].Service, false);
/* Server number */
pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc2].Server, false);
} else pos += 2;
memcpy(SetReq2 + pos, "\x80\x00\x00\x00\x00\x00\x00\x00", 8);
pos += 8;
smprintf(s, "Writing WAP settings part 2 (SMS bearer)\n");
error=GSM_WaitFor (s, SetReq2, pos, 0x3f, 4, ID_SetConnectSet);
if (error != ERR_NONE) return error;
}
/* USSD */
if (phone3 != -1) {
pos = 4;
memset(SetReq2 + pos, 0, 200 - pos);
SetReq2[pos++] = phone3;
SetReq2[pos++] = 0x02;
SetReq2[pos++] = 0x02; /* USSD */
if (loc3 != -1) {
if (!settings->Settings[loc3].IsIP) SetReq2[pos] = 0x01;
}
pos++;
if (loc3 != -1) {
/* Service number or IP address */
pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc3].Service, false);
/* Code number */
pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc3].Code, false);
} else pos+=2;
memcpy(SetReq2 + pos, "\x80\x00\x00\x00\x00\x00\x00\x00", 8);
pos += 8;
smprintf(s, "Writing WAP settings part 2 (USSD bearer)\n");
error=GSM_WaitFor (s, SetReq2, pos, 0x3f, 4, ID_SetConnectSet);
if (error != ERR_NONE) return error;
}
error = DCT3DCT4_SetActiveConnectSet(s, settings);
if (error != ERR_NONE) return error;
return DCT3DCT4_DisableConnectionFunctions(s);
}
GSM_Error DCT3_ReplySendSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[3]) {
case 0x02:
smprintf(s, "SMS sent OK\n");
- if (s->User.SendSMSStatus!=NULL) s->User.SendSMSStatus(s->CurrentConfig->Device,0,0);
+ if (s->User.SendSMSStatus!=NULL) s->User.SendSMSStatus(s->CurrentConfig->Device,0,msg.Buffer[5]);
return ERR_NONE;
case 0x03:
smprintf(s, "Error %i\n",msg.Buffer[6]);
- if (s->User.SendSMSStatus!=NULL) s->User.SendSMSStatus(s->CurrentConfig->Device,msg.Buffer[6],0);
+ if (s->User.SendSMSStatus!=NULL) s->User.SendSMSStatus(s->CurrentConfig->Device,msg.Buffer[6],-1);
return ERR_NONE;
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error DCT3_SendSMSMessage(GSM_StateMachine *s, GSM_SMSMessage *sms)
{
int length;
GSM_Error error;
unsigned char req[256] = {N6110_FRAME_HEADER, 0x01, 0x02, 0x00};
error=PHONE_EncodeSMSFrame(s,sms,req+6,PHONE_SMSSubmit,&length, true);
if (error != ERR_NONE) return error;
smprintf(s, "Sending sms\n");
return s->Protocol.Functions->WriteMessage(s, req, 6+length, 0x02);
}
GSM_Error DCT3_ReplyNetmonitor(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[3]) {
case 0x00:
smprintf(s, "Netmonitor correctly set\n");
break;
default:
smprintf(s, "Menu %i\n",msg.Buffer[3]);
smprintf(s, "%s\n",msg.Buffer+4);
strcpy(s->Phone.Data.Netmonitor,msg.Buffer+4);
break;
}
return ERR_NONE;
}
GSM_Error DCT3_Netmonitor(GSM_StateMachine *s, int testnumber, char *value)
{
GSM_Error error;
unsigned char req[] = {0x00, 0x01, 0x7e,
0x00}; /* Test number */
value[0] = 0;
error=DCT3_EnableSecurity (s, 0x01);
if (error != ERR_NONE) return error;
req[3] = testnumber;
smprintf(s, "Getting netmonitor test\n");
s->Phone.Data.Netmonitor = value;
return GSM_WaitFor (s, req, 4, 0x40, 4, ID_Netmonitor);
}
GSM_Error DCT3_GetManufactureMonth(GSM_StateMachine *s, char *value)
{
GSM_Error error;
error=DCT3_EnableSecurity (s, 0x01);
if (error != ERR_NONE) return error;
return NOKIA_GetPhoneString(s,"\x00\x01\xCC\x02",4,0x40,value,ID_GetManufactureMonth,5);
}
GSM_Error DCT3_GetProductCode(GSM_StateMachine *s, char *value)
{
GSM_Error error;
if (strlen(s->Phone.Data.ProductCodeCache)!=0) {
strcpy(value,s->Phone.Data.ProductCodeCache);
return ERR_NONE;
}
error=DCT3_EnableSecurity (s, 0x01);
if (error != ERR_NONE) return error;
return NOKIA_GetPhoneString(s,"\x00\x01\xCA\x01",4,0x40,value,ID_GetProductCode,5);
}
GSM_Error DCT3_GetOriginalIMEI(GSM_StateMachine *s, char *value)
{
GSM_Error error;
error=DCT3_EnableSecurity (s, 0x01);
if (error != ERR_NONE) return error;
return NOKIA_GetPhoneString(s,"\x00\x01\xCC\x01",4,0x40,value,ID_GetOriginalIMEI,5);
}
GSM_Error DCT3_GetHardware(GSM_StateMachine *s, char *value)
{
GSM_Error error;
if (strlen(s->Phone.Data.HardwareCache)!=0) {
strcpy(value,s->Phone.Data.HardwareCache);
return ERR_NONE;
}
error=DCT3_EnableSecurity (s, 0x01);
if (error != ERR_NONE) return error;
return NOKIA_GetPhoneString(s,"\x00\x01\xC8\x05",4,0x40,value,ID_GetHardware,5);
}
GSM_Error DCT3_GetPPM(GSM_StateMachine *s, char *value)
{
GSM_Error error;
error=DCT3_EnableSecurity (s, 0x01);
if (error != ERR_NONE) return error;
return NOKIA_GetPhoneString(s,"\x00\x01\xC8\x12",4,0x40,value,ID_GetPPM,5);
}
GSM_Error DCT3_GetSMSStatus(GSM_StateMachine *s, GSM_SMSMemoryStatus *status)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x36, 0x64};
s->Phone.Data.SMSStatus=status;
smprintf(s, "Getting SMS status\n");
return GSM_WaitFor (s, req, 5, 0x14, 2, ID_GetSMSStatus);
/* 6210 family doesn't show in frame with SMS status info
* about Templates. We get separately info about this SMS folder.
*/
}
GSM_Error DCT3_ReplyDeleteSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch(msg.Buffer[3]) {
case 0x0b:
smprintf(s, "SMS deleted\n");
return ERR_NONE;
case 0x0c:
smprintf(s, "Error deleting SMS\n");
switch (msg.Buffer[4]) {
case 0x00:
/* Not tested on 6210 */
smprintf(s, "Unknown meaning, SMS seems to be deleted\n");
return ERR_NONE;
case 0x02:
/* Not tested on 6210 */
smprintf(s, "Invalid location\n");
return ERR_INVALIDLOCATION;
case 0x06:
/* Not tested on 6210 */
smprintf(s, "Phone is OFF\n");
return ERR_PHONEOFF;
default:
smprintf(s, "Unknown error: %02x\n",msg.Buffer[4]);
return ERR_UNKNOWNRESPONSE;
}
}
return ERR_UNKNOWNRESPONSE;
}
GSM_Error N71_92_ReplyGetSignalQuality(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Network level received: %i\n",msg.Buffer[4]);
Data->SignalQuality->SignalStrength = -1;
Data->SignalQuality->SignalPercent = ((int)msg.Buffer[4]);
Data->SignalQuality->BitErrorRate = -1;
return ERR_NONE;
}
GSM_Error N71_92_GetSignalQuality(GSM_StateMachine *s, GSM_SignalQuality *sig)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x81};
s->Phone.Data.SignalQuality = sig;
smprintf(s, "Getting network level\n");
return GSM_WaitFor (s, req, 4, 0x0a, 4, ID_GetSignalQuality);
}
GSM_Error N71_92_ReplyGetBatteryCharge(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Battery level received: %i\n",msg.Buffer[5]);
Data->BatteryCharge->BatteryPercent = ((int)msg.Buffer[5]);
Data->BatteryCharge->ChargeState = 0;
return ERR_NONE;
}
GSM_Error N71_92_GetBatteryCharge(GSM_StateMachine *s, GSM_BatteryCharge *bat)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x02};
s->Phone.Data.BatteryCharge = bat;
smprintf(s, "Getting battery level\n");
return GSM_WaitFor (s, req, 4, 0x17, 4, ID_GetBatteryCharge);
}
GSM_Error N71_92_ReplyPhoneSetting(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Bitmap_Types BmpType;
GSM_Phone_Data *Data = &s->Phone.Data;
diff --git a/gammu/emb/common/phone/nokia/dct3/dct3func.h b/gammu/emb/common/phone/nokia/dct3/dct3func.h
index 66b67ec..18b2026 100644
--- a/gammu/emb/common/phone/nokia/dct3/dct3func.h
+++ b/gammu/emb/common/phone/nokia/dct3/dct3func.h
@@ -1,78 +1,80 @@
/* (c) 2002-2003 by Marcin Wiacek */
#ifndef phone_nokia_dct3_h
#define phone_nokia_dct3_h
+#include "../ncommon.h"
+
GSM_Error DCT3_ReplyPressKey (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplyPlayTone (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplyEnableSecurity (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplyGetIMEI (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplyGetSMSC (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplySIMLogin (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplySIMLogout (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplyGetDateTime (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplyGetAlarm (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplySetDateTime (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplySetAlarm (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplyDialCommand (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplyGetWAPBookmark (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplyGetNetworkInfo (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplySendSMSMessage (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplySetSMSC (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplyGetWAPSettings (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplySetWAPSettings (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplyNetmonitor (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplyDeleteSMSMessage (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error N71_92_ReplyGetSignalQuality (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error N71_92_ReplyGetBatteryCharge (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error N71_92_ReplyPhoneSetting (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error N61_71_ReplyResetPhoneSettings(GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error N61_91_ReplySetOpLogo (GSM_Protocol_Message msg, GSM_StateMachine *s);
#ifdef GSM_ENABLE_CELLBROADCAST
GSM_Error DCT3_ReplySetIncomingCB (GSM_Protocol_Message msg, GSM_StateMachine *s);
GSM_Error DCT3_ReplyIncomingCB (GSM_Protocol_Message msg, GSM_StateMachine *s);
#endif
GSM_Error DCT3_DeleteWAPBookmark (GSM_StateMachine *s, GSM_WAPBookmark *bookmark);
GSM_Error DCT3_GetWAPBookmark (GSM_StateMachine *s, GSM_WAPBookmark *bookmark);
GSM_Error DCT3_PressKey (GSM_StateMachine *s, GSM_KeyCode Key, bool Press);
GSM_Error DCT3_PlayTone (GSM_StateMachine *s, int Herz, unsigned char Volume, bool start);
GSM_Error DCT3_EnableSecurity (GSM_StateMachine *s, unsigned char status );
GSM_Error DCT3_GetIMEI (GSM_StateMachine *s);
GSM_Error DCT3_GetSMSC (GSM_StateMachine *s, GSM_SMSC *smsc );
GSM_Error DCT3_GetNetworkInfo (GSM_StateMachine *s, GSM_NetworkInfo *netinfo );
GSM_Error DCT3_DialVoice (GSM_StateMachine *s, char *number, GSM_CallShowNumber ShowNumber);
GSM_Error DCT3_Reset (GSM_StateMachine *s, bool hard );
GSM_Error DCT3_CancelCall (GSM_StateMachine *s, int ID, bool all);
GSM_Error DCT3_AnswerAllCalls (GSM_StateMachine *s);
GSM_Error DCT3_SendSMSMessage (GSM_StateMachine *s, GSM_SMSMessage *sms );
GSM_Error DCT3_GetAlarm (GSM_StateMachine *s, GSM_Alarm *alarm, unsigned char msgtype);
GSM_Error DCT3_GetDateTime (GSM_StateMachine *s, GSM_DateTime *date_time, unsigned char msgtype );
GSM_Error DCT3_SetAlarm (GSM_StateMachine *s, GSM_Alarm *alarm, unsigned char msgtype);
GSM_Error DCT3_SetDateTime (GSM_StateMachine *s, GSM_DateTime *date_time, unsigned char msgtype );
GSM_Error DCT3_SetIncomingCB (GSM_StateMachine *s, bool enable );
GSM_Error DCT3_GetSMSStatus (GSM_StateMachine *s, GSM_SMSMemoryStatus *status );
GSM_Error DCT3_SetSMSC (GSM_StateMachine *s, GSM_SMSC *smsc );
GSM_Error DCT3_GetWAPSettings (GSM_StateMachine *s, GSM_MultiWAPSettings *settings );
GSM_Error DCT3_SetWAPSettings (GSM_StateMachine *s, GSM_MultiWAPSettings *settings);
GSM_Error DCT3_SetWAPBookmark (GSM_StateMachine *s, GSM_WAPBookmark *bookmark);
GSM_Error DCT3_Netmonitor (GSM_StateMachine *s, int testnumber, char *value );
GSM_Error DCT3_GetManufactureMonth (GSM_StateMachine *s, char *value );
GSM_Error DCT3_GetProductCode (GSM_StateMachine *s, char *value);
GSM_Error DCT3_GetOriginalIMEI (GSM_StateMachine *s, char *value);
GSM_Error DCT3_GetHardware (GSM_StateMachine *s, char *value);
GSM_Error DCT3_GetPPM (GSM_StateMachine *s, char *value);
GSM_Error N61_71_ResetPhoneSettings (GSM_StateMachine *s, GSM_ResetSettingsType Type);
GSM_Error N71_92_GetBatteryCharge (GSM_StateMachine *s, GSM_BatteryCharge *bat);
GSM_Error N71_92_GetSignalQuality (GSM_StateMachine *s, GSM_SignalQuality *sig);
GSM_Error N71_92_GetPhoneSetting (GSM_StateMachine *s, int Request, int Setting);
GSM_Error N71_92_GetDateTime (GSM_StateMachine *s, GSM_DateTime *date_time );
GSM_Error N71_92_SetDateTime (GSM_StateMachine *s, GSM_DateTime *date_time );
GSM_Error DCT3_DecodeSMSFrame (GSM_StateMachine *s, GSM_SMSMessage *SMS, unsigned char *buffer);
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/nokia/dct3/n6110.c b/gammu/emb/common/phone/nokia/dct3/n6110.c
index 263d12b..dac6c12 100644
--- a/gammu/emb/common/phone/nokia/dct3/n6110.c
+++ b/gammu/emb/common/phone/nokia/dct3/n6110.c
@@ -1,321 +1,324 @@
/* (c) 2001-2004 by Marcin Wiacek */
-/* based on some work from Markus Plail and Gnokii */
-/* Authentication function (c) 1999 or earlier by Pavel Janik */
/* 5210 calendar IDs by Frederick Ros */
+/* based on some Markus Plail, Pavel Janik & others work from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
#include "../../../gsmstate.h"
#ifdef GSM_ENABLE_NOKIA6110
#include <string.h>
#include "../../../../cfg/config.h"
#include "../../../misc/coding/coding.h"
#include "../../../service/sms/gsmsms.h"
#include "../../../gsmcomon.h"
#include "../../pfunc.h"
#include "../nfunc.h"
#include "n6110.h"
#include "dct3func.h"
static unsigned char N6110_MEMORY_TYPES[] = {
MEM_ME, 0x02,
MEM_SM, 0x03,
MEM_ON, 0x05,
MEM_DC, 0x07,
MEM_RC, 0x08,
MEM_MC, 0x09,
MEM_VM, 0x0b,
0x00, 0x00
};
static GSM_Error N6110_ReplyGetPhoneLanguage(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
N6110_Language lang = N6110_Auto;
if (msg.Buffer[3] == 0x15) return ERR_NONE;
smprintf(s, "Phone language is %02x\n",msg.Buffer[6]);
switch (msg.Buffer[6]) {
case 0x21: lang = N6110_Europe; break; //Polish
}
s->Phone.Data.Priv.N6110.PhoneLanguage = lang;
return ERR_NONE;
}
static GSM_Error N6110_GetPhoneLanguage(GSM_StateMachine *s)
{
unsigned char feat_req[] = {N6110_FRAME_HEADER, 0x13, 0x01,
0x00, /* Profile location */
0x00}; /* Feature number */
s->Phone.Data.Priv.N6110.PhoneLanguage = N6110_Auto;
feat_req[5] = 0;
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES33)) {
feat_req[6] = 0x1E;
} else {
feat_req[6] = 0x21;
}
smprintf(s, "Getting profile feature\n");
return GSM_WaitFor (s, feat_req, 7, 0x05, 4, ID_GetLanguage);
}
struct N6110_Lang_Char {
N6110_Language Lang;
unsigned char Phone;
unsigned char Unicode1;
unsigned char Unicode2;
};
static struct N6110_Lang_Char N6110_Lang_Table[] = {
{N6110_Europe,0x13,0x01,0x04},//Latin capital letter a with ogonek
{N6110_Europe,0x14,0x01,0x05},//Latin small letter a with ogonek
{N6110_Europe,0x15,0x01,0x06},//Latin capital letter c with acute
{N6110_Europe,0x17,0x01,0x07},//Latin small letter c with acute
{N6110_Europe,0x1D,0x01,0x18},//Latin capital letter e with ogonek
{N6110_Europe,0x1E,0x01,0x19},//Latin small letter e with ogonek
{N6110_Europe,0x83,0x00,0xD3},//Latin capital letter o with acute
{N6110_Europe,0x8E,0x01,0x41},//Latin capital letter l with stroke
{N6110_Europe,0x90,0x01,0x42},//Latin small letter l with stroke
{N6110_Europe,0x92,0x01,0x43},//Latin capital letter n with acute
{N6110_Europe,0x93,0x01,0x44},//Latin small letter n with acute
{N6110_Europe,0x9A,0x00,0xF3},//Latin small letter o with acute
{N6110_Europe,0xB2,0x20,0xAC},//euro
{N6110_Europe,0xB5,0x01,0x5A},//Latin capital letter s with acute
{N6110_Europe,0xB6,0x01,0x5B},//Latin small letter s with acute
{N6110_Europe,0xE7,0x01,0x79},//Latin capital letter z with acute
{N6110_Europe,0xEE,0x01,0x7A},//Latin small letter z with acute
{N6110_Europe,0xF4,0x01,0x7C},//Latin small letter z with dot above
{N6110_Europe,0xF0,0x01,0x7B},//Latin capital letter z with dot above
{0,0,0,0}
};
static void N6110_EncodeUnicode(GSM_StateMachine *s, unsigned char *dest, const unsigned char *src, int len)
{
int i_len = 0, o_len, i;
wchar_t wc;
GSM_Phone_N6110Data *Priv = &s->Phone.Data.Priv.N6110;
bool found;
for (o_len = 0; i_len < len; o_len++) {
found = false;
if (Priv->PhoneLanguage != N6110_Auto) {
i = 0;
while(1) {
if (N6110_Lang_Table[i].Lang == 0) break;
if (N6110_Lang_Table[i].Lang == Priv->PhoneLanguage &&
N6110_Lang_Table[i].Phone == src[i_len]) {
dest[o_len*2] = N6110_Lang_Table[i].Unicode1;
dest[(o_len*2)+1] = N6110_Lang_Table[i].Unicode2;
i_len++;
found = true;
break;
}
i++;
}
}
if (!found) {
i_len += EncodeWithUnicodeAlphabet(&src[i_len], &wc);
dest[o_len*2] = (wc >> 8) & 0xff;
dest[(o_len*2)+1] = wc & 0xff;
}
}
dest[o_len*2] = 0;
dest[(o_len*2)+1] = 0;
}
#ifndef ENABLE_LGPL
+/* Pavel Janik */
/* This function provides Nokia authentication protocol.
* Nokia authentication protocol is used in the communication between Nokia
* mobile phones (e.g. Nokia 6110) and Nokia Cellular Data Suite software,
* commercially sold by Nokia Corp.
* The authentication scheme is based on the token send by the phone to the
* software. The software does it's magic (see the function
* N6110_GetNokiaAuthentication) and returns the result back to the phone.
* If the result is correct the phone responds with the message "Accessory
* connected!" displayed on the LCD. Otherwise it will display "Accessory not
* supported" and some functions will not be available for use (?).
* The specification of the protocol is not publicly available, no comment.
*/
static void N6110_GetNokiaAuthentication(unsigned char *Imei, unsigned char *MagicBytes, unsigned char *MagicResponse)
{
int i, j, CRC=0;
unsigned char Temp[16]; /* This is our temporary working area. */
/* Here we put FAC (Final Assembly Code) and serial number into our area. */
Temp[0] = Imei[6]; Temp[1] = Imei[7];
Temp[2] = Imei[8]; Temp[3] = Imei[9];
Temp[4] = Imei[10]; Temp[5] = Imei[11];
Temp[6] = Imei[12]; Temp[7] = Imei[13];
/* And now the TAC (Type Approval Code). */
Temp[8] = Imei[2]; Temp[9] = Imei[3];
Temp[10] = Imei[4]; Temp[11] = Imei[5];
/* And now we pack magic bytes from the phone. */
Temp[12] = MagicBytes[0]; Temp[13] = MagicBytes[1];
Temp[14] = MagicBytes[2]; Temp[15] = MagicBytes[3];
for (i=0; i<=11; i++) if (Temp[i + 1]& 1) Temp[i]<<=1;
switch (Temp[15] & 0x03) {
case 1:
case 2: j = Temp[13] & 0x07;
for (i=0; i<=3; i++) Temp[i+j] ^= Temp[i+12];
break;
default: j = Temp[14] & 0x07;
for (i=0; i<=3; i++) Temp[i + j] |= Temp[i + 12];
}
for (i=0; i<=15; i++) CRC ^= Temp[i];
for (i=0; i<=15; i++) {
switch (Temp[15 - i] & 0x06) {
case 0: j = Temp[i] | CRC; break;
case 2:
case 4: j = Temp[i] ^ CRC; break;
case 6: j = Temp[i] & CRC; break;
}
if (j == CRC) j = 0x2c;
if (Temp[i] == 0) j = 0;
MagicResponse[i] = j;
}
}
static GSM_Error N6110_ReplyGetMagicBytes(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_N6110Data *Priv = &s->Phone.Data.Priv.N6110;
GSM_Phone_Data *Data = &s->Phone.Data;
sprintf(Data->IMEI, "%s", msg.Buffer+9);
sprintf(Data->HardwareCache, "%s", msg.Buffer+39);
sprintf(Data->ProductCodeCache, "%s", msg.Buffer+31);
smprintf(s, "Message: Mobile phone identification received:\n");
smprintf(s, "IMEI : %s\n", msg.Buffer+9);
smprintf(s, "Model : %s\n", msg.Buffer+25);
smprintf(s, "Production Code : %s\n", msg.Buffer+31);
smprintf(s, "HW : %s\n", msg.Buffer+39);
smprintf(s, "Firmware : %s\n", msg.Buffer+44);
/* These bytes are probably the source of the "Accessory not connected"
* messages on the phone when trying to emulate NCDS... I hope....
* UPDATE: of course, now we have the authentication algorithm.
*/
smprintf(s, " Magic bytes : %02x %02x %02x %02x\n", msg.Buffer[50], msg.Buffer[51], msg.Buffer[52], msg.Buffer[53]);
Priv->MagicBytes[0]=msg.Buffer[50];
Priv->MagicBytes[1]=msg.Buffer[51];
Priv->MagicBytes[2]=msg.Buffer[52];
Priv->MagicBytes[3]=msg.Buffer[53];
return ERR_NONE;
}
static GSM_Error N6110_MakeAuthentication(GSM_StateMachine *s)
{
GSM_Phone_N6110Data *Priv = &s->Phone.Data.Priv.N6110;
GSM_Error error;
unsigned char connect4[] = {N6110_FRAME_HEADER, 0x10};
unsigned char magic_connect[] = {
N6110_FRAME_HEADER, 0x12,
/* The real magic goes here ... These bytes are filled in
* with the function N6110_GetNokiaAuthentication. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* NOKIA&GNOKII Accessory */
'N', 'O', 'K', 'I', 'A', '&', 'N', 'O', 'K', 'I', 'A',
'a', 'c', 'c', 'e', 's', 's', 'o', 'r', 'y',
0x00, 0x00, 0x00, 0x00};
smprintf(s, "Getting magic bytes for authentication\n");
error=GSM_WaitFor (s, connect4, 4, 0x64, 4, ID_MakeAuthentication);
if (error!=ERR_NONE) return error;
N6110_GetNokiaAuthentication(s->Phone.Data.IMEI, Priv->MagicBytes, magic_connect+4);
smprintf(s, "Sending authentication bytes\n");
return s->Protocol.Functions->WriteMessage(s, magic_connect, 45, 0x64);
}
#endif
static GSM_Error N6110_ShowStartInfo(GSM_StateMachine *s, bool enable)
{
#ifdef ENABLE_LGPL
return ERR_NONE;
#else
GSM_Error error=ERR_NONE;
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_MAGICBYTES)) {
if (s->ConnectionType == GCT_FBUS2 ||
s->ConnectionType == GCT_FBUS2IRDA) {
error=N6110_MakeAuthentication(s);
}
}
return error;
#endif
}
static GSM_Error N6110_Initialise (GSM_StateMachine *s)
{
#ifdef DEBUG
DCT3_SetIncomingCB(s,true);
#endif
N6110_GetPhoneLanguage(s);
return ERR_NONE;
}
static GSM_Error N6110_GetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
{
return DCT3_GetDateTime(s, date_time, 0x11);
}
static GSM_Error N6110_GetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
{
return DCT3_GetAlarm(s, alarm, 0x11);
}
static GSM_Error N6110_SetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
{
return DCT3_SetDateTime(s, date_time, 0x11);
}
static GSM_Error N6110_SetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
{
return DCT3_SetAlarm(s, alarm, 0x11);
}
static GSM_Error N6110_ReplyGetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int count;
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Phonebook entry received\n");
switch (msg.Buffer[3]) {
case 0x02:
Data->Memory->EntriesNum = 0;
count=5;
/* If name is not empty */
if (msg.Buffer[count]!=0x00) {
if (msg.Buffer[count]>GSM_PHONEBOOK_TEXT_LENGTH) {
smprintf(s, "Too long text\n");
return ERR_UNKNOWNRESPONSE;
}
Data->Memory->Entries[Data->Memory->EntriesNum].EntryType=PBK_Text_Name;
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOPBKUNICODE)) {
if (Data->Memory->MemoryType==MEM_DC ||
Data->Memory->MemoryType==MEM_RC ||
Data->Memory->MemoryType==MEM_MC ||
Data->Memory->MemoryType==MEM_ME) {
N6110_EncodeUnicode(s,Data->Memory->Entries[Data->Memory->EntriesNum].Text,
msg.Buffer+count+1,msg.Buffer[count]);
} else {
EncodeUnicode(Data->Memory->Entries[Data->Memory->EntriesNum].Text,
msg.Buffer+count+1,msg.Buffer[count]);
}
} else {
memcpy(Data->Memory->Entries[Data->Memory->EntriesNum].Text,
msg.Buffer+count+1,msg.Buffer[count]);
Data->Memory->Entries[Data->Memory->EntriesNum].Text[msg.Buffer[count]]=0x00;
Data->Memory->Entries[Data->Memory->EntriesNum].Text[msg.Buffer[count]+1]=0x00;
}
smprintf(s, "Name \"%s\"\n",
@@ -635,384 +638,385 @@ static GSM_Error N6110_GetSignalQuality(GSM_StateMachine *s, GSM_SignalQuality *
if (error!=ERR_NONE) return error;
sig->SignalPercent = 100;
if (value[4]!='-') {
if (value[5]=='9' && value[6]>'4') sig->SignalPercent = 25;
if (value[5]=='9' && value[6]<'5') sig->SignalPercent = 50;
if (value[5]=='8' && value[6]>'4') sig->SignalPercent = 75;
} else sig->SignalPercent = 0;
return ERR_NONE;
} else {
s->Phone.Data.SignalQuality = sig;
return N6110_GetStatus(s, ID_GetSignalQuality);
}
}
static GSM_Error N6110_GetBatteryCharge(GSM_StateMachine *s, GSM_BatteryCharge *bat)
{
char value[100];
GSM_Error error;
smprintf(s, "Getting battery level\n");
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_POWER_BATT)) {
error = DCT3_Netmonitor(s, 23, value);
if (error!=ERR_NONE) return error;
bat->BatteryPercent = 100;
bat->ChargeState = 0;
if (value[29]=='7') bat->BatteryPercent = 75;
if (value[29]=='5') bat->BatteryPercent = 50;
if (value[29]=='2') bat->BatteryPercent = 25;
return ERR_NONE;
} else {
s->Phone.Data.BatteryCharge = bat;
return N6110_GetStatus(s, ID_GetBatteryCharge);
}
}
static GSM_Error N6110_ReplySaveSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "SMS message saving status\n");
switch (msg.Buffer[3]) {
case 0x05:
smprintf(s, "Saved at location %i\n",msg.Buffer[5]);
Data->SaveSMSMessage->Location=msg.Buffer[5];
return ERR_NONE;
case 0x06:
switch (msg.Buffer[4]) {
case 0x02:
smprintf(s, "All locations busy\n");
return ERR_FULL;
case 0x03:
smprintf(s, "Too high ?\n");
return ERR_INVALIDLOCATION;
default:
smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
}
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6110_PrivSetSMSMessage(GSM_StateMachine *s, GSM_SMSMessage *sms)
{
int length;
GSM_Error error;
unsigned char req[256] = {N6110_FRAME_HEADER, 0x04,
0x00, /* SMS status */
0x02,
0x00, /* SMS location */
0x02}; /* SMS type */
req[6] = sms->Location;
if (sms->Folder==1) { /* Inbox */
req[4] = 1; /* SMS status - GSM_Read */
req[7] = 0x00; /* SMS type */
sms->PDU = SMS_Deliver;
error=PHONE_EncodeSMSFrame(s,sms,req+8,PHONE_SMSDeliver,&length,true);
} else { /* Outbox */
req[4] = 5; /* SMS status - GSM_Sent */
req[7] = 0x02; /* SMS type */
sms->PDU = SMS_Submit;
error=PHONE_EncodeSMSFrame(s,sms,req+8,PHONE_SMSSubmit,&length,true);
}
if (error != ERR_NONE) return error;
/* SMS State - GSM_Read -> GSM_Unread and GSM_Sent -> GSM_UnSent */
if (sms->State == SMS_UnSent || sms->State == SMS_UnRead) req[4] |= 0x02;
s->Phone.Data.SaveSMSMessage=sms;
smprintf(s, "Saving sms\n");
return GSM_WaitFor (s, req, 8+length, 0x14, 4, ID_SaveSMSMessage);
}
static GSM_Error N6110_SetSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
{
if (sms->Location == 0) return ERR_INVALIDLOCATION;
return N6110_PrivSetSMSMessage(s, sms);
}
static GSM_Error N6110_AddSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
{
sms->Location = 0;
return N6110_PrivSetSMSMessage(s, sms);
}
static GSM_Error N6110_ReplySetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[3]) {
case 0x37:
smprintf(s, "Ringtone set OK\n");
return ERR_NONE;
break;
case 0x38:
smprintf(s, "Error setting ringtone\n");
switch (msg.Buffer[4]) {
case 0x7d:
smprintf(s, "Too high location ?\n");
return ERR_INVALIDLOCATION;
default:
smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
}
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6110_ReplySetBinRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[4]) {
case 0x00:
smprintf(s, "Set at location %i\n",msg.Buffer[3]+1);
return ERR_NONE;
default:
smprintf(s, "Invalid location. Too high ?\n");
return ERR_INVALIDLOCATION;
}
}
static GSM_Error N6110_SetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength)
{
GSM_NetworkInfo NetInfo;
GSM_Error error;
int size=200,current=8;
GSM_UDHHeader UDHHeader;
unsigned char req[1000] = {N6110_FRAME_HEADER, 0x36,
0x00, /* Location */
0x00,0x78};
unsigned char reqBin[1000] = {0x00,0x01,0xa0,0x00,0x00,0x0c,0x01,0x2c};
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NORING)) return ERR_NOTSUPPORTED;
if (Ringtone->Location == 0) return ERR_INVALIDLOCATION;
switch (Ringtone->Format) {
case RING_NOTETONE:
if (Ringtone->Location==255) {
/* Only 6110, 6130 and 6150 support it */
if (strcmp(s->Phone.Data.Model,"NSE-3") == 0 || strcmp(s->Phone.Data.Model,"NSK-3") == 0 ||
strcmp(s->Phone.Data.Model,"NSM-1") == 0) {
req[0] = 0x0c;
req[1] = 0x01;
UDHHeader.Type = UDH_NokiaRingtone;
GSM_EncodeUDHHeader(&UDHHeader);
/* We copy UDH now */
memcpy(req+2,UDHHeader.Text,UDHHeader.Length);
*maxlength=GSM_EncodeNokiaRTTLRingtone(*Ringtone, req+2+UDHHeader.Length, &size);
error = s->Protocol.Functions->WriteMessage(s, req, 2+UDHHeader.Length+size, 0x12);
if (error!=ERR_NONE) return error;
my_sleep(1000);
/* We have to make something (not important, what) now */
/* no answer from phone*/
return DCT3_GetNetworkInfo(s,&NetInfo);
} else {
return ERR_NOTSUPPORTED;
}
}
*maxlength=GSM_EncodeNokiaRTTLRingtone(*Ringtone, req+7, &size);
req[4] = Ringtone->Location - 1;
smprintf(s, "Setting ringtone\n");
return GSM_WaitFor (s, req, 7 + size, 0x05, 4, ID_SetRingtone);
case RING_NOKIABINARY:
error=DCT3_EnableSecurity (s, 0x01);
if (error!=ERR_NONE) return error;
memcpy(reqBin+current,DecodeUnicodeString(Ringtone->Name),UnicodeLength(Ringtone->Name));
current += UnicodeLength(Ringtone->Name);
reqBin[current++] = 0x00;
reqBin[current++] = 0x00;
reqBin[current++] = 0x00;/*xxx*/
memcpy(reqBin+current,Ringtone->NokiaBinary.Frame,Ringtone->NokiaBinary.Length);
current=current+Ringtone->NokiaBinary.Length;
reqBin[3]=Ringtone->Location-1;
if (!strcmp(s->Phone.Data.ModelInfo->model,"3210")) reqBin[5]=0x10;
smprintf(s, "Setting binary ringtone\n");
return GSM_WaitFor (s, reqBin, current, 0x40, 4, ID_SetRingtone);
case RING_MIDI:
+ case RING_MMF:
return ERR_NOTSUPPORTED;
}
return ERR_NOTSUPPORTED;
}
static GSM_Error N6110_ReplyGetOpLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int count=5;
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Operator logo received\n");
NOKIA_DecodeNetworkCode(msg.Buffer+count,Data->Bitmap->NetworkCode);
count = count + 3;
smprintf(s, "Network code : %s\n", Data->Bitmap->NetworkCode);
smprintf(s, "Network name for Gammu : %s ",
DecodeUnicodeString(GSM_GetNetworkName(Data->Bitmap->NetworkCode)));
smprintf(s, "(%s)\n",DecodeUnicodeString(GSM_GetCountryName(Data->Bitmap->NetworkCode)));
count = count + 3; /* We ignore size */
Data->Bitmap->BitmapWidth = msg.Buffer[count++];
Data->Bitmap->BitmapHeight = msg.Buffer[count++];
count++;
PHONE_DecodeBitmap(GSM_NokiaOperatorLogo,msg.Buffer+count,Data->Bitmap);
return ERR_NONE;
}
static GSM_Error N6110_ReplyGetStartup(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int i, count = 5;
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Startup logo & notes received\n");
for (i=0;i<msg.Buffer[4];i++) {
switch (msg.Buffer[count++]) {
case 0x01:
smprintf(s, "Startup logo\n");
if (Data->Bitmap->Type == GSM_StartupLogo) {
Data->Bitmap->BitmapHeight = msg.Buffer[count++];
Data->Bitmap->BitmapWidth = msg.Buffer[count++];
PHONE_DecodeBitmap(GSM_NokiaStartupLogo, msg.Buffer + count, Data->Bitmap);
} else {
count = count + 2;
}
count = count + PHONE_GetBitmapSize(GSM_NokiaStartupLogo,0,0);
break;
case 0x02:
smprintf(s, "Welcome note\n");
if (Data->Bitmap->Type == GSM_WelcomeNote_Text) {
EncodeUnicode(Data->Bitmap->Text,msg.Buffer+count, msg.Buffer[count]);
smprintf(s, "Text is \"%s\"\n",Data->Bitmap->Text);
}
count = count + msg.Buffer[count] + 1;
break;
case 0x03:
smprintf(s, "Dealer welcome note\n");
if (Data->Bitmap->Type == GSM_DealerNote_Text) {
EncodeUnicode(Data->Bitmap->Text,msg.Buffer+count, msg.Buffer[count]);
smprintf(s, "Text is \"%s\"\n",Data->Bitmap->Text);
}
count = count + msg.Buffer[count] + 1;
break;
default:
smprintf(s, "Unknown block\n");
return ERR_UNKNOWNRESPONSE;
break;
}
}
return ERR_NONE;
}
static GSM_Error N6110_ReplyGetCallerLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int count;
GSM_Phone_Data *Data = &s->Phone.Data;
switch (msg.Buffer[3]) {
case 0x11:
smprintf(s, "Caller group info received\n");
EncodeUnicode(Data->Bitmap->Text,msg.Buffer+6,msg.Buffer[5]);
smprintf(s, "Name : \"%s\"\n",DecodeUnicodeString(Data->Bitmap->Text));
Data->Bitmap->DefaultName = false;
if (msg.Buffer[5] == 0x00) Data->Bitmap->DefaultName = true;
count = msg.Buffer[5] + 6;
Data->Bitmap->RingtoneID = msg.Buffer[count++];
Data->Bitmap->DefaultRingtone = false;
Data->Bitmap->FileSystemRingtone = false;
if (Data->Bitmap->RingtoneID == 16) Data->Bitmap->DefaultRingtone = true;
smprintf(s, "Ringtone ID: %02x\n",Data->Bitmap->RingtoneID);
Data->Bitmap->BitmapEnabled=(msg.Buffer[count++]==1);
#ifdef DEBUG
smprintf(s, "Caller group logo ");
if (Data->Bitmap->BitmapEnabled) {
smprintf(s, "enabled\n");
} else {
smprintf(s, "disabled\n");
}
#endif
count = count + 3; /* We ignore size */
Data->Bitmap->BitmapWidth = msg.Buffer[count++];
Data->Bitmap->BitmapHeight = msg.Buffer[count++];
count++;
PHONE_DecodeBitmap(GSM_NokiaCallerLogo,msg.Buffer+count,Data->Bitmap);
Data->Bitmap->DefaultBitmap = false;
return ERR_NONE;
case 0x12:
smprintf(s, "Error getting caller group info\n");
return ERR_INVALIDLOCATION;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6110_ReplyGetSetPicture(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int count = 5, i;
GSM_Phone_Data *Data = &s->Phone.Data;
switch (msg.Buffer[3]) {
case 0x02:
smprintf(s, "Picture Image received\n");
if (msg.Buffer[count]!=0) {
GSM_UnpackSemiOctetNumber(Data->Bitmap->Sender, msg.Buffer + 5, true);
/* Convert number of semioctets to number of chars */
i = msg.Buffer[5];
if (i % 2) i++;
i=i / 2 + 1;
count = count + i + 1;
} else {
Data->Bitmap->Sender[0] = 0x00;
Data->Bitmap->Sender[1] = 0x00;
count+=2;
}
smprintf(s, "Sender : \"%s\"\n",DecodeUnicodeString(Data->Bitmap->Sender));
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOPICTUREUNI) ||
(!strcmp(Data->Model,"NHM-5") && Data->VerNum < 5.79)) {
count++;
EncodeUnicode(Data->Bitmap->Text,msg.Buffer+count+1,msg.Buffer[count]);
count += UnicodeLength(Data->Bitmap->Text) + 1;
} else {
if (!strcmp(Data->Model,"NHM-5")) {
i = msg.Buffer[count] * 256 + msg.Buffer[count+1];
} else {
/* 3410 4.26 */
i = msg.Buffer[count] * 256 + msg.Buffer[count+1] - 2;
count += 2;
}
memcpy(Data->Bitmap->Text,msg.Buffer+count+2,i);
Data->Bitmap->Text[i] = 0;
Data->Bitmap->Text[i+1] = 0;
count += i + 2;
}
smprintf(s, "Text : \"%s\"\n",DecodeUnicodeString(Data->Bitmap->Text));
Data->Bitmap->BitmapWidth = msg.Buffer[count++];
Data->Bitmap->BitmapHeight = msg.Buffer[count++];
PHONE_DecodeBitmap(GSM_NokiaPictureImage, msg.Buffer + count + 2, Data->Bitmap);
#ifdef DEBUG
if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,Data->Bitmap);
#endif
return ERR_NONE;
break;
case 0x04:
smprintf(s, "Picture Image set OK\n");
return ERR_NONE;
case 0x05:
smprintf(s, "Can't set Picture Image - invalid location ?\n");
return ERR_INVALIDLOCATION;
break;
case 0x06:
smprintf(s, "Can't get Picture Image - invalid location ?\n");
return ERR_INVALIDLOCATION;
break;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6110_GetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
{
GSM_Error error;
unsigned char req[10] = {N6110_FRAME_HEADER};
s->Phone.Data.Bitmap=Bitmap;
switch (Bitmap->Type) {
case GSM_StartupLogo:
case GSM_WelcomeNote_Text:
case GSM_DealerNote_Text:
if (Bitmap->Type == GSM_StartupLogo && IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOSTARTUP)) return ERR_NOTSUPPORTED;
req[3] = 0x16;
return GSM_WaitFor (s, req, 4, 0x05, 4, ID_GetBitmap);
case GSM_CallerGroupLogo:
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOCALLER)) return ERR_NOTSUPPORTED;
req[3] = 0x10;
req[4] = Bitmap->Location - 1;
error = GSM_WaitFor (s, req, 5, 0x03, 4, ID_GetBitmap);
@@ -1335,421 +1339,423 @@ static GSM_Error N6110_ReplyCallInfo(GSM_Protocol_Message msg, GSM_StateMachine
if (msg.Buffer[3] == 0x09) {
if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
/* when we canceled call and see frame about other
* call releasing, we don't give ERR_NONE for "our"
* call release command
*/
return ERR_NEEDANOTHERANSWER;
}
}
if (s->Phone.Data.RequestID == ID_AnswerCall) {
if (msg.Buffer[3] == 0x07) {
if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
return ERR_NEEDANOTHERANSWER;
}
}
if (s->Phone.Data.RequestID == ID_UnholdCall) {
if (msg.Buffer[3] == 0x25) {
if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
return ERR_NEEDANOTHERANSWER;
}
}
if (s->Phone.Data.RequestID == ID_HoldCall) {
if (msg.Buffer[3] == 0x23) {
if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
return ERR_NEEDANOTHERANSWER;
}
}
if (s->Phone.Data.RequestID == ID_ConferenceCall) {
if (msg.Buffer[3] == 0x29) {
if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
return ERR_NEEDANOTHERANSWER;
}
}
if (s->Phone.Data.RequestID == ID_SplitCall) {
if (msg.Buffer[3] == 0x2B) {
if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
return ERR_NEEDANOTHERANSWER;
}
}
return ERR_NONE;
}
static GSM_Error N6110_DeleteSMSMessage(GSM_StateMachine *s, GSM_SMSMessage *sms)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x0a, 0x02,
0x00}; /* Location */
if (sms->Folder!=0x00) return ERR_NOTSUPPORTED;
req[5]=sms->Location;
smprintf(s, "Deleting sms\n");
return GSM_WaitFor (s, req, 6, 0x14, 4, ID_DeleteSMSMessage);
}
static GSM_Error N6110_ReplySetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Reply for writing memory\n");
switch (msg.Buffer[3]) {
case 0x05:
smprintf(s, "Done OK\n");
return ERR_NONE;
case 0x06:
smprintf(s, "Error\n");
switch (msg.Buffer[4]) {
case 0x7d:
smprintf(s, "Too high location ?\n");
return ERR_INVALIDLOCATION;
case 0x90:
smprintf(s, "Too long name...or other error\n");
return ERR_NOTSUPPORTED;
default:
smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
}
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6110_SetMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
int current, Group, Name, Number;
unsigned char req[128] = {N6110_FRAME_HEADER, 0x04,
0x00, /* memory type */
0x00}; /* location */
if (entry->Location == 0) return ERR_NOTSUPPORTED;
GSM_PhonebookFindDefaultNameNumberGroup(entry, &Name, &Number, &Group);
req[4] = NOKIA_GetMemoryType(s, entry->MemoryType,N6110_MEMORY_TYPES);
req[5] = entry->Location;
current = 7;
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOPBKUNICODE)) {
if (Name != -1) {
req[6] = UnicodeLength(entry->Entries[Name].Text);
memcpy(req+current,DecodeUnicodeString(entry->Entries[Name].Text),UnicodeLength(entry->Entries[Name].Text));
current += UnicodeLength(entry->Entries[Name].Text);
} else req[6] = 0;
} else {
if (Name != -1) {
req[6] = UnicodeLength(entry->Entries[Name].Text)*2+2;
memcpy(req+current,entry->Entries[Name].Text,UnicodeLength(entry->Entries[Name].Text)*2);
current += UnicodeLength(entry->Entries[Name].Text)*2;
} else req[6] = 0;
req[current++]=0x00;
req[current++]=0x00;
}
if (Number != -1) {
req[current++]=UnicodeLength(entry->Entries[Number].Text);
memcpy(req+current,DecodeUnicodeString(entry->Entries[Number].Text),UnicodeLength(entry->Entries[Number].Text));
current += UnicodeLength(entry->Entries[Number].Text);
} else req[current++] = 0;
/* This allow to save 14 characters name into SIM memory, when
* no caller group is selected. */
if (Group == -1) {
req[current++] = 0xff;
} else {
req[current++] = entry->Entries[Group].Number-1;
}
smprintf(s, "Writing phonebook entry\n");
return GSM_WaitFor (s, req, current, 0x03, 4, ID_SetMemory);
}
static GSM_Error N6110_DeleteMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
GSM_MemoryEntry dwa;
dwa.Location = entry->Location;
dwa.MemoryType = entry->MemoryType;
dwa.EntriesNum = 0;
return N6110_SetMemory(s, &dwa);
}
static GSM_Error N6110_ReplyGetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
char buffer[2000];
GSM_Error error;
int i,end,start;
smprintf(s, "Ringtone received\n");
switch (msg.Buffer[4]) {
case 0x00:
switch (Data->Ringtone->Format) {
case RING_NOTETONE:
memcpy(buffer,msg.Buffer,msg.Length);
i=7;
if (buffer[9]==0x4a && buffer[10]==0x3a) i=8;
buffer[i]=0x02;
error=GSM_DecodeNokiaRTTLRingtone(Data->Ringtone, buffer+i, msg.Length-i);
if (error!=ERR_NONE) return ERR_EMPTY;
return ERR_NONE;
case RING_NOKIABINARY:
i=8;
while (msg.Buffer[i]!=0) {
i++;
if (i>msg.Length) return ERR_EMPTY;
}
EncodeUnicode(Data->Ringtone->Name,msg.Buffer+8,i-8);
smprintf(s, "Name \"%s\"\n",DecodeUnicodeString(Data->Ringtone->Name));
/* Looking for start && end */
end=0;start=0;i=0;
while (true) {
if (start!=0) {
if (msg.Buffer[i]==0x07 && msg.Buffer[i+1]==0x0b) {
end=i+2; break;
}
if (msg.Buffer[i]==0x0e && msg.Buffer[i+1]==0x0b) {
end=i+2; break;
}
} else {
if (msg.Buffer[i]==0x02 && msg.Buffer[i+1]==0xfc && msg.Buffer[i+2]==0x09) {
start = i;
}
}
i++;
if (i==msg.Length-3) return ERR_EMPTY;
}
/* Copying frame */
memcpy(Data->Ringtone->NokiaBinary.Frame,msg.Buffer+start,end-start);
Data->Ringtone->NokiaBinary.Length=end-start;
#ifdef DEBUG
if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, Data->Ringtone->NokiaBinary.Frame, Data->Ringtone->NokiaBinary.Length);
#endif
return ERR_NONE;
case RING_MIDI:
+ case RING_MMF:
return ERR_NOTSUPPORTED;
}
smprintf(s, "Ringtone format is %i\n",Data->Ringtone->Format);
break;
default:
smprintf(s, "Invalid location. Too high ?\n");
return ERR_INVALIDLOCATION;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6110_GetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone)
{
GSM_Error error;
unsigned char req[] = {0x00, 0x01, 0x9e,
0x00}; /* location */
if (PhoneRingtone) return ERR_NOTSUPPORTED;
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NORING)) return ERR_NOTSUPPORTED;
if (Ringtone->Location == 0) return ERR_INVALIDLOCATION;
if (Ringtone->Format == 0x00) {
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_RING_SM)) {
Ringtone->Format = RING_NOTETONE;
} else {
Ringtone->Format = RING_NOKIABINARY;
}
}
switch (Ringtone->Format) {
case RING_NOTETONE:
if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_RING_SM)) return ERR_NOTSUPPORTED;
break;
case RING_NOKIABINARY:
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_RING_SM)) return ERR_NOTSUPPORTED;
break;
case RING_MIDI:
+ case RING_MMF:
return ERR_NOTSUPPORTED;
}
error=DCT3_EnableSecurity (s, 0x01);
if (error!=ERR_NONE) return error;
req[3]=Ringtone->Location-1;
s->Phone.Data.Ringtone=Ringtone;
smprintf(s, "Getting (binary) ringtone\n");
return GSM_WaitFor (s, req, 4, 0x40, 4, ID_GetRingtone);
}
static GSM_Error N6110_ReplyGetSecurityStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
*s->Phone.Data.SecurityStatus = msg.Buffer[4];
#ifdef DEBUG
smprintf(s, "Security code status\n");
switch(msg.Buffer[4]) {
case SEC_SecurityCode: smprintf(s, "waiting for Security Code.\n"); break;
case SEC_Pin : smprintf(s, "waiting for PIN.\n"); break;
case SEC_Pin2 : smprintf(s, "waiting for PIN2.\n"); break;
case SEC_Puk : smprintf(s, "waiting for PUK.\n"); break;
case SEC_Puk2 : smprintf(s, "waiting for PUK2.\n"); break;
case SEC_None : smprintf(s, "nothing to enter.\n"); break;
default : smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
return ERR_UNKNOWNRESPONSE;
}
#endif
return ERR_NONE;
}
static GSM_Error N6110_GetSecurityStatus(GSM_StateMachine *s, GSM_SecurityCodeType *Status)
{
unsigned char req[4] = {N6110_FRAME_HEADER, 0x07};
s->Phone.Data.SecurityStatus=Status;
smprintf(s, "Getting security code status\n");
return GSM_WaitFor (s, req, 4, 0x08, 2, ID_GetSecurityStatus);
}
static GSM_Error N6110_ReplyEnterSecurityCode(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[3]) {
case 0x0b:
smprintf(s, "Security code OK\n");
return ERR_NONE;
case 0x0c:
switch (msg.Buffer[4]) {
case 0x88:
smprintf(s, "Wrong code\n");
return ERR_SECURITYERROR;
case 0x8b:
smprintf(s, "Not required\n");
return ERR_NONE;
default:
smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
}
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6110_EnterSecurityCode(GSM_StateMachine *s, GSM_SecurityCode Code)
{
int len = 0;
unsigned char req[15] = {N6110_FRAME_HEADER, 0x0a,
0x00}; /* Type of code to enter */
req[4]=Code.Type;
len = strlen(Code.Code);
memcpy(req+5,Code.Code,len);
req[5+len]=0x00;
req[6+len]=0x00;
smprintf(s, "Entering security code\n");
return GSM_WaitFor (s, req, 7+len, 0x08, 4, ID_EnterSecurityCode);
}
static GSM_Error N6110_ReplyGetSpeedDial(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
switch (msg.Buffer[3]) {
case 0x17:
smprintf(s, "Speed dial received\n");
switch (msg.Buffer[4]) {
case 0x02:
Data->SpeedDial->MemoryType = MEM_ME;
smprintf(s, "ME ");
break;
case 0x03:
Data->SpeedDial->MemoryType = MEM_SM;
smprintf(s, "SIM ");
break;
default:
smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
return ERR_UNKNOWNRESPONSE;
}
Data->SpeedDial->MemoryLocation = msg.Buffer[5];
if (msg.Buffer[5] == 0x00) Data->SpeedDial->MemoryLocation = Data->SpeedDial->Location;
Data->SpeedDial->MemoryNumberID = 2;
smprintf(s, "location %i\n",Data->SpeedDial->MemoryLocation);
return ERR_NONE;
case 0x18:
smprintf(s, "Error getting speed dial. Invalid location\n");
return ERR_INVALIDLOCATION;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6110_GetSpeedDial(GSM_StateMachine *s, GSM_SpeedDial *SpeedDial)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x16,
0x01}; /* location */
req[4] = SpeedDial->Location;
s->Phone.Data.SpeedDial=SpeedDial;
smprintf(s, "Getting speed dial\n");
return GSM_WaitFor (s, req, 5, 0x03, 4, ID_GetSpeedDial);
}
static GSM_Error N6110_ReplySendDTMF(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[3]) {
case 0x40:
smprintf(s, "During sending DTMF\n");
return ERR_NONE;
case 0x51:
smprintf(s, "DTMF sent OK\n");
return ERR_NONE;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6110_ReplyGetDisplayStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int i;
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Display status received\n");
if (Data->RequestID == ID_GetDisplayStatus) Data->DisplayFeatures->Number=0;
for (i=0;i<msg.Buffer[4];i++) {
if (msg.Buffer[2*i+6] == 0x02) {
#ifdef DEBUG
switch (msg.Buffer[2*i+5]) {
case 0x01: smprintf(s, "Call in progress\n"); break;
case 0x02: smprintf(s, "Unknown\n"); break;
case 0x03: smprintf(s, "Unread SMS\n"); break;
case 0x04: smprintf(s, "Voice call\n"); break;
case 0x05: smprintf(s, "Fax call active\n"); break;
case 0x06: smprintf(s, "Data call active\n"); break;
case 0x07: smprintf(s, "Keyboard lock\n"); break;
case 0x08: smprintf(s, "SMS storage full\n"); break;
}
#endif
if (Data->RequestID == ID_GetDisplayStatus) {
switch (msg.Buffer[2*i+5]) {
case 0x01: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_CallActive;
break;
case 0x03: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_UnreadSMS;
break;
case 0x04: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_VoiceCall;
break;
case 0x05: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_FaxCall;
break;
case 0x06: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_DataCall;
break;
case 0x07: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_KeypadLocked;
break;
case 0x08: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_SMSMemoryFull;
break;
}
if (msg.Buffer[2*i+5]!=0x02) Data->DisplayFeatures->Number++;
}
}
}
return ERR_NONE;
}
static GSM_Error N6110_GetDisplayStatus(GSM_StateMachine *s, GSM_DisplayFeatures *features)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x51};
if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_DISPSTATUS)) return ERR_NOTSUPPORTED;
s->Phone.Data.DisplayFeatures = features;
smprintf(s, "Getting display status\n");
return GSM_WaitFor (s, req, 4, 0x0d, 4, ID_GetDisplayStatus);
}
@@ -2254,631 +2260,632 @@ static void Decode3310Subset3(int j, GSM_Protocol_Message msg, GSM_Phone_Data *D
i = j;
while (i!=msg.Buffer[23]) {
EncodeWithUnicodeAlphabet(msg.Buffer+24+i,&wc);
charfound = false;
if (i!=msg.Buffer[23]-2) {
if (msg.Buffer[24+i] ==0xe2 && msg.Buffer[24+i+1]==0x82 &&
msg.Buffer[24+i+2]==0xac) {
wc = 0x20 * 256 + 0xac;
i+=2;
charfound = true;
}
}
if (i!=msg.Buffer[23]-1 && !charfound) {
if (msg.Buffer[24+i]>=0xc2) {
wc = DecodeWithUTF8Alphabet(msg.Buffer[24+i],msg.Buffer[24+i+1]);
i++;
}
}
Entry->Entries[Entry->EntriesNum].Text[len++] = (wc >> 8) & 0xff;
Entry->Entries[Entry->EntriesNum].Text[len++] = wc & 0xff;
i++;
}
Entry->Entries[Entry->EntriesNum].Text[len++] = 0;
Entry->Entries[Entry->EntriesNum].Text[len++] = 0;
}
/* For example: "a with : above" char */
static void Decode3310Subset2(int j, GSM_Protocol_Message msg, GSM_Phone_Data *Data)
{
int len = 0;
int i;
GSM_CalendarEntry *Entry = Data->Cal;
i = j;
while (i!=msg.Buffer[23]) {
Entry->Entries[Entry->EntriesNum].Text[len++] = 0x00;
Entry->Entries[Entry->EntriesNum].Text[len++] = msg.Buffer[24+i];
i++;
}
Entry->Entries[Entry->EntriesNum].Text[len++] = 0;
Entry->Entries[Entry->EntriesNum].Text[len++] = 0;
}
static GSM_Error N6110_ReplyGetNextCalendar(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int i = 0;
bool SpecialSubSet = false;
GSM_CalendarEntry *Entry = s->Phone.Data.Cal;
switch (msg.Buffer[4]) {
case 0x01:
smprintf(s, "Calendar note received\n");
switch (msg.Buffer[8]) {
case 0x01: Entry->Type = GSM_CAL_REMINDER; break;
case 0x02: Entry->Type = GSM_CAL_CALL; break;
case 0x03: Entry->Type = GSM_CAL_MEETING; break;
case 0x04: Entry->Type = GSM_CAL_BIRTHDAY; break;
case 0x05: Entry->Type = GSM_CAL_T_ATHL; break;
case 0x06: Entry->Type = GSM_CAL_T_BALL; break;
case 0x07: Entry->Type = GSM_CAL_T_CYCL; break;
case 0x08: Entry->Type = GSM_CAL_T_BUDO; break;
case 0x09: Entry->Type = GSM_CAL_T_DANC; break;
case 0x0a: Entry->Type = GSM_CAL_T_EXTR; break;
case 0x0b: Entry->Type = GSM_CAL_T_FOOT; break;
case 0x0c: Entry->Type = GSM_CAL_T_GOLF; break;
case 0x0d: Entry->Type = GSM_CAL_T_GYM; break;
case 0x0e: Entry->Type = GSM_CAL_T_HORS; break;
case 0x0f: Entry->Type = GSM_CAL_T_HOCK; break;
case 0x10: Entry->Type = GSM_CAL_T_RACE; break;
case 0x11: Entry->Type = GSM_CAL_T_RUGB; break;
case 0x12: Entry->Type = GSM_CAL_T_SAIL; break;
case 0x13: Entry->Type = GSM_CAL_T_STRE; break;
case 0x14: Entry->Type = GSM_CAL_T_SWIM; break;
case 0x15: Entry->Type = GSM_CAL_T_TENN; break;
case 0x16: Entry->Type = GSM_CAL_T_TRAV; break;
case 0x17: Entry->Type = GSM_CAL_T_WINT; break;
default :
smprintf(s, "Unknown note type %i\n",msg.Buffer[8]);
return ERR_UNKNOWNRESPONSE;
}
#ifdef DEBUG
switch (msg.Buffer[8]) {
case 0x01: smprintf(s, "Reminder\n"); break;
case 0x02: smprintf(s, "Call\n"); break;
case 0x03: smprintf(s, "Meeting\n"); break;
case 0x04: smprintf(s, "Birthday\n"); break;
}
#endif
Entry->EntriesNum = 0;
NOKIA_DecodeDateTime(s, msg.Buffer+9, &Entry->Entries[0].Date);
smprintf(s, "Time : %02i-%02i-%04i %02i:%02i:%02i\n",
Entry->Entries[0].Date.Day,Entry->Entries[0].Date.Month,Entry->Entries[0].Date.Year,
Entry->Entries[0].Date.Hour,Entry->Entries[0].Date.Minute,Entry->Entries[0].Date.Second);
Entry->Entries[0].EntryType = CAL_START_DATETIME;
Entry->EntriesNum++;
NOKIA_DecodeDateTime(s, msg.Buffer+16, &Entry->Entries[1].Date);
if (Entry->Entries[1].Date.Year!=0) {
smprintf(s, "Alarm : %02i-%02i-%04i %02i:%02i:%02i\n",
Entry->Entries[1].Date.Day,Entry->Entries[1].Date.Month,Entry->Entries[1].Date.Year,
Entry->Entries[1].Date.Hour,Entry->Entries[1].Date.Minute,Entry->Entries[1].Date.Second);
Entry->Entries[1].EntryType = CAL_ALARM_DATETIME;
Entry->EntriesNum++;
} else {
smprintf(s, "No alarm\n");
}
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL52) ||
IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL82)) {
memcpy(Entry->Entries[Entry->EntriesNum].Text,msg.Buffer+24,msg.Buffer[23]);
Entry->Entries[Entry->EntriesNum].Text[msg.Buffer[23] ]=0;
Entry->Entries[Entry->EntriesNum].Text[msg.Buffer[23]+1]=0;
} else {
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL33)) {
/* first char is subset for 33xx and reminders */
if (Entry->Type == GSM_CAL_REMINDER) {
i=1;
smprintf(s, "Subset %i in reminder note !\n",msg.Buffer[24]);
}
SpecialSubSet = true;
switch (msg.Buffer[24]) {
case 2 : Decode3310Subset2(i,msg,&s->Phone.Data); break;
case 3 : Decode3310Subset3(i,msg,&s->Phone.Data); break;
default : SpecialSubSet = false; break;
}
}
if (!SpecialSubSet) {
N6110_EncodeUnicode(s,Entry->Entries[Entry->EntriesNum].Text,msg.Buffer+24+i,msg.Buffer[23]-i);
}
}
smprintf(s, "Text \"%s\"\n",DecodeUnicodeString(Entry->Entries[Entry->EntriesNum].Text));
if (msg.Buffer[23] != 0x00) {
Entry->Entries[Entry->EntriesNum].EntryType = CAL_TEXT;
Entry->EntriesNum++;
}
if (Entry->Type == GSM_CAL_CALL) {
EncodeUnicode(Entry->Entries[Entry->EntriesNum].Text,msg.Buffer+24+msg.Buffer[23]+1,msg.Buffer[24+msg.Buffer[23]]);
smprintf(s, "Phone : \"%s\"\n",DecodeUnicodeString(Entry->Entries[Entry->EntriesNum].Text));
if (msg.Buffer[24+msg.Buffer[23]] != 0x00) {
Entry->Entries[Entry->EntriesNum].EntryType = CAL_PHONE;
Entry->EntriesNum++;
}
}
return ERR_NONE;
case 0x93:
smprintf(s, "Can't get calendar note - too high location?\n");
return ERR_INVALIDLOCATION;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6110_GetNextCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
{
int Text, Time, Alarm, Phone, Recurrance, EndTime, Location;
GSM_Error error;
GSM_DateTime date_time;
GSM_Phone_N6110Data *Priv = &s->Phone.Data.Priv.N6110;
unsigned char req[] = {N6110_FRAME_HEADER, 0x66,
0x00}; /* Location */
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOCALENDAR)) return ERR_NOTSUPPORTED;
if (start) {
Priv->LastCalendarPos = 1;
} else {
Priv->LastCalendarPos++;
}
Note->Location = Priv->LastCalendarPos;
req[4] = Priv->LastCalendarPos;
s->Phone.Data.Cal=Note;
smprintf(s, "Getting calendar note\n");
error=GSM_WaitFor (s, req, 5, 0x13, 4, ID_GetCalendarNote);
GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(Note, &Text, &Time, &Alarm, &Phone, &Recurrance, &EndTime, &Location);
/* 2090 year is set for example in 3310 */
if (error == ERR_NONE && Note->Entries[Time].Date.Year == 2090) {
error=N6110_GetDateTime(s, &date_time);
if (error == ERR_NONE) Note->Entries[Time].Date.Year = date_time.Year;
}
return error;
}
GSM_Error N6110_ReplyUSSDInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
unsigned char buffer[2000],buffer2[4000];
int tmp;
- tmp=GSM_UnpackEightBitsToSeven(0, 82, 82, msg.Buffer+8, buffer);
- msg.Buffer[tmp] = 0;
+ tmp=GSM_UnpackEightBitsToSeven(0, msg.Buffer[7], 82, msg.Buffer+8, buffer);
+ buffer[tmp] = 0;
smprintf(s, "USSD reply: \"%s\"\n",buffer);
if (s->Phone.Data.EnableIncomingUSSD && s->User.IncomingUSSD!=NULL) {
EncodeUnicode(buffer2,buffer,strlen(buffer));
s->User.IncomingUSSD(s->CurrentConfig->Device, buffer2);
}
return ERR_NONE;
}
GSM_Error N6110_AnswerCall(GSM_StateMachine *s, int ID, bool all)
{
GSM_Error error;
unsigned char req1[] = {N6110_FRAME_HEADER, 0x42, 0x05, 0x01,
0x07, 0xa2, 0x88, 0x81, 0x21, 0x15, 0x63, 0xa8,
0x00, 0x00, 0x07, 0xa3, 0xb8, 0x81, 0x20, 0x15,
0x63, 0x80};
if (!all) {
smprintf(s, "Answering call part 1\n");
error = GSM_WaitFor (s, req1, 24, 0x01, 5, ID_AnswerCall);
if (error != ERR_NONE) return error;
return DCT3DCT4_AnswerCall(s,ID);
}
return DCT3_AnswerAllCalls(s);
}
static GSM_Error N6110_DialVoice(GSM_StateMachine *s, char *number, GSM_CallShowNumber ShowNumber)
{
unsigned int pos = 4;
unsigned char req[100] = {N6110_FRAME_HEADER,0x01,
0x0c}; /* Length of number */
if (ShowNumber == GSM_CALL_DefaultNumberPresence) return DCT3_DialVoice(s,number,ShowNumber);
req[pos++] = strlen(number);
memcpy(req+pos,number,strlen(number));
pos += strlen(number);
req[pos++] = 0x05; /* call type: voice - 0x05, data - 0x01 */
req[pos++] = 0x01;
req[pos++] = 0x01;
req[pos++] = 0x05;
req[pos++] = 0x81;
switch (ShowNumber) {
case GSM_CALL_HideNumber:
req[pos++] = 0x02;
break;
case GSM_CALL_ShowNumber:
req[pos++] = 0x03;
break;
case GSM_CALL_DefaultNumberPresence:
req[pos++] = 0x01;
break;
}
req[pos++] = 0x00;
req[pos++] = 0x00;
smprintf(s, "Making voice call\n");
return GSM_WaitFor (s, req, pos, 0x01, 4, ID_DialVoice);
}
GSM_Error N6110_UnholdCall(GSM_StateMachine *s, int ID)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x24, 0x00, 0x02};
req[4] = (unsigned char)ID;
s->Phone.Data.CallID = ID;
smprintf(s, "Unholding call\n");
return GSM_WaitFor (s, req, 6, 0x01, 4, ID_UnholdCall);
}
GSM_Error N6110_HoldCall(GSM_StateMachine *s, int ID)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x22, 0x00, 0x00};
req[4] = (unsigned char)ID;
s->Phone.Data.CallID = ID;
smprintf(s, "Unholding call\n");
return GSM_WaitFor (s, req, 6, 0x01, 4, ID_HoldCall);
}
/* Joining selected call to current (and making conference) */
GSM_Error N6110_ConferenceCall(GSM_StateMachine *s, int ID)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x28, 0x00, 0x01};
req[4] = (unsigned char)ID;
s->Phone.Data.CallID = ID;
smprintf(s, "Conference call\n");
return GSM_WaitFor (s, req, 6, 0x01, 4, ID_ConferenceCall);
}
/* Removing selected call from conference and making private call with it
* (conference call is on hold) */
GSM_Error N6110_SplitCall(GSM_StateMachine *s, int ID)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x2A, 0x00, 0x01};
req[4] = (unsigned char)ID;
s->Phone.Data.CallID = ID;
smprintf(s, "Split call\n");
return GSM_WaitFor (s, req, 6, 0x01, 4, ID_SplitCall);
}
/* This probably need more investigation */
GSM_Error N6110_SwitchCall(GSM_StateMachine *s, int ID, bool next)
{
// unsigned char req[] = {N6110_FRAME_HEADER, 0x20}; calls info
unsigned char req[] = {N6110_FRAME_HEADER, 0x26, 0x00};
s->Phone.Data.CallID = ID;
if (next) {
smprintf(s, "Switch call\n");
return GSM_WaitFor (s, req, 4, 0x01, 4, ID_SwitchCall);
} else {
req[4] = (unsigned char)ID;
smprintf(s, "Switch call\n");
return GSM_WaitFor (s, req, 5, 0x01, 4, ID_SwitchCall);
}
}
/* This probably need more investigation */
GSM_Error N6110_TransferCall(GSM_StateMachine *s, int ID, bool next)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x2C, 0x00};
s->Phone.Data.CallID = ID;
if (next) {
smprintf(s, "Transfer call\n");
return GSM_WaitFor (s, req, 4, 0x01, 4, ID_TransferCall);
} else {
req[4] = (unsigned char)ID;
smprintf(s, "Transfer call\n");
return GSM_WaitFor (s, req, 5, 0x01, 4, ID_TransferCall);
}
}
static GSM_Reply_Function N6110ReplyFunctions[] = {
{N6110_ReplyCallInfo, "\x01",0x03,0x02,ID_IncomingFrame },
{N6110_ReplyCallInfo, "\x01",0x03,0x03,ID_IncomingFrame },
{N6110_ReplyCallInfo, "\x01",0x03,0x04,ID_IncomingFrame },
{N6110_ReplyCallInfo, "\x01",0x03,0x05,ID_IncomingFrame },
{N6110_ReplyCallInfo, "\x01",0x03,0x07,ID_AnswerCall },
{N6110_ReplyCallInfo, "\x01",0x03,0x07,ID_IncomingFrame },
{N6110_ReplyCallInfo, "\x01",0x03,0x09,ID_CancelCall },
{N6110_ReplyCallInfo, "\x01",0x03,0x09,ID_IncomingFrame },
{N6110_ReplyCallInfo, "\x01",0x03,0x0A,ID_IncomingFrame },
{N6110_ReplyCallInfo, "\x01",0x03,0x23,ID_HoldCall },
{N6110_ReplyCallInfo, "\x01",0x03,0x23,ID_IncomingFrame },
{N6110_ReplyCallInfo, "\x01",0x03,0x25,ID_UnholdCall },
{N6110_ReplyCallInfo, "\x01",0x03,0x25,ID_IncomingFrame },
{N6110_ReplyCallInfo, "\x01",0x03,0x27,ID_IncomingFrame },
{N6110_ReplyCallInfo, "\x01",0x03,0x29,ID_ConferenceCall },
{N6110_ReplyCallInfo, "\x01",0x03,0x29,ID_IncomingFrame },
{N6110_ReplyCallInfo, "\x01",0x03,0x2B,ID_SplitCall },
{N6110_ReplyCallInfo, "\x01",0x03,0x2B,ID_IncomingFrame },
{N6110_ReplySendDTMF, "\x01",0x03,0x40,ID_SendDTMF },
{NoneReply, "\x01",0x03,0x40,ID_DialVoice },
{NoneReply, "\x01",0x03,0x40,ID_IncomingFrame },
{NoneReply, "\x01",0x03,0x43,ID_AnswerCall },
{N6110_ReplySendDTMF, "\x01",0x03,0x51,ID_SendDTMF },
{DCT3_ReplySendSMSMessage, "\x02",0x03,0x02,ID_IncomingFrame },
{DCT3_ReplySendSMSMessage, "\x02",0x03,0x03,ID_IncomingFrame },
{N6110_ReplyIncomingSMS, "\x02",0x03,0x10,ID_IncomingFrame },
#ifdef GSM_ENABLE_CELLBROADCAST
{DCT3_ReplySetIncomingCB, "\x02",0x03,0x21,ID_SetIncomingCB },
{DCT3_ReplySetIncomingCB, "\x02",0x03,0x22,ID_SetIncomingCB },
{DCT3_ReplyIncomingCB, "\x02",0x03,0x23,ID_IncomingFrame },
#endif
{DCT3_ReplySetSMSC, "\x02",0x03,0x31,ID_SetSMSC },
{DCT3_ReplyGetSMSC, "\x02",0x03,0x34,ID_GetSMSC },
{DCT3_ReplyGetSMSC, "\x02",0x03,0x35,ID_GetSMSC },
{N6110_ReplyGetMemory, "\x03",0x03,0x02,ID_GetMemory },
{N6110_ReplyGetMemory, "\x03",0x03,0x03,ID_GetMemory },
{N6110_ReplySetMemory, "\x03",0x03,0x05,ID_SetMemory },
{N6110_ReplySetMemory, "\x03",0x03,0x06,ID_SetMemory },
{N6110_ReplyGetMemoryStatus, "\x03",0x03,0x08,ID_GetMemoryStatus },
{N6110_ReplyGetMemoryStatus, "\x03",0x03,0x09,ID_GetMemoryStatus },
{N6110_ReplyGetCallerLogo, "\x03",0x03,0x11,ID_GetBitmap },
{N6110_ReplyGetCallerLogo, "\x03",0x03,0x12,ID_GetBitmap },
{N6110_ReplySetCallerLogo, "\x03",0x03,0x14,ID_SetBitmap },
{N6110_ReplySetCallerLogo, "\x03",0x03,0x15,ID_SetBitmap },
{N6110_ReplyGetSpeedDial, "\x03",0x03,0x17,ID_GetSpeedDial },
{N6110_ReplyGetSpeedDial, "\x03",0x03,0x18,ID_GetSpeedDial },
/* 0x1A, 0x1B - reply set speed dial */
{N6110_ReplyGetStatus, "\x04",0x03,0x02,ID_GetSignalQuality },
{N6110_ReplyGetStatus, "\x04",0x03,0x02,ID_GetBatteryCharge },
{N6110_ReplySetProfileFeature, "\x05",0x03,0x11,ID_SetProfile },
{N6110_ReplySetProfileFeature, "\x05",0x03,0x12,ID_SetProfile },
{N6110_ReplyGetProfileFeature, "\x05",0x03,0x14,ID_GetProfile },
{N6110_ReplyGetPhoneLanguage, "\x05",0x03,0x14,ID_GetLanguage },
{N6110_ReplyGetProfileFeature, "\x05",0x03,0x15,ID_GetProfile },
{N6110_ReplyGetPhoneLanguage, "\x05",0x03,0x15,ID_GetLanguage },
{N6110_ReplyGetStartup, "\x05",0x03,0x17,ID_GetBitmap },
{N6110_ReplySetStartup, "\x05",0x03,0x19,ID_SetBitmap },
{N6110_ReplyGetProfileFeature, "\x05",0x03,0x1b,ID_GetProfile },
{N61_91_ReplySetOpLogo, "\x05",0x03,0x31,ID_SetBitmap },
{N61_91_ReplySetOpLogo, "\x05",0x03,0x32,ID_SetBitmap },
{N6110_ReplyGetOpLogo, "\x05",0x03,0x34,ID_GetBitmap },
{N6110_ReplySetRingtone, "\x05",0x03,0x37,ID_SetRingtone },
{N6110_ReplySetRingtone, "\x05",0x03,0x38,ID_SetRingtone },
{DCT3DCT4_ReplyCallDivert, "\x06",0x03,0x02,ID_Divert },
{DCT3DCT4_ReplyCallDivert, "\x06",0x03,0x03,ID_Divert },
{N6110_ReplyUSSDInfo, "\x06",0x03,0x05,ID_IncomingFrame },
{NoneReply, "\x06",0x03,0x06,ID_IncomingFrame },//incoming call divert info
{N6110_ReplyGetSecurityStatus, "\x08",0x03,0x08,ID_GetSecurityStatus },
{N6110_ReplyEnterSecurityCode, "\x08",0x03,0x0b,ID_EnterSecurityCode },
{N6110_ReplyEnterSecurityCode, "\x08",0x03,0x0c,ID_EnterSecurityCode },
{DCT3_ReplySIMLogin, "\x09",0x03,0x80,ID_IncomingFrame },
{DCT3_ReplySIMLogout, "\x09",0x03,0x81,ID_IncomingFrame },
{DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_GetNetworkInfo },
{DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_IncomingFrame },
{N6110_ReplyGetDisplayStatus, "\x0D",0x03,0x52,ID_GetDisplayStatus },
{N6110_ReplyGetDisplayStatus, "\x0D",0x03,0x52,ID_IncomingFrame },
{DCT3_ReplySetDateTime, "\x11",0x03,0x61,ID_SetDateTime },
{DCT3_ReplyGetDateTime, "\x11",0x03,0x63,ID_GetDateTime },
{DCT3_ReplySetAlarm, "\x11",0x03,0x6C,ID_SetAlarm },
{DCT3_ReplyGetAlarm, "\x11",0x03,0x6E,ID_GetAlarm },
{N6110_ReplyAddCalendar, "\x13",0x03,0x65,ID_SetCalendarNote },
{N6110_ReplyAddCalendar, "\x13",0x03,0x65,ID_IncomingFrame },
{N6110_ReplyGetNextCalendar, "\x13",0x03,0x67,ID_GetCalendarNote },
{N6110_ReplyDeleteCalendar, "\x13",0x03,0x69,ID_DeleteCalendarNote },
{N6110_ReplyDeleteCalendar, "\x13",0x03,0x69,ID_IncomingFrame },
{N6110_ReplySaveSMSMessage, "\x14",0x03,0x05,ID_SaveSMSMessage },
{N6110_ReplySaveSMSMessage, "\x14",0x03,0x06,ID_SaveSMSMessage },
{N6110_ReplyGetSMSMessage, "\x14",0x03,0x08,ID_GetSMSMessage },
{N6110_ReplyGetSMSMessage, "\x14",0x03,0x09,ID_GetSMSMessage },
{DCT3_ReplyDeleteSMSMessage, "\x14",0x03,0x0B,ID_DeleteSMSMessage },
{DCT3_ReplyDeleteSMSMessage, "\x14",0x03,0x0C,ID_DeleteSMSMessage },
{N6110_ReplyGetSMSStatus, "\x14",0x03,0x37,ID_GetSMSStatus },
{N6110_ReplyGetSMSStatus, "\x14",0x03,0x38,ID_GetSMSStatus },
{DCT3DCT4_ReplyEnableConnectFunc, "\x3f",0x03,0x01,ID_EnableConnectFunc },
{DCT3DCT4_ReplyEnableConnectFunc, "\x3f",0x03,0x02,ID_EnableConnectFunc },
{DCT3DCT4_ReplyDisableConnectFunc,"\x3f",0x03,0x04,ID_DisableConnectFunc },
{DCT3DCT4_ReplyDisableConnectFunc,"\x3f",0x03,0x05,ID_DisableConnectFunc },
{DCT3_ReplyGetWAPBookmark, "\x3f",0x03,0x07,ID_GetWAPBookmark },
{DCT3_ReplyGetWAPBookmark, "\x3f",0x03,0x08,ID_GetWAPBookmark },
{DCT3DCT4_ReplySetWAPBookmark, "\x3f",0x03,0x0A,ID_SetWAPBookmark },
{DCT3DCT4_ReplySetWAPBookmark, "\x3f",0x03,0x0B,ID_SetWAPBookmark },
{DCT3DCT4_ReplyDelWAPBookmark, "\x3f",0x03,0x0D,ID_DeleteWAPBookmark },
{DCT3DCT4_ReplyDelWAPBookmark, "\x3f",0x03,0x0E,ID_DeleteWAPBookmark },
{DCT3DCT4_ReplyGetActiveConnectSet,"\x3f",0x03,0x10,ID_GetConnectSet },
{DCT3DCT4_ReplySetActiveConnectSet,"\x3f",0x03,0x13,ID_SetConnectSet },
{DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x16,ID_GetConnectSet },
{DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x17,ID_GetConnectSet },
{DCT3_ReplySetWAPSettings, "\x3f",0x03,0x19,ID_SetConnectSet },
{DCT3_ReplySetWAPSettings, "\x3f",0x03,0x1A,ID_SetConnectSet },
{DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x1C,ID_GetConnectSet },
{DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x1D,ID_GetConnectSet },
{DCT3_ReplySetWAPSettings, "\x3f",0x03,0x1F,ID_SetConnectSet },
{DCT3_ReplyEnableSecurity, "\x40",0x02,0x64,ID_EnableSecurity },
{N61_71_ReplyResetPhoneSettings, "\x40",0x02,0x65,ID_ResetPhoneSettings },
{DCT3_ReplyGetIMEI, "\x40",0x02,0x66,ID_GetIMEI },
{DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_DialVoice },
{DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_CancelCall },
{DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_AnswerCall },
{DCT3_ReplyNetmonitor, "\x40",0x02,0x7E,ID_Netmonitor },
{DCT3_ReplyPlayTone, "\x40",0x02,0x8F,ID_PlayTone },
{N6110_ReplyGetRingtone, "\x40",0x02,0x9E,ID_GetRingtone },
{N6110_ReplySetBinRingtone, "\x40",0x02,0xA0,ID_SetRingtone },
{NOKIA_ReplyGetPhoneString, "\x40",0x02,0xC8,ID_GetHardware },
{NOKIA_ReplyGetPhoneString, "\x40",0x02,0xC8,ID_GetPPM },
{NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCA,ID_GetProductCode },
{NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCC,ID_GetManufactureMonth},
{NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCC,ID_GetOriginalIMEI },
{N6110_ReplyGetSetPicture, "\x47",0x03,0x02,ID_GetBitmap },
{N6110_ReplyGetSetPicture, "\x47",0x03,0x04,ID_SetBitmap },
{N6110_ReplyGetSetPicture, "\x47",0x03,0x05,ID_SetBitmap },
{N6110_ReplyGetSetPicture, "\x47",0x03,0x06,ID_GetBitmap },
#ifndef ENABLE_LGPL
{N6110_ReplyGetMagicBytes, "\x64",0x00,0x00,ID_MakeAuthentication },
#endif
{DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetModel },
{DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetFirmware },
{DCT3_ReplyPressKey, "\xD2",0x02,0x46,ID_PressKey },
{DCT3_ReplyPressKey, "\xD2",0x02,0x47,ID_PressKey },
{NULL, "\x00",0x00,0x00,ID_None }
};
GSM_Phone_Functions N6110Phone = {
"2100|3210|3310|3330|3390|3410|3610|5110|5110i|5130|5190|5210|5510|6110|6130|6150|6190|8210|8250|8290|8850|8855|8890",
N6110ReplyFunctions,
N6110_Initialise,
PHONE_Terminate,
GSM_DispatchMessage,
N6110_ShowStartInfo,
NOKIA_GetManufacturer,
DCT3DCT4_GetModel,
DCT3DCT4_GetFirmware,
DCT3_GetIMEI,
DCT3_GetOriginalIMEI,
DCT3_GetManufactureMonth,
DCT3_GetProductCode,
DCT3_GetHardware,
DCT3_GetPPM,
NOTSUPPORTED, /* GetSIMIMSI */
N6110_GetDateTime,
N6110_SetDateTime,
N6110_GetAlarm,
N6110_SetAlarm,
NOTSUPPORTED, /* GetLocale */
NOTSUPPORTED, /* SetLocale */
DCT3_PressKey,
DCT3_Reset,
N61_71_ResetPhoneSettings,
N6110_EnterSecurityCode,
N6110_GetSecurityStatus,
N6110_GetDisplayStatus,
NOTIMPLEMENTED, /* SetAutoNetworkLogin */
N6110_GetBatteryCharge,
N6110_GetSignalQuality,
DCT3_GetNetworkInfo,
NOTSUPPORTED, /* GetCategory */
NOTSUPPORTED, /* AddCategory */
NOTSUPPORTED, /* GetCategoryStatus */
N6110_GetMemoryStatus,
N6110_GetMemory,
NOTIMPLEMENTED, /* GetNextMemory */
N6110_SetMemory,
NOTIMPLEMENTED, /* AddMemory */
N6110_DeleteMemory,
NOTIMPLEMENTED, /* DeleteAllMemory */
N6110_GetSpeedDial,
NOTIMPLEMENTED, /* SetSpeedDial */
DCT3_GetSMSC,
DCT3_SetSMSC,
DCT3_GetSMSStatus,
N6110_GetSMSMessage,
N6110_GetNextSMSMessage,
N6110_SetSMS,
N6110_AddSMS,
N6110_DeleteSMSMessage,
DCT3_SendSMSMessage,
NOTSUPPORTED, /* SendSavedSMS */
+ NOTSUPPORTED, /* SetFastSMSSending */
NOKIA_SetIncomingSMS,
DCT3_SetIncomingCB,
PHONE_GetSMSFolders,
NOTSUPPORTED, /* AddSMSFolder */
NOTSUPPORTED, /* DeleteSMSFolder */
N6110_DialVoice,
N6110_AnswerCall,
DCT3_CancelCall,
N6110_HoldCall,
N6110_UnholdCall,
N6110_ConferenceCall,
N6110_SplitCall,
N6110_TransferCall,
N6110_SwitchCall,
DCT3DCT4_GetCallDivert,
DCT3DCT4_SetCallDivert,
DCT3DCT4_CancelAllDiverts,
NOKIA_SetIncomingCall,
NOKIA_SetIncomingUSSD,
DCT3DCT4_SendDTMF,
N6110_GetRingtone,
N6110_SetRingtone,
NOTSUPPORTED, /* GetRingtonesInfo */
NOTSUPPORTED, /* DeleteUserRingtones */
DCT3_PlayTone,
DCT3_GetWAPBookmark,
DCT3_SetWAPBookmark,
DCT3_DeleteWAPBookmark,
DCT3_GetWAPSettings,
DCT3_SetWAPSettings,
NOTSUPPORTED, /* GetMMSSettings */
NOTSUPPORTED, /* SetMMSSettings */
NOTSUPPORTED, /* GetSyncMLSettings */
NOTSUPPORTED, /* SetSyncMLSettings */
NOTSUPPORTED, /* GetChatSettings */
NOTSUPPORTED, /* SetChatSettings */
N6110_GetBitmap,
N6110_SetBitmap,
NOTSUPPORTED, /* GetToDoStatus */
NOTSUPPORTED, /* GetToDo */
NOTSUPPORTED, /* GetNextToDo */
NOTSUPPORTED, /* SetToDo */
NOTSUPPORTED, /* AddToDo */
NOTSUPPORTED, /* DeleteToDo */
NOTSUPPORTED, /* DeleteAllToDo */
NOTIMPLEMENTED, /* GetCalendarStatus */
NOTIMPLEMENTED, /* GetCalendar */
N6110_GetNextCalendarNote,
NOTIMPLEMENTED, /* SetCalendar */
N6110_AddCalendarNote,
N6110_DeleteCalendarNote,
NOTIMPLEMENTED, /* DeleteAllCalendar */
NOTSUPPORTED, /* GetCalendarSettings */
NOTSUPPORTED, /* SetCalendarSettings */
- NOTSUPPORTED, /* GetNote */
+ NOTSUPPORTED, /* GetNextNote */
N6110_GetProfile,
N6110_SetProfile,
NOTSUPPORTED, /* GetFMStation */
NOTSUPPORTED, /* SetFMStation */
NOTSUPPORTED, /* ClearFMStations */
NOTSUPPORTED, /* GetNextFileFolder */
NOTSUPPORTED, /* GetFilePart */
NOTSUPPORTED, /* AddFile */
NOTSUPPORTED, /* GetFileSystemStatus */
NOTSUPPORTED, /* DeleteFile */
NOTSUPPORTED, /* AddFolder */
NOTSUPPORTED, /* GetGPRSAccessPoint */
NOTSUPPORTED /* SetGPRSAccessPoint */
};
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/nokia/dct3/n7110.c b/gammu/emb/common/phone/nokia/dct3/n7110.c
index 5a02c9c..b597f9b 100644
--- a/gammu/emb/common/phone/nokia/dct3/n7110.c
+++ b/gammu/emb/common/phone/nokia/dct3/n7110.c
@@ -1,194 +1,197 @@
/* (c) 2001-2004 by Marcin Wiacek */
-/* based on some work from Markus Plail and Gnokii */
+/* based on some Markus Plail work from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
#include "../../../gsmstate.h"
#ifdef GSM_ENABLE_NOKIA7110
#include <string.h>
#include <time.h>
#include "../../../misc/coding/coding.h"
#include "../../../gsmcomon.h"
#include "../../../service/gsmlogo.h"
#include "../../pfunc.h"
#include "../nfunc.h"
#include "../nfuncold.h"
#include "n7110.h"
#include "dct3func.h"
static GSM_Error N7110_GetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
{
return DCT3_GetAlarm(s, alarm, 0x19);
}
static GSM_Error N7110_SetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
{
return DCT3_SetAlarm(s, alarm, 0x19);
}
static GSM_Error N7110_ReplyGetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Phonebook entry received\n");
switch (msg.Buffer[6]) {
case 0x0f:
return N71_65_ReplyGetMemoryError(msg.Buffer[10], s);
default:
return N71_65_DecodePhonebook(s, Data->Memory,Data->Bitmap,Data->SpeedDial,msg.Buffer+18,msg.Length-18,false);
}
return ERR_UNKNOWN;
}
static GSM_Error N7110_GetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
0x02, /* memory type */
0x05,
0x00, 0x00, /* location */
0x00, 0x00};
req[9] = NOKIA_GetMemoryType(s, entry->MemoryType,N71_65_MEMORY_TYPES);
if (req[9]==0xff) return ERR_NOTSUPPORTED;
if (entry->Location==0x00) return ERR_INVALIDLOCATION;
req[10] = entry->Location / 256;
req[11] = entry->Location % 256;
s->Phone.Data.Memory=entry;
smprintf(s, "Getting phonebook entry\n");
return GSM_WaitFor (s, req, 14, 0x03, 4, ID_GetMemory);
}
static GSM_Error N7110_ReplyGetMemoryStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Memory status received\n");
/* Quess ;-)) */
if (msg.Buffer[10]==0x10) {
Data->MemoryStatus->MemoryFree = msg.Buffer[14]*256 + msg.Buffer[15];
} else {
Data->MemoryStatus->MemoryFree = msg.Buffer[18];
}
smprintf(s, " Size : %i\n",Data->MemoryStatus->MemoryFree);
Data->MemoryStatus->MemoryUsed = msg.Buffer[16]*256 + msg.Buffer[17];
smprintf(s, " Used : %i\n",Data->MemoryStatus->MemoryUsed);
Data->MemoryStatus->MemoryFree -= Data->MemoryStatus->MemoryUsed;
smprintf(s, " Free : %i\n",Data->MemoryStatus->MemoryFree);
return ERR_NONE;
}
static GSM_Error N7110_GetMemoryStatus(GSM_StateMachine *s, GSM_MemoryStatus *Status)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x03, 0x02,
0x05}; /* Memory type */
req[5] = NOKIA_GetMemoryType(s, Status->MemoryType,N71_65_MEMORY_TYPES);
if (req[5]==0xff) return ERR_NOTSUPPORTED;
s->Phone.Data.MemoryStatus=Status;
smprintf(s, "Getting memory status\n");
return GSM_WaitFor (s, req, 6, 0x03, 4, ID_GetMemoryStatus);
}
static void N7110_GetSMSLocation(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char *folderid, int *location)
{
int ifolderid;
/* simulate flat SMS memory */
if (sms->Folder==0x00) {
ifolderid = sms->Location / PHONE_MAXSMSINFOLDER;
*folderid = (ifolderid + 1) * 0x08;
*location = sms->Location - ifolderid * PHONE_MAXSMSINFOLDER;
} else {
*folderid = sms->Folder * 0x08;
*location = sms->Location;
}
smprintf(s, "SMS folder %i & location %i -> 7110 folder %i & location %i\n",
sms->Folder,sms->Location,*folderid,*location);
}
static void N7110_SetSMSLocation(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char folderid, int location)
{
sms->Folder = 0;
sms->Location = (folderid / 0x08 - 1) * PHONE_MAXSMSINFOLDER + location;
smprintf(s, "7110 folder %i & location %i -> SMS folder %i & location %i\n",
folderid,location,sms->Folder,sms->Location);
}
static GSM_Error N7110_ReplyGetSMSFolders(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int j,current=5;
unsigned char buffer[200];
GSM_Phone_Data *Data = &s->Phone.Data;
switch (msg.Buffer[3]) {
case 0x7B:
smprintf(s, "Names for SMS folders received\n");
Data->SMSFolders->Number=msg.Buffer[4];
for (j=0;j<msg.Buffer[4];j++) {
smprintf(s, "Folder index: %02x",msg.Buffer[current]);
current++;
smprintf(s, ", folder name: \"");
CopyUnicodeString(buffer,msg.Buffer+current);
if ((UnicodeLength(buffer))>GSM_MAX_SMS_FOLDER_NAME_LEN) {
smprintf(s, "Too long text\n");
return ERR_UNKNOWNRESPONSE;
}
CopyUnicodeString(Data->SMSFolders->Folder[j].Name,buffer);
smprintf(s, "%s\"\n",DecodeUnicodeString(buffer));
current=current+2+UnicodeLength(buffer)*2;
Data->SMSFolders->Folder[j].InboxFolder = false;
if (j==0) Data->SMSFolders->Folder[j].InboxFolder = true;
Data->SMSFolders->Folder[j].Memory = MEM_ME;
if (j==0 || j==1) Data->SMSFolders->Folder[j].InboxFolder = MEM_MT;
}
return ERR_NONE;
case 0x7C:
smprintf(s, "Security error ? No PIN ?\n");
return ERR_SECURITYERROR;
case 0xCA:
smprintf(s, "Wait a moment. Phone is during power on and busy now\n");
return ERR_SECURITYERROR;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N7110_GetSMSFolders(GSM_StateMachine *s, GSM_SMSFolders *folders)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x7A, 0x00, 0x00};
s->Phone.Data.SMSFolders=folders;
smprintf(s, "Getting SMS folders\n");
return GSM_WaitFor (s, req, 6, 0x14, 4, ID_GetSMSFolders);
}
static GSM_Error N7110_ReplyGetSMSFolderStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int i;
GSM_Phone_N7110Data *Priv = &s->Phone.Data.Priv.N7110;
smprintf(s, "SMS folder status received\n");
Priv->LastSMSFolder.Number=msg.Buffer[4]*256+msg.Buffer[5];
smprintf(s, "Number of Entries: %i\n",Priv->LastSMSFolder.Number);
smprintf(s, "Locations: ");
for (i=0;i<Priv->LastSMSFolder.Number;i++) {
Priv->LastSMSFolder.Location[i]=msg.Buffer[6+(i*2)]*256+msg.Buffer[(i*2)+7];
if (Priv->LastSMSFolder.Location[i] > PHONE_MAXSMSINFOLDER) {
smprintf(s, "Increase PHONE_MAXSMSINFOLDER\n");
return ERR_UNKNOWNRESPONSE;
}
smprintf(s, "%i ",Priv->LastSMSFolder.Location[i]);
}
smprintf(s, "\n");
NOKIA_SortSMSFolderStatus(s, &Priv->LastSMSFolder);
return ERR_NONE;
}
static GSM_Error N7110_PrivGetSMSFolderStatus(GSM_StateMachine *s, int folderid)
{
unsigned char req[] = {N7110_FRAME_HEADER, 0x6b,
0x08, /* folderID */
@@ -337,384 +340,385 @@ static GSM_Error N7110_ReplyGetSMSMessage(GSM_Protocol_Message msg, GSM_StateMac
return ERR_NONE;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N7110_PrivGetSMSMessage(GSM_StateMachine *s, GSM_MultiSMSMessage *sms)
{
GSM_Error error;
unsigned char folderid;
int location;
int i;
unsigned char req[] = {N6110_FRAME_HEADER, 0x07,
0x08, /* folder ID */
0x00, 0x05, /* location */
0x01, 0x65, 0x01};
unsigned char NameReq[] = {N6110_FRAME_HEADER, 0x6E,
0x08, /* folder ID */
0x00, 0x05}; /* location */
N7110_GetSMSLocation(s, &sms->SMS[0], &folderid, &location);
req[4]=folderid;
req[5]=location / 256;
req[6]=location;
s->Phone.Data.GetSMSMessage=sms;
smprintf(s, "Getting sms\n");
error=GSM_WaitFor (s, req, 10, 0x14, 4, ID_GetSMSMessage);
if (error==ERR_NONE) {
NameReq[4] = folderid;
NameReq[5] = location / 256;
NameReq[6] = location;
smprintf(s, "Getting sms info\n");
error=GSM_WaitFor (s, NameReq, 7, 0x14, 4, ID_GetSMSMessage);
if (error != ERR_NONE) return error;
for (i=0;i<sms->Number;i++) {
N7110_SetSMSLocation(s, &sms->SMS[i], folderid, location);
sms->SMS[i].Folder = folderid/0x08;
sms->SMS[i].InboxFolder = true;
if (folderid/0x08 != 0x01) sms->SMS[i].InboxFolder = false;
CopyUnicodeString(sms->SMS[i].Name,sms->SMS[0].Name);
sms->SMS[i].Memory = MEM_ME;
if (folderid/0x08 == 0x01 || folderid/0x08 == 0x02) {
sms->SMS[i].Memory = MEM_MT;
if (folderid/0x08 == 0x01) { /* Inbox */
if (sms->SMS[i].State == SMS_Sent) sms->SMS[i].Memory = MEM_ME;
if (sms->SMS[i].State == SMS_UnSent) sms->SMS[i].Memory = MEM_ME;
if (sms->SMS[i].State == SMS_Read) sms->SMS[i].Memory = MEM_SM;
if (sms->SMS[i].State == SMS_UnRead) sms->SMS[i].Memory = MEM_SM;
}
if (folderid/0x08 == 0x02) { /* Outbox */
if (sms->SMS[i].State == SMS_Sent) sms->SMS[i].Memory = MEM_SM;
if (sms->SMS[i].State == SMS_UnSent) sms->SMS[i].Memory = MEM_SM;
if (sms->SMS[i].State == SMS_Read) sms->SMS[i].Memory = MEM_ME;
if (sms->SMS[i].State == SMS_UnRead) sms->SMS[i].Memory = MEM_ME;
}
}
}
}
return error;
}
static GSM_Error N7110_GetSMSMessage(GSM_StateMachine *s, GSM_MultiSMSMessage *sms)
{
GSM_Error error;
unsigned char folderid;
int location;
GSM_Phone_N7110Data *Priv = &s->Phone.Data.Priv.N7110;
int i;
bool found = false;
N7110_GetSMSLocation(s, &sms->SMS[0], &folderid, &location);
error=N7110_GetSMSFolderStatus(s, folderid);
if (error!=ERR_NONE) return error;
for (i=0;i<Priv->LastSMSFolder.Number;i++) {
if (Priv->LastSMSFolder.Location[i]==location) {
found = true;
break;
}
}
if (!found) return ERR_EMPTY;
return N7110_PrivGetSMSMessage(s,sms);
}
static GSM_Error N7110_GetNextSMSMessage(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, bool start)
{
GSM_Phone_N7110Data *Priv = &s->Phone.Data.Priv.N7110;
unsigned char folderid;
int location;
GSM_Error error;
int i;
bool findnextfolder = false;
if (start) {
folderid=0x00;
findnextfolder=true;
error=N7110_GetSMSFolders(s,&Priv->LastSMSFolders);
if (error!=ERR_NONE) return error;
} else {
N7110_GetSMSLocation(s, &sms->SMS[0], &folderid, &location);
for (i=0;i<Priv->LastSMSFolder.Number;i++) {
if (Priv->LastSMSFolder.Location[i]==location) break;
}
/* Is this last location in this folder ? */
if (i==Priv->LastSMSFolder.Number-1) {
findnextfolder=true;
} else {
location=Priv->LastSMSFolder.Location[i+1];
}
}
if (findnextfolder) {
Priv->LastSMSFolder.Number=0;
while (Priv->LastSMSFolder.Number==0) {
folderid=folderid+0x08;
/* Too high folder number */
if ((folderid/0x08)>Priv->LastSMSFolders.Number) return ERR_EMPTY;
/* Get next folder status */
error=N7110_GetSMSFolderStatus(s, folderid);
if (error!=ERR_NONE) return error;
/* First location from this folder */
location=Priv->LastSMSFolder.Location[0];
}
}
N7110_SetSMSLocation(s, &sms->SMS[0], folderid, location);
return N7110_PrivGetSMSMessage(s, sms);
}
static int N7110_ReturnBinaryRingtoneLocation(char *model)
{
if (strcmp(model,"NSE-5") == 0) return 0x72; /* first 0x72 - 7110 */
if (strcmp(model,"NPE-3") == 0) return 0x89; /* first 0x89 - 6210 */
if (strcmp(model,"NHM-3") == 0) return 0x89; /* quess for 6250 */
return 0;
}
static GSM_Error N7110_ReplyGetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int tmp,i;
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Ringtone received\n");
switch (msg.Buffer[3]) {
case 0x23:
tmp=0;i=4;
while (msg.Buffer[i]!=0 || msg.Buffer[i+1]!=0) {
tmp++;
i=i+2;
if (i>msg.Length) return ERR_EMPTY;
}
memcpy(Data->Ringtone->Name,msg.Buffer+6,tmp*2);
smprintf(s, "Name \"%s\"\n",DecodeUnicodeString(Data->Ringtone->Name));
/* Looking for end */
i=37;
while (true) {
if (msg.Buffer[i]==0x07 && msg.Buffer[i+1]==0x0b) {
i=i+2; break;
}
if (msg.Buffer[i]==0x0e && msg.Buffer[i+1]==0x0b) {
i=i+2; break;
}
i++;
if (i==msg.Length) return ERR_EMPTY;
}
/* Copying frame */
memcpy(Data->Ringtone->NokiaBinary.Frame,msg.Buffer+37,i-37);
Data->Ringtone->NokiaBinary.Length=i-37;
return ERR_NONE;
case 0x24:
smprintf(s, "Invalid location. Too high ?\n");
return ERR_INVALIDLOCATION;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N7110_GetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone)
{
unsigned char req[] = {N7110_FRAME_HEADER, 0x22, 0x00, 0x00};
if (PhoneRingtone) return ERR_NOTSUPPORTED;
if (Ringtone->Format == 0x00) Ringtone->Format = RING_NOKIABINARY;
switch (Ringtone->Format) {
case RING_NOTETONE:
/* In the future get binary and convert */
return ERR_NOTSUPPORTED;
case RING_NOKIABINARY:
req[5]=N7110_ReturnBinaryRingtoneLocation(s->Phone.Data.Model)+Ringtone->Location;
s->Phone.Data.Ringtone=Ringtone;
smprintf(s, "Getting binary ringtone\n");
return GSM_WaitFor (s, req, 6, 0x1f, 4, ID_GetRingtone);
case RING_MIDI:
+ case RING_MMF:
return ERR_NOTSUPPORTED;
}
return ERR_NOTSUPPORTED;
}
static GSM_Error N7110_ReplyGetPictureImageInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int i;
GSM_Phone_N7110Data *Priv = &s->Phone.Data.Priv.N7110;
smprintf(s, "Received info for Picture Images\n");
smprintf(s, "Number : %i\n",msg.Buffer[4]*256+msg.Buffer[5]);
smprintf(s, "Locations :");
Priv->LastPictureImageFolder.Number=msg.Buffer[4]*256+msg.Buffer[5];
for (i=0;i<Priv->LastPictureImageFolder.Number;i++) {
Priv->LastPictureImageFolder.Location[i]=msg.Buffer[6+i*2]*256+msg.Buffer[7+i*2];
smprintf(s, " %i",Priv->LastPictureImageFolder.Location[i]);
}
smprintf(s, "\n");
return ERR_NONE;
}
static GSM_Error N7110_GetPictureImageLocation(GSM_StateMachine *s, GSM_Bitmap *Bitmap, unsigned char *folder, int *location)
{
GSM_Phone_N7110Data *Priv = &s->Phone.Data.Priv.N7110;
GSM_SMSFolders folders;
GSM_Error error;
int i, j = 0, count = 0;
unsigned char req[] = {N6110_FRAME_HEADER, 0x96,
0x00, /* Folder ID */
0x0f, 0x07};
error=N7110_GetSMSFolders (s, &folders);
if (error!=ERR_NONE) return error;
for (i=0;i<folders.Number;i++) {
req[4] = (i+1) * 0x08; /* SMS folder ID */
error = GSM_WaitFor (s, req, 7, 0x14, 4, ID_GetBitmap);
if (error!=ERR_NONE) return error;
for (j=0;j<Priv->LastPictureImageFolder.Number;j++) {
count++;
if (count==Bitmap->Location) break;
}
if (count==Bitmap->Location) break;
}
if (count!=Bitmap->Location) return ERR_INVALIDLOCATION;
*folder = (i+1) * 0x08; /* SMS Folder ID */
*location = Priv->LastPictureImageFolder.Location[j];
return ERR_NONE;
}
static GSM_Error N7110_GetPictureImage(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
{
unsigned char folder;
int location;
GSM_Error error;
unsigned char req[] = {N6110_FRAME_HEADER, 0x07,
0x00, /* Folder ID */
0x00, 0x00, /* Location */
0x00, 0x64};
error = N7110_GetPictureImageLocation(s, Bitmap, &folder, &location);
switch (error) {
case ERR_NONE:
req[4] = folder;
req[5] = location / 256;
req[6] = location % 256;
return GSM_WaitFor (s, req, 9, 0x14, 4, ID_GetBitmap);
default:
return error;
}
}
static GSM_Error N7110_GetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
{
GSM_MemoryEntry pbk;
GSM_Error error;
unsigned char OpReq[] = {N6110_FRAME_HEADER, 0x70};
s->Phone.Data.Bitmap=Bitmap;
switch (Bitmap->Type) {
case GSM_StartupLogo:
smprintf(s, "Getting startup logo\n");
return N71_92_GetPhoneSetting(s, ID_GetBitmap, 0x15);
case GSM_WelcomeNote_Text:
smprintf(s, "Getting welcome note\n");
return N71_92_GetPhoneSetting(s, ID_GetBitmap, 0x02);
case GSM_DealerNote_Text:
smprintf(s, "Getting dealer note\n");
return N71_92_GetPhoneSetting(s, ID_GetBitmap, 0x17);
case GSM_CallerGroupLogo:
pbk.MemoryType = MEM7110_CG;
pbk.Location = Bitmap->Location;
smprintf(s, "Getting caller group logo\n");
error=N7110_GetMemory(s,&pbk);
if (error==ERR_NONE) NOKIA_GetDefaultCallerGroupName(s,Bitmap);
return error;
case GSM_OperatorLogo:
smprintf(s, "Getting operator logo\n");
/* This is like DCT3_GetNetworkInfo */
return GSM_WaitFor (s, OpReq, 4, 0x0a, 4, ID_GetBitmap);
case GSM_PictureImage:
/* 7110 doesn't support it */
if (strcmp(s->Phone.Data.Model,"NSE-5") == 0) return ERR_NOTSUPPORTED;
return N7110_GetPictureImage(s, Bitmap);
default:
break;
}
return ERR_NOTSUPPORTED;
}
static GSM_Error N7110_SetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength)
{
GSM_Ringtone dest;
GSM_Error error;
GSM_NetworkInfo NetInfo;
int size=200;
unsigned char req[1000] = {0x7C, 0x01, 0x00, 0x0D, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00}; /*Length*/
unsigned char req2[4000] = {N7110_FRAME_HEADER, 0x1F, 0x00,
0x87, /* Location */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
switch (Ringtone->Format) {
case RING_NOTETONE:
if (Ringtone->Location==255) {
/* 7110 doesn't support it */
if (strcmp(s->Phone.Data.Model,"NSE-5") == 0) return ERR_NOTSUPPORTED;
*maxlength=GSM_EncodeNokiaRTTLRingtone(*Ringtone, req+11, &size);
req[10] = size;
error = s->Protocol.Functions->WriteMessage(s, req, size+11, 0x00);
if (error!=ERR_NONE) return error;
my_sleep(1000);
/* We have to make something (not important, what) now */
/* no answer from phone*/
return DCT3_GetNetworkInfo(s,&NetInfo);
}
GSM_RingtoneConvert(&dest, Ringtone, RING_NOKIABINARY);
break;
case RING_NOKIABINARY:
memcpy(&dest,Ringtone,sizeof(GSM_Ringtone));
break;
default:
return ERR_NOTSUPPORTED;
}
req2[5]=N7110_ReturnBinaryRingtoneLocation(s->Phone.Data.Model)+Ringtone->Location;
CopyUnicodeString(req2+6,Ringtone->Name);
memcpy(req2+37,dest.NokiaBinary.Frame,dest.NokiaBinary.Length);
error = s->Protocol.Functions->WriteMessage(s, req2, 37+dest.NokiaBinary.Length, 0x1F);
if (error!=ERR_NONE) return error;
my_sleep(1000);
/* We have to make something (not important, what) now */
/* no answer from phone*/
return DCT3_GetNetworkInfo(s,&NetInfo);
}
static GSM_Error N7110_ReplySaveSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
switch (msg.Buffer[3]) {
case 0x05:
smprintf(s, "SMS message saving status\n");
smprintf(s, "Saved in folder %i at location %i\n",msg.Buffer[4], msg.Buffer[5]*256+msg.Buffer[6]);
if (msg.Buffer[4] == 0xf8) {
N7110_SetSMSLocation(s, Data->SaveSMSMessage,0x08,msg.Buffer[5]*256+msg.Buffer[6]);
Data->SaveSMSMessage->Folder = 0x01;
} else {
N7110_SetSMSLocation(s, Data->SaveSMSMessage,msg.Buffer[4],msg.Buffer[5]*256+msg.Buffer[6]);
Data->SaveSMSMessage->Folder = msg.Buffer[4] / 0x08;
}
return ERR_NONE;
case 0x06:
smprintf(s, "SMS message saving status\n");
switch (msg.Buffer[4]) {
case 0x03:
smprintf(s, "Too high location ?\n");
return ERR_INVALIDLOCATION;
default:
smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
}
break;
case 0x84:
smprintf(s, "Name for SMS changed OK to \"%s\"\n",DecodeUnicodeString(msg.Buffer+7));
smprintf(s, "Saved in folder %i at location %i\n",msg.Buffer[4], msg.Buffer[5]*256+msg.Buffer[6]);
if (msg.Buffer[4] == 0xf8) {
N7110_SetSMSLocation(s, Data->SaveSMSMessage,0x08,msg.Buffer[5]*256+msg.Buffer[6]);
@@ -1458,267 +1462,268 @@ static GSM_Reply_Function N7110ReplyFunctions[] = {
{N71_65_ReplySendDTMF, "\x01",0x03,0x5E,ID_SendDTMF },
{DCT3_ReplySendSMSMessage, "\x02",0x03,0x02,ID_IncomingFrame },
{DCT3_ReplySendSMSMessage, "\x02",0x03,0x03,ID_IncomingFrame },
{N7110_ReplyIncomingSMS, "\x02",0x03,0x10,ID_IncomingFrame },
#ifdef GSM_ENABLE_CELLBROADCAST
{DCT3_ReplySetIncomingCB, "\x02",0x03,0x21,ID_SetIncomingCB },
{DCT3_ReplySetIncomingCB, "\x02",0x03,0x22,ID_SetIncomingCB },
{DCT3_ReplyIncomingCB, "\x02",0x03,0x23,ID_IncomingFrame },
#endif
{DCT3_ReplySetSMSC, "\x02",0x03,0x31,ID_SetSMSC },
{DCT3_ReplyGetSMSC, "\x02",0x03,0x34,ID_GetSMSC },
{DCT3_ReplyGetSMSC, "\x02",0x03,0x35,ID_GetSMSC },
#ifdef GSM_ENABLE_CELLBROADCAST
{DCT3_ReplySetIncomingCB, "\x02",0x03,0xCA,ID_SetIncomingCB },
#endif
{N7110_ReplyGetMemoryStatus, "\x03",0x03,0x04,ID_GetMemoryStatus },
{N7110_ReplyGetMemory, "\x03",0x03,0x08,ID_GetMemory },
{N7110_ReplyDeleteMemory, "\x03",0x03,0x10,ID_SetMemory },
{N71_65_ReplyWritePhonebook, "\x03",0x03,0x0C,ID_SetBitmap },
{N71_65_ReplyWritePhonebook, "\x03",0x03,0x0C,ID_SetMemory },
{N71_65_ReplyUSSDInfo, "\x06",0x03,0x03,ID_IncomingFrame },
{NoneReply, "\x06",0x03,0x06,ID_IncomingFrame },
{DCT3_ReplySIMLogin, "\x09",0x03,0x80,ID_IncomingFrame },
{DCT3_ReplySIMLogout, "\x09",0x03,0x81,ID_IncomingFrame },
{DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_GetNetworkInfo },
{DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_GetBitmap },
{DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_IncomingFrame },
{N7110_ReplyGetNetworkInfoError, "\x0A",0x03,0x72,ID_GetNetworkInfo },
{DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x73,ID_IncomingFrame },
{N71_92_ReplyGetSignalQuality, "\x0A",0x03,0x82,ID_GetSignalQuality },
{N7110_ReplySetOperatorLogo, "\x0A",0x03,0xA4,ID_SetBitmap },
{N7110_ReplyClearOperatorLogo, "\x0A",0x03,0xB0,ID_SetBitmap },
{NoneReply, "\x0A",0x03,0xB5,ID_IncomingFrame },
#ifdef DEBUG
{N71_65_ReplyAddCalendar1, "\x13",0x03,0x02,ID_SetCalendarNote },/*method 1*/
{N71_65_ReplyAddCalendar1, "\x13",0x03,0x04,ID_SetCalendarNote },/*method 1*/
{N71_65_ReplyAddCalendar1, "\x13",0x03,0x06,ID_SetCalendarNote },/*method 1*/
{N71_65_ReplyAddCalendar1, "\x13",0x03,0x08,ID_SetCalendarNote },/*method 1*/
#endif
{N71_65_ReplyDelCalendar, "\x13",0x03,0x0C,ID_DeleteCalendarNote },
{N71_65_ReplyGetNextCalendar1, "\x13",0x03,0x1A,ID_GetCalendarNote },/*method 1*/
#ifdef DEBUG
{N7110_ReplyGetCalendarNotePos, "\x13",0x03,0x32,ID_GetCalendarNotePos },/*method 1*/
#endif
{N7110_ReplyGetCalendarInfo, "\x13",0x03,0x3B,ID_GetCalendarNotesInfo},/*method 1*/
#ifdef DEBUG
{N71_65_ReplyGetNextCalendar2, "\x13",0x03,0x3F,ID_GetCalendarNote },/*method 2*/
#endif
{N71_65_ReplyAddCalendar2, "\x13",0x03,0x41,ID_SetCalendarNote },/*method 2*/
{N7110_ReplySaveSMSMessage, "\x14",0x03,0x05,ID_SaveSMSMessage },
{N7110_ReplySaveSMSMessage, "\x14",0x03,0x06,ID_SaveSMSMessage },
{N7110_ReplyGetSMSMessage, "\x14",0x03,0x08,ID_GetSMSMessage },
{N7110_ReplyGetSMSMessage, "\x14",0x03,0x08,ID_GetBitmap },
{N7110_ReplyGetSMSMessage, "\x14",0x03,0x09,ID_GetSMSMessage },
{DCT3_ReplyDeleteSMSMessage, "\x14",0x03,0x0B,ID_DeleteSMSMessage },
{DCT3_ReplyDeleteSMSMessage, "\x14",0x03,0x0C,ID_DeleteSMSMessage },
{N7110_ReplyGetSMSStatus, "\x14",0x03,0x37,ID_GetSMSStatus },
{N7110_ReplyGetSMSStatus, "\x14",0x03,0x38,ID_GetSMSStatus },
{N7110_ReplySetPicture, "\x14",0x03,0x51,ID_SetBitmap },
{N7110_ReplyGetSMSFolderStatus, "\x14",0x03,0x6C,ID_GetSMSFolderStatus },
{N7110_ReplyGetSMSMessage, "\x14",0x03,0x6F,ID_GetSMSMessage },
{N7110_ReplyGetSMSFolders, "\x14",0x03,0x7B,ID_GetSMSFolders },
{N7110_ReplyGetSMSFolders, "\x14",0x03,0x7C,ID_GetSMSFolders },
{N7110_ReplySaveSMSMessage, "\x14",0x03,0x84,ID_SaveSMSMessage },
{N7110_ReplyGetPictureImageInfo, "\x14",0x03,0x97,ID_GetBitmap },
{N7110_ReplyGetSMSFolders, "\x14",0x03,0xCA,ID_GetSMSFolders },
{N71_92_ReplyGetBatteryCharge, "\x17",0x03,0x03,ID_GetBatteryCharge },
{DCT3_ReplySetDateTime, "\x19",0x03,0x61,ID_SetDateTime },
{DCT3_ReplyGetDateTime, "\x19",0x03,0x63,ID_GetDateTime },
{DCT3_ReplySetAlarm, "\x19",0x03,0x6C,ID_SetAlarm },
{DCT3_ReplyGetAlarm, "\x19",0x03,0x6E,ID_GetAlarm },
{N7110_ReplyGetRingtone, "\x1f",0x03,0x23,ID_GetRingtone },
{N7110_ReplyGetRingtone, "\x1f",0x03,0x24,ID_GetRingtone },
{DCT3DCT4_ReplyEnableConnectFunc, "\x3f",0x03,0x01,ID_EnableConnectFunc },
{DCT3DCT4_ReplyEnableConnectFunc, "\x3f",0x03,0x02,ID_EnableConnectFunc },
{DCT3DCT4_ReplyDisableConnectFunc,"\x3f",0x03,0x04,ID_DisableConnectFunc },
{DCT3DCT4_ReplyDisableConnectFunc,"\x3f",0x03,0x05,ID_DisableConnectFunc },
{DCT3_ReplyGetWAPBookmark, "\x3f",0x03,0x07,ID_GetWAPBookmark },
{DCT3_ReplyGetWAPBookmark, "\x3f",0x03,0x08,ID_GetWAPBookmark },
{DCT3DCT4_ReplySetWAPBookmark, "\x3f",0x03,0x0A,ID_SetWAPBookmark },
{DCT3DCT4_ReplySetWAPBookmark, "\x3f",0x03,0x0B,ID_SetWAPBookmark },
{DCT3DCT4_ReplyDelWAPBookmark, "\x3f",0x03,0x0D,ID_DeleteWAPBookmark },
{DCT3DCT4_ReplyDelWAPBookmark, "\x3f",0x03,0x0E,ID_DeleteWAPBookmark },
{DCT3DCT4_ReplyGetActiveConnectSet,"\x3f",0x03,0x10,ID_GetConnectSet },
{DCT3DCT4_ReplySetActiveConnectSet,"\x3f",0x03,0x13,ID_SetConnectSet },
{DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x16,ID_GetConnectSet },
{DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x17,ID_GetConnectSet },
{DCT3_ReplySetWAPSettings, "\x3f",0x03,0x19,ID_SetConnectSet },
{DCT3_ReplySetWAPSettings, "\x3f",0x03,0x1A,ID_SetConnectSet },
{DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x1C,ID_GetConnectSet },
{DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x1D,ID_GetConnectSet },
{DCT3_ReplySetWAPSettings, "\x3f",0x03,0x1F,ID_SetConnectSet },
{N7110_ReplyGetProfileFeature, "\x39",0x03,0x02,ID_GetProfile },
{N7110_ReplySetProfileFeature, "\x39",0x03,0x04,ID_SetProfile },
{DCT3_ReplyEnableSecurity, "\x40",0x02,0x64,ID_EnableSecurity },
{N61_71_ReplyResetPhoneSettings, "\x40",0x02,0x65,ID_ResetPhoneSettings },
{DCT3_ReplyGetIMEI, "\x40",0x02,0x66,ID_GetIMEI },
{DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_DialVoice },
{DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_CancelCall },
{DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_AnswerCall },
{DCT3_ReplyNetmonitor, "\x40",0x02,0x7E,ID_Netmonitor },
{DCT3_ReplyPlayTone, "\x40",0x02,0x8F,ID_PlayTone },
{NOKIA_ReplyGetPhoneString, "\x40",0x02,0xC8,ID_GetHardware },
{NOKIA_ReplyGetPhoneString, "\x40",0x02,0xC8,ID_GetPPM },
{NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCA,ID_GetProductCode },
{NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCC,ID_GetManufactureMonth },
{NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCC,ID_GetOriginalIMEI },
{NoneReply, "\x40",0x02,0xFF,ID_IncomingFrame },
{N71_92_ReplyPhoneSetting, "\x7a",0x04,0x02,ID_GetBitmap },
{N71_92_ReplyPhoneSetting, "\x7a",0x04,0x02,ID_SetBitmap },
{N71_92_ReplyPhoneSetting, "\x7a",0x04,0x15,ID_GetBitmap },
{N71_92_ReplyPhoneSetting, "\x7a",0x04,0x15,ID_SetBitmap },
{N71_92_ReplyPhoneSetting, "\x7a",0x04,0x17,ID_GetBitmap },
{N71_92_ReplyPhoneSetting, "\x7a",0x04,0x17,ID_SetBitmap },
{DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetModel },
{DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetFirmware },
{DCT3_ReplyPressKey, "\xD2",0x02,0x46,ID_PressKey },
{DCT3_ReplyPressKey, "\xD2",0x02,0x47,ID_PressKey },
{NULL, "\x00",0x00,0x00,ID_None }
};
GSM_Phone_Functions N7110Phone = {
"6210|6250|7110|7190",
N7110ReplyFunctions,
N7110_Initialise,
PHONE_Terminate,
GSM_DispatchMessage,
NOTSUPPORTED, /* ShowStartInfo */
NOKIA_GetManufacturer,
DCT3DCT4_GetModel,
DCT3DCT4_GetFirmware,
DCT3_GetIMEI,
DCT3_GetOriginalIMEI,
DCT3_GetManufactureMonth,
DCT3_GetProductCode,
DCT3_GetHardware,
DCT3_GetPPM,
NOTSUPPORTED, /* GetSIMIMSI */
N71_92_GetDateTime,
N71_92_SetDateTime,
N7110_GetAlarm,
N7110_SetAlarm,
NOTSUPPORTED, /* GetLocale */
NOTSUPPORTED, /* SetLocale */
DCT3_PressKey,
DCT3_Reset,
N61_71_ResetPhoneSettings,
NOTSUPPORTED, /* EnterSecurityCode */
NOTSUPPORTED, /* GetSecurityStatus */
NOTSUPPORTED, /* GetDisplayStatus */
NOTIMPLEMENTED, /* SetAutoNetworkLogin */
N71_92_GetBatteryCharge,
N71_92_GetSignalQuality,
DCT3_GetNetworkInfo,
NOTSUPPORTED, /* GetCategory */
NOTSUPPORTED, /* AddCategory */
NOTSUPPORTED, /* GetCategoryStatus */
N7110_GetMemoryStatus,
N7110_GetMemory,
NOTIMPLEMENTED, /* GetNextMemory */
N7110_SetMemory,
NOTIMPLEMENTED, /* AddMemory */
N7110_DeleteMemory,
NOTIMPLEMENTED, /* DeleteAllMemory */
N7110_GetSpeedDial,
NOTIMPLEMENTED, /* SetSpeedDial */
DCT3_GetSMSC,
DCT3_SetSMSC,
N7110_GetSMSStatus,
N7110_GetSMSMessage,
N7110_GetNextSMSMessage,
N7110_SetSMS,
N7110_AddSMS,
N7110_DeleteSMS,
DCT3_SendSMSMessage,
NOTSUPPORTED, /* SendSavedSMS */
+ NOTSUPPORTED, /* SetFastSMSSending */
N7110_SetIncomingSMS,
DCT3_SetIncomingCB,
N7110_GetSMSFolders,
NOTIMPLEMENTED, /* AddSMSFolder */
NOTIMPLEMENTED, /* DeleteSMSFolder */
DCT3_DialVoice,
N7110_AnswerCall,
DCT3_CancelCall,
NOTIMPLEMENTED, /* HoldCall */
NOTIMPLEMENTED, /* UnholdCall */
NOTIMPLEMENTED, /* ConferenceCall */
NOTIMPLEMENTED, /* SplitCall */
NOTIMPLEMENTED, /* TransferCall */
NOTIMPLEMENTED, /* SwitchCall */
NOTSUPPORTED, /* GetCallDivert */
N7110_SetCallDivert,
N7110_CancelAllDiverts,
N7110_SetIncomingCall,
N7110_SetIncomingUSSD,
DCT3DCT4_SendDTMF,
N7110_GetRingtone,
N7110_SetRingtone,
NOTSUPPORTED, /* GetRingtonesInfo */
NOTSUPPORTED, /* DeleteUserRingtones */
DCT3_PlayTone,
DCT3_GetWAPBookmark,
DCT3_SetWAPBookmark,
DCT3_DeleteWAPBookmark,
DCT3_GetWAPSettings,
DCT3_SetWAPSettings,
NOTSUPPORTED, /* GetMMSSettings */
NOTSUPPORTED, /* SetMMSSettings */
NOTSUPPORTED, /* GetSyncMLSettings */
NOTSUPPORTED, /* SetSyncMLSettings */
NOTSUPPORTED, /* GetChatSettings */
NOTSUPPORTED, /* SetChatSettings */
N7110_GetBitmap,
N7110_SetBitmap,
NOTSUPPORTED, /* GetToDoStatus */
NOTSUPPORTED, /* GetToDo */
NOTSUPPORTED, /* GetNextToDo */
NOTSUPPORTED, /* SetToDo */
NOTSUPPORTED, /* AddToDo */
NOTSUPPORTED, /* DeleteToDo */
NOTSUPPORTED, /* DeleteAllToDo */
N7110_GetCalendarStatus,
NOTIMPLEMENTED, /* GetCalendar */
N7110_GetNextCalendar,
NOTIMPLEMENTED, /* SetCalendar */
N7110_AddCalendar,
N71_65_DelCalendar,
NOTIMPLEMENTED, /* DeleteAllCalendar */
NOTSUPPORTED, /* GetCalendarSettings */
NOTSUPPORTED, /* SetCalendarSettings */
- NOTSUPPORTED, /* GetNote */
+ NOTSUPPORTED, /* GetNextNote */
N7110_GetProfile,
N7110_SetProfile,
NOTSUPPORTED, /* GetFMStation */
NOTSUPPORTED, /* SetFMStation */
NOTSUPPORTED, /* ClearFMStations */
NOTSUPPORTED, /* GetNextFileFolder */
NOTSUPPORTED, /* GetFilePart */
NOTSUPPORTED, /* AddFile */
NOTSUPPORTED, /* GetFileSystemStatus */
NOTSUPPORTED, /* DeleteFile */
NOTSUPPORTED, /* AddFolder */
NOTSUPPORTED, /* GetGPRSAccessPoint */
NOTSUPPORTED /* SetGPRSAccessPoint */
};
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/nokia/dct3/n9210.c b/gammu/emb/common/phone/nokia/dct3/n9210.c
index e82d530..ff71ad3 100644
--- a/gammu/emb/common/phone/nokia/dct3/n9210.c
+++ b/gammu/emb/common/phone/nokia/dct3/n9210.c
@@ -130,267 +130,268 @@ static GSM_Error N9210_SetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
static GSM_Error N9210_ReplyIncomingSMS(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_SMSMessage sms;
GSM_Phone_Data *Data = &s->Phone.Data;
#ifdef DEBUG
smprintf(s, "SMS message received\n");
sms.State = SMS_UnRead;
sms.InboxFolder = true;
DCT3_DecodeSMSFrame(s, &sms,msg.Buffer+5);
#endif
if (Data->EnableIncomingSMS && s->User.IncomingSMS!=NULL) {
sms.State = SMS_UnRead;
sms.InboxFolder = true;
DCT3_DecodeSMSFrame(s, &sms,msg.Buffer+5);
s->User.IncomingSMS(s->CurrentConfig->Device,sms);
}
return ERR_NONE;
}
#ifdef GSM_ENABLE_N71_92INCOMINGINFO
static GSM_Error N9210_ReplySetIncomingSMS(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[3]) {
case 0x0e:
s->Phone.Data.EnableIncomingSMS = true;
smprintf(s, "Incoming SMS enabled\n");
return ERR_NONE;
case 0x0f:
smprintf(s, "Error enabling incoming SMS\n");
switch (msg.Buffer[4]) {
case 0x0c:
smprintf(s, "No PIN ?\n");
return ERR_SECURITYERROR;
default:
smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
}
}
return ERR_UNKNOWNRESPONSE;
}
#endif
static GSM_Error N9210_SetIncomingSMS(GSM_StateMachine *s, bool enable)
{
#ifdef GSM_ENABLE_N71_92INCOMINGINFO
unsigned char req[] = {N6110_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x02};
if (enable!=s->Phone.Data.EnableIncomingSMS) {
if (enable) {
smprintf(s, "Enabling incoming SMS\n");
return GSM_WaitFor (s, req, 7, 0x02, 4, ID_SetIncomingSMS);
} else {
s->Phone.Data.EnableIncomingSMS = false;
smprintf(s, "Disabling incoming SMS\n");
}
}
return ERR_NONE;
#else
return ERR_SOURCENOTAVAILABLE;
#endif
}
static GSM_Error N9210_Initialise (GSM_StateMachine *s)
{
#ifdef DEBUG
DCT3_SetIncomingCB(s,true);
#ifdef GSM_ENABLE_N71_92INCOMINGINFO
N9210_SetIncomingSMS(s,true);
#endif
#endif
return ERR_NONE;
}
GSM_Error N9210_AnswerCall(GSM_StateMachine *s, int ID, bool all)
{
if (!all) return DCT3DCT4_AnswerCall(s,ID);
return DCT3_AnswerAllCalls(s);
}
static GSM_Reply_Function N9210ReplyFunctions[] = {
{DCT3_ReplySendSMSMessage, "\x02",0x03,0x02,ID_IncomingFrame },
{DCT3_ReplySendSMSMessage, "\x02",0x03,0x03,ID_IncomingFrame },
#ifdef GSM_ENABLE_N71_92INCOMINGINFO
{N9210_ReplySetIncomingSMS, "\x02",0x03,0x0E,ID_SetIncomingSMS },
{N9210_ReplySetIncomingSMS, "\x02",0x03,0x0F,ID_SetIncomingSMS },
#endif
{N9210_ReplyIncomingSMS, "\x02",0x03,0x11,ID_IncomingFrame },
#ifdef GSM_ENABLE_CELLBROADCAST
{DCT3_ReplySetIncomingCB, "\x02",0x03,0x21,ID_SetIncomingCB },
{DCT3_ReplySetIncomingCB, "\x02",0x03,0x22,ID_SetIncomingCB },
{DCT3_ReplyIncomingCB, "\x02",0x03,0x23,ID_IncomingFrame },
#endif
{DCT3_ReplySetSMSC, "\x02",0x03,0x31,ID_SetSMSC },
{DCT3_ReplyGetSMSC, "\x02",0x03,0x34,ID_GetSMSC },
{DCT3_ReplyGetSMSC, "\x02",0x03,0x35,ID_GetSMSC },
{N61_91_ReplySetOpLogo, "\x05",0x03,0x31,ID_SetBitmap },
{N61_91_ReplySetOpLogo, "\x05",0x03,0x32,ID_SetBitmap },
{DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_GetNetworkInfo },
{DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_IncomingFrame },
{N71_92_ReplyGetSignalQuality, "\x0A",0x03,0x82,ID_GetSignalQuality },
{N9210_ReplySetOpLogo, "\x0A",0x03,0xA4,ID_SetBitmap },
{N9210_ReplySetOpLogo, "\x0A",0x03,0xB0,ID_SetBitmap },
{N71_92_ReplyGetBatteryCharge, "\x17",0x03,0x03,ID_GetBatteryCharge },
{DCT3_ReplySetDateTime, "\x19",0x03,0x61,ID_SetDateTime },
{DCT3_ReplyGetDateTime, "\x19",0x03,0x63,ID_GetDateTime },
{DCT3_ReplyEnableSecurity, "\x40",0x02,0x64,ID_EnableSecurity },
{DCT3_ReplyGetIMEI, "\x40",0x02,0x66,ID_GetIMEI },
{DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_DialVoice },
{DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_CancelCall },
{DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_AnswerCall },
{DCT3_ReplyNetmonitor, "\x40",0x02,0x7E,ID_Netmonitor },
{NOKIA_ReplyGetPhoneString, "\x40",0x02,0xC8,ID_GetHardware },
{NOKIA_ReplyGetPhoneString, "\x40",0x02,0xC8,ID_GetPPM },
{NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCA,ID_GetProductCode },
{NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCC,ID_GetManufactureMonth },
{NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCC,ID_GetOriginalIMEI },
{N71_92_ReplyPhoneSetting, "\x7a",0x04,0x02,ID_GetBitmap },
{N71_92_ReplyPhoneSetting, "\x7a",0x04,0x02,ID_SetBitmap },
{N71_92_ReplyPhoneSetting, "\x7a",0x04,0x15,ID_GetBitmap },
{N71_92_ReplyPhoneSetting, "\x7a",0x04,0x15,ID_SetBitmap },
{DCT3DCT4_ReplyGetModelFirmware,"\xD2",0x02,0x00,ID_GetModel },
{DCT3DCT4_ReplyGetModelFirmware,"\xD2",0x02,0x00,ID_GetFirmware },
{NULL, "\x00",0x00,0x00,ID_None }
};
GSM_Phone_Functions N9210Phone = {
"9210|9210i",
N9210ReplyFunctions,
N9210_Initialise,
PHONE_Terminate,
GSM_DispatchMessage,
NOTSUPPORTED, /* ShowStartInfo */
NOKIA_GetManufacturer,
DCT3DCT4_GetModel,
DCT3DCT4_GetFirmware,
DCT3_GetIMEI,
DCT3_GetOriginalIMEI,
DCT3_GetManufactureMonth,
DCT3_GetProductCode,
DCT3_GetHardware,
DCT3_GetPPM,
NOTSUPPORTED, /* GetSIMIMSI */
N71_92_GetDateTime,
N71_92_SetDateTime,
NOTIMPLEMENTED, /* GetAlarm */
NOTIMPLEMENTED, /* SetAlarm */
NOTSUPPORTED, /* GetLocale */
NOTSUPPORTED, /* SetLocale */
NOTIMPLEMENTED, /* PressKey */
NOTIMPLEMENTED, /* Reset */
NOTIMPLEMENTED, /* ResetPhoneSettings */
NOTSUPPORTED, /* EnterSecurityCode */
NOTSUPPORTED, /* GetSecurityStatus */
NOTSUPPORTED, /* GetDisplayStatus */
NOTIMPLEMENTED, /* SetAutoNetworkLogin */
N71_92_GetBatteryCharge,
N71_92_GetSignalQuality,
DCT3_GetNetworkInfo,
NOTSUPPORTED, /* GetCategory */
NOTSUPPORTED, /* AddCategory */
NOTSUPPORTED, /* GetCategoryStatus */
NOTIMPLEMENTED, /* GetMemoryStatus */
NOTIMPLEMENTED, /* GetMemory */
NOTIMPLEMENTED, /* GetNextMemory */
NOTIMPLEMENTED, /* SetMemory */
NOTIMPLEMENTED, /* AddMemory */
NOTIMPLEMENTED, /* DeleteMemory */
NOTIMPLEMENTED, /* DeleteAllMemory */
NOTIMPLEMENTED, /* GetSpeedDial */
NOTIMPLEMENTED, /* SetSpeedDial */
DCT3_GetSMSC,
DCT3_SetSMSC, /* FIXME: test it */
NOTIMPLEMENTED, /* GetSMSStatus */
NOTIMPLEMENTED, /* GetSMS */
NOTIMPLEMENTED, /* GetNextSMS */
NOTIMPLEMENTED, /* SetSMS */
NOTIMPLEMENTED, /* AddSMS */
NOTIMPLEMENTED, /* DeleteSMS */
DCT3_SendSMSMessage,
NOTSUPPORTED, /* SendSavedSMS */
+ NOTSUPPORTED, /* SetFastSMSSending */
N9210_SetIncomingSMS,
DCT3_SetIncomingCB,
NOTIMPLEMENTED, /* GetSMSFolders */
NOTSUPPORTED, /* AddSMSFolder */
NOTSUPPORTED, /* DeleteSMSFolder */
DCT3_DialVoice,
N9210_AnswerCall,
DCT3_CancelCall,
NOTSUPPORTED, /* HoldCall */
NOTSUPPORTED, /* UnholdCall */
NOTSUPPORTED, /* ConferenceCall */
NOTSUPPORTED, /* SplitCall */
NOTSUPPORTED, /* TransferCall */
NOTSUPPORTED, /* SwitchCall */
NOTSUPPORTED, /* GetCallDivert */
NOTSUPPORTED, /* SetCallDivert */
NOTSUPPORTED, /* CancelAllDiverts */
NOTSUPPORTED, /* SetIncomingCall */
NOTIMPLEMENTED, /* SetIncomingUSSD */
NOTSUPPORTED, /* SendDTMF */
NOTIMPLEMENTED, /* GetRingtone */
NOTIMPLEMENTED, /* SetRingtone */
NOTSUPPORTED, /* GetRingtonesInfo */
NOTSUPPORTED, /* DeleteUserRingtones */
NOTSUPPORTED, /* PlayTone */
NOTIMPLEMENTED, /* GetWAPBookmark */
NOTIMPLEMENTED, /* SetWAPBookmark */
NOTIMPLEMENTED, /* DeleteWAPBookmark */
NOTIMPLEMENTED, /* GetWAPSettings */
NOTSUPPORTED, /* SetWAPSettings */
NOTSUPPORTED, /* GetMMSSettings */
NOTSUPPORTED, /* SetMMSSettings */
NOTSUPPORTED, /* GetSyncMLSettings */
NOTSUPPORTED, /* SetSyncMLSettings */
NOTSUPPORTED, /* GetChatSettings */
NOTSUPPORTED, /* SetChatSettings */
N9210_GetBitmap,
N9210_SetBitmap,
NOTSUPPORTED, /* GetToDoStatus */
NOTSUPPORTED, /* GetToDo */
NOTSUPPORTED, /* GetNextToDo */
NOTSUPPORTED, /* SetToDo */
NOTSUPPORTED, /* AddToDo */
NOTSUPPORTED, /* DeleteToDo */
NOTSUPPORTED, /* DeleteAllToDo */
NOTSUPPORTED, /* GetCalendarStatus */
NOTSUPPORTED, /* GetCalendar */
NOTSUPPORTED, /* GetNextCalendar */
NOTSUPPORTED, /* SetCalendar */
NOTSUPPORTED, /* AddCalendar */
NOTSUPPORTED, /* DeleteCalendar */
NOTSUPPORTED, /* DeleteAllCalendar */
NOTSUPPORTED, /* GetCalendarSettings */
NOTSUPPORTED, /* SetCalendarSettings */
- NOTSUPPORTED, /* GetNote */
+ NOTSUPPORTED, /* GetNextNote */
NOTIMPLEMENTED, /* GetProfile */
NOTSUPPORTED, /* SetProfile */
NOTSUPPORTED, /* GetFMStation */
NOTSUPPORTED, /* SetFMStation */
NOTSUPPORTED, /* ClearFMStations */
NOTSUPPORTED, /* GetNextFileFolder */
NOTSUPPORTED, /* GetFilePart */
NOTSUPPORTED, /* AddFile */
NOTSUPPORTED, /* GetFileSystemStatus */
NOTSUPPORTED, /* DeleteFile */
NOTSUPPORTED, /* AddFolder */
NOTSUPPORTED, /* GetGPRSAccessPoint */
NOTSUPPORTED /* SetGPRSAccessPoint */
};
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/nokia/dct4/n3320.c b/gammu/emb/common/phone/nokia/dct4/n3320.c
index 51e6f18..9b1d6cd 100644
--- a/gammu/emb/common/phone/nokia/dct4/n3320.c
+++ b/gammu/emb/common/phone/nokia/dct4/n3320.c
@@ -5,267 +5,268 @@
#ifdef GSM_ENABLE_NOKIA3320
#include <string.h>
#include <time.h>
#include "../../../gsmcomon.h"
#include "../../../misc/coding/coding.h"
#include "../../../service/gsmlogo.h"
#include "../nfunc.h"
#include "../nfuncold.h"
#include "../../pfunc.h"
#include "n3320.h"
static GSM_Error N3320_ReplyGetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Phonebook entry received\n");
switch (msg.Buffer[6]) {
case 0x0f:
return N71_65_ReplyGetMemoryError(msg.Buffer[10], s);
default:
return N71_65_DecodePhonebook(s, s->Phone.Data.Memory, s->Phone.Data.Bitmap, s->Phone.Data.SpeedDial, msg.Buffer+22, msg.Length-22,true);
}
return ERR_UNKNOWN;
}
static GSM_Error N3320_GetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
0xfe, 0x10, /* memory type */
0x00, 0x00, 0x00, 0x00,
0x00, 0x01, /* location */
0x00, 0x00, 0x01};
req[9] = NOKIA_GetMemoryType(s, entry->MemoryType,N71_65_MEMORY_TYPES);
if (entry->MemoryType == MEM_SM) return ERR_NOTSUPPORTED;
if (req[9]==0xff) return ERR_NOTSUPPORTED;
if (entry->Location==0x00) return ERR_INVALIDLOCATION;
req[14] = entry->Location / 256;
req[15] = entry->Location % 256;
s->Phone.Data.Memory=entry;
smprintf(s, "Getting phonebook entry\n");
return GSM_WaitFor (s, req, 19, 0x03, 4, ID_GetMemory);
}
static GSM_Error N3320_ReplyGetMemoryStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Memory status received\n");
/* Quess ;-)) */
if (msg.Buffer[14]==0x10) {
Data->MemoryStatus->MemoryFree = msg.Buffer[18]*256 + msg.Buffer[19];
} else {
Data->MemoryStatus->MemoryFree = msg.Buffer[17];
}
smprintf(s, "Size : %i\n",Data->MemoryStatus->MemoryFree);
Data->MemoryStatus->MemoryUsed = msg.Buffer[20]*256 + msg.Buffer[21];
smprintf(s, "Used : %i\n",Data->MemoryStatus->MemoryUsed);
Data->MemoryStatus->MemoryFree -= Data->MemoryStatus->MemoryUsed;
smprintf(s, "Free : %i\n",Data->MemoryStatus->MemoryFree);
return ERR_NONE;
}
static GSM_Error N3320_GetMemoryStatus(GSM_StateMachine *s, GSM_MemoryStatus *Status)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x03, 0x02,
0x00, /* memory type */
0x55, 0x55, 0x55, 0x00};
req[5] = NOKIA_GetMemoryType(s, Status->MemoryType,N71_65_MEMORY_TYPES);
if (Status->MemoryType == MEM_SM) return ERR_NOTSUPPORTED;
if (req[5]==0xff) return ERR_NOTSUPPORTED;
s->Phone.Data.MemoryStatus=Status;
smprintf(s, "Getting memory status\n");
return GSM_WaitFor (s, req, 10, 0x03, 4, ID_GetMemoryStatus);
}
static GSM_Error N3320_ReplyGetDateTime(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Date & time received\n");
if (msg.Buffer[4]==0x01) {
NOKIA_DecodeDateTime(s, msg.Buffer+10, s->Phone.Data.DateTime);
return ERR_NONE;
}
smprintf(s, "Not set in phone\n");
return ERR_EMPTY;
}
static GSM_Error N3320_GetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x0A, 0x00, 0x00};
s->Phone.Data.DateTime=date_time;
smprintf(s, "Getting date & time\n");
return GSM_WaitFor (s, req, 6, 0x19, 4, ID_GetDateTime);
}
static GSM_Error N3320_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
{
return N71_65_GetNextCalendar1(s,Note,start,&s->Phone.Data.Priv.N3320.LastCalendar,&s->Phone.Data.Priv.N3320.LastCalendarYear,&s->Phone.Data.Priv.N3320.LastCalendarPos);
}
static GSM_Error N3320_GetCalendarStatus(GSM_StateMachine *s, GSM_CalendarStatus *Status)
{
GSM_Error error;
/* Method 1 */
error=N71_65_GetCalendarInfo1(s, &s->Phone.Data.Priv.N3320.LastCalendar);
if (error!=ERR_NONE) return error;
Status->Used = s->Phone.Data.Priv.N3320.LastCalendar.Number;
return ERR_NONE;
}
static GSM_Error N3320_ReplyGetCalendarInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
return N71_65_ReplyGetCalendarInfo1(msg, s, &s->Phone.Data.Priv.N3320.LastCalendar);
}
static GSM_Reply_Function N3320ReplyFunctions[] = {
{N3320_ReplyGetMemoryStatus, "\x03",0x03,0x04,ID_GetMemoryStatus },
{N3320_ReplyGetMemory, "\x03",0x03,0x08,ID_GetMemory },
{N71_65_ReplyGetNextCalendar1, "\x13",0x03,0x1A,ID_GetCalendarNote },/*method 1*/
{N3320_ReplyGetCalendarInfo, "\x13",0x03,0x3B,ID_GetCalendarNotesInfo},/*method 1*/
{N3320_ReplyGetDateTime, "\x19",0x03,0x0B,ID_GetDateTime },
{DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetModel },
{DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetFirmware },
{NULL, "\x00",0x00,0x00,ID_None }
};
GSM_Phone_Functions N3320Phone = {
"3320",
N3320ReplyFunctions,
NONEFUNCTION, /* Initialise */
NONEFUNCTION, /* Terminate */
GSM_DispatchMessage,
NOTSUPPORTED, /* ShowStartInfo */
NOKIA_GetManufacturer,
DCT3DCT4_GetModel,
DCT3DCT4_GetFirmware,
NOTSUPPORTED, /* GetIMEI */
NOTSUPPORTED, /* GetOriginalIMEI */
NOTSUPPORTED, /* GetManufactureMonth */
NOTSUPPORTED, /* GetProductCode */
NOTSUPPORTED, /* GetHardware */
NOTSUPPORTED, /* GetPPM */
NOTSUPPORTED, /* GetSIMIMSI */
N3320_GetDateTime,
NOTSUPPORTED, /* SetDateTime */
NOTSUPPORTED, /* GetAlarm */
NOTSUPPORTED, /* SetAlarm */
NOTSUPPORTED, /* GetLocale */
NOTSUPPORTED, /* SetLocale */
NOTSUPPORTED, /* PressKey */
NOTSUPPORTED, /* Reset */
NOTSUPPORTED, /* ResetPhoneSettings */
NOTSUPPORTED, /* EnterSecurityCode */
NOTSUPPORTED, /* GetSecurityStatus */
NOTSUPPORTED, /* GetDisplayStatus */
NOTSUPPORTED, /* SetAutoNetworkLogin */
NOTSUPPORTED, /* GetBatteryCharge */
NOTSUPPORTED, /* GetSignalQuality */
NOTSUPPORTED, /* GetNetworkInfo */
NOTSUPPORTED, /* GetCategory */
NOTSUPPORTED, /* AddCategory */
NOTSUPPORTED, /* GetCategoryStatus */
N3320_GetMemoryStatus,
N3320_GetMemory,
NOTSUPPORTED, /* GetNextMemory */
NOTSUPPORTED, /* SetMemory */
NOTSUPPORTED, /* AddMemory */
NOTSUPPORTED, /* DeleteMemory */
NOTIMPLEMENTED, /* DeleteAllMemory */
NOTSUPPORTED, /* GetSpeedDial */
NOTSUPPORTED, /* SetSpeedDial */
NOTSUPPORTED, /* GetSMSC */
NOTSUPPORTED, /* SetSMSC */
NOTSUPPORTED, /* GetSMSStatus */
NOTSUPPORTED, /* GetSMS */
NOTSUPPORTED, /* GetNextSMS */
NOTSUPPORTED, /* SetSMS */
NOTSUPPORTED, /* AddSMS */
NOTSUPPORTED, /* DeleteSMS */
NOTSUPPORTED, /* SendSMS */
NOTSUPPORTED, /* SendSavedSMS */
+ NOTSUPPORTED, /* SetFastSMSSending */
NOTSUPPORTED, /* SetIncomingSMS */
NOTSUPPORTED, /* SetIncomingCB */
NOTSUPPORTED, /* GetSMSFolders */
NOTSUPPORTED, /* AddSMSFolder */
NOTSUPPORTED, /* DeleteSMSFolder */
NOTIMPLEMENTED, /* DialVoice */
NOTIMPLEMENTED, /* AnswerCall */
NOTIMPLEMENTED, /* CancelCall */
NOTIMPLEMENTED, /* HoldCall */
NOTIMPLEMENTED, /* UnholdCall */
NOTIMPLEMENTED, /* ConferenceCall */
NOTIMPLEMENTED, /* SplitCall */
NOTIMPLEMENTED, /* TransferCall */
NOTIMPLEMENTED, /* SwitchCall */
NOTSUPPORTED, /* GetCallDivert */
NOTSUPPORTED, /* SetCallDivert */
NOTSUPPORTED, /* CancelAllDiverts */
NOTIMPLEMENTED, /* SetIncomingCall */
NOTIMPLEMENTED, /* SetIncomingUSSD */
NOTSUPPORTED, /* SendDTMF */
NOTSUPPORTED, /* GetRingtone */
NOTSUPPORTED, /* SetRingtone */
NOTSUPPORTED, /* GetRingtonesInfo */
NOTIMPLEMENTED, /* DeleteUserRingtones */
NOTSUPPORTED, /* PlayTone */
NOTSUPPORTED, /* GetWAPBookmark */
NOTSUPPORTED, /* SetWAPBookmark */
NOTSUPPORTED, /* DeleteWAPBookmark */
NOTSUPPORTED, /* GetWAPSettings */
NOTSUPPORTED, /* SetWAPSettings */
NOTSUPPORTED, /* GetMMSSettings */
NOTSUPPORTED, /* SetMMSSettings */
NOTSUPPORTED, /* GetSyncMLSettings */
NOTSUPPORTED, /* SetSyncMLSettings */
NOTSUPPORTED, /* GetChatSettings */
NOTSUPPORTED, /* SetChatSettings */
NOTSUPPORTED, /* GetBitmap */
NOTSUPPORTED, /* SetBitmap */
NOTSUPPORTED, /* GetToDoStatus */
NOTSUPPORTED, /* GetToDo */
NOTSUPPORTED, /* GetNextToDo */
NOTSUPPORTED, /* SetToDo */
NOTSUPPORTED, /* AddToDo */
NOTSUPPORTED, /* DeleteToDo */
NOTSUPPORTED, /* DeleteAllToDo */
N3320_GetCalendarStatus,
NOTIMPLEMENTED, /* GetCalendar */
N3320_GetNextCalendar,
NOTIMPLEMENTED, /* SetCalendar */
NOTSUPPORTED, /* AddCalendar */
NOTSUPPORTED, /* DeleteCalendar */
NOTIMPLEMENTED, /* DeleteAllCalendar */
NOTSUPPORTED, /* GetCalendarSettings */
NOTSUPPORTED, /* SetCalendarSettings */
- NOTSUPPORTED, /* GetNote */
+ NOTSUPPORTED, /* GetNextNote */
NOTSUPPORTED, /* GetProfile */
NOTSUPPORTED, /* SetProfile */
NOTSUPPORTED, /* GetFMStation */
NOTSUPPORTED, /* SetFMStation */
NOTSUPPORTED, /* ClearFMStations */
NOTSUPPORTED, /* GetNextFileFolder */
NOTSUPPORTED, /* GetFilePart */
NOTIMPLEMENTED, /* AddFilePart */
NOTSUPPORTED, /* GetFileSystemStatus */
NOTIMPLEMENTED, /* DeleteFile */
NOTIMPLEMENTED, /* AddFolder */
NOTSUPPORTED, /* GetGPRSAccessPoint */
NOTSUPPORTED /* SetGPRSAccessPoint */
};
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/nokia/dct4/n3650.c b/gammu/emb/common/phone/nokia/dct4/n3650.c
index 2da55bf..d4746a7 100644
--- a/gammu/emb/common/phone/nokia/dct4/n3650.c
+++ b/gammu/emb/common/phone/nokia/dct4/n3650.c
@@ -126,267 +126,268 @@ static GSM_Error N3650_ReplyGetFolderInfo(GSM_Protocol_Message msg, GSM_StateMac
}
dbgprintf("\n");
return ERR_NONE;
}
static GSM_Error N3650_GetFolderInfo(GSM_StateMachine *s, GSM_File *File)
{
int len=10;
unsigned char req[500] = {
N7110_FRAME_HEADER, 0x0B, 0x00, 0x01, 0x07,
0x18, /* folder name length + 6 */
0x12, /* folder name length */
0x00,
0x00}; /* folder name */
sprintf(req+10,File->ID_FullName);
len +=strlen(File->ID_FullName);
req[7] = strlen(File->ID_FullName) + 6;
req[8] = strlen(File->ID_FullName);
req[len++] = 0x00;
req[len++] = 0x00;
s->Phone.Data.FileInfo = File;
return GSM_WaitFor (s, req, len, 0x58, 4, ID_GetFile);
}
static GSM_Error N3650_GetNextFileFolder(GSM_StateMachine *s, GSM_File *File, bool start)
{
GSM_Error error;
GSM_Phone_N3650Data *Priv = &s->Phone.Data.Priv.N3650;
if (start) {
error = DCT4_SetPhoneMode(s, DCT4_MODE_LOCAL);
if (error != ERR_NONE) return error;
Priv->Files[0]->Folder = true;
Priv->Files[0]->Level = 1;
Priv->Files[0]->Name[0] = 0;
Priv->Files[0]->Name[1] = 0;
Priv->Files[0]->ID_FullName[0] = 'Z';
Priv->Files[0]->ID_FullName[1] = ':';
Priv->Files[0]->ID_FullName[2] = 0;
Priv->Files[1]->Folder = true;
Priv->Files[1]->Level = 1;
Priv->Files[1]->Name[0] = 0;
Priv->Files[1]->Name[1] = 0;
Priv->Files[1]->ID_FullName[0] = 'E';
Priv->Files[1]->ID_FullName[1] = ':';
Priv->Files[1]->ID_FullName[2] = 0;
Priv->Files[2]->Folder = true;
Priv->Files[2]->Level = 1;
Priv->Files[2]->Name[0] = 0;
Priv->Files[2]->Name[1] = 0;
Priv->Files[2]->ID_FullName[0] = 'C';
Priv->Files[2]->ID_FullName[1] = ':';
Priv->Files[2]->ID_FullName[2] = 0;
Priv->FilesLocationsUsed = 3;
Priv->FilesLocationsCurrent = 0;
Priv->FileLev = 1;
}
if (Priv->FilesLocationsCurrent == Priv->FilesLocationsUsed) {
// error = DCT4_SetPhoneMode(s, DCT4_MODE_NORMAL);
// if (error != ERR_NONE) return error;
return ERR_EMPTY;
}
strcpy(File->ID_FullName,Priv->Files[Priv->FilesLocationsCurrent]->ID_FullName);
File->Level = Priv->Files[Priv->FilesLocationsCurrent]->Level;
File->Folder = Priv->Files[Priv->FilesLocationsCurrent]->Folder;
CopyUnicodeString(File->Name,Priv->Files[Priv->FilesLocationsCurrent]->Name);
Priv->FilesLocationsCurrent++;
if (!File->Folder) return ERR_NONE;
if (Priv->FilesLocationsCurrent > 1) {
if (File->ID_FullName[0]!=Priv->Files[Priv->FilesLocationsCurrent-2]->ID_FullName[0]) {
if (File->ID_FullName[0] == 'E') {
error = DCT4_SetPhoneMode(s, DCT4_MODE_TEST);
error = DCT4_SetPhoneMode(s, DCT4_MODE_TEST);
}
if (File->ID_FullName[0] == 'C') {
error = DCT4_SetPhoneMode(s, DCT4_MODE_LOCAL);
error = DCT4_SetPhoneMode(s, DCT4_MODE_LOCAL);
}
// if (error != ERR_NONE) return error;
}
}
File->ReadOnly = false;
File->System = false;
File->Protected = false;
File->Hidden = false;
return N3650_GetFolderInfo(s, File);
}
static GSM_Error N3650_Initialise (GSM_StateMachine *s)
{
GSM_Phone_N3650Data *Priv = &s->Phone.Data.Priv.N3650;
int i;
for (i=0;i<10000;i++) {
Priv->Files[i] = malloc(sizeof(GSM_File));
if (Priv->Files[i] == NULL) return ERR_MOREMEMORY;
}
return ERR_NONE;
}
static GSM_Error N3650_Terminate(GSM_StateMachine *s)
{
GSM_Phone_N3650Data *Priv = &s->Phone.Data.Priv.N3650;
int i;
for (i=0;i<10000;i++) free(Priv->Files[i]);
return ERR_NONE;
}
static GSM_Reply_Function N3650ReplyFunctions[] = {
{DCT4_ReplySetPhoneMode, "\x15",0x03,0x64,ID_Reset },
{DCT4_ReplyGetPhoneMode, "\x15",0x03,0x65,ID_Reset },
{NoneReply, "\x15",0x03,0x68,ID_Reset },
{DCT4_ReplyGetIMEI, "\x1B",0x03,0x01,ID_GetIMEI },
{NOKIA_ReplyGetPhoneString, "\x1B",0x03,0x08,ID_GetHardware },
{NOKIA_ReplyGetPhoneString, "\x1B",0x03,0x0C,ID_GetProductCode },
{N3650_ReplyGetFolderInfo, "\x58",0x03,0x0C,ID_GetFile },
{N3650_ReplyGetFilePart, "\x58",0x03,0x0E,ID_GetFile },
{NULL, "\x00",0x00,0x00,ID_None }
};
GSM_Phone_Functions N3650Phone = {
"3650|NGAGE",
N3650ReplyFunctions,
N3650_Initialise,
N3650_Terminate,
GSM_DispatchMessage,
NOTSUPPORTED, /* ShowStartInfo */
NOKIA_GetManufacturer,
DCT3DCT4_GetModel,
DCT3DCT4_GetFirmware,
DCT4_GetIMEI,
NOTSUPPORTED, /* GetOriginalIMEI */
NOTSUPPORTED, /* GetManufactureMonth */
DCT4_GetProductCode,
DCT4_GetHardware,
NOTSUPPORTED, /* GetPPM */
NOTSUPPORTED, /* GetSIMIMSI */
NOTSUPPORTED, /* GetDateTime */
NOTSUPPORTED, /* SetDateTime */
NOTSUPPORTED, /* GetAlarm */
NOTSUPPORTED, /* SetAlarm */
NOTSUPPORTED, /* GetLocale */
NOTSUPPORTED, /* SetLocale */
NOTSUPPORTED, /* PressKey */
DCT4_Reset,
NOTSUPPORTED, /* ResetPhoneSettings */
NOTSUPPORTED, /* EnterSecurityCode */
NOTSUPPORTED, /* GetSecurityStatus */
NOTSUPPORTED, /* GetDisplayStatus */
NOTSUPPORTED, /* SetAutoNetworkLogin */
NOTSUPPORTED, /* GetBatteryCharge */
NOTSUPPORTED, /* GetSignalQuality */
NOTSUPPORTED, /* GetNetworkInfo */
NOTSUPPORTED, /* GetCategory */
NOTSUPPORTED, /* AddCategory */
NOTSUPPORTED, /* GetCategoryStatus */
NOTSUPPORTED, /* GetMemoryStatus */
NOTSUPPORTED, /* GetMemory */
NOTSUPPORTED, /* GetNextMemory */
NOTSUPPORTED, /* SetMemory */
NOTSUPPORTED, /* AddMemory */
NOTSUPPORTED, /* DeleteMemory */
NOTIMPLEMENTED, /* DeleteAllMemory */
NOTSUPPORTED, /* GetSpeedDial */
NOTSUPPORTED, /* SetSpeedDial */
NOTSUPPORTED, /* GetSMSC */
NOTSUPPORTED, /* SetSMSC */
NOTSUPPORTED, /* GetSMSStatus */
NOTSUPPORTED, /* GetSMS */
NOTSUPPORTED, /* GetNextSMS */
NOTSUPPORTED, /* SetSMS */
NOTSUPPORTED, /* AddSMS */
NOTSUPPORTED, /* DeleteSMS */
NOTSUPPORTED, /* SendSMS */
NOTSUPPORTED, /* SendSavedSMS */
+ NOTSUPPORTED, /* SetFastSMSSending */
NOTSUPPORTED, /* SetIncomingSMS */
NOTSUPPORTED, /* SetIncomingCB */
NOTSUPPORTED, /* GetSMSFolders */
NOTSUPPORTED, /* AddSMSFolder */
NOTSUPPORTED, /* DeleteSMSFolder */
NOTIMPLEMENTED, /* DialVoice */
NOTIMPLEMENTED, /* AnswerCall */
NOTIMPLEMENTED, /* CancelCall */
NOTIMPLEMENTED, /* HoldCall */
NOTIMPLEMENTED, /* UnholdCall */
NOTIMPLEMENTED, /* ConferenceCall */
NOTIMPLEMENTED, /* SplitCall */
NOTIMPLEMENTED, /* TransferCall */
NOTIMPLEMENTED, /* SwitchCall */
NOTSUPPORTED, /* GetCallDivert */
NOTSUPPORTED, /* SetCallDivert */
NOTSUPPORTED, /* CancelAllDiverts */
NOTIMPLEMENTED, /* SetIncomingCall */
NOTIMPLEMENTED, /* SetIncomingUSSD */
NOTSUPPORTED, /* SendDTMF */
NOTSUPPORTED, /* GetRingtone */
NOTSUPPORTED, /* SetRingtone */
NOTSUPPORTED, /* GetRingtonesInfo */
NOTIMPLEMENTED, /* DeleteUserRingtones */
NOTSUPPORTED, /* PlayTone */
NOTSUPPORTED, /* GetWAPBookmark */
NOTSUPPORTED, /* SetWAPBookmark */
NOTSUPPORTED, /* DeleteWAPBookmark */
NOTSUPPORTED, /* GetWAPSettings */
NOTSUPPORTED, /* SetWAPSettings */
NOTSUPPORTED, /* GetMMSSettings */
NOTSUPPORTED, /* SetMMSSettings */
NOTSUPPORTED, /* GetSyncMLSettings */
NOTSUPPORTED, /* SetSyncMLSettings */
NOTSUPPORTED, /* GetChatSettings */
NOTSUPPORTED, /* SetChatSettings */
NOTSUPPORTED, /* GetBitmap */
NOTSUPPORTED, /* SetBitmap */
NOTSUPPORTED, /* GetToDoStatus */
NOTSUPPORTED, /* GetToDo */
NOTSUPPORTED, /* GetNextToDo */
NOTSUPPORTED, /* SetToDo */
NOTSUPPORTED, /* AddToDo */
NOTSUPPORTED, /* DeleteToDo */
NOTSUPPORTED, /* DeleteAllToDo */
NOTIMPLEMENTED, /* GetCalendarStatus */
NOTIMPLEMENTED, /* GetCalendar */
NOTSUPPORTED, /* GetNextCalendar */
NOTIMPLEMENTED, /* SetCalendar */
NOTSUPPORTED, /* AddCalendar */
NOTSUPPORTED, /* DeleteCalendar */
NOTIMPLEMENTED, /* DeleteAllCalendar */
NOTSUPPORTED, /* GetCalendarSettings */
NOTSUPPORTED, /* SetCalendarSettings */
- NOTSUPPORTED, /* GetNote */
+ NOTSUPPORTED, /* GetNextNote */
NOTSUPPORTED, /* GetProfile */
NOTSUPPORTED, /* SetProfile */
NOTSUPPORTED, /* GetFMStation */
NOTSUPPORTED, /* SetFMStation */
NOTSUPPORTED, /* ClearFMStations */
N3650_GetNextFileFolder,
N3650_GetFilePart,
NOTIMPLEMENTED, /* AddFilePart */
NOTSUPPORTED, /* GetFileSystemStatus */
NOTIMPLEMENTED, /* DeleteFile */
NOTIMPLEMENTED, /* AddFolder */
NOTSUPPORTED, /* GetGPRSAccessPoint */
NOTSUPPORTED /* SetGPRSAccessPoint */
};
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/nokia/dct4/n6510.c b/gammu/emb/common/phone/nokia/dct4/n6510.c
index 67fe492..2208def 100644
--- a/gammu/emb/common/phone/nokia/dct4/n6510.c
+++ b/gammu/emb/common/phone/nokia/dct4/n6510.c
@@ -1,460 +1,465 @@
/* (c) 2002-2004 by Marcin Wiacek */
-/* based on some work from Markus Plail, Pawel Kot and Gnokii */
+/* based on some Markus Plail, Pawel Kot work from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
/* function for making CRC for filesystem (c) 2003 by Michael Schroeder */
#include "../../../gsmstate.h"
#ifdef GSM_ENABLE_NOKIA6510
#include <string.h>
#include <time.h>
#include "../../../misc/coding/coding.h"
#include "../../../gsmcomon.h"
#include "../../../service/gsmlogo.h"
#include "../nfunc.h"
#include "../nfuncold.h"
#include "../../pfunc.h"
#include "dct4func.h"
#include "n6510.h"
static GSM_Error N6510_Initialise (GSM_StateMachine *s)
{
s->Phone.Data.Priv.N6510.CalendarIconsNum = 0;
/* Enables various things like incoming SMS, call info, etc. */
return N71_65_EnableFunctions (s, "\x01\x02\x06\x0A\x14\x17\x39", 7);
}
static GSM_Error N6510_ReplyGetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Phonebook entry received\n");
switch (msg.Buffer[6]) {
case 0x0f:
return N71_65_ReplyGetMemoryError(msg.Buffer[10], s);
default:
return N71_65_DecodePhonebook(s, s->Phone.Data.Memory, s->Phone.Data.Bitmap, s->Phone.Data.SpeedDial, msg.Buffer+22, msg.Length-22,false);
}
return ERR_UNKNOWN;
}
static GSM_Error N6510_GetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
0xfe, 0x10, /* memory type */
0x00, 0x00, 0x00, 0x00,
0x00, 0x01, /* location */
0x00, 0x00, 0x01};
req[9] = NOKIA_GetMemoryType(s, entry->MemoryType,N71_65_MEMORY_TYPES);
if (req[9]==0xff) return ERR_NOTSUPPORTED;
if (entry->Location==0x00) return ERR_INVALIDLOCATION;
req[14] = entry->Location / 256;
req[15] = entry->Location % 256;
s->Phone.Data.Memory=entry;
smprintf(s, "Getting phonebook entry\n");
return GSM_WaitFor (s, req, 19, 0x03, 4, ID_GetMemory);
}
static GSM_Error N6510_ReplyGetMemoryStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Memory status received\n");
/* Quess ;-)) */
if (msg.Buffer[14]==0x10) {
Data->MemoryStatus->MemoryFree = msg.Buffer[18]*256 + msg.Buffer[19];
} else {
Data->MemoryStatus->MemoryFree = msg.Buffer[17];
}
smprintf(s, "Size : %i\n",Data->MemoryStatus->MemoryFree);
Data->MemoryStatus->MemoryUsed = msg.Buffer[20]*256 + msg.Buffer[21];
smprintf(s, "Used : %i\n",Data->MemoryStatus->MemoryUsed);
Data->MemoryStatus->MemoryFree -= Data->MemoryStatus->MemoryUsed;
smprintf(s, "Free : %i\n",Data->MemoryStatus->MemoryFree);
return ERR_NONE;
}
static GSM_Error N6510_GetMemoryStatus(GSM_StateMachine *s, GSM_MemoryStatus *Status)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x03, 0x02,
0x00, /* memory type */
0x55, 0x55, 0x55, 0x00};
req[5] = NOKIA_GetMemoryType(s, Status->MemoryType,N71_65_MEMORY_TYPES);
if (req[5]==0xff) return ERR_NOTSUPPORTED;
s->Phone.Data.MemoryStatus=Status;
smprintf(s, "Getting memory status\n");
return GSM_WaitFor (s, req, 10, 0x03, 4, ID_GetMemoryStatus);
}
static GSM_Error N6510_ReplyGetSMSC(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int i, current, j;
GSM_Phone_Data *Data = &s->Phone.Data;
switch (msg.Buffer[4]) {
case 0x00:
smprintf(s, "SMSC received\n");
break;
case 0x02:
smprintf(s, "SMSC empty\n");
return ERR_INVALIDLOCATION;
default:
smprintf(s, "Unknown SMSC state: %02x\n",msg.Buffer[4]);
return ERR_UNKNOWNRESPONSE;
}
memset(Data->SMSC,0,sizeof(GSM_SMSC));
Data->SMSC->Location = msg.Buffer[8];
Data->SMSC->Format = SMS_FORMAT_Text;
switch (msg.Buffer[10]) {
case 0x00: Data->SMSC->Format = SMS_FORMAT_Text; break;
case 0x22: Data->SMSC->Format = SMS_FORMAT_Fax; break;
case 0x26: Data->SMSC->Format = SMS_FORMAT_Pager; break;
case 0x32: Data->SMSC->Format = SMS_FORMAT_Email; break;
}
Data->SMSC->Validity.Format = SMS_Validity_RelativeFormat;
Data->SMSC->Validity.Relative = msg.Buffer[12];
+ if (msg.Buffer[12] == 0x00) Data->SMSC->Validity.Relative = SMS_VALID_Max_Time;
+
current = 14;
for (i=0;i<msg.Buffer[13];i++) {
switch (msg.Buffer[current]) {
case 0x81:
j=current+4;
while (msg.Buffer[j]!=0) {j++;}
j=j-33;
if (j>GSM_MAX_SMSC_NAME_LENGTH) {
smprintf(s, "Too long name\n");
return ERR_UNKNOWNRESPONSE;
}
CopyUnicodeString(Data->SMSC->Name,msg.Buffer+current+4);
smprintf(s, " Name \"%s\"\n", DecodeUnicodeString(Data->SMSC->Name));
break;
case 0x82:
switch (msg.Buffer[current+2]) {
case 0x01:
GSM_UnpackSemiOctetNumber(Data->SMSC->DefaultNumber,msg.Buffer+current+4,true);
smprintf(s, " Default number \"%s\"\n", DecodeUnicodeString(Data->SMSC->DefaultNumber));
break;
case 0x02:
GSM_UnpackSemiOctetNumber(Data->SMSC->Number,msg.Buffer+current+4,false);
smprintf(s, " Number \"%s\"\n", DecodeUnicodeString(Data->SMSC->Number));
break;
default:
smprintf(s, "Unknown SMSC number: %02x\n",msg.Buffer[current+2]);
return ERR_UNKNOWNRESPONSE;
}
break;
default:
smprintf(s, "Unknown SMSC block: %02x\n",msg.Buffer[current]);
return ERR_UNKNOWNRESPONSE;
}
current = current + msg.Buffer[current+1];
}
return ERR_NONE;
}
static GSM_Error N6510_GetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x14,
0x01, /* location */
0x00};
if (smsc->Location==0x00) return ERR_INVALIDLOCATION;
req[4]=smsc->Location;
s->Phone.Data.SMSC=smsc;
smprintf(s, "Getting SMSC\n");
return GSM_WaitFor (s, req, 6, 0x02, 4, ID_GetSMSC);
}
static GSM_Error N6510_ReplySetSMSC(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[4]) {
case 0x00:
smprintf(s, "SMSC set OK\n");
return ERR_NONE;
case 0x02:
smprintf(s, "Invalid SMSC location\n");
return ERR_INVALIDLOCATION;
default:
smprintf(s, "Unknown SMSC state: %02x\n",msg.Buffer[4]);
return ERR_UNKNOWNRESPONSE;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_SetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
{
int count = 13,i;
unsigned char req[256] = {N6110_FRAME_HEADER,
0x12, 0x55, 0x01, 0x0B, 0x34,
0x05, /* Location */
0x00,
0x00, /* Format */
0x00,
0xFF}; /* Validity */
req[8] = smsc->Location;
switch (smsc->Format) {
case SMS_FORMAT_Text: req[10] = 0x00; break;
case SMS_FORMAT_Fax: req[10] = 0x22; break;
case SMS_FORMAT_Pager: req[10] = 0x26; break;
case SMS_FORMAT_Email: req[10] = 0x32; break;
}
req[12] = smsc->Validity.Relative;
/* We have now blocks. Number of blocks = 3 */
req[count++] = 0x03;
/* -------------- SMSC number ----------------- */
/* Block type: number */
req[count++] = 0x82;
/* Offset to next block */
req[count++] = 0x1A;
/* Type of number: SMSC number */
req[count++] = 0x02;
req[count] = GSM_PackSemiOctetNumber(smsc->Number, req+count+2, false) + 1;
if (req[count]>18) {
smprintf(s, "Too long SMSC number in frame\n");
return ERR_UNKNOWN;
}
req[count+1] = req[count] - 1;
count += 23;
/* --------------- Default number ------------- */
/* Block type: number */
req[count++] = 0x82;
/* Offset to next block */
req[count++] = 0x14;
/* Type of number: default number */
req[count++] = 0x01;
req[count] = GSM_PackSemiOctetNumber(smsc->DefaultNumber, req+count+2, true) + 1;
if (req[count]*2>12) {
smprintf(s, "Too long SMSC number in frame\n");
return ERR_UNKNOWN;
}
req[count+1] = req[count] - 1;
count += 17;
/* -------------- SMSC name ------------------- */
req[count++] = 0x81;
req[count++] = UnicodeLength(smsc->Name)*2 + 2 + 4;
req[count++] = UnicodeLength(smsc->Name)*2 + 2;
req[count++] = 0x00;
/* Can't make CopyUnicodeString(req+count,sms->Name) !!!!
* with MSVC6 count is changed then
*/
i = count;
CopyUnicodeString(req+i,smsc->Name);
count += UnicodeLength(smsc->Name)*2 + 2;
smprintf(s, "Setting SMSC\n");
return GSM_WaitFor (s, req, count, 0x02, 4, ID_SetSMSC);
}
static GSM_Error N6510_ReplyGetNetworkInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int current = msg.Buffer[7]+7, tmp;
GSM_Phone_Data *Data = &s->Phone.Data;
#ifdef DEBUG
char name[100];
GSM_NetworkInfo NetInfo;
- smprintf(s, "Network status: ");
+ smprintf(s, "Network status : ");
switch (msg.Buffer[8]) {
case 0x00 : smprintf(s, "home network\n"); break;
case 0x01 : smprintf(s, "roaming network\n"); break;
case 0x04 : smprintf(s, "not logged"); break;
case 0x06 : smprintf(s, "SIM card rejected\n"); break;
case 0x09 : smprintf(s, "not logged"); break;
default : smprintf(s, "unknown %i!\n",msg.Buffer[8]); break;
}
if (msg.Buffer[8]==0x00 || msg.Buffer[8] == 0x01) {
NOKIA_DecodeNetworkCode(msg.Buffer + (current + 7),NetInfo.NetworkCode);
smprintf(s, "Network code : %s\n", NetInfo.NetworkCode);
smprintf(s, "Network name for Gammu : %s ",
DecodeUnicodeString(GSM_GetNetworkName(NetInfo.NetworkCode)));
smprintf(s, "(%s)\n",DecodeUnicodeString(GSM_GetCountryName(NetInfo.NetworkCode)));
sprintf(NetInfo.LAC, "%02x%02x", msg.Buffer[current+1], msg.Buffer[current+2]);
smprintf(s, "LAC : %s\n", NetInfo.LAC);
sprintf(NetInfo.CID, "%02x%02x", msg.Buffer[current+5], msg.Buffer[current+6]);
smprintf(s, "CID : %s\n", NetInfo.CID);
tmp = 10;
NOKIA_GetUnicodeString(s, &tmp, msg.Buffer,name,true);
smprintf(s, "Network name for phone : %s\n",DecodeUnicodeString(name));
}
#endif
if (Data->RequestID==ID_GetNetworkInfo) {
Data->NetworkInfo->NetworkName[0] = 0x00;
Data->NetworkInfo->NetworkName[1] = 0x00;
Data->NetworkInfo->State = 0;
switch (msg.Buffer[8]) {
case 0x00: Data->NetworkInfo->State = GSM_HomeNetwork; break;
case 0x01: Data->NetworkInfo->State = GSM_RoamingNetwork; break;
case 0x04:
case 0x06:
case 0x09: Data->NetworkInfo->State = GSM_NoNetwork; break;
}
if (Data->NetworkInfo->State == GSM_HomeNetwork || Data->NetworkInfo->State == GSM_RoamingNetwork) {
tmp = 10;
NOKIA_GetUnicodeString(s, &tmp, msg.Buffer,Data->NetworkInfo->NetworkName,true);
sprintf(Data->NetworkInfo->LAC, "%02x%02x", msg.Buffer[current+1], msg.Buffer[current+2]);
sprintf(Data->NetworkInfo->CID, "%02x%02x", msg.Buffer[current+5], msg.Buffer[current+6]);
NOKIA_DecodeNetworkCode(msg.Buffer + (current+7),Data->NetworkInfo->NetworkCode);
}
}
return ERR_NONE;
}
static GSM_Error N6510_GetNetworkInfo(GSM_StateMachine *s, GSM_NetworkInfo *netinfo)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x00, 0x00};
s->Phone.Data.NetworkInfo=netinfo;
smprintf(s, "Getting network info\n");
return GSM_WaitFor (s, req, 5, 0x0a, 4, ID_GetNetworkInfo);
}
static GSM_Error N6510_EncodeSMSFrame(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char *req, GSM_SMSMessageLayout *Layout, int *length)
{
int start, count = 0, pos1, pos2, pos3, pos4, pos5;
GSM_Error error;
memset(Layout,255,sizeof(GSM_SMSMessageLayout));
start = *length;
req[count++] = 0x01;
if (sms->PDU != SMS_Deliver) {
req[count++] = 0x02;
} else {
req[count++] = 0x00;
}
pos1 = count; count++;
/* firstbyte set in SMS Layout */
Layout->firstbyte = count; count++;
if (sms->PDU != SMS_Deliver) {
Layout->TPMR = count; count++;
Layout->TPPID = count; count++;
/* TP.DCS set in SMS layout */
Layout->TPDCS = count; count++;
req[count++] = 0x00;
} else {
Layout->TPPID = count; count++;
/* TP.DCS set in SMS layout */
Layout->TPDCS = count; count++;
Layout->DateTime = count; count += 7;
req[count++] = 0x55;
req[count++] = 0x55;
req[count++] = 0x55;
}
/* We have now blocks. Number of blocks = 3 or 4 */
if (sms->PDU != SMS_Deliver) {
req[count++] = 0x04;
} else {
req[count++] = 0x03;
}
/* -------------- Phone number ------------- */
/* Block type: number */
req[count++] = 0x82;
/* Offset to next block */
req[count++] = 0x10;
/* Type of number: default number */
req[count++] = 0x01;
pos4 = count; count++;
/* now coded Number in SMS Layout */
Layout->Number = count; count+= 12;
/* -------------- SMSC number -------------- */
/* Block type: number */
req[count++] = 0x82;
/* Offset to next block */
req[count++] = 0x10;
/* Type of number: SMSC number */
req[count++] = 0x02;
pos5 = count; count++;
/* now coded SMSC number in SMS Layout */
Layout->SMSCNumber = count; count += 12;
/* -------------- SMS validity ------------- */
if (sms->PDU != SMS_Deliver) {
/* Block type: validity */
req[count++] = 0x08;
req[count++] = 0x04;
/* data length */
req[count++] = 0x01;
Layout->TPVP = count; count++;
}
/* --------------- SMS text ---------------- */
/* Block type: SMS text */
req[count++] = 0x80;
/* this the same as req[11] but starting from req[42] */
pos2 = count; count++;
pos3 = count; count++;
/* FIXME*/
Layout->TPUDL = count; count++;
/* SMS text and UDH coded in SMS Layout */
Layout->Text = count;
error = PHONE_EncodeSMSFrame(s,sms,req,*Layout,length,false);
if (error != ERR_NONE) return error;
req[pos1] = *length - 1;
req[pos2] = *length - Layout->Text + 6;
req[pos3] = *length - Layout->Text;
/* Convert number of semioctets to number of chars */
req[pos4] = req[Layout->Number] + 4;
if (req[pos4] % 2) req[pos4]++;
req[pos4] /= 2;
req[pos5] = req[Layout->SMSCNumber] + 1;
if (req[pos4]>12 || req[pos5]>12) {
smprintf(s, "Too long phone number in frame\n");
return ERR_UNKNOWN;
}
return ERR_NONE;
}
static GSM_Error N6510_ReplyGetSMSFolders(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int j, num = 0, pos;
GSM_Phone_Data *Data = &s->Phone.Data;
switch (msg.Buffer[3]) {
case 0x13:
smprintf(s, "SMS folders names received\n");
Data->SMSFolders->Number = msg.Buffer[5]+2;
pos = 6;
for (j=0;j<msg.Buffer[5];j++) {
while (true) {
if (msg.Buffer[pos] == msg.Buffer[6] &&
msg.Buffer[pos+1] == msg.Buffer[7]) break;
if (pos+4 > msg.Length) return ERR_UNKNOWNRESPONSE;
pos++;
}
pos+=4;
smprintf(s, "Folder index: %02x",msg.Buffer[pos - 2]);
if (msg.Buffer[pos - 1]>GSM_MAX_SMS_FOLDER_NAME_LEN) {
smprintf(s, "Too long text\n");
return ERR_UNKNOWNRESPONSE;
}
CopyUnicodeString(Data->SMSFolders->Folder[num].Name,msg.Buffer + pos);
smprintf(s, ", folder name: \"%s\"\n",DecodeUnicodeString(Data->SMSFolders->Folder[num].Name));
Data->SMSFolders->Folder[num].InboxFolder = false;
@@ -796,389 +801,389 @@ static GSM_Error N6510_GetNextSMSMessageBitmap(GSM_StateMachine *s, GSM_MultiSMS
if (i==Priv->LastSMSFolder.Number-1) {
findnextfolder=true;
} else {
location=Priv->LastSMSFolder.Location[i+1];
}
}
if (findnextfolder) {
Priv->LastSMSFolder.Number=0;
while (Priv->LastSMSFolder.Number==0) {
folderid++;
/* Too high folder number */
if ((folderid-1)>Priv->LastSMSFolders.Number) return ERR_EMPTY;
/* Get next folder status */
error=N6510_GetSMSFolderStatus(s, folderid);
if (error!=ERR_NONE) return error;
/* First location from this folder */
location=Priv->LastSMSFolder.Location[0];
}
}
N6510_SetSMSLocation(s, &sms->SMS[0], folderid, location);
return N6510_PrivGetSMSMessageBitmap(s, sms, bitmap);
}
static GSM_Error N6510_GetNextSMSMessage(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, bool start)
{
return N6510_GetNextSMSMessageBitmap(s, sms, start, NULL);
}
static GSM_Error N6510_ReplyStartupNoteLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
if (Data->RequestID == ID_GetBitmap) {
switch (msg.Buffer[4]) {
case 0x01:
smprintf(s, "Welcome note text received\n");
CopyUnicodeString(Data->Bitmap->Text,msg.Buffer+6);
smprintf(s, "Text is \"%s\"\n",DecodeUnicodeString(Data->Bitmap->Text));
return ERR_NONE;
case 0x10:
smprintf(s, "Dealer note text received\n");
CopyUnicodeString(Data->Bitmap->Text,msg.Buffer+6);
smprintf(s, "Text is \"%s\"\n",DecodeUnicodeString(Data->Bitmap->Text));
return ERR_NONE;
case 0x0f:
smprintf(s, "Startup logo received\n");
PHONE_DecodeBitmap(GSM_Nokia7110StartupLogo, msg.Buffer + 22, Data->Bitmap);
return ERR_NONE;
}
}
if (Data->RequestID == ID_SetBitmap) {
switch (msg.Buffer[4]) {
case 0x01:
case 0x10:
case 0x0f:
case 0x25:
return ERR_NONE;
}
}
return ERR_UNKNOWN;
}
static GSM_Error N6510_GetPictureImage(GSM_StateMachine *s, GSM_Bitmap *Bitmap, int *location)
{
GSM_MultiSMSMessage sms;
int Number;
GSM_Bitmap bitmap;
GSM_Error error;
sms.SMS[0].Folder = 0;
Number = 0;
bitmap.Location = 255;
error=N6510_GetNextSMSMessageBitmap(s, &sms, true, &bitmap);
while (error == ERR_NONE) {
if (bitmap.Location != 255) {
Number++;
if (Number == Bitmap->Location) {
bitmap.Location = Bitmap->Location;
memcpy(Bitmap,&bitmap,sizeof(GSM_Bitmap));
*location = sms.SMS[0].Location;
return ERR_NONE;
}
}
bitmap.Location = 255;
sms.SMS[0].Folder = 0;
error=N6510_GetNextSMSMessageBitmap(s, &sms, false, &bitmap);
}
return ERR_INVALIDLOCATION;
}
static GSM_Error N6510_GetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
{
unsigned char reqOp [] = {N6110_FRAME_HEADER, 0x23, 0x00, 0x00, 0x55, 0x55, 0x55};
unsigned char reqStartup[] = {N6110_FRAME_HEADER, 0x02, 0x0f};
unsigned char reqNote [] = {N6110_FRAME_HEADER, 0x02, 0x01, 0x00};
GSM_MemoryEntry pbk;
GSM_Error error;
int Location;
s->Phone.Data.Bitmap=Bitmap;
switch (Bitmap->Type) {
case GSM_StartupLogo:
Bitmap->BitmapWidth = 96;
Bitmap->BitmapHeight = 65;
GSM_ClearBitmap(Bitmap);
smprintf(s, "Getting startup logo\n");
return GSM_WaitFor (s, reqStartup, 5, 0x7A, 4, ID_GetBitmap);
case GSM_DealerNote_Text:
reqNote[4] = 0x10;
smprintf(s, "Getting dealer note\n");
return GSM_WaitFor (s, reqNote, 6, 0x7A, 4, ID_GetBitmap);
case GSM_WelcomeNote_Text:
smprintf(s, "Getting welcome note\n");
return GSM_WaitFor (s, reqNote, 6, 0x7A, 4, ID_GetBitmap);
case GSM_CallerGroupLogo:
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PBK35)) return ERR_NOTSUPPORTED;
Bitmap->BitmapWidth = 72;
Bitmap->BitmapHeight = 14;
GSM_ClearBitmap(Bitmap);
pbk.MemoryType = MEM7110_CG;
pbk.Location = Bitmap->Location;
smprintf(s, "Getting caller group logo\n");
error=N6510_GetMemory(s,&pbk);
if (error==ERR_NONE) NOKIA_GetDefaultCallerGroupName(s, Bitmap);
return error;
case GSM_OperatorLogo:
smprintf(s, "Getting operator logo\n");
return GSM_WaitFor (s, reqOp, 9, 0x0A, 4, ID_GetBitmap);
case GSM_PictureImage:
return N6510_GetPictureImage(s, Bitmap, &Location);
default:
break;
}
return ERR_NOTSUPPORTED;
}
static GSM_Error N6510_ReplyGetIncSignalQuality(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Network level changed to: %i\n",msg.Buffer[4]);
return ERR_NONE;
}
static GSM_Error N6510_ReplyGetSignalQuality(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Network level received: %i\n",msg.Buffer[8]);
Data->SignalQuality->SignalStrength = -1;
Data->SignalQuality->SignalPercent = ((int)msg.Buffer[8]);
Data->SignalQuality->BitErrorRate = -1;
return ERR_NONE;
}
static GSM_Error N6510_GetSignalQuality(GSM_StateMachine *s, GSM_SignalQuality *sig)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x0B, 0x00, 0x02, 0x00, 0x00, 0x00};
s->Phone.Data.SignalQuality = sig;
smprintf(s, "Getting network level\n");
return GSM_WaitFor (s, req, 9, 0x0a, 4, ID_GetSignalQuality);
}
static GSM_Error N6510_ReplyGetBatteryCharge(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Battery level received: %i\n",msg.Buffer[9]*100/7);
Data->BatteryCharge->BatteryPercent = ((int)(msg.Buffer[9]*100/7));
Data->BatteryCharge->ChargeState = 0;
return ERR_NONE;
}
static GSM_Error N6510_GetBatteryCharge(GSM_StateMachine *s, GSM_BatteryCharge *bat)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x0A, 0x02, 0x00};
s->Phone.Data.BatteryCharge = bat;
smprintf(s, "Getting battery level\n");
return GSM_WaitFor (s, req, 6, 0x17, 4, ID_GetBatteryCharge);
}
static GSM_Error N6510_ReplyGetWAPBookmark(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
return DCT3DCT4_ReplyGetWAPBookmark (msg, s, true);
}
static GSM_Error N6510_ReplyGetOperatorLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Operator logo received\n");
+ if (msg.Length == 18) return ERR_EMPTY;
NOKIA_DecodeNetworkCode(msg.Buffer+12,Data->Bitmap->NetworkCode);
smprintf(s, "Network code %s\n",Data->Bitmap->NetworkCode);
Data->Bitmap->BitmapWidth = msg.Buffer[20];
Data->Bitmap->BitmapHeight = msg.Buffer[21];
- if (msg.Length == 18) return ERR_EMPTY;
PHONE_DecodeBitmap(GSM_Nokia6510OperatorLogo,msg.Buffer+26,Data->Bitmap);
return ERR_NONE;
}
GSM_Error N6510_ReplyDeleteMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Phonebook entry deleted\n");
return ERR_NONE;
}
GSM_Error N6510_DeleteMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
unsigned char req[] = {N7110_FRAME_HEADER, 0x0f, 0x55, 0x01,
0x04, 0x55, 0x00, 0x10, 0xFF, 0x02,
0x00, 0x01, /* location */
0x00, 0x00, 0x00, 0x00,
0x05, /* memory type */
0x55, 0x55, 0x55};
req[12] = entry->Location / 256;
req[13] = entry->Location % 256;
req[18] = NOKIA_GetMemoryType(s, entry->MemoryType,N71_65_MEMORY_TYPES);
if (req[18]==0xff) return ERR_NOTSUPPORTED;
smprintf(s, "Deleting phonebook entry\n");
return GSM_WaitFor (s, req, 22, 0x03, 4, ID_SetMemory);
}
static GSM_Error N6510_SetMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
{
int count = 22, blocks;
unsigned char req[500] = {
N7110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x10,
0x02, 0x00, /* memory type */
0x00, 0x00, /* location */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
if (entry->Location == 0) return ERR_NOTSUPPORTED;
req[11] = NOKIA_GetMemoryType(s, entry->MemoryType,N71_65_MEMORY_TYPES);
if (req[11]==0xff) return ERR_NOTSUPPORTED;
req[12] = entry->Location / 256;
req[13] = entry->Location % 256;
count = count + N71_65_EncodePhonebookFrame(s, req+22, *entry, &blocks, true, IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_VOICETAGS));
req[21] = blocks;
smprintf(s, "Writing phonebook entry\n");
return GSM_WaitFor (s, req, count, 0x03, 4, ID_SetMemory);
}
static GSM_Error N6510_ReplySetOperatorLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Operator logo set OK\n");
return ERR_NONE;
}
static GSM_Error N6510_SetCallerLogo(GSM_StateMachine *s, GSM_Bitmap *bitmap)
{
char string[500];
int block=0, i, Width, Height;
unsigned int count = 22;
unsigned char req[500] = {
N6110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x10,
0xfe, 0x10, /* memory type */
0x00, 0x00, /* location */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
req[13] = bitmap->Location;
/* Enabling/disabling logo */
string[0] = bitmap->BitmapEnabled?1:0;
string[1] = 0;
count += N71_65_PackPBKBlock(s, N7110_PBK_LOGOON, 2, block++, string, req + count);
/* Ringtone */
if (!bitmap->DefaultRingtone) {
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PBKTONEGAL)) {
} else {
string[0] = 0x00;
string[1] = 0x00;
string[2] = bitmap->RingtoneID;
count += N71_65_PackPBKBlock(s, N7110_PBK_RINGTONE_ID, 3, block++, string, req + count);
count --;
req[count-5] = 8;
}
}
/* Number of group */
string[0] = bitmap->Location;
string[1] = 0;
count += N71_65_PackPBKBlock(s, N7110_PBK_GROUP, 2, block++, string, req + count);
/* Name */
if (!bitmap->DefaultName) {
i = UnicodeLength(bitmap->Text) * 2;
string[0] = i + 2;
memcpy(string + 1, bitmap->Text, i);
string[i + 1] = 0;
count += N71_65_PackPBKBlock(s, N7110_PBK_NAME, i + 2, block++, string, req + count);
}
/* Logo */
if (!bitmap->DefaultBitmap) {
PHONE_GetBitmapWidthHeight(GSM_NokiaCallerLogo, &Width, &Height);
string[0] = Width;
string[1] = Height;
string[2] = 0;
string[3] = 0;
string[4] = PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0);
PHONE_EncodeBitmap(GSM_NokiaCallerLogo, string + 5, bitmap);
count += N71_65_PackPBKBlock(s, N7110_PBK_GROUPLOGO, PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0) + 5, block++, string, req + count);
}
req[21] = block;
return GSM_WaitFor (s, req, count, 0x03, 4, ID_SetBitmap);
}
static GSM_Error N6510_ReplySetPicture(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
// smprintf(s, "Picture Image written OK, folder %i, location %i\n",msg.Buffer[4],msg.Buffer[5]*256+msg.Buffer[6]);
return ERR_NONE;
}
static GSM_Error N6510_SetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
{
GSM_SMSMessage sms;
GSM_Phone_Bitmap_Types Type;
int Width, Height, i, count;
#ifdef DEVELOP
unsigned char folderid;
int location;
#endif
GSM_NetworkInfo NetInfo;
GSM_Error error;
unsigned char reqStartup[1000] = {
N7110_FRAME_HEADER, 0x04, 0x0F,
0x00, 0x00, 0x00,
0x04, 0xC0, 0x02, 0x00,
0x41, 0xC0, 0x03, 0x00,
0x60, 0xC0, 0x04};
unsigned char reqColourWallPaper[200] = {
N6110_FRAME_HEADER, 0x07, 0x00, 0x00, 0x00, 0xD5,
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00,
0x18}; /* Bitmap ID */
unsigned char reqColourStartup[200] = {
N6110_FRAME_HEADER, 0x04, 0x25, 0x00, 0x01, 0x00, 0x18};
unsigned char reqOp[1000] = {
N7110_FRAME_HEADER, 0x25, 0x01,
0x55, 0x00, 0x00, 0x55,
0x01, /* 0x01 - not set, 0x02 - set */
0x0C, 0x08,
0x62, 0xF0, 0x10, /* Network code */
0x03, 0x55, 0x55};
unsigned char reqColourOp[200] = {
N6110_FRAME_HEADER,
0x07, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, 0xF9, 0x00,
0x08, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00,
0x18, /* File ID */
0x00,
0x00, 0x00, 0x00}; /* Network code */
unsigned char reqNote[200] = {N6110_FRAME_HEADER, 0x04, 0x01};
unsigned char reqPicture[2000] = {
N6110_FRAME_HEADER, 0x00,
0x02, 0x05, /* SMS folder */
0x00, 0x00, /* location */
0x01, 0x01, 0xa0, 0x02, 0x01, 0x40, 0x00, 0x34,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x55, 0x55, 0x55, 0x03, 0x82, 0x10,
0x01, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x10,
0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04,
0x00, 0x00, 0xa1, 0x55, 0x01, 0x08, 0x00, 0x00,
0x00, 0x01, 0x48, 0x1c, 0x00, 0xfc, 0x00};
switch (Bitmap->Type) {
case GSM_ColourWallPaper_ID:
reqColourWallPaper[21] = Bitmap->ID;
smprintf(s, "Setting colour wall paper\n");
return GSM_WaitFor (s, reqColourWallPaper, 22, 0x43, 4, ID_SetBitmap);
case GSM_StartupLogo:
Type = GSM_Nokia7110StartupLogo;
switch (Bitmap->Location) {
case 1: PHONE_EncodeBitmap(Type, reqStartup + 22, Bitmap);
break;
case 2: memset(reqStartup+5,0x00,15);
PHONE_ClearBitmap(Type, reqStartup + 22,0,0);
@@ -1576,385 +1581,386 @@ static GSM_Error N6510_ReplyGetConnectionSettings(GSM_Protocol_Message msg, GSM_
switch (msg.Buffer[tmp+2]) {
case 0x00: smprintf(s, "manual\n"); break;
case 0x01: smprintf(s, "automatic\n"); break;
default: smprintf(s, "unknown\n"); break;
}
#endif
Data->WAPSettings->Settings[num].IsNormalAuthentication=true;
if (msg.Buffer[tmp]==0x01) Data->WAPSettings->Settings[num].IsNormalAuthentication=false;
Data->WAPSettings->Settings[num].IsContinuous = true;
if (msg.Buffer[tmp+1] == 0x01) Data->WAPSettings->Settings[num].IsContinuous = false;
Data->WAPSettings->Settings[num].ManualLogin=false;
if (msg.Buffer[tmp+2]==0x00) Data->WAPSettings->Settings[num].ManualLogin = true;
tmp+=3;
NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[num].DialUp,false);
smprintf(s, "Access point: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[num].DialUp));
NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[num].IPAddress,true);
smprintf(s, "IP address: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[num].IPAddress));
NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[num].User,true);
smprintf(s, "User name: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[num].User));
NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[num].Password,true);
smprintf(s, "Password: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[num].Password));
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_WAPMMSPROXY)) {
if (msg.Buffer[tmp] == 0x00 && msg.Buffer[tmp+1] == 0x00) tmp = tmp+2;
memcpy(buff,msg.Buffer+tmp+10,msg.Buffer[tmp+4]);
buff[msg.Buffer[tmp+4]] = 0x00;
smprintf(s, "Proxy 1: \"%s\", port %i\n",buff,msg.Buffer[tmp+6]*256+msg.Buffer[tmp+7]);
EncodeUnicode(Data->WAPSettings->Proxy,buff,strlen(buff));
Data->WAPSettings->ProxyPort = msg.Buffer[tmp+6]*256+msg.Buffer[tmp+7];
memcpy(buff,msg.Buffer+tmp+10+msg.Buffer[tmp+4],msg.Buffer[tmp+5]);
buff[msg.Buffer[tmp+5]] = 0x00;
smprintf(s, "Proxy 2: \"%s\", port %i\n",buff,msg.Buffer[tmp+8]*256+msg.Buffer[tmp+9]);
EncodeUnicode(Data->WAPSettings->Proxy2,buff,strlen(buff));
Data->WAPSettings->Proxy2Port = msg.Buffer[tmp+8]*256+msg.Buffer[tmp+9];
tmp = tmp + msg.Buffer[tmp+3] + 19;
for (i=0;i<4;i++) {
#ifdef DEBUG
smprintf(s, "Proxy data %i\n",i+1);
if (msg.Buffer[tmp+2]!=0) memcpy(buff,msg.Buffer+tmp+9,msg.Buffer[tmp+2]*2);
buff[msg.Buffer[tmp+2]*2] =0;
buff[msg.Buffer[tmp+2]*2+1]=0;
smprintf(s, "IP: \"%s\"",DecodeUnicodeString(buff));
smprintf(s, ", port %i\n",msg.Buffer[tmp+3]*256+msg.Buffer[tmp+4]);
#endif
tmp = tmp + msg.Buffer[tmp];
}
#ifdef DEBUG
smprintf(s, "%02x %02x\n",msg.Buffer[tmp],msg.Buffer[tmp+1]);
smprintf(s, "Port %i\n",msg.Buffer[tmp+3]*256+msg.Buffer[tmp+4]);
tmp = tmp + msg.Buffer[tmp];
#endif
}
return ERR_NONE;
case 0x17:
smprintf(s, "Connection settings receiving error\n");
switch (msg.Buffer[4]) {
case 0x01:
smprintf(s, "Security error. Inside phone settings menu\n");
return ERR_INSIDEPHONEMENU;
case 0x02:
smprintf(s, "Invalid or empty\n");
return ERR_INVALIDLOCATION;
default:
smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
return ERR_UNKNOWNRESPONSE;
}
break;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_GetConnectionSettings(GSM_StateMachine *s, GSM_MultiWAPSettings *settings, N6510_Connection_Settings Type)
{
GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
GSM_Error error;
unsigned char req[] = {N6110_FRAME_HEADER, 0x15,
0x00}; /* Location */
error = N6510_EnableConnectionFunctions(s, Type);
if (error!=ERR_NONE) return error;
req[4] = settings->Location-1;
s->Phone.Data.WAPSettings = settings;
switch (Type) {
case N6510_MMS_SETTINGS:
smprintf(s, "Getting MMS settings\n");
Priv->BearerNumber = 1;
break;
case N6510_WAP_SETTINGS:
smprintf(s, "Getting WAP settings\n");
Priv->BearerNumber = 2;
break;
case N6510_SYNCML_SETTINGS:
smprintf(s, "Getting SyncML settings\n");
Priv->BearerNumber = 2;
break;
case N6510_CHAT_SETTINGS:
smprintf(s, "Getting Chat settings\n");
Priv->BearerNumber = 1;
break;
}
error=GSM_WaitFor (s, req, 5, 0x3f, 4, ID_GetConnectSet);
if (error != ERR_NONE) {
if (error == ERR_INVALIDLOCATION || error == ERR_INSIDEPHONEMENU) {
DCT3DCT4_DisableConnectionFunctions(s);
}
return error;
}
error=DCT3DCT4_GetActiveConnectSet(s);
if (error != ERR_NONE) return error;
return DCT3DCT4_DisableConnectionFunctions(s);
}
static GSM_Error N6510_GetWAPSettings(GSM_StateMachine *s, GSM_MultiWAPSettings *settings)
{
return N6510_GetConnectionSettings(s, settings, N6510_WAP_SETTINGS);
}
static GSM_Error N6510_GetMMSSettings(GSM_StateMachine *s, GSM_MultiWAPSettings *settings)
{
return N6510_GetConnectionSettings(s, settings, N6510_MMS_SETTINGS);
}
static GSM_Error N6510_ReplyGetSyncMLSettings(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_SyncMLSettings *Sett = s->Phone.Data.SyncMLSettings;
smprintf(s, "SyncML settings received OK\n");
CopyUnicodeString(Sett->User,msg.Buffer+18);
CopyUnicodeString(Sett->Password,msg.Buffer+86);
CopyUnicodeString(Sett->PhonebookDataBase,msg.Buffer+130);
CopyUnicodeString(Sett->CalendarDataBase,msg.Buffer+234);
CopyUnicodeString(Sett->Server,msg.Buffer+338);
Sett->SyncPhonebook = false;
Sett->SyncCalendar = false;
if ((msg.Buffer[598] & 0x02)==0x02) Sett->SyncCalendar = true;
if ((msg.Buffer[598] & 0x01)==0x01) Sett->SyncPhonebook = true;
return ERR_NONE;
}
static GSM_Error N6510_ReplyGetSyncMLName(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_SyncMLSettings *Sett = s->Phone.Data.SyncMLSettings;
smprintf(s, "SyncML names received OK\n");
CopyUnicodeString(Sett->Name,msg.Buffer+18);
return ERR_NONE;
}
static GSM_Error N6510_GetSyncMLSettings(GSM_StateMachine *s, GSM_SyncMLSettings *settings)
{
GSM_Error error;
// unsigned char NameReq[] = {N6110_FRAME_HEADER, 0x05,
// 0x00, 0x00, 0x00, 0x31, 0x00,
// 0x06, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00};
// unsigned char GetActive[] = {N6110_FRAME_HEADER, 0x05,
// 0x00, 0x00, 0x00, 0x31, 0x00,
// 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00};
unsigned char req[] = {N6110_FRAME_HEADER, 0x05,
0x00, 0x00, 0x00, 0x31, 0x00,
0x01, //location
0x00, 0x00, 0x02, 0x46, 0x00, 0x00};
settings->Connection.Location = settings->Location;
error = N6510_GetConnectionSettings(s, &settings->Connection, N6510_SYNCML_SETTINGS);
if (error != ERR_NONE) return error;
settings->Active = settings->Connection.Active;
settings->Name[0] = 0;
settings->Name[1] = 0;
-// s->Phone.Data.SyncMLSettings = settings;
+ s->Phone.Data.SyncMLSettings = settings;
+
// smprintf(s, "Getting SyncML settings name\n");
// error = GSM_WaitFor (s, NameReq, 16, 0x43, 4, ID_GetSyncMLName);
// if (error != ERR_NONE) return error;
req[9] = settings->Location - 1;
smprintf(s, "Getting additional SyncML settings\n");
return GSM_WaitFor (s, req, 16, 0x43, 4, ID_GetSyncMLSettings);
}
static GSM_Error N6510_ReplyGetChatSettings(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_ChatSettings *Sett = s->Phone.Data.ChatSettings;
int i;
Sett->Name[0] = 0;
Sett->Name[1] = 0;
Sett->HomePage[0] = 0;
Sett->HomePage[1] = 0;
Sett->User[0] = 0;
Sett->User[1] = 0;
Sett->Password[0] = 0;
Sett->Password[1] = 0;
switch(msg.Buffer[3]) {
case 0x3B:
smprintf(s, "Chat settings received OK\n");
memcpy(Sett->Name,msg.Buffer+20,msg.Buffer[12]*2);
Sett->Name[msg.Buffer[12]*2] = 0;
Sett->Name[msg.Buffer[12]*2+1] = 0;
memcpy(Sett->HomePage,msg.Buffer+20+msg.Buffer[12]*2,msg.Buffer[15]*2);
Sett->HomePage[msg.Buffer[15]*2] = 0;
Sett->HomePage[msg.Buffer[15]*2+1] = 0;
i = msg.Buffer[12]*2 + msg.Buffer[15]*2 + 29;
memcpy(Sett->User,msg.Buffer+i+3,msg.Buffer[i]*2);
Sett->User[msg.Buffer[i]*2] = 0;
Sett->User[msg.Buffer[i]*2+1] = 0;
memcpy(Sett->Password,msg.Buffer+i+3+msg.Buffer[i]*2,msg.Buffer[i+1]*2);
Sett->Password[msg.Buffer[i+1]*2] = 0;
Sett->Password[msg.Buffer[i+1]*2+1] = 0;
return ERR_NONE;
case 0x3C:
smprintf(s, "Empty chat settings received\n");
return ERR_NONE;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_GetChatSettings(GSM_StateMachine *s, GSM_ChatSettings *settings)
{
GSM_Error error;
unsigned char req[] = {N6110_FRAME_HEADER, 0x3a,
0x09, // location
0x01, 0x0e};
settings->Connection.Location = settings->Location;
error = N6510_GetConnectionSettings(s, &settings->Connection, N6510_CHAT_SETTINGS);
if (error != ERR_NONE) return error;
settings->Active = settings->Connection.Active;
s->Phone.Data.ChatSettings = settings;
req[4] = settings->Location - 1;
smprintf(s, "Getting additional Chat settings\n");
return GSM_WaitFor (s, req, 7, 0x3f, 4, ID_GetChatSettings);
}
static GSM_Error N6510_ReplySetConnectionSettings(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[3]) {
case 0x19:
smprintf(s, "Connection settings cleaned\n");
return ERR_NONE;
case 0x1a:
smprintf(s, "Connection settings setting status\n");
switch (msg.Buffer[4]) {
case 0x01:
smprintf(s, "Security error. Inside phone settings menu\n");
return ERR_INSIDEPHONEMENU;
case 0x03:
smprintf(s, "Invalid location\n");
return ERR_INVALIDLOCATION;
case 0x05:
smprintf(s, "Written OK\n");
return ERR_NONE;
default:
smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
return ERR_UNKNOWNRESPONSE;
}
case 0x28:
case 0x2B:
smprintf(s, "Set OK\n");
return ERR_NONE;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_SetConnectionSettings(GSM_StateMachine *s, GSM_MultiWAPSettings *settings, N6510_Connection_Settings Type)
{
GSM_Error error;
int i, pad = 0, length, pos = 5, loc1=-1,loc2=-1,port;
unsigned char *Proxy;
unsigned char req[2000] = {N6110_FRAME_HEADER, 0x18,
0x00}; /* Location */
unsigned char Lock[5] = {N6110_FRAME_HEADER, 0x27,
0x00}; /* Location */
unsigned char UnLock[5] = {N6110_FRAME_HEADER, 0x2A,
0x00}; /* Location */
error = N6510_EnableConnectionFunctions(s, Type);
if (error!=ERR_NONE) return error;
memset(req + pos, 0, 1000 - pos);
req[4] = settings->Location-1;
for (i=0;i<settings->Number;i++) {
if (settings->Settings[i].Bearer == WAPSETTINGS_BEARER_DATA) loc1=i;
if (settings->Settings[i].Bearer == WAPSETTINGS_BEARER_GPRS) loc2=i;
}
if (loc1 != -1) {
/* Name */
length = UnicodeLength(settings->Settings[loc1].Title);
if (!(length % 2)) pad = 1;
pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc1].Title, false);
/* Home */
length = UnicodeLength(settings->Settings[loc1].HomePage);
if (((length + pad) % 2)) pad = 2; else pad = 0;
pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc1].HomePage, true);
if (settings->Settings[loc1].IsContinuous) req[pos] = 0x01; pos++;
if (settings->Settings[loc1].IsSecurity) req[pos] = 0x01; pos++;
} else if (loc2 != -1) {
/* Name */
length = UnicodeLength(settings->Settings[loc2].Title);
if (!(length % 2)) pad = 1;
pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc2].Title, false);
/* Home */
length = UnicodeLength(settings->Settings[loc2].HomePage);
if (((length + pad) % 2)) pad = 2; else pad = 0;
pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc2].HomePage, true);
if (settings->Settings[loc2].IsContinuous) req[pos] = 0x01; pos++;
if (settings->Settings[loc2].IsSecurity) req[pos] = 0x01; pos++;
} else {
/* Name */
length = 0;
if (!(length % 2)) pad = 1;
pos ++;
/* Home */
length = 0;
if (((length + pad) % 2)) pad = 2; else pad = 0;
pos += 2;
pos += 2;
}
if (Type == N6510_MMS_SETTINGS || Type == N6510_CHAT_SETTINGS) {
req[pos++] = 0x03; //active bearer: GPRS
} else {
if (settings->ActiveBearer == WAPSETTINGS_BEARER_GPRS && loc2 != -1) {
req[pos++] = 0x03; //active bearer: GPRS
} else {
req[pos++] = 0x01; //active bearer: data set
}
}
/* Number of sent bearers */
if (Type == N6510_MMS_SETTINGS || Type == N6510_CHAT_SETTINGS) {
req[pos] = 0x01;
} else {
req[pos] = 0x02;
}
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_WAPMMSPROXY)) req[pos] += 2;
pos++;
pos += pad;
if (Type != N6510_MMS_SETTINGS && Type != N6510_CHAT_SETTINGS) {
/* GSM data block */
memcpy(req + pos, "\x01\x00", 2); pos += 2;
if (loc1 != -1) {
length = UnicodeLength(settings->Settings[loc1].IPAddress)*2+1;
length += UnicodeLength(settings->Settings[loc1].DialUp) *2+2;
length += UnicodeLength(settings->Settings[loc1].User) *2+2;
length += UnicodeLength(settings->Settings[loc1].Password) *2+2;
} else {
length = 1 + 2 + 2 + 2;
}
@@ -2094,385 +2100,385 @@ static GSM_Error N6510_SetConnectionSettings(GSM_StateMachine *s, GSM_MultiWAPSe
req[pos++] = 0x00;
req[pos++] = 0x01;
req[pos++] = 0x00;
if (Proxy != NULL && UnicodeLength(Proxy)!=0) {
CopyUnicodeString(req+pos,Proxy);
pos+=UnicodeLength(Proxy)*2;
if (UnicodeLength(Proxy)%2 != 0) {
req[pos++] = 0x00;
req[pos++] = 0x00;
}
}
}
req[pos++] = 0x09; req[pos++] = 0x00; req[pos++] = 0x00;
req[pos++] = 0x0C; req[pos++] = 0x02; req[pos++] = 0x00;
req[pos++] = 0x00; req[pos++] = 0x02; req[pos++] = 0x00;
req[pos++] = 0x00; req[pos++] = 0x00; req[pos++] = 0x00;
} else {
/* end of blocks ? */
memcpy(req + pos, "\x80\x00\x00\x0c", 4); pos += 4;
}
UnLock[4] = settings->Location-1;
smprintf(s, "Making Connection settings read-write\n");
error = GSM_WaitFor (s, UnLock, 5, 0x3f, 4, ID_SetConnectSet);
if (error != ERR_NONE) return error;
switch (Type) {
case N6510_MMS_SETTINGS:
smprintf(s, "Setting MMS settings\n");
break;
case N6510_CHAT_SETTINGS:
smprintf(s, "Setting Chat settings\n");
break;
case N6510_WAP_SETTINGS:
smprintf(s, "Setting WAP settings\n");
break;
case N6510_SYNCML_SETTINGS:
smprintf(s, "Setting SyncML settings\n");
break;
}
error = GSM_WaitFor (s, req, pos, 0x3f, 4, ID_SetConnectSet);
if (error != ERR_NONE) {
if (error == ERR_INSIDEPHONEMENU || error == ERR_INVALIDLOCATION) {
DCT3DCT4_DisableConnectionFunctions(s);
}
return error;
}
if (settings->ReadOnly) {
Lock[4] = settings->Location-1;
smprintf(s, "Making Connection settings readonly\n");
error = GSM_WaitFor (s, Lock, 5, 0x3f, 4, ID_SetConnectSet);
if (error != ERR_NONE) return error;
}
error = DCT3DCT4_SetActiveConnectSet(s, settings);
if (error != ERR_NONE) return error;
return DCT3DCT4_DisableConnectionFunctions(s);
}
static GSM_Error N6510_SetWAPSettings(GSM_StateMachine *s, GSM_MultiWAPSettings *settings)
{
return N6510_SetConnectionSettings(s, settings, N6510_WAP_SETTINGS);
}
static GSM_Error N6510_SetMMSSettings(GSM_StateMachine *s, GSM_MultiWAPSettings *settings)
{
return N6510_SetConnectionSettings(s, settings, N6510_MMS_SETTINGS);
}
static GSM_Error N6510_ReplyGetOriginalIMEI(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
if (msg.Buffer[7] == 0x00) {
smprintf(s, "No SIM card\n");
return ERR_SECURITYERROR;
} else {
return NOKIA_ReplyGetPhoneString(msg, s);
}
}
static GSM_Error N6510_GetOriginalIMEI(GSM_StateMachine *s, char *value)
{
return NOKIA_GetPhoneString(s,"\x00\x07\x02\x01\x00\x01",6,0x42,value,ID_GetOriginalIMEI,14);
}
static GSM_Error N6510_ReplyGetSMSStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
switch (msg.Buffer[3]) {
case 0x09:
switch (msg.Buffer[4]) {
case 0x00:
smprintf(s, "Max. in phone memory : %i\n",msg.Buffer[10]*256+msg.Buffer[11]);
smprintf(s, "Used in phone memory : %i\n",msg.Buffer[12]*256+msg.Buffer[13]);
smprintf(s, "Unread in phone memory : %i\n",msg.Buffer[14]*256+msg.Buffer[15]);
smprintf(s, "Max. in SIM : %i\n",msg.Buffer[22]*256+msg.Buffer[23]);
smprintf(s, "Used in SIM : %i\n",msg.Buffer[24]*256+msg.Buffer[25]);
smprintf(s, "Unread in SIM : %i\n",msg.Buffer[26]*256+msg.Buffer[27]);
Data->SMSStatus->PhoneSize = msg.Buffer[10]*256+msg.Buffer[11];
Data->SMSStatus->PhoneUsed = msg.Buffer[12]*256+msg.Buffer[13];
Data->SMSStatus->PhoneUnRead = msg.Buffer[14]*256+msg.Buffer[15];
Data->SMSStatus->SIMSize = msg.Buffer[22]*256+msg.Buffer[23];
Data->SMSStatus->SIMUsed = msg.Buffer[24]*256+msg.Buffer[25];
Data->SMSStatus->SIMUnRead = msg.Buffer[26]*256+msg.Buffer[27];
return ERR_NONE;
case 0x0f:
smprintf(s, "No PIN\n");
return ERR_SECURITYERROR;
default:
smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
return ERR_UNKNOWNRESPONSE;
}
case 0x1a:
smprintf(s, "Wait a moment. Phone is during power on and busy now\n");
return ERR_SECURITYERROR;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_GetSMSStatus(GSM_StateMachine *s, GSM_SMSMemoryStatus *status)
{
GSM_Error error;
GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
unsigned char req[] = {N6110_FRAME_HEADER, 0x08, 0x00, 0x00};
s->Phone.Data.SMSStatus=status;
smprintf(s, "Getting SMS status\n");
error = GSM_WaitFor (s, req, 6, 0x14, 2, ID_GetSMSStatus);
if (error != ERR_NONE) return error;
/* DCT4 family doesn't show in frame with SMS status info
* about Templates. We get separately info about this SMS folder.
*/
error = N6510_GetSMSFolderStatus(s, 0x06);
if (error != ERR_NONE) return error;
status->TemplatesUsed = Priv->LastSMSFolder.Number;
return error;
}
static GSM_Error N6510_ReplyDeleteSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[3]) {
case 0x05:
smprintf(s, "SMS deleted OK\n");
return ERR_NONE;
case 0x06:
switch (msg.Buffer[4]) {
case 0x02:
smprintf(s, "Invalid location\n");
return ERR_INVALIDLOCATION;
default:
smprintf(s, "Unknown error: %02x\n",msg.Buffer[4]);
return ERR_UNKNOWNRESPONSE;
}
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_DeleteSMSMessage(GSM_StateMachine *s, GSM_SMSMessage *sms)
{
unsigned char folderid;
int location;
unsigned char req[] = {N6110_FRAME_HEADER, 0x04,
0x01, /* 0x01=SM, 0x02=ME */
0x00, /* FolderID */
0x00, 0x02, /* Location */
0x0F, 0x55};
N6510_GetSMSLocation(s, sms, &folderid, &location);
switch (folderid) {
case 0x01: req[5] = 0x02; break; /* INBOX SIM */
case 0x02: req[5] = 0x03; break; /* OUTBOX SIM */
default : req[5] = folderid - 1; req[4] = 0x02; break; /* ME folders */
}
req[6]=location / 256;
req[7]=location;
smprintf(s, "Deleting sms\n");
return GSM_WaitFor (s, req, 10, 0x14, 4, ID_DeleteSMSMessage);
}
static GSM_Error N6510_ReplySendSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[8]) {
case 0x00:
- smprintf(s, "SMS sent OK, TPMR for sent sms is %02x\n",msg.Buffer[10]);
+ smprintf(s, "SMS sent OK, TPMR for sent sms is %d\n",msg.Buffer[10]);
if (s->User.SendSMSStatus!=NULL) s->User.SendSMSStatus(s->CurrentConfig->Device,0,msg.Buffer[10]);
return ERR_NONE;
default:
smprintf(s, "SMS not sent OK, error code probably %i\n",msg.Buffer[8]);
if (s->User.SendSMSStatus!=NULL) s->User.SendSMSStatus(s->CurrentConfig->Device,msg.Buffer[8],msg.Buffer[10]);
return ERR_NONE;
}
}
static GSM_Error N6510_SendSMSMessage(GSM_StateMachine *s, GSM_SMSMessage *sms)
{
int length = 11;
GSM_Error error;
GSM_SMSMessageLayout Layout;
unsigned char req [300] = {
N6110_FRAME_HEADER, 0x02, 0x00, 0x00, 0x00, 0x55, 0x55};
if (sms->PDU == SMS_Deliver) sms->PDU = SMS_Submit;
memset(req+9,0x00,sizeof(req) - 9);
error=N6510_EncodeSMSFrame(s, sms, req + 9, &Layout, &length);
if (error != ERR_NONE) return error;
smprintf(s, "Sending sms\n");
return s->Protocol.Functions->WriteMessage(s, req, length + 9, 0x02);
}
static GSM_Error N6510_ReplyGetSecurityStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Security Code status received: ");
switch (msg.Buffer[4]) {
case 0x01 : smprintf(s, "waiting for Security Code.\n"); *Data->SecurityStatus = SEC_SecurityCode; break;
case 0x07 :
case 0x02 : smprintf(s, "waiting for PIN.\n"); *Data->SecurityStatus = SEC_Pin; break;
case 0x03 : smprintf(s, "waiting for PUK.\n"); *Data->SecurityStatus = SEC_Puk; break;
case 0x05 : smprintf(s, "PIN ok, SIM ok\n"); *Data->SecurityStatus = SEC_None; break;
case 0x06 : smprintf(s, "No input status\n"); *Data->SecurityStatus = SEC_None; break;
case 0x16 : smprintf(s, "No SIM card\n"); *Data->SecurityStatus = SEC_None; break;
case 0x1A : smprintf(s, "SIM card rejected!\n"); *Data->SecurityStatus = SEC_None; break;
default : smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
return ERR_UNKNOWNRESPONSE;
}
return ERR_NONE;
}
static GSM_Error N6510_GetSecurityStatus(GSM_StateMachine *s, GSM_SecurityCodeType *Status)
{
unsigned char req[5] = {N6110_FRAME_HEADER, 0x11, 0x00};
s->Phone.Data.SecurityStatus=Status;
smprintf(s, "Getting security code status\n");
return GSM_WaitFor (s, req, 5, 0x08, 2, ID_GetSecurityStatus);
}
static GSM_Error N6510_ReplyEnterSecurityCode(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[3]) {
case 0x08:
smprintf(s, "Security code OK\n");
return ERR_NONE;
case 0x09:
switch (msg.Buffer[4]) {
case 0x06:
smprintf(s, "Wrong PIN\n");
return ERR_SECURITYERROR;
case 0x09:
smprintf(s, "Wrong PUK\n");
return ERR_SECURITYERROR;
default:
smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
}
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_EnterSecurityCode(GSM_StateMachine *s, GSM_SecurityCode Code)
{
int len = 0;
unsigned char req[15] = {N6110_FRAME_HEADER, 0x07,
0x00}; /* Code type */
switch (Code.Type) {
case SEC_Pin : req[4] = 0x02; break;
case SEC_Puk : req[4] = 0x03; break;/* FIXME */
default : return ERR_NOTSUPPORTED;
}
len = strlen(Code.Code);
memcpy(req+5,Code.Code,len);
req[5+len]=0x00;
smprintf(s, "Entering security code\n");
return GSM_WaitFor (s, req, 6+len, 0x08, 4, ID_EnterSecurityCode);
}
static GSM_Error N6510_ReplySaveSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
unsigned char folder;
GSM_Phone_Data *Data = &s->Phone.Data;
switch (msg.Buffer[3]) {
case 0x01:
switch (msg.Buffer[4]) {
case 0x00:
smprintf(s, "Done OK\n");
smprintf(s, "Folder info: %i %i\n",msg.Buffer[5],msg.Buffer[8]);
switch (msg.Buffer[8]) {
case 0x02 : if (msg.Buffer[5] == 0x02) {
folder = 0x03; /* INBOX ME */
} else {
folder = 0x01; /* INBOX SIM */
}
break;
case 0x03 : if (msg.Buffer[5] == 0x02) {
folder = 0x04; /* OUTBOX ME */
} else {
folder = 0x02; /* OUTBOX SIM */
}
break;
default : folder = msg.Buffer[8] + 1;
}
N6510_SetSMSLocation(s, Data->SaveSMSMessage,folder,msg.Buffer[6]*256+msg.Buffer[7]);
smprintf(s, "Saved in folder %i at location %i\n",folder, msg.Buffer[6]*256+msg.Buffer[7]);
Data->SaveSMSMessage->Folder = folder;
return ERR_NONE;
case 0x02:
printf("Incorrect location\n");
return ERR_INVALIDLOCATION;
case 0x05:
printf("Incorrect folder\n");
return ERR_INVALIDLOCATION;
default:
smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
return ERR_UNKNOWNRESPONSE;
}
case 0x17:
smprintf(s, "SMS name changed\n");
return ERR_NONE;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_PrivSetSMSMessage(GSM_StateMachine *s, GSM_SMSMessage *sms)
{
int location, length = 11;
unsigned char folderid, folder;
GSM_SMSMessageLayout Layout;
GSM_Error error;
unsigned char req [300] = {
N6110_FRAME_HEADER, 0x00,
0x01, /* 1 = SIM, 2 = ME */
0x02, /* Folder */
0x00, 0x01, /* Location */
0x01}; /* SMS state */
unsigned char NameReq[200] = {
N6110_FRAME_HEADER, 0x16,
0x01, /* 1 = SIM, 2 = ME */
0x02, /* Folder */
0x00, 0x01}; /* Location */
N6510_GetSMSLocation(s, sms, &folderid, &location);
switch (folderid) {
case 0x01: req[5] = 0x02; break; /* INBOX SIM */
case 0x02: req[5] = 0x03; break; /* OUTBOX SIM */
default : req[5] = folderid - 1; req[4] = 0x02; break; /* ME folders */
}
req[6]=location / 256;
req[7]=location;
switch (sms->PDU) {
case SMS_Submit:
/* Inbox */
if (folderid == 0x01 || folderid == 0x03) sms->PDU = SMS_Deliver;
break;
case SMS_Deliver:
/* SIM Outbox */
if (folderid == 0x02) sms->PDU = SMS_Submit;
break;
default:
return ERR_UNKNOWN;
}
if (sms->PDU == SMS_Deliver) {
switch (sms->State) {
case SMS_Sent : /* We use GSM_Read, because phone return error */
case SMS_Read : req[8] = 0x01; break;
case SMS_UnSent : /* We use GSM_UnRead, because phone return error */
case SMS_UnRead : req[8] = 0x03; break;
}
} else {
switch (sms->State) {
case SMS_Sent : /* We use GSM_Sent, because phone change folder */
@@ -2581,2013 +2587,2089 @@ static GSM_Error N6510_ReplyGetManufactureMonth(GSM_Protocol_Message msg, GSM_St
} else {
sprintf(s->Phone.Data.PhoneString,"%02i/%04i",msg.Buffer[13],msg.Buffer[14]*256+msg.Buffer[15]);
return ERR_NONE;
}
}
static GSM_Error N6510_GetManufactureMonth(GSM_StateMachine *s, char *value)
{
unsigned char req[6] = {0x00, 0x05, 0x02, 0x01, 0x00, 0x02};
// unsigned char req[6] = {0x00, 0x03, 0x04, 0x0B, 0x01, 0x00};
s->Phone.Data.PhoneString=value;
smprintf(s, "Getting manufacture month\n");
return GSM_WaitFor (s, req, 6, 0x42, 2, ID_GetManufactureMonth);
// return GSM_WaitFor (s, req, 6, 0x1B, 2, ID_GetManufactureMonth);
}
static GSM_Error N6510_ReplyGetAlarm(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
switch(msg.Buffer[3]) {
case 0x1A:
smprintf(s, " Alarm: %02d:%02d\n", msg.Buffer[14], msg.Buffer[15]);
Data->Alarm->Repeating = true;
Data->Alarm->Text[0] = 0;
Data->Alarm->Text[1] = 0;
Data->Alarm->DateTime.Hour = msg.Buffer[14];
Data->Alarm->DateTime.Minute = msg.Buffer[15];
Data->Alarm->DateTime.Second = 0;
return ERR_NONE;
case 0x20:
smprintf(s, "Alarm state received\n");
if (msg.Buffer[37] == 0x01) {
smprintf(s, " Not set in phone\n");
return ERR_EMPTY;
}
smprintf(s, "Enabled\n");
return ERR_NONE;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_GetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
{
unsigned char StateReq[] = {N6110_FRAME_HEADER, 0x1f, 0x01, 0x00};
unsigned char GetReq [] = {N6110_FRAME_HEADER, 0x19, 0x00, 0x02};
GSM_Error error;
if (alarm->Location != 1) return ERR_NOTSUPPORTED;
s->Phone.Data.Alarm=alarm;
smprintf(s, "Getting alarm state\n");
error = GSM_WaitFor (s, StateReq, 6, 0x19, 4, ID_GetAlarm);
if (error != ERR_NONE) return error;
smprintf(s, "Getting alarm\n");
return GSM_WaitFor (s, GetReq, 6, 0x19, 4, ID_GetAlarm);
}
static GSM_Error N6510_ReplySetAlarm(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Alarm set\n");
return ERR_NONE;
}
static GSM_Error N6510_SetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
{
unsigned char req[] = {N6110_FRAME_HEADER,
0x11, 0x00, 0x01, 0x01, 0x0c, 0x02,
0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, /* Hours, Minutes */
0x00, 0x00, 0x00 };
if (alarm->Location != 1) return ERR_NOTSUPPORTED;
req[14] = alarm->DateTime.Hour;
req[15] = alarm->DateTime.Minute;
smprintf(s, "Setting alarm\n");
return GSM_WaitFor (s, req, 19, 0x19, 4, ID_SetAlarm);
}
static GSM_Error N6510_ReplyGetRingtonesInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int tmp,i;
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Ringtones info received\n");
memset(Data->RingtonesInfo,0,sizeof(GSM_AllRingtonesInfo));
if (msg.Buffer[4] * 256 + msg.Buffer[5] == 0x00) return ERR_EMPTY;
Data->RingtonesInfo->Number = msg.Buffer[4] * 256 + msg.Buffer[5];
tmp = 6;
for (i=0;i<Data->RingtonesInfo->Number;i++) {
Data->RingtonesInfo->Ringtone[i].Group = msg.Buffer[tmp+4];
Data->RingtonesInfo->Ringtone[i].ID = msg.Buffer[tmp+2] * 256 + msg.Buffer[tmp+3];
memcpy(Data->RingtonesInfo->Ringtone[i].Name,msg.Buffer+tmp+8,(msg.Buffer[tmp+6]*256+msg.Buffer[tmp+7])*2);
smprintf(s, "%5i (%5i). \"%s\"\n",
Data->RingtonesInfo->Ringtone[i].ID,
Data->RingtonesInfo->Ringtone[i].Group,
DecodeUnicodeString(Data->RingtonesInfo->Ringtone[i].Name));
tmp = tmp + (msg.Buffer[tmp]*256+msg.Buffer[tmp+1]);
}
return ERR_NONE;
}
static GSM_Error N6510_PrivGetRingtonesInfo(GSM_StateMachine *s, GSM_AllRingtonesInfo *Info, bool AllRingtones)
{
GSM_Error error;
unsigned char UserReq[8] = {N7110_FRAME_HEADER, 0x07, 0x00, 0x00, 0x00, 0x02};
// unsigned char All_Req[9] = {N7110_FRAME_HEADER, 0x07, 0x00, 0x00, 0xFE, 0x00, 0x7D};
unsigned char All_Req[8] = {N7110_FRAME_HEADER, 0x07, 0x00, 0x00, 0x00, 0x00};
s->Phone.Data.RingtonesInfo=Info;
smprintf(s, "Getting binary ringtones ID\n");
if (AllRingtones) {
// error = GSM_WaitFor (s, All_Req, 9, 0x1f, 4, ID_GetRingtonesInfo);
error = GSM_WaitFor (s, All_Req, 8, 0x1f, 4, ID_GetRingtonesInfo);
if (error == ERR_EMPTY && Info->Number == 0) return ERR_NOTSUPPORTED;
return error;
} else {
error = GSM_WaitFor (s, UserReq, 8, 0x1f, 4, ID_GetRingtonesInfo);
if (error == ERR_EMPTY && Info->Number == 0) return ERR_NOTSUPPORTED;
return error;
}
}
static GSM_Error N6510_GetRingtonesInfo(GSM_StateMachine *s, GSM_AllRingtonesInfo *Info)
{
return N6510_PrivGetRingtonesInfo(s, Info, true);
}
static GSM_Error N6510_ReplyGetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int tmp,i;
GSM_Phone_Data *Data = &s->Phone.Data;
smprintf(s, "Ringtone received\n");
memcpy(Data->Ringtone->Name,msg.Buffer+8,msg.Buffer[7]*2);
Data->Ringtone->Name[msg.Buffer[7]*2]=0;
Data->Ringtone->Name[msg.Buffer[7]*2+1]=0;
smprintf(s, "Name \"%s\"\n",DecodeUnicodeString(Data->Ringtone->Name));
if (msg.Buffer[msg.Buffer[7]*2+10] == 'M' &&
msg.Buffer[msg.Buffer[7]*2+11] == 'T' &&
msg.Buffer[msg.Buffer[7]*2+12] == 'h' &&
msg.Buffer[msg.Buffer[7]*2+13] == 'd') {
smprintf(s,"MIDI\n");
tmp = msg.Buffer[7]*2+10;
i = msg.Length - 2; /* ?????? */
Data->Ringtone->Format = RING_MIDI;
} else {
/* Looking for end */
i=8+msg.Buffer[7]*2+3;
tmp = i;
while (true) {
if (msg.Buffer[i]==0x07 && msg.Buffer[i+1]==0x0b) {
i=i+2; break;
}
i++;
if (i==msg.Length) return ERR_EMPTY;
}
}
/* Copying frame */
memcpy(Data->Ringtone->NokiaBinary.Frame,msg.Buffer+tmp,i-tmp);
Data->Ringtone->NokiaBinary.Length=i-tmp;
return ERR_NONE;
}
static GSM_Error N6510_GetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone)
{
GSM_AllRingtonesInfo Info;
GSM_Error error;
unsigned char req2[6] = {N7110_FRAME_HEADER, 0x12,
0x00, 0xe7}; /* Location */
if (Ringtone->Format == 0x00) Ringtone->Format = RING_NOKIABINARY;
switch (Ringtone->Format) {
case RING_NOTETONE:
/* In the future get binary and convert */
return ERR_NOTSUPPORTED;
case RING_NOKIABINARY:
s->Phone.Data.Ringtone = Ringtone;
Info.Number = 0;
error=N6510_PrivGetRingtonesInfo(s, &Info, PhoneRingtone);
if (error != ERR_NONE) return error;
if (Ringtone->Location > Info.Number) return ERR_INVALIDLOCATION;
req2[4] = Info.Ringtone[Ringtone->Location-1].ID / 256;
req2[5] = Info.Ringtone[Ringtone->Location-1].ID % 256;
smprintf(s, "Getting binary ringtone\n");
return GSM_WaitFor (s, req2, 6, 0x1f, 4, ID_GetRingtone);
case RING_MIDI:
+ case RING_MMF:
return ERR_NOTSUPPORTED;
}
return ERR_NOTSUPPORTED;
}
static GSM_Error N6510_PlayTone(GSM_StateMachine *s, int Herz, unsigned char Volume, bool start)
{
GSM_Error error;
unsigned char reqStart[] = {
0x00,0x06,0x01,0x00,0x07,0x00 };
unsigned char reqPlay[] = {
0x00,0x06,0x01,0x14,0x05,0x04,
0x00,0x00,0x00,0x03,0x03,0x08,
0x00,0x00,0x00,0x01,0x00,0x00,
0x03,0x08,0x01,0x00,
0x07,0xd0, /*Frequency */
0x00,0x00,0x03,0x08,0x02,0x00,0x00,
0x05, /*Volume */
0x00,0x00};
unsigned char reqOff[] = {
0x00,0x06,0x01,0x14,0x05,0x05,
0x00,0x00,0x00,0x01,0x03,0x08,
0x05,0x00,0x00,0x08,0x00,0x00};
// unsigned char reqOff2[] = {
// 0x00,0x06,0x01,0x14,0x05,0x04,
// 0x00,0x00,0x00,0x01,0x03,0x08,
// 0x00,0x00,0x00,0x00,0x00,0x00};
if (start) {
smprintf(s, "Enabling sound - part 1\n");
error=GSM_WaitFor (s, reqStart, 6, 0x0b, 4, ID_PlayTone);
if (error!=ERR_NONE) return error;
smprintf(s, "Enabling sound - part 2 (disabling sound command)\n");
error=GSM_WaitFor (s, reqOff, 18, 0x0b, 4, ID_PlayTone);
if (error!=ERR_NONE) return error;
}
/* For Herz==255*255 we have silent */
if (Herz!=255*255) {
reqPlay[23] = Herz%256;
reqPlay[22] = Herz/256;
reqPlay[31] = Volume;
smprintf(s, "Playing sound\n");
return GSM_WaitFor (s, reqPlay, 34, 0x0b, 4, ID_PlayTone);
} else {
reqPlay[23] = 0;
reqPlay[22] = 0;
reqPlay[31] = 0;
smprintf(s, "Playing silent sound\n");
return GSM_WaitFor (s, reqPlay, 34, 0x0b, 4, ID_PlayTone);
// smprintf(s, "Disabling sound - part 1\n");
// error=GSM_WaitFor (s, reqOff, 18, 0x0b, 4, ID_PlayTone);
// if (error!=ERR_NONE) return error;
// smprintf(s, "Disabling sound - part 2\n");
// return GSM_WaitFor (s, reqOff2, 18, 0x0b, 4, ID_PlayTone);
}
}
static GSM_Error N6510_ReplyGetPPM(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Phone_Data *Data = &s->Phone.Data;
int pos = 6,len;
smprintf(s, "Received phone info\n");
while(pos < msg.Length) {
if (msg.Buffer[pos] == 0x55 && msg.Buffer[pos+1] == 0x55) {
while(1) {
if (msg.Buffer[pos] != 0x55) break;
pos++;
}
}
len = pos;
while(1) {
if (msg.Buffer[len] == 0x00 && msg.Buffer[len+1] == 0x00) break;
len++;
}
while(1) {
if (msg.Buffer[len] != 0x00) break;
len++;
}
len = len-pos;
smprintf(s, "Block with ID %02x",msg.Buffer[pos]);
#ifdef DEBUG
if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, msg.Buffer+pos, len);
#endif
switch (msg.Buffer[pos]) {
case 0x49:
smprintf(s, "hardware version\n");
break;
case 0x58:
pos += 3;
while (msg.Buffer[pos] != 0x00) pos++;
Data->PhoneString[0] = msg.Buffer[pos - 1];
Data->PhoneString[1] = 0x00;
smprintf(s, "PPM %s\n",Data->PhoneString);
return ERR_NONE;
default:
break;
}
pos += len;
}
return ERR_NOTSUPPORTED;
}
static GSM_Error N6510_GetPPM(GSM_StateMachine *s,char *value)
{
// unsigned char req[6] = {N6110_FRAME_HEADER, 0x07, 0x01, 0xff};
unsigned char req[6] = {N6110_FRAME_HEADER, 0x07, 0x01, 0x00};
s->Phone.Data.PhoneString=value;
smprintf(s, "Getting PPM\n");
return GSM_WaitFor (s, req, 6, 0x1b, 3, ID_GetPPM);
}
static GSM_Error N6510_GetSpeedDial(GSM_StateMachine *s, GSM_SpeedDial *SpeedDial)
{
GSM_MemoryEntry pbk;
GSM_Error error;
pbk.MemoryType = MEM7110_SP;
pbk.Location = SpeedDial->Location;
SpeedDial->MemoryLocation = 0;
s->Phone.Data.SpeedDial = SpeedDial;
smprintf(s, "Getting speed dial\n");
error=N6510_GetMemory(s,&pbk);
switch (error) {
case ERR_NOTSUPPORTED:
smprintf(s, "No speed dials set in phone\n");
return ERR_EMPTY;
case ERR_NONE:
if (SpeedDial->MemoryLocation == 0) {
smprintf(s, "Speed dial not assigned or error in firmware\n");
return ERR_EMPTY;
}
return ERR_NONE;
default:
return error;
}
}
static GSM_Error N6510_ReplyGetProfile(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
unsigned char *blockstart;
int i,j;
GSM_Phone_Data *Data = &s->Phone.Data;
switch (msg.Buffer[3]) {
case 0x02:
blockstart = msg.Buffer + 7;
for (i = 0; i < 11; i++) {
smprintf(s, "Profile feature %02x ",blockstart[1]);
#ifdef DEBUG
if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, blockstart, blockstart[0]);
#endif
switch (blockstart[1]) {
case 0x03:
smprintf(s, "Ringtone ID\n");
Data->Profile->FeatureID [Data->Profile->FeaturesNumber] = Profile_RingtoneID;
Data->Profile->FeatureValue [Data->Profile->FeaturesNumber] = blockstart[7];
if (blockstart[7] == 0x00) {
Data->Profile->FeatureValue[Data->Profile->FeaturesNumber] = blockstart[10];
}
Data->Profile->FeaturesNumber++;
break;
case 0x05: /* SMS tone */
j = Data->Profile->FeaturesNumber;
NOKIA_FindFeatureValue(s, Profile71_65,blockstart[1],blockstart[7],Data,false);
if (j == Data->Profile->FeaturesNumber) {
Data->Profile->FeatureID [Data->Profile->FeaturesNumber] = Profile_MessageTone;
Data->Profile->FeatureValue [Data->Profile->FeaturesNumber] = PROFILE_MESSAGE_PERSONAL;
Data->Profile->FeaturesNumber++;
Data->Profile->FeatureID [Data->Profile->FeaturesNumber] = Profile_MessageToneID;
Data->Profile->FeatureValue [Data->Profile->FeaturesNumber] = blockstart[7];
Data->Profile->FeaturesNumber++;
}
break;
case 0x08: /* Caller groups */
NOKIA_FindFeatureValue(s, Profile71_65,blockstart[1],blockstart[7],Data,true);
break;
case 0x0c :
CopyUnicodeString(Data->Profile->Name,blockstart + 7);
smprintf(s, "profile Name: \"%s\"\n", DecodeUnicodeString(Data->Profile->Name));
Data->Profile->DefaultName = false;
break;
default:
NOKIA_FindFeatureValue(s, Profile71_65,blockstart[1],blockstart[7],Data,false);
}
blockstart = blockstart + blockstart[0];
}
return ERR_NONE;
case 0x06:
Data->Profile->Active = false;
if (Data->Profile->Location == msg.Buffer[5]) Data->Profile->Active = true;
return ERR_NONE;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_GetProfile(GSM_StateMachine *s, GSM_Profile *Profile)
{
unsigned char req[150] = {N6110_FRAME_HEADER, 0x01, 0x01, 0x0C, 0x01};
unsigned char reqActive[] = {N6110_FRAME_HEADER, 0x05};
int i, length = 7;
GSM_Error error;
/* For now !!! */
if (!strcmp(s->Phone.Data.ModelInfo->model,"3510")) {
if (s->Phone.Data.VerNum>3.37) return ERR_NOTSUPPORTED;
}
if (!strcmp(s->Phone.Data.ModelInfo->model,"6230")) {
return ERR_NOTSUPPORTED;
}
+ if (!strcmp(s->Phone.Data.ModelInfo->model,"5140")) {
+ return ERR_NOTSUPPORTED;
+ }
if (Profile->Location>5) return ERR_INVALIDLOCATION;
for (i = 0; i < 0x0a; i++) {
req[length++] = 0x04;
req[length++] = Profile->Location;
req[length++] = i;
req[length++] = 0x01;
}
req[length++] = 0x04;
req[length++] = Profile->Location;
req[length++] = 0x0c;
req[length++] = 0x01;
req[length++] = 0x04;
Profile->CarKitProfile = false;
Profile->HeadSetProfile = false;
Profile->FeaturesNumber = 0;
s->Phone.Data.Profile=Profile;
smprintf(s, "Getting profile\n");
error = GSM_WaitFor (s, req, length, 0x39, 4, ID_GetProfile);
if (error != ERR_NONE) return error;
smprintf(s, "Checking, which profile is active\n");
return GSM_WaitFor (s, reqActive, 4, 0x39, 4, ID_GetProfile);
}
static GSM_Error N6510_ReplySetProfile(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
unsigned char *blockstart;
int i;
smprintf(s, "Response to profile writing received!\n");
blockstart = msg.Buffer + 6;
for (i = 0; i < msg.Buffer[5]; i++) {
switch (blockstart[2]) {
case 0x00: smprintf(s, "keypad tone level"); break;
case 0x02: smprintf(s, "call alert"); break;
case 0x03: smprintf(s, "ringtone"); break;
case 0x04: smprintf(s, "ringtone volume"); break;
case 0x05: smprintf(s, "SMS tone"); break;
case 0x06: smprintf(s, "vibration"); break;
case 0x07: smprintf(s, "warning tone level"); break;
case 0x08: smprintf(s, "caller groups"); break;
case 0x09: smprintf(s, "automatic answer"); break;
case 0x0c: smprintf(s, "name"); break;
default:
smprintf(s, "Unknown block type %02x", blockstart[2]);
break;
}
if (msg.Buffer[4] == 0x00) {
smprintf(s, ": set OK\n");
} else {
smprintf(s, ": setting error %i\n", msg.Buffer[4]);
}
blockstart = blockstart + blockstart[1];
}
return ERR_NONE;
}
static GSM_Error N6510_SetProfile(GSM_StateMachine *s, GSM_Profile *Profile)
{
int i, length = 7, blocks = 0;
bool found;
unsigned char ID,Value;
unsigned char req[150] = {N6110_FRAME_HEADER, 0x03, 0x01,
0x06, /* Number of blocks */
0x03};
if (Profile->Location>5) return ERR_INVALIDLOCATION;
for (i=0;i<Profile->FeaturesNumber;i++) {
found = false;
switch (Profile->FeatureID[i]) {
case Profile_RingtoneID:
ID = 0x03;
Value = Profile->FeatureValue[i];
found = true;
break;
default:
found=NOKIA_FindPhoneFeatureValue(
s,
Profile71_65,
Profile->FeatureID[i],Profile->FeatureValue[i],
&ID,&Value);
}
if (found) {
req[length] = 0x09;
req[length + 1] = ID;
req[length + 2] = Profile->Location;
memcpy(req + length + 4, "\x00\x00\x01", 3);
req[length + 8] = 0x03;
req[length + 3] = req[length + 7] = Value;
blocks++;
length += 9;
}
}
smprintf(s, "Setting profile\n");
return GSM_WaitFor (s, req, length, 0x39, 4, ID_SetProfile);
}
static GSM_Error N6510_ReplyIncomingSMS(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_SMSMessage sms;
#ifdef DEBUG
smprintf(s, "SMS message received\n");
N6510_DecodeSMSFrame(s, &sms, msg.Buffer+10);
#endif
if (s->Phone.Data.EnableIncomingSMS && s->User.IncomingSMS!=NULL) {
sms.State = SMS_UnRead;
sms.InboxFolder = true;
N6510_DecodeSMSFrame(s, &sms, msg.Buffer+10);
s->User.IncomingSMS(s->CurrentConfig->Device,sms);
}
return ERR_NONE;
}
static GSM_Error N6510_DialVoice(GSM_StateMachine *s, char *number, GSM_CallShowNumber ShowNumber)
{
+ unsigned int pos2 = 15;
unsigned int pos = 4;
+ unsigned char req2[100] = {N6110_FRAME_HEADER,0x01,
+ 0x00,0x02,0x07,0x04,
+ 0x01, // 1 - voice, 2 - data
+ 0x00,0x03,
+ 0x18, // length of rest + 1
+ 0x00,0x00,0x00};
unsigned char req[100] = {N6110_FRAME_HEADER,0x01,
0x0c}; /* Number length */
+ GSM_Error error;
+
+ /* USSD not supported */
+ if (number[0] == '*') return ERR_NOTSUPPORTED;
+ if (number[0] == '#') return ERR_NOTSUPPORTED;
req[pos++] = strlen(number);
EncodeUnicode(req+pos,number,strlen(number));
pos += strlen(number)*2;
req[pos++] = 0x05; /* call type: voice - 0x05, data - 0x01 */
req[pos++] = 0x01;
req[pos++] = 0x05;
req[pos++] = 0x00;
req[pos++] = 0x02;
req[pos++] = 0x00;
req[pos++] = 0x00;
switch (ShowNumber) {
case GSM_CALL_HideNumber:
req[pos++] = 0x02;
break;
case GSM_CALL_ShowNumber:
req[pos++] = 0x03;
break;
case GSM_CALL_DefaultNumberPresence:
req[pos++] = 0x01;
break;
}
+ smprintf(s, "Making voice call\n");
+ error = GSM_WaitFor (s, req, pos, 0x01, 4, ID_DialVoice);
+ if (error != ERR_NOTSUPPORTED) return error;
+
+ if (ShowNumber != GSM_CALL_DefaultNumberPresence) return ERR_NOTSUPPORTED;
+
+ req2[11] = strlen(number)*2+6;
+ req2[pos2++] = strlen(number);
+ EncodeUnicode(req2+pos2,number,strlen(number));
+ pos2 += strlen(number)*2;
smprintf(s, "Making voice call\n");
- return GSM_WaitFor (s, req, pos, 0x01, 4, ID_DialVoice);
+ error = GSM_WaitFor (s, req2, pos2, 0x01, 4, ID_DialVoice);
+ if (error == ERR_NOTSUPPORTED) return ERR_NONE;
+ return error;
}
/* method 3 */
static GSM_Error N6510_ReplyGetCalendarInfo3(GSM_Protocol_Message msg, GSM_StateMachine *s, GSM_NOKIACalToDoLocations *Last)
{
int i=0,j=0;
while (Last->Location[j] != 0x00) j++;
if (j >= GSM_MAXCALENDARTODONOTES) {
smprintf(s, "Increase GSM_MAXCALENDARTODONOTES\n");
return ERR_UNKNOWN;
}
if (j == 0) {
Last->Number=msg.Buffer[8]*256+msg.Buffer[9];
smprintf(s, "Number of Entries: %i\n",Last->Number);
}
smprintf(s, "Locations: ");
while (14+(i*4) <= msg.Length) {
Last->Location[j++]=msg.Buffer[12+i*4]*256+msg.Buffer[13+i*4];
smprintf(s, "%i ",Last->Location[j-1]);
i++;
}
smprintf(s, "\nNumber of Entries in frame: %i\n",i);
Last->Location[j] = 0;
smprintf(s, "\n");
if (i == 1 && msg.Buffer[12+0*4]*256+msg.Buffer[13+0*4] == 0) return ERR_EMPTY;
if (i == 0) return ERR_EMPTY;
return ERR_NONE;
}
/* method 3 */
-static GSM_Error N6510_GetCalendarInfo3(GSM_StateMachine *s, GSM_NOKIACalToDoLocations *Last, bool Calendar)
+static GSM_Error N6510_GetCalendarInfo3(GSM_StateMachine *s, GSM_NOKIACalToDoLocations *Last, char Type)
{
- GSM_Error error;
+ GSM_Error error = ERR_UNKNOWN;
int i;
unsigned char req[] = {N6110_FRAME_HEADER, 0x9E, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, /* First location */
- 0x00}; /* 0 = calendar, 1 = ToDo in 6610 style */
+ 0x00}; /* 0 = calendar, 1 = ToDo in 6610 style, 2 = Notes */
Last->Location[0] = 0x00;
Last->Number = 0;
- if (Calendar) {
+ req[10] = Type;
+ if (Type == 0) {
smprintf(s, "Getting locations for calendar method 3\n");
error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetCalendarNotesInfo);
- } else {
- req[10] = 0x01;
+ } else if (Type == 1) {
smprintf(s, "Getting locations for ToDo method 2\n");
error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetToDo);
+ } else if (Type == 2) {
+ smprintf(s, "Getting locations for Notes\n");
+ error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetNote);
}
if (error != ERR_NONE && error != ERR_EMPTY) return error;
while (1) {
i=0;
while (Last->Location[i] != 0x00) i++;
smprintf(s, "i = %i %i\n",i,Last->Number);
if (i == Last->Number) break;
if (i != Last->Number && error == ERR_EMPTY) {
smprintf(s, "Phone doesn't support some notes with this method. Workaround\n");
Last->Number = i;
break;
}
req[8] = Last->Location[i-1] / 256;
req[9] = Last->Location[i-1] % 256;
- if (Calendar) {
+ if (Type == 0) {
smprintf(s, "Getting locations for calendar method 3\n");
error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetCalendarNotesInfo);
- } else {
+ } else if (Type == 1) {
smprintf(s, "Getting locations for todo method 2\n");
error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetToDo);
+ } else if (Type == 2) {
+ smprintf(s, "Getting locations for Notes\n");
+ error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetNote);
}
if (error != ERR_NONE && error != ERR_EMPTY) return error;
}
return ERR_NONE;
}
/* method 3 */
GSM_Error N6510_ReplyGetCalendar3(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_CalendarEntry *entry = s->Phone.Data.Cal;
GSM_DateTime Date;
unsigned long diff;
int i;
bool found = false;
GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
smprintf(s, "Calendar note received method 3\n");
smprintf(s,"Note type %02i: ",msg.Buffer[27]);
switch(msg.Buffer[27]) {
case 0x00: smprintf(s,"Reminder\n"); entry->Type = GSM_CAL_REMINDER; break;
case 0x01: smprintf(s,"Meeting\n"); entry->Type = GSM_CAL_MEETING; break;
case 0x02: smprintf(s,"Call\n"); entry->Type = GSM_CAL_CALL; break;
case 0x04: smprintf(s,"Birthday\n"); entry->Type = GSM_CAL_BIRTHDAY; break;
case 0x08: smprintf(s,"Memo\n"); entry->Type = GSM_CAL_MEMO; break;
default : smprintf(s,"unknown\n");
}
smprintf(s,"StartTime: %04i-%02i-%02i %02i:%02i\n",
msg.Buffer[28]*256+msg.Buffer[29],
msg.Buffer[30],msg.Buffer[31],msg.Buffer[32],
msg.Buffer[33]);
Date.Year = msg.Buffer[28]*256+msg.Buffer[29];
if (entry->Type == GSM_CAL_BIRTHDAY) {
Date.Year = entry->Entries[0].Date.Year;
smprintf(s,"%i\n",Date.Year);
}
Date.Month = msg.Buffer[30];
Date.Day = msg.Buffer[31];
Date.Hour = msg.Buffer[32];
Date.Minute = msg.Buffer[33];
/* Garbage seen with 3510i 3.51 */
if (Date.Month == 0 && Date.Day == 0 && Date.Hour == 0 && Date.Minute == 0) return ERR_EMPTY;
Date.Second = 0;
entry->Entries[0].EntryType = CAL_START_DATETIME;
memcpy(&entry->Entries[0].Date,&Date,sizeof(GSM_DateTime));
entry->EntriesNum++;
if (entry->Type != GSM_CAL_BIRTHDAY) {
smprintf(s,"EndTime: %04i-%02i-%02i %02i:%02i\n",
msg.Buffer[34]*256+msg.Buffer[35],
msg.Buffer[36],msg.Buffer[37],msg.Buffer[38],
msg.Buffer[39]);
Date.Year = msg.Buffer[34]*256+msg.Buffer[35];
Date.Month = msg.Buffer[36];
Date.Day = msg.Buffer[37];
Date.Hour = msg.Buffer[38];
Date.Minute = msg.Buffer[39];
Date.Second = 0;
entry->Entries[1].EntryType = CAL_END_DATETIME;
memcpy(&entry->Entries[1].Date,&Date,sizeof(GSM_DateTime));
entry->EntriesNum++;
}
smprintf(s, "Note icon: %02x\n",msg.Buffer[21]);
for(i=0;i<Priv->CalendarIconsNum;i++) {
if (Priv->CalendarIconsTypes[i] == entry->Type) {
found = true;
}
}
if (!found) {
Priv->CalendarIconsTypes[Priv->CalendarIconsNum] = entry->Type;
Priv->CalendarIcons [Priv->CalendarIconsNum] = msg.Buffer[21];
Priv->CalendarIconsNum++;
}
if (msg.Buffer[14] == 0xFF && msg.Buffer[15] == 0xFF && msg.Buffer[16] == 0xff && msg.Buffer[17] == 0xff)
{
smprintf(s, "No alarm\n");
} else {
diff = ((unsigned int)msg.Buffer[14]) << 24;
diff += ((unsigned int)msg.Buffer[15]) << 16;
diff += ((unsigned int)msg.Buffer[16]) << 8;
diff += msg.Buffer[17];
memcpy(&entry->Entries[entry->EntriesNum].Date,&entry->Entries[0].Date,sizeof(GSM_DateTime));
GetTimeDifference(diff, &entry->Entries[entry->EntriesNum].Date, false, 60);
smprintf(s, "Alarm date : %02i-%02i-%04i %02i:%02i:%02i\n",
entry->Entries[entry->EntriesNum].Date.Day, entry->Entries[entry->EntriesNum].Date.Month,
entry->Entries[entry->EntriesNum].Date.Year, entry->Entries[entry->EntriesNum].Date.Hour,
entry->Entries[entry->EntriesNum].Date.Minute,entry->Entries[entry->EntriesNum].Date.Second);
entry->Entries[entry->EntriesNum].EntryType = CAL_ALARM_DATETIME;
if (msg.Buffer[22]==0x00 && msg.Buffer[23]==0x00 &&
msg.Buffer[24]==0x00 && msg.Buffer[25]==0x00)
{
entry->Entries[entry->EntriesNum].EntryType = CAL_SILENT_ALARM_DATETIME;
smprintf(s, "Alarm type : Silent\n");
}
entry->EntriesNum++;
}
N71_65_GetCalendarRecurrance(s, msg.Buffer+40, entry);
if (entry->Type == GSM_CAL_BIRTHDAY) {
if (msg.Buffer[42] == 0xff && msg.Buffer[43] == 0xff) {
entry->Entries[0].Date.Year = 0;
} else {
entry->Entries[0].Date.Year = msg.Buffer[42]*256+msg.Buffer[43];
}
}
memcpy(entry->Entries[entry->EntriesNum].Text, msg.Buffer+54, msg.Buffer[51]*2);
entry->Entries[entry->EntriesNum].Text[msg.Buffer[51]*2] = 0;
entry->Entries[entry->EntriesNum].Text[msg.Buffer[51]*2+1] = 0;
entry->Entries[entry->EntriesNum].EntryType = CAL_TEXT;
entry->EntriesNum++;
smprintf(s, "Note text: \"%s\"\n",DecodeUnicodeString(entry->Entries[entry->EntriesNum-1].Text));
if (entry->Type == GSM_CAL_CALL) {
memcpy(entry->Entries[entry->EntriesNum].Text, msg.Buffer+(54+msg.Buffer[51]*2), msg.Buffer[52]*2);
entry->Entries[entry->EntriesNum].Text[msg.Buffer[52]*2] = 0;
entry->Entries[entry->EntriesNum].Text[msg.Buffer[52]*2+1] = 0;
entry->Entries[entry->EntriesNum].EntryType = CAL_PHONE;
entry->EntriesNum++;
}
if (entry->Type == GSM_CAL_MEETING) {
memcpy(entry->Entries[entry->EntriesNum].Text, msg.Buffer+(54+msg.Buffer[51]*2), msg.Buffer[52]*2);
entry->Entries[entry->EntriesNum].Text[msg.Buffer[52]*2] = 0;
entry->Entries[entry->EntriesNum].Text[msg.Buffer[52]*2+1] = 0;
entry->Entries[entry->EntriesNum].EntryType = CAL_LOCATION;
entry->EntriesNum++;
}
return ERR_NONE;
}
+static GSM_Error N6510_PrivGetGenericCalendar3(GSM_StateMachine *s, int Location, GSM_Phone_RequestID ID)
+{
+ unsigned char req[] = {N6110_FRAME_HEADER,0x7D,0x00,0x00,0x00,0x00,
+ 0x00,0x99, /* Location */
+ 0xff,0xff,0xff,0xff};
+
+ req[8] = Location / 256;
+ req[9] = Location % 256;
+
+ return GSM_WaitFor (s, req, 14, 0x13, 4, ID);
+}
+
static GSM_Error N6510_PrivGetCalendar3(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start, int *LastCalendarYear)
{
GSM_Error error;
GSM_DateTime date_time;
- unsigned char req[] = {N6110_FRAME_HEADER,0x7D,0x00,0x00,0x00,0x00,
- 0x00,0x99, /* Location */
- 0xff,0xff,0xff,0xff,0x01};
if (start) {
/* We have to get current year. It's NOT written in frame for
* Birthday
*/
error=s->Phone.Functions->GetDateTime(s,&date_time);
switch (error) {
case ERR_EMPTY:
case ERR_NOTIMPLEMENTED:
GSM_GetCurrentDateTime(&date_time);
break;
case ERR_NONE:
break;
default:
return error;
}
*LastCalendarYear = date_time.Year;
}
Note->EntriesNum = 0;
Note->Entries[0].Date.Year = *LastCalendarYear;
- req[8] = Note->Location / 256;
- req[9] = Note->Location % 256;
-
s->Phone.Data.Cal=Note;
smprintf(s, "Getting calendar note method 3\n");
- return GSM_WaitFor (s, req, 15, 0x13, 4, ID_GetCalendarNote);
+ return N6510_PrivGetGenericCalendar3(s, Note->Location, ID_GetCalendarNote);
}
/* method 3 */
GSM_Error N6510_GetNextCalendar3(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start, GSM_NOKIACalToDoLocations *LastCalendar, int *LastCalendarYear, int *LastCalendarPos)
{
GSM_Error error;
bool start2;
if (start) {
- error=N6510_GetCalendarInfo3(s,LastCalendar,true);
+ error=N6510_GetCalendarInfo3(s,LastCalendar,0);
if (error!=ERR_NONE) return error;
if (LastCalendar->Number == 0) return ERR_EMPTY;
*LastCalendarPos = 0;
} else {
(*LastCalendarPos)++;
}
error = ERR_EMPTY;
start2 = start;
while (error == ERR_EMPTY) {
if (*LastCalendarPos >= LastCalendar->Number) return ERR_EMPTY;
Note->Location = LastCalendar->Location[*LastCalendarPos];
error=N6510_PrivGetCalendar3(s, Note, start2, LastCalendarYear);
if (error == ERR_EMPTY) (*LastCalendarPos)++;
start2 = false;
}
return error;
}
static GSM_Error N6510_ReplyGetCalendarInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[3]) {
case 0x3B:
/* Old method 1 for accessing calendar */
return N71_65_ReplyGetCalendarInfo1(msg, s, &s->Phone.Data.Priv.N6510.LastCalendar);
case 0x9F:
smprintf(s, "Info with calendar notes locations received method 3\n");
return N6510_ReplyGetCalendarInfo3(msg, s, &s->Phone.Data.Priv.N6510.LastCalendar);
}
return ERR_UNKNOWNRESPONSE;
}
/* method 3 */
GSM_Error N6510_ReplyGetCalendarNotePos3(GSM_Protocol_Message msg, GSM_StateMachine *s,int *FirstCalendarPos)
{
smprintf(s, "First calendar location: %i\n",msg.Buffer[8]*256+msg.Buffer[9]);
*FirstCalendarPos = msg.Buffer[8]*256+msg.Buffer[9];
return ERR_NONE;
}
/* method 3 */
static GSM_Error N6510_GetCalendarNotePos3(GSM_StateMachine *s)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x95, 0x00};
smprintf(s, "Getting first free calendar note location\n");
return GSM_WaitFor (s, req, 5, 0x13, 4, ID_GetCalendarNotePos);
}
static GSM_Error N6510_ReplyGetCalendarNotePos(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[3]) {
case 0x32:
/* Old method 1 for accessing calendar */
return N71_65_ReplyGetCalendarNotePos1(msg, s,&s->Phone.Data.Priv.N6510.FirstCalendarPos);
case 0x96:
return N6510_ReplyGetCalendarNotePos3(msg, s,&s->Phone.Data.Priv.N6510.FirstCalendarPos);
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_FindCalendarIconID3(GSM_StateMachine *s, GSM_CalendarEntry *Entry, unsigned char *ID)
{
int i,j,LastCalendarYear;
GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
GSM_CalendarEntry Note;
GSM_NOKIACalToDoLocations LastCalendar1,LastCalendar2;
GSM_Error error;
bool found;
for(i=0;i<Priv->CalendarIconsNum;i++) {
if (Priv->CalendarIconsTypes[i] == Entry->Type) {
*ID = Priv->CalendarIcons[i];
return ERR_NONE;
}
}
smprintf(s, "Starting finding note ID\n");
- error=N6510_GetCalendarInfo3(s, &Priv->LastCalendar,true);
+ error=N6510_GetCalendarInfo3(s, &Priv->LastCalendar,0);
memcpy(&LastCalendar1,&Priv->LastCalendar,sizeof(GSM_NOKIACalToDoLocations));
if (error != ERR_NONE) return error;
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL35) ||
IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL65) ||
IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62)) {
error=N71_65_AddCalendar2(s,Entry);
} else {
if (Entry->Type == GSM_CAL_MEETING) {
error=N71_65_AddCalendar1(s, Entry, &s->Phone.Data.Priv.N6510.FirstCalendarPos);
} else {
error=N71_65_AddCalendar2(s,Entry);
}
}
if (error != ERR_NONE) return error;
- error=N6510_GetCalendarInfo3(s, &Priv->LastCalendar,true);
+ error=N6510_GetCalendarInfo3(s, &Priv->LastCalendar,0);
memcpy(&LastCalendar2,&Priv->LastCalendar,sizeof(GSM_NOKIACalToDoLocations));
if (error != ERR_NONE) return error;
smprintf(s,"Number of entries: %i %i\n",LastCalendar1.Number,LastCalendar2.Number);
for(i=0;i<LastCalendar2.Number;i++) {
found = true;
for(j=0;j<LastCalendar1.Number;j++) {
if (LastCalendar1.Location[j] == LastCalendar2.Location[i]) {
found = false;
break;
}
}
if (found) {
Note.Location = LastCalendar2.Location[i];
error=N6510_PrivGetCalendar3(s, &Note, true, &LastCalendarYear);
if (error != ERR_NONE) return error;
error=N71_65_DelCalendar(s, &Note);
if (error != ERR_NONE) return error;
smprintf(s, "Ending finding note ID\n");
for(j=0;j<Priv->CalendarIconsNum;j++) {
if (Priv->CalendarIconsTypes[j] == Entry->Type) {
*ID = Priv->CalendarIcons[j];
return ERR_NONE;
}
}
return ERR_UNKNOWN;
}
}
return ERR_UNKNOWN;
}
/* method 3 */
static GSM_Error N6510_ReplyAddCalendar3(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Calendar note added\n");
return ERR_NONE;
}
/* method 3 */
GSM_Error N6510_AddCalendar3(GSM_StateMachine *s, GSM_CalendarEntry *Note, int *FirstCalendarPos)
{
GSM_CalendarNoteType NoteType, OldNoteType;
time_t t_time1,t_time2;
long diff;
GSM_Error error;
GSM_DateTime DT,date_time;
int Text, Time, Alarm, Phone, Recurrance, EndTime, Location, count=54;
unsigned char req[5000] = {
N6110_FRAME_HEADER, 0x65,
0x00, /* 0 = calendar, 1 = todo */
0x00, 0x00, 0x00,
0x00, 0x00, /* location */
0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, /* alarm */
0x80, 0x00, 0x00,
0x01, /* note icon */
0xFF, 0xFF, 0xFF, 0xFF, /* alarm type */
0x00, /* 0x02 or 0x00 */
0x01, /* note type */
0x07, 0xD0, 0x01, 0x12, 0x0C, 0x00, /* start date/time */
0x07, 0xD0, 0x01, 0x12, 0x0C, 0x00, /* end date/time */
0x00, 0x00, /* recurrance */
0x00, 0x00, /* birth year */
0x20, /* ToDo priority */
0x00, /* ToDo completed ? */
0x00, 0x00, 0x00,
0x00, /* note text length */
0x00, /* phone length/meeting place */
0x00, 0x00, 0x00};
error=N6510_GetCalendarNotePos3(s);
if (error!=ERR_NONE) return error;
req[8] = *FirstCalendarPos/256;
req[9] = *FirstCalendarPos%256;
NoteType = N71_65_FindCalendarType(Note->Type, s->Phone.Data.ModelInfo);
switch(NoteType) {
case GSM_CAL_REMINDER : req[27]=0x00; req[26]=0x02; break;
case GSM_CAL_MEETING : req[27]=0x01; break;
case GSM_CAL_CALL : req[27]=0x02; break;
case GSM_CAL_BIRTHDAY : req[27]=0x04; break;
case GSM_CAL_MEMO : req[27]=0x08; break;
default : return ERR_UNKNOWN;
}
OldNoteType = Note->Type;
Note->Type = NoteType;
error=N6510_FindCalendarIconID3(s, Note, &req[21]);
Note->Type = OldNoteType;
if (error!=ERR_NONE) return error;
GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(Note, &Text, &Time, &Alarm, &Phone, &Recurrance, &EndTime, &Location);
if (Time == -1) return ERR_UNKNOWN;
memcpy(&DT,&Note->Entries[Time].Date,sizeof(GSM_DateTime));
req[28] = DT.Year / 256;
req[29] = DT.Year % 256;
req[30] = DT.Month;
req[31] = DT.Day;
req[32] = DT.Hour;
req[33] = DT.Minute;
if (NoteType == GSM_CAL_BIRTHDAY) {
error=s->Phone.Functions->GetDateTime(s,&date_time);
switch (error) {
case ERR_EMPTY:
case ERR_NOTIMPLEMENTED:
GSM_GetCurrentDateTime(&date_time);
break;
case ERR_NONE:
break;
default:
return error;
}
req[28] = date_time.Year / 256;
req[29] = date_time.Year % 256;
if (DT.Year == 0) {
req[42] = 0xff;
req[43] = 0xff;
} else {
req[42] = DT.Year / 256;
req[43] = DT.Year % 256;
}
}
if (EndTime != -1) memcpy(&DT,&Note->Entries[EndTime].Date,sizeof(GSM_DateTime));
req[34] = DT.Year / 256;
req[35] = DT.Year % 256;
req[36] = DT.Month;
req[37] = DT.Day;
req[38] = DT.Hour;
req[39] = DT.Minute;
if (NoteType == GSM_CAL_BIRTHDAY) {
req[34] = date_time.Year / 256;
req[35] = date_time.Year % 256;
}
if (Recurrance != -1) {
/* max. 1 Year = 8760 hours */
if (Note->Entries[Recurrance].Number >= 8760) {
req[40] = 0xff;
req[41] = 0xff;
} else {
req[40] = Note->Entries[Recurrance].Number / 256;
req[41] = Note->Entries[Recurrance].Number % 256;
}
}
if (Alarm != -1) {
memcpy(&DT,&Note->Entries[Time].Date,sizeof(GSM_DateTime));
if (Note->Entries[Alarm].EntryType == CAL_SILENT_ALARM_DATETIME) {
req[22] = 0x00; req[23] = 0x00; req[24] = 0x00; req[25] = 0x00;
}
if (NoteType == GSM_CAL_BIRTHDAY) DT.Year = date_time.Year;
t_time2 = Fill_Time_T(DT,8);
t_time1 = Fill_Time_T(Note->Entries[Alarm].Date,8);
diff = (t_time1-t_time2)/60;
smprintf(s, " Difference : %li seconds or minutes\n", -diff);
req[14] = (unsigned char)(-diff >> 24);
req[15] = (unsigned char)(-diff >> 16);
req[16] = (unsigned char)(-diff >> 8);
req[17] = (unsigned char)(-diff);
}
if (Text != -1) {
req[49] = UnicodeLength(Note->Entries[Text].Text);
CopyUnicodeString(req+54,Note->Entries[Text].Text);
count+= req[49]*2;
}
if (Phone != -1 && NoteType == GSM_CAL_CALL) {
req[50] = UnicodeLength(Note->Entries[Phone].Text);
CopyUnicodeString(req+54+req[49]*2,Note->Entries[Phone].Text);
count+= req[50]*2;
}
if (Location != -1 && NoteType == GSM_CAL_MEETING) {
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62) ||
IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL65) ||
IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL35)) {
} else {
req[50] = UnicodeLength(Note->Entries[Location].Text);
CopyUnicodeString(req+54+req[49]*2,Note->Entries[Location].Text);
count+= req[50]*2;
}
}
req[count++] = 0x00;
smprintf(s, "Writing calendar note method 3\n");
return GSM_WaitFor (s, req, count, 0x13, 4, ID_SetCalendarNote);
}
static GSM_Error N6510_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
{
#ifdef GSM_FORCE_DCT4_CALENDAR_6210
/* Method 1. Some features missed. Not working with some notes in 3510 */
return N71_65_GetNextCalendar1(s,Note,start,&s->Phone.Data.Priv.N6510.LastCalendar,&s->Phone.Data.Priv.N6510.LastCalendarYear,&s->Phone.Data.Priv.N6510.LastCalendarPos);
#endif
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62)) {
/* Method 1. Some features missed. Not working with some notes in 3510 */
return N71_65_GetNextCalendar1(s,Note,start,&s->Phone.Data.Priv.N6510.LastCalendar,&s->Phone.Data.Priv.N6510.LastCalendarYear,&s->Phone.Data.Priv.N6510.LastCalendarPos);
/* Method 2. In known phones texts of notes cut to 50 chars. Some features missed */
// return N71_65_GetNextCalendar2(s,Note,start,&s->Phone.Data.Priv.N6510.LastCalendarYear,&s->Phone.Data.Priv.N6510.LastCalendarPos);
} else {
/* Method 3. All DCT4 features supported. Not supported by 8910 */
return N6510_GetNextCalendar3(s,Note,start,&s->Phone.Data.Priv.N6510.LastCalendar,&s->Phone.Data.Priv.N6510.LastCalendarYear,&s->Phone.Data.Priv.N6510.LastCalendarPos);
}
}
static GSM_Error N6510_GetCalendarStatus(GSM_StateMachine *s, GSM_CalendarStatus *Status)
{
GSM_Error error;
#ifdef GSM_FORCE_DCT4_CALENDAR_6210
/* Method 1 */
error=N71_65_GetCalendarInfo1(s, &s->Phone.Data.Priv.N6510.LastCalendar);
if (error!=ERR_NONE) return error;
Status->Used = s->Phone.Data.Priv.N6510.LastCalendar.Number;
return ERR_NONE;
#endif
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62)) {
/* Method 1 */
error=N71_65_GetCalendarInfo1(s, &s->Phone.Data.Priv.N6510.LastCalendar);
if (error!=ERR_NONE) return error;
Status->Used = s->Phone.Data.Priv.N6510.LastCalendar.Number;
return ERR_NONE;
/* Method 2 */
// return ERR_NOTSUPPORTED;
} else {
/* Method 3 */
- error=N6510_GetCalendarInfo3(s,&s->Phone.Data.Priv.N6510.LastCalendar,true);
+ error=N6510_GetCalendarInfo3(s,&s->Phone.Data.Priv.N6510.LastCalendar,0);
if (error!=ERR_NONE) return error;
Status->Used = s->Phone.Data.Priv.N6510.LastCalendar.Number;
return ERR_NONE;
}
}
static GSM_Error N6510_AddCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
{
#ifdef GSM_FORCE_DCT4_CALENDAR_6210
return N71_65_AddCalendar2(s,Note);
#endif
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62)) {
return N71_65_AddCalendar2(s,Note);
// return N71_65_AddCalendar1(s, Note, &s->Phone.Data.Priv.N6510.FirstCalendarPos);
} else {
/* Method 3. All DCT4 features supported. Not supported by 8910 */
return N6510_AddCalendar3(s, Note, &s->Phone.Data.Priv.N6510.FirstCalendarPos);
}
}
static GSM_Error N6510_ReplyLogIntoNetwork(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Probably phone says: I log into network\n");
return ERR_NONE;
}
void N6510_EncodeFMFrequency(double freq, unsigned char *buff)
{
double freq0;
unsigned char buffer[20];
unsigned int i,freq2;
sprintf(buffer,"%.3f",freq);
for (i=0;i<strlen(buffer);i++) {
if (buffer[i] == ',' || buffer[i] == '.') buffer[i] = ' ';
}
StringToDouble(buffer, &freq0);
freq2 = (unsigned int)freq0;
dbgprintf("Frequency: %s %i\n",buffer,freq2);
freq2 = freq2 - 0xffff;
buff[0] = freq2 / 0x100;
buff[1] = freq2 % 0x100;
}
void N6510_DecodeFMFrequency(double *freq, unsigned char *buff)
{
unsigned char buffer[20];
sprintf(buffer,"%i.%i",(0xffff + buff[0] * 0x100 + buff[1])/1000,
(0xffff + buff[0] * 0x100 + buff[1])%1000);
dbgprintf("Frequency: %s\n",buffer);
StringToDouble(buffer, freq);
}
static GSM_Error N6510_ReplyGetFMStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "getting FM status OK\n");
memcpy(s->Phone.Data.Priv.N6510.FMStatus,msg.Buffer,msg.Length);
s->Phone.Data.Priv.N6510.FMStatusLength = msg.Length;
return ERR_NONE;
}
static GSM_Error N6510_GetFMStatus(GSM_StateMachine *s)
{
unsigned char req[7] = {N6110_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x01};
if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_RADIO)) return ERR_NOTSUPPORTED;
return GSM_WaitFor (s, req, 7, 0x3E, 2, ID_GetFMStation);
}
static GSM_Error N6510_ReplyGetFMStation(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
unsigned char name[GSM_MAX_FMSTATION_LENGTH*2+2];
int length;
GSM_Phone_Data *Data = &s->Phone.Data;
switch (msg.Buffer[3]) {
case 0x06:
smprintf(s, "Received FM station\n");
length = msg.Buffer[8];
memcpy(name,msg.Buffer+18,length*2);
name[length*2] = 0x00;
name[length*2+1] = 0x00;
CopyUnicodeString(Data->FMStation->StationName,name);
smprintf(s,"Station name: \"%s\"\n",DecodeUnicodeString(Data->FMStation->StationName));
N6510_DecodeFMFrequency(&Data->FMStation->Frequency, msg.Buffer+16);
return ERR_NONE;
case 0x16:
smprintf(s, "Received FM station. Empty ?\n");
return ERR_EMPTY;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_GetFMStation (GSM_StateMachine *s, GSM_FMStation *FMStation)
{
GSM_Error error;
int location;
unsigned char req[7] = {N6110_FRAME_HEADER, 0x05,
0x00, // location
0x00,0x01};
if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_RADIO)) return ERR_NOTSUPPORTED;
if (FMStation->Location > GSM_MAX_FM_STATION) return ERR_INVALIDLOCATION;
s->Phone.Data.FMStation = FMStation;
error = N6510_GetFMStatus(s);
if (error != ERR_NONE) return error;
location = FMStation->Location-1;
if (s->Phone.Data.Priv.N6510.FMStatus[14+location] == 0xFF) return ERR_EMPTY;
req[4] = s->Phone.Data.Priv.N6510.FMStatus[14+location];
smprintf(s, "Getting FM Station %i\n",FMStation->Location);
return GSM_WaitFor (s, req, 7, 0x3E, 2, ID_GetFMStation);
}
static GSM_Error N6510_ReplySetFMStation(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
#ifdef DEBUG
switch (msg.Buffer[4]){
case 0x03: smprintf(s, "FM stations cleaned\n"); break;
case 0x11: smprintf(s, "Setting FM station status OK\n"); break;
case 0x12: smprintf(s, "Setting FM station OK\n"); break;
}
#endif
return ERR_NONE;
}
static GSM_Error N6510_ClearFMStations (GSM_StateMachine *s)
{
unsigned char req[7] = {N6110_FRAME_HEADER, 0x03,0x0f,0x00,0x01};
if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_RADIO)) return ERR_NOTSUPPORTED;
smprintf(s, "Cleaning FM Stations\n");
return GSM_WaitFor (s, req, 7, 0x3E, 2, ID_SetFMStation);
}
static GSM_Error N6510_SetFMStation (GSM_StateMachine *s, GSM_FMStation *FMStation)
{
unsigned int len, location;
GSM_Error error;
unsigned char setstatus[36] = {N6110_FRAME_HEADER,0x11,0x00,0x01,0x01,
0x00,0x00,0x1c,0x00,0x14,0x00,0x00,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0x01};
unsigned char req[64] = {N6110_FRAME_HEADER, 0x12,0x00,0x01,0x00,
0x00, // 0x0e + (strlen(name) * 2)
0x00, // strlen(name)
0x14,0x09,0x00,
0x00, // location
0x00,0x00,0x01,
0x00, // freqHi
0x00, // freqLo
0x01};
if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_RADIO)) return ERR_NOTSUPPORTED;
s->Phone.Data.FMStation = FMStation;
location = FMStation->Location-1;
error = N6510_GetFMStatus(s);
if (error != ERR_NONE) return error;
memcpy(setstatus+14,s->Phone.Data.Priv.N6510.FMStatus+14,20);
setstatus [14+location] = location;
smprintf(s, "Setting FM status %i\n",FMStation->Location);
error = GSM_WaitFor (s, setstatus, 36 , 0x3E, 2, ID_SetFMStation);
if (error != ERR_NONE) return error;
req[12] = location;
/* Name */
len = UnicodeLength(FMStation->StationName);
req[8] = len;
req[7] = 0x0e + len * 2;
memcpy (req+18,FMStation->StationName,len*2);
/* Frequency */
N6510_EncodeFMFrequency(FMStation->Frequency, req+16);
smprintf(s, "Setting FM Station %i\n",FMStation->Location);
return GSM_WaitFor (s, req, 0x13+len*2, 0x3E, 2, ID_SetFMStation);
}
static GSM_Error N6510_ReplySetLight(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Light set\n");
return ERR_NONE;
}
GSM_Error N6510_SetLight(GSM_StateMachine *s, N6510_PHONE_LIGHTS light, bool enable)
{
unsigned char req[14] = {
N6110_FRAME_HEADER, 0x05,
0x01, /* 0x01 = Display, 0x03 = keypad */
0x01, /* 0x01 = Enable, 0x02 = disable */
0x00, 0x00, 0x00, 0x01,
0x05, 0x04, 0x02, 0x00};
req[4] = light;
if (!enable) req[5] = 0x02;
smprintf(s, "Setting light\n");
return GSM_WaitFor (s, req, 14, 0x3A, 4, ID_SetLight);
}
static GSM_Error N6510_ShowStartInfo(GSM_StateMachine *s, bool enable)
{
GSM_Error error;
if (enable) {
error=N6510_SetLight(s,N6510_LIGHT_DISPLAY,true);
if (error != ERR_NONE) return error;
error=N6510_SetLight(s,N6510_LIGHT_TORCH,true);
if (error != ERR_NONE) return error;
return N6510_SetLight(s,N6510_LIGHT_KEYPAD,true);
} else {
error=N6510_SetLight(s,N6510_LIGHT_DISPLAY,false);
if (error != ERR_NONE) return error;
error=N6510_SetLight(s,N6510_LIGHT_TORCH,false);
if (error != ERR_NONE) return error;
return N6510_SetLight(s,N6510_LIGHT_KEYPAD,false);
}
}
+static GSM_Error N6510_ReplyGetNoteInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
+{
+ return N6510_ReplyGetCalendarInfo3(msg, s, &s->Phone.Data.Priv.N6510.LastNote);
+}
+
+static GSM_Error N6510_ReplyGetNote(GSM_Protocol_Message msg, GSM_StateMachine *s)
+{
+ smprintf(s, "Note received\n");
+ memcpy(s->Phone.Data.Note->Text,msg.Buffer+54,(msg.Buffer[50]*256+msg.Buffer[51])*2);
+ s->Phone.Data.Note->Text[(msg.Buffer[50]*256+msg.Buffer[51])*2] = 0;
+ s->Phone.Data.Note->Text[(msg.Buffer[50]*256+msg.Buffer[51])*2+1] = 0;
+ return ERR_NONE;
+}
+
+GSM_Error N6510_GetNextNote(GSM_StateMachine *s, GSM_NoteEntry *Note, bool start)
+{
+ GSM_Error error;
+ GSM_NOKIACalToDoLocations *LastNote = &s->Phone.Data.Priv.N6510.LastNote;
+
+ if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOTES)) return ERR_NOTSUPPORTED;
+
+ if (start) {
+ error=N6510_GetCalendarInfo3(s,LastNote,2);
+ if (error!=ERR_NONE) return error;
+ Note->Location = 1;
+ } else {
+ Note->Location++;
+ }
+
+ if (Note->Location > LastNote->Number) return ERR_EMPTY;
+
+ s->Phone.Data.Note = Note;
+ smprintf(s, "Getting note\n");
+ return N6510_PrivGetGenericCalendar3(s, LastNote->Location[Note->Location-1], ID_GetNote);
+}
+
static int N6510_FindFileCheckSum(unsigned char *ptr, int len)
{
int acc, i, accx;
accx = 0;
acc = 0xffff;
while (len--) {
accx = (accx & 0xffff00ff) | (acc & 0xff00);
acc = (acc & 0xffff00ff) | *ptr++ << 8;
for (i = 0; i < 8; i++) {
acc <<= 1;
if (acc & 0x10000) acc ^= 0x1021;
if (accx & 0x80000000) acc ^= 0x1021;
accx <<= 1;
}
}
dbgprintf("Checksum from Gammu is %04X\n",(acc & 0xffff));
return (acc & 0xffff);
}
static GSM_Error N6510_ReplyGetFileFolderInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_File *File = s->Phone.Data.FileInfo;
GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
int i;
switch (msg.Buffer[3]) {
case 0x15:
smprintf(s,"File or folder details received\n");
CopyUnicodeString(File->Name,msg.Buffer+10);
if (!strncmp(DecodeUnicodeString(File->Name),"GMSTemp",7)) return ERR_EMPTY;
if (File->Name[0] == 0x00 && File->Name[1] == 0x00) return ERR_UNKNOWN;
i = msg.Buffer[8]*256+msg.Buffer[9];
dbgprintf("%02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
msg.Buffer[i-5],msg.Buffer[i-4],msg.Buffer[i-3],
msg.Buffer[i-2],msg.Buffer[i-1],msg.Buffer[i],
msg.Buffer[i+1],msg.Buffer[i+2],msg.Buffer[i+3]);
File->Folder = false;
if (msg.Buffer[i-5] == 0x00) File->Folder = true;
File->ReadOnly = false;
File->Protected = false;
File->System = false;
File->Hidden = false;
if (msg.Buffer[i+2] == 0x01) File->Protected = true;
if (msg.Buffer[i+4] == 0x01) File->ReadOnly = true;
if (msg.Buffer[i+5] == 0x01) File->Hidden = true;
if (msg.Buffer[i+6] == 0x01) File->System = true;//fixme
File->ModifiedEmpty = false;
NOKIA_DecodeDateTime(s, msg.Buffer+i-22, &File->Modified);
if (File->Modified.Year == 0x00) File->ModifiedEmpty = true;
dbgprintf("%02x %02x %02x %02x\n",msg.Buffer[i-22],msg.Buffer[i-21],msg.Buffer[i-20],msg.Buffer[i-19]);
Priv->FileToken = msg.Buffer[i-10]*256+msg.Buffer[i-9];
Priv->ParentID = msg.Buffer[i]*256+msg.Buffer[i+1];
smprintf(s,"ParentID is %i\n",Priv->ParentID);
File->Type = GSM_File_Other;
if (msg.Length > 240){
i = 227;
if (msg.Buffer[i]==0x02 && msg.Buffer[i+2]==0x01)
File->Type = GSM_File_Image_JPG;
else if (msg.Buffer[i]==0x02 && msg.Buffer[i+2]==0x02)
File->Type = GSM_File_Image_BMP;
else if (msg.Buffer[i]==0x02 && msg.Buffer[i+2]==0x07)
File->Type = GSM_File_Image_BMP;
else if (msg.Buffer[i]==0x02 && msg.Buffer[i+2]==0x03)
File->Type = GSM_File_Image_PNG;
else if (msg.Buffer[i]==0x02 && msg.Buffer[i+2]==0x05)
File->Type = GSM_File_Image_GIF;
else if (msg.Buffer[i]==0x02 && msg.Buffer[i+2]==0x09)
File->Type = GSM_File_Image_WBMP;
else if (msg.Buffer[i]==0x04 && msg.Buffer[i+2]==0x01)
File->Type = GSM_File_Sound_AMR;
else if (msg.Buffer[i]==0x04 && msg.Buffer[i+2]==0x02)
File->Type = GSM_File_Sound_MIDI;
else if (msg.Buffer[i]==0x08 && msg.Buffer[i+2]==0x05)
File->Type = GSM_File_Video_3GP;
else if (msg.Buffer[i]==0x10 && msg.Buffer[i+2]==0x01)
File->Type = GSM_File_Java_JAR;
-#if DEVELOP
+#ifdef DEVELOP
else if (msg.Buffer[i]==0x00 && msg.Buffer[i+2]==0x01)
File->Type = GSM_File_MMS;
#endif
}
return ERR_NONE;
case 0x2F:
smprintf(s,"File or folder used bytes received\n");
File->Used = msg.Buffer[6]*256*256*256+
msg.Buffer[7]*256*256+
msg.Buffer[8]*256+
msg.Buffer[9];
return ERR_NONE;
case 0x33:
if (s->Phone.Data.RequestID == ID_GetFileInfo) {
i = Priv->FilesLocationsUsed-1;
while (1) {
if (i==Priv->FilesLocationsCurrent-1) break;
dbgprintf("Copying %i to %i, max %i, current %i\n",
i,i+msg.Buffer[9],
Priv->FilesLocationsUsed,Priv->FilesLocationsCurrent);
Priv->FilesLocations[i+msg.Buffer[9]] = Priv->FilesLocations[i];
Priv->FilesLevels[i+msg.Buffer[9]] = Priv->FilesLevels[i];
i--;
}
Priv->FilesLocationsUsed += msg.Buffer[9];
for (i=0;i<msg.Buffer[9];i++) {
Priv->FilesLocations[Priv->FilesLocationsCurrent+i] = msg.Buffer[13+i*4-1]*256 + msg.Buffer[13+i*4];
Priv->FilesLevels[Priv->FilesLocationsCurrent+i] = File->Level+1;
dbgprintf("%i ",Priv->FilesLocations[Priv->FilesLocationsCurrent+i]);
}
dbgprintf("\n");
}
if (msg.Buffer[9] != 0x00) File->Folder = true;
return ERR_NONE;
case 0x43:
Priv->FileCheckSum = msg.Buffer[6] * 256 + msg.Buffer[7];
smprintf(s,"File checksum from phone is %04X\n",Priv->FileCheckSum);
return ERR_NONE;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_GetFileFolderInfo(GSM_StateMachine *s, GSM_File *File, GSM_Phone_RequestID Request)
{
GSM_Error error;
unsigned char req[10] = {
N7110_FRAME_HEADER,
0x14, /* 0x14 - info, 0x22 - free/total, 0x2E - used, 0x32 - sublocations */
0x01, /* 0x00 for sublocations reverse sorting, 0x01 for free */
0x00, 0x00, 0x01,
0x00, 0x01}; /* Folder or file number */
unsigned char GetCRC[] = {
N7110_FRAME_HEADER, 0x42, 0x00, 0x00, 0x00, 0x01,
0x00, 0x1E}; /* file ID */
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
s->Phone.Data.FileInfo = File;
req[8] = atoi(File->ID_FullName) / 256;
req[9] = atoi(File->ID_FullName) % 256;
req[3] = 0x14;
req[4] = 0x01;
smprintf(s,"Getting info for file in filesystem\n");
error=GSM_WaitFor (s, req, 10, 0x6D, 4, Request);
if (error != ERR_NONE) return error;
if (Request != ID_AddFile) {
req[3] = 0x32;
req[4] = 0x00;
smprintf(s,"Getting subfolders for filesystem\n");
error=GSM_WaitFor (s, req, 10, 0x6D, 4, Request);
if (error != ERR_NONE) return error;
if (!File->Folder) {
req[3] = 0x2E;
req[4] = 0x01;
smprintf(s,"Getting used memory for file in filesystem\n");
error=GSM_WaitFor (s, req, 10, 0x6D, 4, Request);
if (error != ERR_NONE) return error;
GetCRC[8] = atoi(File->ID_FullName) / 256;
GetCRC[9] = atoi(File->ID_FullName) % 256;
smprintf(s,"Getting CRC for file in filesystem\n");
error=GSM_WaitFor (s, GetCRC, 10, 0x6D, 4, Request);
}
}
return error;
}
static GSM_Error N6510_GetNextFileFolder(GSM_StateMachine *s, GSM_File *File, bool start)
{
GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
GSM_Error error;
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
if (start) {
Priv->FilesLocationsUsed = 1;
Priv->FilesLocationsCurrent = 0;
Priv->FilesLocations[0] = 0x01;
Priv->FilesLevels[0] = 1;
}
while (1) {
if (Priv->FilesLocationsCurrent == Priv->FilesLocationsUsed) return ERR_EMPTY;
sprintf(File->ID_FullName,"%i",Priv->FilesLocations[Priv->FilesLocationsCurrent]);
File->Level = Priv->FilesLevels[Priv->FilesLocationsCurrent];
Priv->FilesLocationsCurrent++;
error = N6510_GetFileFolderInfo(s, File, ID_GetFileInfo);
if (error == ERR_EMPTY) continue;
return error;
}
}
static GSM_Error N6510_ReplyGetFileSystemStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[3]) {
case 0x23:
if (!strcmp(s->Phone.Data.ModelInfo->model,"6310i")) {
smprintf(s,"File or folder total bytes received\n");
s->Phone.Data.FileSystemStatus->Free =
3*256*256 + msg.Buffer[8]*256 + msg.Buffer[9] -
s->Phone.Data.FileSystemStatus->Used;
} else {
smprintf(s,"File or folder free bytes received\n");
s->Phone.Data.FileSystemStatus->Free =
msg.Buffer[6]*256*256*256+
msg.Buffer[7]*256*256+
msg.Buffer[8]*256+
msg.Buffer[9];
}
return ERR_NONE;
case 0x2F:
smprintf(s,"File or folder used bytes received\n");
s->Phone.Data.FileSystemStatus->Used =
msg.Buffer[6]*256*256*256+
msg.Buffer[7]*256*256+
msg.Buffer[8]*256+
msg.Buffer[9];
return ERR_NONE;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_GetFileSystemStatus(GSM_StateMachine *s, GSM_FileSystemStatus *status)
{
GSM_Error error;
unsigned char req[10] = {
N7110_FRAME_HEADER,
0x22, /* 0x14 - info, 0x22 - free/total, 0x2E - used, 0x32 - sublocations */
0x01, /* 0x00 for sublocations reverse sorting, 0x01 for free */
0x00, 0x00, 0x01,
0x00, 0x01}; /* Folder or file number */
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
s->Phone.Data.FileSystemStatus = status;
status->Free = 0;
req[3] = 0x2E;
req[4] = 0x01;
smprintf(s, "Getting used/total memory in filesystem\n");
error = GSM_WaitFor (s, req, 10, 0x6D, 4, ID_FileSystemStatus);
req[3] = 0x22;
req[4] = 0x01;
smprintf(s, "Getting free memory in filesystem\n");
return GSM_WaitFor (s, req, 10, 0x6D, 4, ID_FileSystemStatus);
}
static GSM_Error N6510_SearchForFileName(GSM_StateMachine *s, GSM_File *File)
{
GSM_File File2;
GSM_Error error;
int FilesLocations[1000],FilesLocations2[1000];
int FilesLevels[1000];
int FilesLocationsUsed, FilesLocationsCurrent;
int FilesLocationsUsed2, FilesLocationsCurrent2;
GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
memcpy(FilesLocations, Priv->FilesLocations, sizeof(FilesLocations));
memcpy(FilesLevels, Priv->FilesLevels, sizeof(FilesLevels));
FilesLocationsUsed = Priv->FilesLocationsUsed;
FilesLocationsCurrent = Priv->FilesLocationsCurrent;
Priv->FilesLocationsUsed = 1;
Priv->FilesLocationsCurrent = 1;
Priv->FilesLocations[0] = atoi(File->ID_FullName);
Priv->FilesLevels[0] = 1;
strcpy(File2.ID_FullName,File->ID_FullName);
error = N6510_GetFileFolderInfo(s, &File2, ID_GetFileInfo);
memcpy(FilesLocations2, Priv->FilesLocations, sizeof(FilesLocations2));
FilesLocationsUsed2 = Priv->FilesLocationsUsed;
FilesLocationsCurrent2 = Priv->FilesLocationsCurrent;
memcpy(Priv->FilesLocations, FilesLocations, sizeof(FilesLocations));
memcpy(Priv->FilesLevels, FilesLevels, sizeof(FilesLevels));
Priv->FilesLocationsUsed = FilesLocationsUsed;
Priv->FilesLocationsCurrent = FilesLocationsCurrent;
if (error != ERR_NONE) return error;
while (1) {
if (FilesLocationsCurrent2 == FilesLocationsUsed2) return ERR_EMPTY;
sprintf(File2.ID_FullName,"%i",FilesLocations2[FilesLocationsCurrent2]);
dbgprintf("Current is %i\n",FilesLocations2[FilesLocationsCurrent2]);
FilesLocationsCurrent2++;
error = N6510_GetFileFolderInfo(s, &File2, ID_AddFile);
if (error == ERR_EMPTY) continue;
if (error != ERR_NONE) return error;
dbgprintf("%s %s\n",DecodeUnicodeString(File->Name),DecodeUnicodeString(File2.Name));
if (mywstrncasecmp(File2.Name,File->Name,0)) return ERR_NONE;
}
return ERR_EMPTY;
}
static GSM_Error N6510_ReplyGetFilePart(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int old;
smprintf(s,"File part received\n");
old = s->Phone.Data.File->Used;
s->Phone.Data.File->Used += msg.Buffer[6]*256*256*256+
msg.Buffer[7]*256*256+
msg.Buffer[8]*256+
msg.Buffer[9];
smprintf(s,"Length of file part: %i\n",
msg.Buffer[6]*256*256*256+
msg.Buffer[7]*256*256+
msg.Buffer[8]*256+
msg.Buffer[9]);
s->Phone.Data.File->Buffer = (unsigned char *)realloc(s->Phone.Data.File->Buffer,s->Phone.Data.File->Used);
memcpy(s->Phone.Data.File->Buffer+old,msg.Buffer+10,s->Phone.Data.File->Used-old);
return ERR_NONE;
}
static GSM_Error N6510_GetFilePart(GSM_StateMachine *s, GSM_File *File)
{
GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
int old;
GSM_Error error;
unsigned char req[] = {
N7110_FRAME_HEADER, 0x0E, 0x00, 0x00, 0x00, 0x01,
0x00, 0x01, /* Folder or file number */
0x00, 0x00, 0x00, 0x00, /* Start from xxx byte */
0x00, 0x00,
0x03, 0xE8}; /* Read xxx bytes */
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
if (File->Used == 0x00) {
error = N6510_GetFileFolderInfo(s, File, ID_GetFile);
if (error != ERR_NONE) return error;
File->Used = 0;
}
old = File->Used;
req[8] = atoi(File->ID_FullName) / 256;
req[9] = atoi(File->ID_FullName) % 256;
req[10] = old / (256*256*256);
req[11] = old / (256*256);
req[12] = old / 256;
req[13] = old % 256;
s->Phone.Data.File = File;
smprintf(s, "Getting file part from filesystem\n");
error=GSM_WaitFor (s, req, 18, 0x6D, 4, ID_GetFile);
if (error != ERR_NONE) return error;
if (File->Used - old != (0x03 * 256 + 0xE8)) {
if (N6510_FindFileCheckSum(File->Buffer, File->Used) != Priv->FileCheckSum) {
smprintf(s,"File2 checksum is %i, File checksum is %i\n",N6510_FindFileCheckSum(File->Buffer, File->Used),Priv->FileCheckSum);
return ERR_WRONGCRC;
}
return ERR_EMPTY;
}
return ERR_NONE;
}
static GSM_Error N6510_SetReadOnly(GSM_StateMachine *s, unsigned char *ID, bool enable)
{
unsigned char SetAttr[] = {
N7110_FRAME_HEADER, 0x18, 0x00, 0x00, 0x00, 0x01,
0x00, 0x20}; /* File ID */
if (!enable) SetAttr[4] = 0x06;
SetAttr[8] = atoi(ID) / 256;
SetAttr[9] = atoi(ID) % 256;
smprintf(s, "Setting readonly attribute\n");
return GSM_WaitFor (s, SetAttr, 10, 0x6D, 4, ID_DeleteFile);
}
static GSM_Error N6510_ReplyAddFileHeader(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[3]) {
case 0x03:
smprintf(s,"File header added\n");
sprintf(s->Phone.Data.File->ID_FullName,"%i",msg.Buffer[9]);
return ERR_NONE;
case 0x13:
return ERR_NONE;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_ReplyAddFilePart(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
return ERR_NONE;
}
static GSM_Error N6510_AddFilePart(GSM_StateMachine *s, GSM_File *File, int *Pos)
{
GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
GSM_File File2;
GSM_Error error;
int j;
unsigned char Header[400] = {
N7110_FRAME_HEADER, 0x02, 0x00, 0x00, 0x00, 0x01,
0x00, 0x0C, /* parent folder ID */
0x00, 0x00, 0x00, 0xE8};
unsigned char Add[15000] = {
N7110_FRAME_HEADER, 0x40, 0x00, 0x00, 0x00, 0x01,
0x00, 0x04, /* file ID */
0x00, 0x00,
0x01, 0x28}; /* length */
unsigned char end[30] = {
N7110_FRAME_HEADER, 0x40, 0x00, 0x00, 0x00, 0x01,
0x00, 0x04, /* file ID */
0x00, 0x00, 0x00, 0x00};
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
s->Phone.Data.File = File;
if (*Pos == 0) {
error = N6510_SearchForFileName(s,File);
- if (error == ERR_NONE) return ERR_INVALIDLOCATION;
+ if (error == ERR_NONE) return ERR_FILEALREADYEXIST;
if (error != ERR_EMPTY) return error;
Header[8] = atoi(File->ID_FullName) / 256;
Header[9] = atoi(File->ID_FullName) % 256;
memset(Header+14, 0x00, 300);
CopyUnicodeString(Header+14,File->Name);
Header[222] = File->Used / (256*256*256);
Header[223] = File->Used / (256*256);
Header[224] = File->Used / 256;
Header[225] = File->Used % 256;
switch(File->Type) {
case GSM_File_Image_JPG : Header[231]=0x02; Header[233]=0x01; break;
case GSM_File_Image_BMP : Header[231]=0x02; Header[233]=0x02; break;
case GSM_File_Image_PNG : Header[231]=0x02; Header[233]=0x03; break;
case GSM_File_Image_GIF : Header[231]=0x02; Header[233]=0x05; break;
case GSM_File_Image_WBMP : Header[231]=0x02; Header[233]=0x09; break;
case GSM_File_Sound_AMR : Header[231]=0x04; Header[233]=0x01; break;
case GSM_File_Sound_MIDI : Header[231]=0x04; Header[233]=0x05; break; //Header[238]=0x01;
case GSM_File_Sound_NRT : Header[231]=0x04; Header[233]=0x06; break;
case GSM_File_Video_3GP : Header[231]=0x08; Header[233]=0x05; break;
case GSM_File_Java_JAR : Header[231]=0x10; Header[233]=0x01; break;
#ifdef DEVELOP
case GSM_File_MMS:
Header[214]=0x07;
Header[215]=0xd3;
Header[216]=0x06;
Header[217]=0x01;
Header[218]=0x12;
Header[219]=0x13;
Header[220]=0x29;
Header[233]=0x01;
break;
#endif
default : Header[231]=0x01; Header[233]=0x05;
}
Header[235] = 0x01;
Header[236] = atoi(File->ID_FullName) / 256;
Header[237] = atoi(File->ID_FullName) % 256;
if (File->Protected) Header[238] = 0x01; //Nokia forward lock
if (File->Hidden) Header[241] = 0x01;
if (File->System) Header[242] = 0x01; //fixme
smprintf(s, "Adding file header\n");
error=GSM_WaitFor (s, Header, 246, 0x6D, 4, ID_AddFile);
if (error != ERR_NONE) return error;
}
j = 1000;
if (File->Used - *Pos < 1000) j = File->Used - *Pos;
Add[ 8] = atoi(File->ID_FullName) / 256;
Add[ 9] = atoi(File->ID_FullName) % 256;
Add[12] = j / 256;
Add[13] = j % 256;
memcpy(Add+14,File->Buffer+(*Pos),j);
smprintf(s, "Adding file part %i %i\n",*Pos,j);
error=GSM_WaitFor (s, Add, 14+j, 0x6D, 4, ID_AddFile);
if (error != ERR_NONE) return error;
*Pos = *Pos + j;
if (j < 1000) {
end[8] = atoi(File->ID_FullName) / 256;
end[9] = atoi(File->ID_FullName) % 256;
smprintf(s, "Frame for ending adding file\n");
error = GSM_WaitFor (s, end, 14, 0x6D, 4, ID_AddFile);
if (error != ERR_NONE) return error;
strcpy(File2.ID_FullName,File->ID_FullName);
error = N6510_GetFileFolderInfo(s, &File2, ID_GetFileInfo);
if (error != ERR_NONE) return error;
if (!File->ModifiedEmpty) {
Header[3] = 0x12;
Header[4] = 0x01;
Header[12] = 0x00;
Header[13] = 0xE8;
Header[8] = atoi(File->ID_FullName) / 256;
Header[9] = atoi(File->ID_FullName) % 256;
memset(Header+14, 0x00, 300);
CopyUnicodeString(Header+14,File->Name);
NOKIA_EncodeDateTime(s,Header+214,&File->Modified);
/* When you save too big file for phone and it changes
* size (some part is cut by firmware), you HAVE to write
* here correct file size. In other case filesystem
* will be damaged
*/
Header[224] = File2.Used / 256;
Header[225] = File2.Used % 256;
Header[226] = Priv->FileToken / 256;
Header[227] = Priv->FileToken % 256;
switch(File->Type) {
case GSM_File_Image_JPG : Header[231]=0x02; Header[233]=0x01; break;
case GSM_File_Image_BMP : Header[231]=0x02; Header[233]=0x02; break;
case GSM_File_Image_PNG : Header[231]=0x02; Header[233]=0x03; break;
case GSM_File_Image_GIF : Header[231]=0x02; Header[233]=0x05; break;
case GSM_File_Image_WBMP : Header[231]=0x02; Header[233]=0x09; break;
case GSM_File_Sound_AMR : Header[231]=0x04; Header[233]=0x01; break;
case GSM_File_Sound_MIDI : Header[231]=0x04; Header[233]=0x05; break; //Header[238]=0x01;
case GSM_File_Sound_NRT : Header[231]=0x04; Header[233]=0x06; break;
case GSM_File_Video_3GP : Header[231]=0x08; Header[233]=0x05; break;
case GSM_File_Java_JAR : Header[231]=0x10; Header[233]=0x01; break;
#ifdef DEVELOP
case GSM_File_MMS:
Header[214]=0x07;
Header[215]=0xd3;
Header[216]=0x06;
Header[217]=0x01;
Header[218]=0x12;
Header[219]=0x13;
Header[220]=0x29;
Header[233]=0x01;
break;
#endif
default : Header[231]=0x01; Header[233]=0x05;
}
Header[235] = 0x01;
Header[236] = Priv->ParentID / 256;
Header[237] = Priv->ParentID % 256;
smprintf(s, "Adding file header\n");
error=GSM_WaitFor (s, Header, 246, 0x6D, 4, ID_AddFile);
if (error != ERR_NONE) return error;
}
/* Can't delete from phone menu */
if (File->ReadOnly) {
error = N6510_SetReadOnly(s, File->ID_FullName, true);
if (error != ERR_NONE) return error;
}
if (N6510_FindFileCheckSum(File->Buffer, File->Used) != Priv->FileCheckSum) {
smprintf(s,"File2 checksum is %i, File checksum is %i\n",N6510_FindFileCheckSum(File->Buffer, File->Used),Priv->FileCheckSum);
return ERR_WRONGCRC;
}
return ERR_EMPTY;
}
return ERR_NONE;
}
static GSM_Error N6510_ReplyDeleteFile(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
return ERR_NONE;
}
static GSM_Error N6510_DeleteFile(GSM_StateMachine *s, unsigned char *ID)
{
GSM_Error error;
unsigned char Delete[40] = {
N7110_FRAME_HEADER, 0x1E, 0x00, 0x00, 0x00, 0x01,
0x00, 0x35}; /* File ID */
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
error = N6510_SetReadOnly(s, ID, false);
if (error != ERR_NONE) return error;
Delete[8] = atoi(ID) / 256;
Delete[9] = atoi(ID) % 256;
return GSM_WaitFor (s, Delete, 10, 0x6D, 4, ID_DeleteFile);
}
static GSM_Error N6510_ReplyAddFolder(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
sprintf(s->Phone.Data.File->ID_FullName,"%i",msg.Buffer[9]);
return ERR_NONE;
}
static GSM_Error N6510_AddFolder(GSM_StateMachine *s, GSM_File *File)
{
GSM_Error error;
unsigned char Header[400] = {
N7110_FRAME_HEADER, 0x04, 0x00, 0x00, 0x00, 0x01,
0x00, 0x0C, /* parent folder ID */
0x00, 0x00, 0x00, 0xE8};
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
error = N6510_SearchForFileName(s,File);
if (error == ERR_NONE) return ERR_INVALIDLOCATION;
if (error != ERR_EMPTY) return error;
Header[8] = atoi(File->ID_FullName) / 256;
Header[9] = atoi(File->ID_FullName) % 256;
memset(Header+14, 0x00, 300);
CopyUnicodeString(Header+14,File->Name);
Header[233] = 0x02;
Header[235] = 0x01;
Header[236] = atoi(File->ID_FullName) / 256;
Header[237] = atoi(File->ID_FullName) % 256;
s->Phone.Data.File = File;
smprintf(s, "Adding folder\n");
error = GSM_WaitFor (s, Header, 246, 0x6D, 4, ID_AddFolder);
@@ -4625,614 +4707,605 @@ static GSM_Error N6510_EnableGPRSAccessPoint(GSM_StateMachine *s)
error = GSM_WaitFor (s, req, 16, 0x43, 4, ID_EnableGPRSPoint);
if (error != ERR_NONE) return error;
}
return error;
}
#endif
static GSM_Error N6510_ReplyGetGPRSAccessPoint(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_GPRSAccessPoint *point = s->Phone.Data.GPRSPoint;
switch (msg.Buffer[13]) {
case 0x01:
smprintf(s,"Active GPRS point received\n");
point->Active = false;
if (point->Location == msg.Buffer[18]) point->Active = true;
return ERR_NONE;
case 0xD2:
smprintf(s,"Names for GPRS points received\n");
CopyUnicodeString(point->Name,msg.Buffer+18+(point->Location-1)*42);
smprintf(s,"\"%s\"\n",DecodeUnicodeString(point->Name));
return ERR_NONE;
case 0xF2:
smprintf(s,"URL for GPRS points received\n");
CopyUnicodeString(point->URL,msg.Buffer+18+(point->Location-1)*202);
smprintf(s,"\"%s\"\n",DecodeUnicodeString(point->URL));
return ERR_NONE;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_GetGPRSAccessPoint(GSM_StateMachine *s, GSM_GPRSAccessPoint *point)
{
GSM_Error error;
unsigned char URL[] = {
N7110_FRAME_HEADER, 0x05, 0x00, 0x00, 0x00, 0x2C, 0x00,
0x00, 0x00, 0x00, 0x03, 0xF2, 0x00, 0x00};
unsigned char Name[] = {
N7110_FRAME_HEADER, 0x05, 0x00, 0x00, 0x00, 0x2C, 0x00,
0x01, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00};
unsigned char Active[] = {
N7110_FRAME_HEADER, 0x05, 0x00, 0x00, 0x00, 0x2C, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00};
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOGPRSPOINT)) return ERR_NOTSUPPORTED;
if (point->Location < 1) return ERR_UNKNOWN;
if (point->Location > 5) return ERR_INVALIDLOCATION;
s->Phone.Data.GPRSPoint = point;
#ifdef DEVELOP
error = N6510_EnableGPRSAccessPoint(s);
if (error != ERR_NONE) return error;
#endif
smprintf(s, "Getting GPRS access point name\n");
error=GSM_WaitFor (s, Name, 16, 0x43, 4, ID_GetGPRSPoint);
if (error != ERR_NONE) return error;
smprintf(s, "Getting GPRS access point URL\n");
error=GSM_WaitFor (s, URL, 16, 0x43, 4, ID_GetGPRSPoint);
if (error != ERR_NONE) return error;
smprintf(s, "Getting number of active GPRS access point\n");
error=GSM_WaitFor (s, Active, 16, 0x43, 4, ID_GetGPRSPoint);
if (error != ERR_NONE) return error;
if (UnicodeLength(point->URL)==0 && UnicodeLength(point->Name)==0) return ERR_EMPTY;
return error;
}
static GSM_Error N6510_ReplySetGPRSAccessPoint1(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
switch (msg.Buffer[13]) {
case 0x01:
case 0xD2:
case 0xF2:
memcpy(s->Phone.Data.Priv.N6510.GPRSPoints,msg.Buffer,msg.Length);
s->Phone.Data.Priv.N6510.GPRSPointsLength = msg.Length;
return ERR_NONE;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_SetGPRSAccessPoint(GSM_StateMachine *s, GSM_GPRSAccessPoint *point)
{
unsigned char *buff = s->Phone.Data.Priv.N6510.GPRSPoints;
GSM_Error error;
unsigned char URL[] = {
N7110_FRAME_HEADER, 0x05, 0x00, 0x00, 0x00, 0x2C, 0x00,
0x00, 0x00, 0x00, 0x03, 0xF2, 0x00, 0x00};
unsigned char Name[] = {
N7110_FRAME_HEADER, 0x05, 0x00, 0x00, 0x00, 0x2C, 0x00,
0x01, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00};
unsigned char Active[] = {
N7110_FRAME_HEADER, 0x05, 0x00, 0x00, 0x00, 0x2C, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00};
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOGPRSPOINT)) return ERR_NOTSUPPORTED;
if (point->Location < 1) return ERR_UNKNOWN;
if (point->Location > 5) return ERR_INVALIDLOCATION;
s->Phone.Data.GPRSPoint = point;
#ifdef DEVELOP
error = N6510_EnableGPRSAccessPoint(s);
if (error != ERR_NONE) return error;
#endif
smprintf(s, "Getting GPRS access point name\n");
error=GSM_WaitFor (s, Name, 16, 0x43, 4, ID_SetGPRSPoint);
if (error != ERR_NONE) return error;
CopyUnicodeString(buff+18+(point->Location-1)*42,point->Name);
buff[0] = 0x00;
buff[1] = 0x01;
buff[2] = 0x01;
buff[3] = 0x07;
smprintf(s, "Setting GPRS access point name\n");
error=GSM_WaitFor (s, buff, s->Phone.Data.Priv.N6510.GPRSPointsLength, 0x43, 4, ID_SetGPRSPoint);
if (error != ERR_NONE) return error;
smprintf(s, "Getting GPRS access point URL\n");
error=GSM_WaitFor (s, URL, 16, 0x43, 4, ID_SetGPRSPoint);
if (error != ERR_NONE) return error;
CopyUnicodeString(buff+18+(point->Location-1)*42,point->URL);
buff[0] = 0x00;
buff[1] = 0x01;
buff[2] = 0x01;
buff[3] = 0x07;
smprintf(s, "Setting GPRS access point URL\n");
error=GSM_WaitFor (s, buff, s->Phone.Data.Priv.N6510.GPRSPointsLength, 0x43, 4, ID_SetGPRSPoint);
if (error != ERR_NONE) return error;
if (point->Active) {
smprintf(s, "Getting number of active GPRS access point\n");
error=GSM_WaitFor (s, Active, 16, 0x43, 4, ID_SetGPRSPoint);
if (error != ERR_NONE) return error;
buff[0] = 0x00;
buff[1] = 0x01;
buff[2] = 0x01;
buff[3] = 0x07;
buff[18]= point->Location;
smprintf(s, "Setting number of active GPRS access point\n");
error=GSM_WaitFor (s, buff, s->Phone.Data.Priv.N6510.GPRSPointsLength, 0x43, 4, ID_SetGPRSPoint);
if (error != ERR_NONE) return error;
}
return error;
}
/* ToDo support - 6310 style */
static GSM_Error N6510_ReplyGetToDoStatus1(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
int i;
GSM_NOKIACalToDoLocations *Last = &s->Phone.Data.Priv.N6510.LastToDo;
smprintf(s, "TODO locations received\n");
Last->Number=msg.Buffer[6]*256+msg.Buffer[7];
smprintf(s, "Number of Entries: %i\n",Last->Number);
smprintf(s, "Locations: ");
for (i=0;i<Last->Number;i++) {
Last->Location[i]=msg.Buffer[12+(i*4)]*256+msg.Buffer[(i*4)+13];
smprintf(s, "%i ",Last->Location[i]);
}
smprintf(s, "\n");
return ERR_NONE;
}
/* ToDo support - 6310 style */
static GSM_Error N6510_GetToDoStatus1(GSM_StateMachine *s, GSM_ToDoStatus *status)
{
GSM_Error error;
GSM_NOKIACalToDoLocations *LastToDo = &s->Phone.Data.Priv.N6510.LastToDo;
unsigned char reqLoc[] = {
N6110_FRAME_HEADER,
0x15, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00};
smprintf(s, "Getting ToDo locations\n");
error = GSM_WaitFor (s, reqLoc, 10, 0x55, 4, ID_GetToDo);
if (error != ERR_NONE) return error;
status->Used = LastToDo->Number;
return ERR_NONE;
}
static GSM_Error N6510_GetToDoStatus2(GSM_StateMachine *s, GSM_ToDoStatus *status)
{
GSM_NOKIACalToDoLocations *LastToDo = &s->Phone.Data.Priv.N6510.LastToDo;
GSM_Error error;
- error = N6510_GetCalendarInfo3(s,LastToDo,false);
+ error = N6510_GetCalendarInfo3(s,LastToDo,1);
if (error!=ERR_NONE) return error;
status->Used = LastToDo->Number;
return ERR_NONE;
}
static GSM_Error N6510_GetToDoStatus(GSM_StateMachine *s, GSM_ToDoStatus *status)
{
status->Used = 0;
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO63)) {
return N6510_GetToDoStatus1(s, status);
} else if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO66)) {
return N6510_GetToDoStatus2(s, status);
} else {
return ERR_NOTSUPPORTED;
}
}
/* ToDo support - 6310 style */
static GSM_Error N6510_ReplyGetToDo1(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_ToDoEntry *Last = s->Phone.Data.ToDo;
smprintf(s, "TODO received method 1\n");
switch (msg.Buffer[4]) {
case 1 : Last->Priority = GSM_Priority_High; break;
case 2 : Last->Priority = GSM_Priority_Medium; break;
case 3 : Last->Priority = GSM_Priority_Low; break;
default : return ERR_UNKNOWN;
}
smprintf(s, "Priority: %i\n",msg.Buffer[4]);
CopyUnicodeString(Last->Entries[0].Text,msg.Buffer+14);
Last->Entries[0].EntryType = TODO_TEXT;
Last->EntriesNum = 1;
smprintf(s, "Text: \"%s\"\n",DecodeUnicodeString(Last->Entries[0].Text));
return ERR_NONE;
}
/* ToDo support - 6310 style */
static GSM_Error N6510_GetNextToDo1(GSM_StateMachine *s, GSM_ToDoEntry *ToDo, bool refresh)
{
GSM_Error error;
GSM_ToDoStatus status;
GSM_NOKIACalToDoLocations *LastToDo = &s->Phone.Data.Priv.N6510.LastToDo;
unsigned char reqGet[] = {
N6110_FRAME_HEADER,
0x03, 0x00, 0x00, 0x80, 0x00,
0x00, 0x17}; /* Location */
if (refresh) {
error = N6510_GetToDoStatus(s, &status);
if (error != ERR_NONE) return error;
ToDo->Location = 1;
} else {
ToDo->Location++;
}
if (ToDo->Location > LastToDo->Number) return ERR_EMPTY;
reqGet[8] = LastToDo->Location[ToDo->Location-1] / 256;
reqGet[9] = LastToDo->Location[ToDo->Location-1] % 256;
s->Phone.Data.ToDo = ToDo;
smprintf(s, "Getting ToDo\n");
return GSM_WaitFor (s, reqGet, 10, 0x55, 4, ID_GetToDo);
}
static GSM_Error N6510_ReplyGetToDoStatus2(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
return N6510_ReplyGetCalendarInfo3(msg, s, &s->Phone.Data.Priv.N6510.LastToDo);
}
/* Similiar to getting calendar method 3 */
static GSM_Error N6510_ReplyGetToDo2(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_ToDoEntry *Last = s->Phone.Data.ToDo;
GSM_DateTime Date;
unsigned long diff;
smprintf(s, "ToDo received method 2\n");
switch (msg.Buffer[44]) {
case 0x10: Last->Priority = GSM_Priority_Low; break;
case 0x20: Last->Priority = GSM_Priority_Medium; break;
case 0x30: Last->Priority = GSM_Priority_High; break;
default : return ERR_UNKNOWN;
}
memcpy(Last->Entries[0].Text,msg.Buffer+54,msg.Buffer[51]*2);
Last->Entries[0].Text[msg.Buffer[51]*2] = 0;
Last->Entries[0].Text[msg.Buffer[51]*2+1] = 0;
Last->Entries[0].EntryType = TODO_TEXT;
smprintf(s, "Text: \"%s\"\n",DecodeUnicodeString(Last->Entries[0].Text));
smprintf(s,"EndTime: %04i-%02i-%02i %02i:%02i\n",
msg.Buffer[34]*256+msg.Buffer[35],
msg.Buffer[36],msg.Buffer[37],msg.Buffer[38],
msg.Buffer[39]);
Date.Year = msg.Buffer[34]*256+msg.Buffer[35];
Date.Month = msg.Buffer[36];
Date.Day = msg.Buffer[37];
Date.Hour = msg.Buffer[38];
Date.Minute = msg.Buffer[39];
Date.Second = 0;
Last->Entries[1].EntryType = TODO_END_DATETIME;
memcpy(&Last->Entries[1].Date,&Date,sizeof(GSM_DateTime));
smprintf(s,"StartTime: %04i-%02i-%02i %02i:%02i\n",
msg.Buffer[28]*256+msg.Buffer[29],
msg.Buffer[30],msg.Buffer[31],msg.Buffer[32],
msg.Buffer[33]);
Date.Year = msg.Buffer[28]*256+msg.Buffer[29];
Date.Month = msg.Buffer[30];
Date.Day = msg.Buffer[31];
Date.Hour = msg.Buffer[32];
Date.Minute = msg.Buffer[33];
Date.Second = 0;
Last->EntriesNum = 2;
if (msg.Buffer[45] == 0x01) {
Last->Entries[2].Number = msg.Buffer[45];
Last->Entries[2].EntryType = TODO_COMPLETED;
Last->EntriesNum++;
smprintf(s,"Completed\n");
}
- if (msg.Buffer[14] == 0xFF && msg.Buffer[15] == 0xFF && msg.Buffer[16] == 0xff && msg.Buffer[17] == 0xff)
- {
+ if (msg.Buffer[14] == 0xFF && msg.Buffer[15] == 0xFF && msg.Buffer[16] == 0xff && msg.Buffer[17] == 0xff) {
smprintf(s, "No alarm\n");
} else {
diff = ((unsigned int)msg.Buffer[14]) << 24;
diff += ((unsigned int)msg.Buffer[15]) << 16;
diff += ((unsigned int)msg.Buffer[16]) << 8;
diff += msg.Buffer[17];
memcpy(&Last->Entries[Last->EntriesNum].Date,&Date,sizeof(GSM_DateTime));
GetTimeDifference(diff, &Last->Entries[Last->EntriesNum].Date, false, 60);
smprintf(s, "Alarm date : %02i-%02i-%04i %02i:%02i:%02i\n",
Last->Entries[Last->EntriesNum].Date.Day, Last->Entries[Last->EntriesNum].Date.Month,
Last->Entries[Last->EntriesNum].Date.Year, Last->Entries[Last->EntriesNum].Date.Hour,
Last->Entries[Last->EntriesNum].Date.Minute,Last->Entries[Last->EntriesNum].Date.Second);
Last->Entries[Last->EntriesNum].EntryType = TODO_ALARM_DATETIME;
if (msg.Buffer[22]==0x00 && msg.Buffer[23]==0x00 &&
msg.Buffer[24]==0x00 && msg.Buffer[25]==0x00)
{
Last->Entries[Last->EntriesNum].EntryType = TODO_SILENT_ALARM_DATETIME;
smprintf(s, "Alarm type : Silent\n");
}
Last->EntriesNum++;
}
return ERR_NONE;
}
/* ToDo support - 6610 style */
static GSM_Error N6510_GetNextToDo2(GSM_StateMachine *s, GSM_ToDoEntry *ToDo, bool refresh)
{
GSM_Error error;
GSM_NOKIACalToDoLocations *LastToDo = &s->Phone.Data.Priv.N6510.LastToDo;
- /* The same to getting calendar method 3 */
- unsigned char req[] = {
- N6110_FRAME_HEADER,0x7D,0x00,0x00,0x00,0x00,
- 0x00,0x99, /* Location */
- 0xff,0xff,0xff,0xff,0x01};
if (refresh) {
- error=N6510_GetCalendarInfo3(s,LastToDo,false);
+ error=N6510_GetCalendarInfo3(s,LastToDo,1);
if (error!=ERR_NONE) return error;
ToDo->Location = 1;
} else {
ToDo->Location++;
}
if (ToDo->Location > LastToDo->Number) return ERR_EMPTY;
- req[8] = LastToDo->Location[ToDo->Location-1] / 256;
- req[9] = LastToDo->Location[ToDo->Location-1] % 256;
-
s->Phone.Data.ToDo = ToDo;
smprintf(s, "Getting todo method 2\n");
- return GSM_WaitFor (s, req, 15, 0x13, 4, ID_GetToDo);
+ return N6510_PrivGetGenericCalendar3(s, LastToDo->Location[ToDo->Location-1], ID_GetToDo);
}
static GSM_Error N6510_GetNextToDo(GSM_StateMachine *s, GSM_ToDoEntry *ToDo, bool refresh)
{
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO63)) {
return N6510_GetNextToDo1(s, ToDo, refresh);
} else if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO66)) {
return N6510_GetNextToDo2(s, ToDo, refresh);
} else {
return ERR_NOTSUPPORTED;
}
}
/* ToDo support - 6310 style */
static GSM_Error N6510_ReplyDeleteAllToDo1(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "All TODO deleted\n");
return ERR_NONE;
}
/* ToDo support - 6310 style */
static GSM_Error N6510_DeleteAllToDo1(GSM_StateMachine *s)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x11};
if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO63)) {
return ERR_NOTSUPPORTED;
}
smprintf(s, "Deleting all ToDo method 1\n");
return GSM_WaitFor (s, req, 4, 0x55, 4, ID_DeleteAllToDo);
}
static GSM_Error N6510_DeleteToDo2(GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
{
GSM_Error error;
GSM_NOKIACalToDoLocations *LastToDo = &s->Phone.Data.Priv.N6510.LastToDo;
GSM_CalendarEntry Note;
if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO66)) {
return ERR_NOTSUPPORTED;
}
- error=N6510_GetCalendarInfo3(s,LastToDo,false);
+ error=N6510_GetCalendarInfo3(s,LastToDo,1);
if (error!=ERR_NONE) return error;
smprintf(s, "Deleting ToDo method 2\n");
if (ToDo->Location > LastToDo->Number || ToDo->Location == 0) return ERR_INVALIDLOCATION;
Note.Location = LastToDo->Location[ToDo->Location-1];
return N71_65_DelCalendar(s,&Note);
}
/* ToDo support - 6310 style */
static GSM_Error N6510_ReplyGetToDoFirstLoc1(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "TODO first location received method 1: %02x\n",msg.Buffer[9]);
s->Phone.Data.ToDo->Location = msg.Buffer[9];
return ERR_NONE;
}
/* ToDo support - 6310 style */
static GSM_Error N6510_ReplyAddToDo1(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "TODO set OK\n");
return ERR_NONE;
}
/* ToDo support - 6310 style */
static GSM_Error N6510_AddToDo1(GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
{
int Text, Alarm, EndTime, Completed, ulen, Phone;
GSM_Error error;
unsigned char reqLoc[] = {N6110_FRAME_HEADER, 0x0F};
unsigned char reqSet[500] = {
N6110_FRAME_HEADER, 0x01,
0x03, /* Priority */
0x00, /* Length of text */
0x80,0x00,0x00,
0x18}; /* Location */
s->Phone.Data.ToDo = ToDo;
smprintf(s, "Getting first ToDo location\n");
error = GSM_WaitFor (s, reqLoc, 4, 0x55, 4, ID_SetToDo);
if (error != ERR_NONE) return error;
reqSet[9] = ToDo->Location;
switch (ToDo->Priority) {
case GSM_Priority_Low : reqSet[4] = 3; break;
case GSM_Priority_Medium: reqSet[4] = 2; break;
case GSM_Priority_High : reqSet[4] = 1; break;
}
GSM_ToDoFindDefaultTextTimeAlarmCompleted(ToDo, &Text, &Alarm, &Completed, &EndTime, &Phone);
if (Text == -1) return ERR_NOTSUPPORTED; /* XXX: shouldn't this be handled different way? */
ulen = UnicodeLength(ToDo->Entries[Text].Text);
reqSet[5] = ulen+1;
CopyUnicodeString(reqSet+10,ToDo->Entries[Text].Text);
reqSet[10+ulen*2] = 0x00;
reqSet[10+ulen*2+1] = 0x00;
smprintf(s, "Adding ToDo method 1\n");
return GSM_WaitFor (s, reqSet, 12+ulen*2, 0x55, 4, ID_SetToDo);
}
static GSM_Error N6510_ReplyAddToDo2(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "ToDo added method 2\n");
return ERR_NONE;
}
static GSM_Error N6510_ReplyGetToDoFirstLoc2(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "First ToDo location method 2: %i\n",msg.Buffer[8]*256+msg.Buffer[9]);
s->Phone.Data.ToDo->Location = msg.Buffer[9];
return ERR_NONE;
}
static GSM_Error N6510_AddToDo2(GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
{
GSM_CalendarEntry Note;
time_t t_time1,t_time2;
long diff;
GSM_Error error;
GSM_DateTime DT;
int Text, Alarm, EndTime, Completed, count=54, Phone;
unsigned char reqLoc[] = {N6110_FRAME_HEADER, 0x95, 0x01};
unsigned char req[5000] = {
N6110_FRAME_HEADER, 0x65,
0x01, /* 0 = calendar, 1 = todo */
0x00, 0x00, 0x00,
0x00, 0x00, /* location */
0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, /* alarm */
0x80, 0x00, 0x00,
0x01, /* note icon */
0xFF, 0xFF, 0xFF, 0xFF, /* alarm type */
0x00, /* 0x02 or 0x00 */
0x01, /* note type */
0x07, 0xD0, 0x01, 0x12, 0x0C, 0x00, /* start date/time */
0x07, 0xD0, 0x01, 0x12, 0x0C, 0x00, /* end date/time */
0x00, 0x00, /* recurrance */
0x00, 0x00, /* birth year */
0x20, /* ToDo priority */
0x00, /* ToDo completed ? */
0x00, 0x00, 0x00,
0x00, /* note text length */
0x00, /* phone length/meeting place */
0x00, 0x00, 0x00};
s->Phone.Data.ToDo = ToDo;
smprintf(s, "Getting first free ToDo location method 2\n");
error = GSM_WaitFor (s, reqLoc, 5, 0x13, 4, ID_SetToDo);
if (error!=ERR_NONE) return error;
req[8] = ToDo->Location/256;
req[9] = ToDo->Location%256;
Note.Type = GSM_CAL_MEETING;
DT.Year = 2004; DT.Month = 1; DT.Day = 1;
DT.Hour = 12; DT.Minute = 12; DT.Second = 0;
memcpy(&Note.Entries[0].Date,&DT,sizeof(GSM_DateTime));
Note.Entries[0].EntryType = CAL_START_DATETIME;
memcpy(&Note.Entries[1].Date,&DT,sizeof(GSM_DateTime));
Note.Entries[1].EntryType = CAL_END_DATETIME;
EncodeUnicode(Note.Entries[2].Text,"ala",3);
Note.Entries[2].EntryType = CAL_TEXT;
Note.EntriesNum = 3;
error=N6510_FindCalendarIconID3(s, &Note, &req[21]);
if (error!=ERR_NONE) return error;
switch (ToDo->Priority) {
case GSM_Priority_Low : req[44] = 0x10; break;
case GSM_Priority_Medium: req[44] = 0x20; break;
case GSM_Priority_High : req[44] = 0x30; break;
}
GSM_ToDoFindDefaultTextTimeAlarmCompleted(ToDo, &Text, &Alarm, &Completed, &EndTime, &Phone);
if (Completed != -1) req[45] = 0x01;
if (EndTime == -1) {
GSM_GetCurrentDateTime(&DT);
} else {
memcpy(&DT,&ToDo->Entries[EndTime].Date,sizeof(GSM_DateTime));
}
/*Start time*/
req[28] = DT.Year / 256;
req[29] = DT.Year % 256;
req[30] = DT.Month;
req[31] = DT.Day;
req[32] = DT.Hour;
req[33] = DT.Minute;
/*End time*/
req[34] = DT.Year / 256;
req[35] = DT.Year % 256;
req[36] = DT.Month;
req[37] = DT.Day;
req[38] = DT.Hour;
req[39] = DT.Minute;
if (Alarm != -1) {
if (ToDo->Entries[Alarm].EntryType == CAL_SILENT_ALARM_DATETIME)
{
req[22] = 0x00; req[23] = 0x00; req[24] = 0x00; req[25] = 0x00;
}
t_time2 = Fill_Time_T(DT,8);
t_time1 = Fill_Time_T(ToDo->Entries[Alarm].Date,8);
diff = (t_time1-t_time2)/60;
smprintf(s, " Difference : %li seconds or minutes\n", -diff);
req[14] = (unsigned char)(-diff >> 24);
req[15] = (unsigned char)(-diff >> 16);
req[16] = (unsigned char)(-diff >> 8);
req[17] = (unsigned char)(-diff);
}
if (Text != -1) {
req[49] = UnicodeLength(ToDo->Entries[Text].Text);
CopyUnicodeString(req+54,ToDo->Entries[Text].Text);
count+= req[49]*2;
}
req[count++] = 0x00;
smprintf(s, "Adding ToDo method 2\n");
return GSM_WaitFor (s, req, count, 0x13, 4, ID_SetToDo);
}
static GSM_Error N6510_AddToDo(GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
{
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO63)) {
return N6510_AddToDo1(s, ToDo);
} else if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO66)) {
@@ -5262,521 +5335,530 @@ static GSM_Error N6510_ReplyGetLocale(GSM_Protocol_Message msg, GSM_StateMachine
locale->DateFormat = GSM_Date_YYYYMMDD;
locale->DateSeparator = '.';
break;
case 0x04:
locale->DateFormat = GSM_Date_DDMMYYYY;
locale->DateSeparator = '/';
break;
case 0x05:
locale->DateFormat = GSM_Date_MMDDYYYY;
locale->DateSeparator = '/';
break;
case 0x06:
locale->DateFormat = GSM_Date_YYYYMMDD;
locale->DateSeparator = '/';
break;
case 0x08:
locale->DateFormat = GSM_Date_DDMMYYYY;
locale->DateSeparator = '-';
break;
case 0x09:
locale->DateFormat = GSM_Date_MMDDYYYY;
locale->DateSeparator = '-';
break;
case 0x0A:
locale->DateFormat = GSM_Date_YYYYMMDD;
locale->DateSeparator = '-';
break;
default:/* FIXME */
locale->DateFormat = GSM_Date_DDMMYYYY;
locale->DateSeparator = '/';
break;
}
return ERR_NONE;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_GetLocale(GSM_StateMachine *s, GSM_Locale *locale)
{
unsigned char req[] = {N6110_FRAME_HEADER, 0x89};
s->Phone.Data.Locale = locale;
smprintf(s, "Getting date format\n");
return GSM_WaitFor (s, req, 4, 0x13, 4, ID_GetLocale);
}
static GSM_Error N6510_ReplyGetCalendarSettings(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_CalendarSettings *sett = s->Phone.Data.CalendarSettings;
switch (msg.Buffer[3]) {
case 0x86:
smprintf(s, "Auto deleting setting received\n");
sett->AutoDelete = msg.Buffer[4];
return ERR_NONE;
case 0x8E:
smprintf(s, "Start day for calendar received\n");
switch(msg.Buffer[4]) {
case 0x03:
sett->StartDay = 6;
return ERR_NONE;
case 0x02:
sett->StartDay = 7;
return ERR_NONE;
case 0x01:
sett->StartDay = 1;
return ERR_NONE;
}
break;
}
return ERR_UNKNOWNRESPONSE;
}
static GSM_Error N6510_GetCalendarSettings(GSM_StateMachine *s, GSM_CalendarSettings *settings)
{
GSM_Error error;
unsigned char req1[] = {N6110_FRAME_HEADER, 0x85};
unsigned char req2[] = {N6110_FRAME_HEADER, 0x8D};
s->Phone.Data.CalendarSettings = settings;
smprintf(s, "Getting auto delete\n");
error = GSM_WaitFor (s, req1, 4, 0x13, 4, ID_GetCalendarSettings);
if (error != ERR_NONE) return error;
smprintf(s, "Getting start day for week\n");
return GSM_WaitFor (s, req2, 4, 0x13, 4, ID_GetCalendarSettings);
}
GSM_Error N6510_CancelCall(GSM_StateMachine *s, int ID, bool all)
{
if (all) return ERR_NOTSUPPORTED;
return DCT3DCT4_CancelCall(s,ID);
}
GSM_Error N6510_AnswerCall(GSM_StateMachine *s, int ID, bool all)
{
if (all) return ERR_NOTSUPPORTED;
return DCT3DCT4_AnswerCall(s,ID);
}
static GSM_Error N6510_ReplyAddSMSFolder(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s,"SMS folder \"%s\" has been added\n",DecodeUnicodeString(msg.Buffer+10));
return ERR_NONE;
}
GSM_Error N6510_AddSMSFolder(GSM_StateMachine *s, unsigned char *name)
{
unsigned char req[200] = {N6110_FRAME_HEADER, 0x10, 0x01, 0x00, 0x01,
0x00, /* Length */
0x00, 0x00};
CopyUnicodeString(req+10,name);
req[7] = UnicodeLength(name)*2 + 6;
smprintf(s, "Adding SMS folder\n");
return GSM_WaitFor (s, req, req[7] + 6, 0x14, 4, ID_AddSMSFolder);
}
static GSM_Error N6510_SetWAPBookmark(GSM_StateMachine *s, GSM_WAPBookmark *bookmark)
{
GSM_Error error;
int count=4, location;
unsigned char req[600] = {N6110_FRAME_HEADER, 0x09};
/* We have to enable WAP frames in phone */
error=N6510_EnableConnectionFunctions(s,N6510_WAP_SETTINGS);
if (error!=ERR_NONE) return error;
location = bookmark->Location - 1;
if (bookmark->Location == 0) location = 0xffff;
req[count++] = (location & 0xff00) >> 8;
req[count++] = location & 0x00ff;
count += NOKIA_SetUnicodeString(s, req+count, bookmark->Title, true);
count += NOKIA_SetUnicodeString(s, req+count, bookmark->Address, true);
req[count++] = 0x00;
req[count++] = 0x00;
req[count++] = 0x00;
req[count++] = 0x00;
smprintf(s, "Setting WAP bookmark\n");
error = GSM_WaitFor (s, req, count, 0x3f, 4, ID_SetWAPBookmark);
if (error != ERR_NONE) {
if (error == ERR_INSIDEPHONEMENU || error == ERR_EMPTY || error == ERR_FULL) {
DCT3DCT4_DisableConnectionFunctions(s);
}
return error;
}
return DCT3DCT4_DisableConnectionFunctions(s);
}
GSM_Error N6510_DeleteWAPBookmark(GSM_StateMachine *s, GSM_WAPBookmark *bookmark)
{
GSM_Error error;
/* We have to enable WAP frames in phone */
error=N6510_EnableConnectionFunctions(s,N6510_WAP_SETTINGS);
if (error!=ERR_NONE) return error;
return DCT3DCT4_DeleteWAPBookmarkPart(s,bookmark);
}
GSM_Error N6510_GetWAPBookmark(GSM_StateMachine *s, GSM_WAPBookmark *bookmark)
{
GSM_Error error;
/* We have to enable WAP frames in phone */
error=N6510_EnableConnectionFunctions(s,N6510_WAP_SETTINGS);
if (error!=ERR_NONE) return error;
return DCT3DCT4_GetWAPBookmarkPart(s,bookmark);
}
static GSM_Reply_Function N6510ReplyFunctions[] = {
{N71_65_ReplyCallInfo, "\x01",0x03,0x02,ID_IncomingFrame },
{N71_65_ReplyCallInfo, "\x01",0x03,0x03,ID_IncomingFrame },
{N71_65_ReplyCallInfo, "\x01",0x03,0x04,ID_IncomingFrame },
{N71_65_ReplyCallInfo, "\x01",0x03,0x05,ID_IncomingFrame },
{N71_65_ReplyCallInfo, "\x01",0x03,0x07,ID_AnswerCall },
{N71_65_ReplyCallInfo, "\x01",0x03,0x07,ID_IncomingFrame },
{N71_65_ReplyCallInfo, "\x01",0x03,0x09,ID_CancelCall },
{N71_65_ReplyCallInfo, "\x01",0x03,0x09,ID_IncomingFrame },
{N71_65_ReplyCallInfo, "\x01",0x03,0x0A,ID_IncomingFrame },
{N71_65_ReplyCallInfo, "\x01",0x03,0x0B,ID_IncomingFrame },
{N71_65_ReplyCallInfo, "\x01",0x03,0x0C,ID_DialVoice },
{N71_65_ReplyCallInfo, "\x01",0x03,0x0C,ID_IncomingFrame },
+ {N71_65_ReplyCallInfo, "\x01",0x03,0x0F,ID_IncomingFrame },
+ {N71_65_ReplyCallInfo, "\x01",0x03,0x10,ID_DialVoice },
+ {N71_65_ReplyCallInfo, "\x01",0x03,0x10,ID_IncomingFrame },
{N71_65_ReplyCallInfo, "\x01",0x03,0x23,ID_IncomingFrame },
{N71_65_ReplyCallInfo, "\x01",0x03,0x25,ID_IncomingFrame },
{N71_65_ReplyCallInfo, "\x01",0x03,0x27,ID_IncomingFrame },
{N71_65_ReplySendDTMF, "\x01",0x03,0x51,ID_SendDTMF },
{N71_65_ReplyCallInfo, "\x01",0x03,0x53,ID_IncomingFrame },
{N71_65_ReplySendDTMF, "\x01",0x03,0x59,ID_SendDTMF },
{N71_65_ReplySendDTMF, "\x01",0x03,0x5E,ID_SendDTMF },
+ {N71_65_ReplyCallInfo, "\x01",0x03,0xA6,ID_IncomingFrame },
+ {N71_65_ReplyCallInfo, "\x01",0x03,0xD2,ID_IncomingFrame },
+ {N71_65_ReplyCallInfo, "\x01",0x03,0xD3,ID_IncomingFrame },
{N6510_ReplySendSMSMessage, "\x02",0x03,0x03,ID_IncomingFrame },
{N6510_ReplyIncomingSMS, "\x02",0x03,0x04,ID_IncomingFrame },
{N6510_ReplySetSMSC, "\x02",0x03,0x13,ID_SetSMSC },
{N6510_ReplyGetSMSC, "\x02",0x03,0x15,ID_GetSMSC },
{N6510_ReplyGetMemoryStatus, "\x03",0x03,0x04,ID_GetMemoryStatus },
{N6510_ReplyGetMemory, "\x03",0x03,0x08,ID_GetMemory },
{N6510_ReplyDeleteMemory, "\x03",0x03,0x10,ID_SetMemory },
{N71_65_ReplyWritePhonebook, "\x03",0x03,0x0C,ID_SetBitmap },
{N71_65_ReplyWritePhonebook, "\x03",0x03,0x0C,ID_SetMemory },
{DCT3DCT4_ReplyCallDivert, "\x06",0x03,0x02,ID_Divert },
{N71_65_ReplyUSSDInfo, "\x06",0x03,0x03,ID_IncomingFrame },
{NoneReply, "\x06",0x03,0x06,ID_IncomingFrame },
{NoneReply, "\x06",0x03,0x09,ID_IncomingFrame },
{N6510_ReplyEnterSecurityCode, "\x08",0x03,0x08,ID_EnterSecurityCode },
{N6510_ReplyEnterSecurityCode, "\x08",0x03,0x09,ID_EnterSecurityCode },
{N6510_ReplyGetSecurityStatus, "\x08",0x03,0x12,ID_GetSecurityStatus },
{N6510_ReplyGetNetworkInfo, "\x0A",0x03,0x01,ID_GetNetworkInfo },
{N6510_ReplyGetNetworkInfo, "\x0A",0x03,0x01,ID_IncomingFrame },
{N6510_ReplyLogIntoNetwork, "\x0A",0x03,0x02,ID_IncomingFrame },
{N6510_ReplyGetSignalQuality, "\x0A",0x03,0x0C,ID_GetSignalQuality },
{N6510_ReplyGetIncSignalQuality, "\x0A",0x03,0x1E,ID_IncomingFrame },
{NoneReply, "\x0A",0x03,0x20,ID_IncomingFrame },
{N6510_ReplyGetOperatorLogo, "\x0A",0x03,0x24,ID_GetBitmap },
{N6510_ReplySetOperatorLogo, "\x0A",0x03,0x26,ID_SetBitmap },
{NoneReply, "\x0B",0x03,0x01,ID_PlayTone },
{NoneReply, "\x0B",0x03,0x15,ID_PlayTone },
{NoneReply, "\x0B",0x03,0x16,ID_PlayTone },
{N71_65_ReplyAddCalendar1, "\x13",0x03,0x02,ID_SetCalendarNote },
{N71_65_ReplyAddCalendar1, "\x13",0x03,0x04,ID_SetCalendarNote },
{N71_65_ReplyAddCalendar1, "\x13",0x03,0x06,ID_SetCalendarNote },
{N71_65_ReplyAddCalendar1, "\x13",0x03,0x08,ID_SetCalendarNote },
{N71_65_ReplyDelCalendar, "\x13",0x03,0x0C,ID_DeleteCalendarNote },
{N71_65_ReplyGetNextCalendar1, "\x13",0x03,0x1A,ID_GetCalendarNote },/*method 1*/
{N6510_ReplyGetCalendarNotePos, "\x13",0x03,0x32,ID_GetCalendarNotePos },/*method 1*/
{N6510_ReplyGetCalendarInfo, "\x13",0x03,0x3B,ID_GetCalendarNotesInfo},/*method 1*/
#ifdef DEBUG
{N71_65_ReplyGetNextCalendar2, "\x13",0x03,0x3F,ID_GetCalendarNote },
#endif
{N71_65_ReplyAddCalendar2, "\x13",0x03,0x41,ID_SetCalendarNote },/*method 2*/
{N6510_ReplyAddCalendar3, "\x13",0x03,0x66,ID_SetCalendarNote },/*method 3*/
{N6510_ReplyAddToDo2, "\x13",0x03,0x66,ID_SetToDo },
{N6510_ReplyGetCalendar3, "\x13",0x03,0x7E,ID_GetCalendarNote },/*method 3*/
{N6510_ReplyGetToDo2, "\x13",0x03,0x7E,ID_GetToDo },
+ {N6510_ReplyGetNote, "\x13",0x03,0x7E,ID_GetNote },
{N6510_ReplyGetCalendarSettings, "\x13",0x03,0x86,ID_GetCalendarSettings },
{N6510_ReplyGetLocale, "\x13",0x03,0x8A,ID_GetLocale },
{N6510_ReplyGetCalendarSettings, "\x13",0x03,0x8E,ID_GetCalendarSettings },
{N6510_ReplyGetCalendarNotePos, "\x13",0x03,0x96,ID_GetCalendarNotePos },/*method 3*/
{N6510_ReplyGetToDoFirstLoc2, "\x13",0x03,0x96,ID_SetToDo },
{N6510_ReplyGetCalendarInfo, "\x13",0x03,0x9F,ID_GetCalendarNotesInfo},/*method 3*/
{N6510_ReplyGetToDoStatus2, "\x13",0x03,0x9F,ID_GetToDo },
+ {N6510_ReplyGetNoteInfo, "\x13",0x03,0x9F,ID_GetNote },
{N6510_ReplySaveSMSMessage, "\x14",0x03,0x01,ID_SaveSMSMessage },
{N6510_ReplySetPicture, "\x14",0x03,0x01,ID_SetBitmap },
{N6510_ReplyGetSMSMessage, "\x14",0x03,0x03,ID_GetSMSMessage },
{N6510_ReplyDeleteSMSMessage, "\x14",0x03,0x05,ID_DeleteSMSMessage },
{N6510_ReplyDeleteSMSMessage, "\x14",0x03,0x06,ID_DeleteSMSMessage },
{N6510_ReplyGetSMSStatus, "\x14",0x03,0x09,ID_GetSMSStatus },
{N6510_ReplyGetSMSFolderStatus, "\x14",0x03,0x0d,ID_GetSMSFolderStatus },
{N6510_ReplyGetSMSMessage, "\x14",0x03,0x0f,ID_GetSMSMessage },
{N6510_ReplyAddSMSFolder, "\x14",0x03,0x11,ID_AddSMSFolder },
{N6510_ReplyGetSMSFolders, "\x14",0x03,0x13,ID_GetSMSFolders },
{N6510_ReplySaveSMSMessage, "\x14",0x03,0x17,ID_SaveSMSMessage },
{N6510_ReplyGetSMSStatus, "\x14",0x03,0x1a,ID_GetSMSStatus },
{DCT4_ReplySetPhoneMode, "\x15",0x03,0x64,ID_Reset },
{DCT4_ReplyGetPhoneMode, "\x15",0x03,0x65,ID_Reset },
{NoneReply, "\x15",0x03,0x68,ID_Reset },
{N6510_ReplyGetBatteryCharge, "\x17",0x03,0x0B,ID_GetBatteryCharge },
{N6510_ReplySetDateTime, "\x19",0x03,0x02,ID_SetDateTime },
{N6510_ReplyGetDateTime, "\x19",0x03,0x0B,ID_GetDateTime },
{N6510_ReplySetAlarm, "\x19",0x03,0x12,ID_SetAlarm },
{N6510_ReplyGetAlarm, "\x19",0x03,0x1A,ID_GetAlarm },
{N6510_ReplyGetAlarm, "\x19",0x03,0x20,ID_GetAlarm },
{DCT4_ReplyGetIMEI, "\x1B",0x03,0x01,ID_GetIMEI },
{NOKIA_ReplyGetPhoneString, "\x1B",0x03,0x08,ID_GetHardware },
{N6510_ReplyGetPPM, "\x1B",0x03,0x08,ID_GetPPM },
{NOKIA_ReplyGetPhoneString, "\x1B",0x03,0x0C,ID_GetProductCode },
/* 0x1C - vibra */
{N6510_ReplyGetRingtonesInfo, "\x1f",0x03,0x08,ID_GetRingtonesInfo },
{N6510_ReplyDeleteRingtones, "\x1f",0x03,0x11,ID_SetRingtone },
{N6510_ReplyGetRingtone, "\x1f",0x03,0x13,ID_GetRingtone },
{N6510_ReplySetBinRingtone, "\x1f",0x03,0x0F,ID_SetRingtone },
/* 0x23 - voice records */
{N6510_ReplyGetProfile, "\x39",0x03,0x02,ID_GetProfile },
{N6510_ReplySetProfile, "\x39",0x03,0x04,ID_SetProfile },
{N6510_ReplyGetProfile, "\x39",0x03,0x06,ID_GetProfile },
{N6510_ReplySetLight, "\x3A",0x03,0x06,ID_SetLight },
{N6510_ReplyGetFMStation, "\x3E",0x03,0x06,ID_GetFMStation },
{N6510_ReplyGetFMStatus, "\x3E",0x03,0x0E,ID_GetFMStation },
{N6510_ReplySetFMStation, "\x3E",0x03,0x15,ID_SetFMStation },
{N6510_ReplyGetFMStation, "\x3E",0x03,0x16,ID_GetFMStation },
{DCT3DCT4_ReplyEnableConnectFunc, "\x3f",0x03,0x01,ID_EnableConnectFunc },
{DCT3DCT4_ReplyEnableConnectFunc, "\x3f",0x03,0x02,ID_EnableConnectFunc },
{DCT3DCT4_ReplyDisableConnectFunc,"\x3f",0x03,0x04,ID_DisableConnectFunc },
{DCT3DCT4_ReplyDisableConnectFunc,"\x3f",0x03,0x05,ID_DisableConnectFunc },
{N6510_ReplyGetWAPBookmark, "\x3f",0x03,0x07,ID_GetWAPBookmark },
{N6510_ReplyGetWAPBookmark, "\x3f",0x03,0x08,ID_GetWAPBookmark },
{DCT3DCT4_ReplySetWAPBookmark, "\x3f",0x03,0x0A,ID_SetWAPBookmark },
{DCT3DCT4_ReplySetWAPBookmark, "\x3f",0x03,0x0B,ID_SetWAPBookmark },
{DCT3DCT4_ReplyDelWAPBookmark, "\x3f",0x03,0x0D,ID_DeleteWAPBookmark },
{DCT3DCT4_ReplyDelWAPBookmark, "\x3f",0x03,0x0E,ID_DeleteWAPBookmark },
{DCT3DCT4_ReplyGetActiveConnectSet,"\x3f",0x03,0x10,ID_GetConnectSet },
{DCT3DCT4_ReplySetActiveConnectSet,"\x3f",0x03,0x13,ID_SetConnectSet },
{N6510_ReplyGetConnectionSettings,"\x3f",0x03,0x16,ID_GetConnectSet },
{N6510_ReplyGetConnectionSettings,"\x3f",0x03,0x17,ID_GetConnectSet },
{N6510_ReplySetConnectionSettings,"\x3f",0x03,0x19,ID_SetConnectSet },
{N6510_ReplySetConnectionSettings,"\x3f",0x03,0x1A,ID_SetConnectSet },
{N6510_ReplySetConnectionSettings,"\x3f",0x03,0x28,ID_SetConnectSet },
{N6510_ReplySetConnectionSettings,"\x3f",0x03,0x2B,ID_SetConnectSet },
{N6510_ReplyGetChatSettings, "\x3f",0x03,0x3B,ID_GetChatSettings },
{N6510_ReplyGetChatSettings, "\x3f",0x03,0x3C,ID_GetChatSettings },
{N6510_ReplyGetOriginalIMEI, "\x42",0x07,0x00,ID_GetOriginalIMEI },
{N6510_ReplyGetManufactureMonth, "\x42",0x07,0x00,ID_GetManufactureMonth },
{N6510_ReplyGetOriginalIMEI, "\x42",0x07,0x01,ID_GetOriginalIMEI },
{N6510_ReplyGetManufactureMonth, "\x42",0x07,0x02,ID_GetManufactureMonth },
{N6510_ReplySetOperatorLogo, "\x43",0x03,0x08,ID_SetBitmap },
{N6510_ReplyGetGPRSAccessPoint, "\x43",0x03,0x06,ID_GetGPRSPoint },
{N6510_ReplySetGPRSAccessPoint1, "\x43",0x03,0x06,ID_SetGPRSPoint },
#ifdef DEVELOP
{N6510_ReplyEnableGPRSAccessPoint,"\x43",0x03,0x06,ID_EnableGPRSPoint },
#endif
{N6510_ReplyGetSyncMLSettings, "\x43",0x03,0x06,ID_GetSyncMLSettings },
{N6510_ReplyGetSyncMLName, "\x43",0x03,0x06,ID_GetSyncMLName },
{NoneReply, "\x43",0x03,0x08,ID_SetGPRSPoint },
/* 0x4A - voice records */
/* 0x53 - simlock */
{N6510_ReplyAddToDo1, "\x55",0x03,0x02,ID_SetToDo },
{N6510_ReplyGetToDo1, "\x55",0x03,0x04,ID_GetToDo },
{N6510_ReplyGetToDoFirstLoc1, "\x55",0x03,0x10,ID_SetToDo },
{N6510_ReplyDeleteAllToDo1, "\x55",0x03,0x12,ID_DeleteAllToDo },
{N6510_ReplyGetToDoStatus1, "\x55",0x03,0x16,ID_GetToDo },
{N6510_ReplyAddFileHeader, "\x6D",0x03,0x03,ID_AddFile },
{N6510_ReplyAddFolder, "\x6D",0x03,0x05,ID_AddFolder },
{N6510_ReplyGetFilePart, "\x6D",0x03,0x0F,ID_GetFile },
{N6510_ReplyAddFileHeader, "\x6D",0x03,0x13,ID_AddFile },
{N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x15,ID_GetFileInfo },
{N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x15,ID_GetFile },
{N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x15,ID_AddFile },
{N6510_ReplyDeleteFile, "\x6D",0x03,0x19,ID_DeleteFile },
{N6510_ReplyDeleteFile, "\x6D",0x03,0x1F,ID_DeleteFile },
{N6510_ReplyGetFileSystemStatus, "\x6D",0x03,0x23,ID_FileSystemStatus },
{N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x2F,ID_GetFileInfo },
{N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x2F,ID_GetFile },
{N6510_ReplyGetFileSystemStatus, "\x6D",0x03,0x2F,ID_FileSystemStatus },
{N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x33,ID_GetFileInfo },
{N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x33,ID_GetFile },
{N6510_ReplyAddFilePart, "\x6D",0x03,0x41,ID_AddFile },
{N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x43,ID_AddFile },
{N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x43,ID_GetFile },
{N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x43,ID_GetFileInfo },
{N6510_ReplyStartupNoteLogo, "\x7A",0x04,0x01,ID_GetBitmap },
{N6510_ReplyStartupNoteLogo, "\x7A",0x04,0x01,ID_SetBitmap },
{N6510_ReplyStartupNoteLogo, "\x7A",0x04,0x0F,ID_GetBitmap },
{N6510_ReplyStartupNoteLogo, "\x7A",0x04,0x0F,ID_SetBitmap },
{N6510_ReplyStartupNoteLogo, "\x7A",0x04,0x10,ID_GetBitmap },
{N6510_ReplyStartupNoteLogo, "\x7A",0x04,0x10,ID_SetBitmap },
{N6510_ReplyStartupNoteLogo, "\x7A",0x04,0x25,ID_SetBitmap },
{DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetModel },
{DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetFirmware },
/* 0xD7 - Bluetooth */
{N6510_ReplyGetRingtoneID, "\xDB",0x03,0x02,ID_SetRingtone },
{NULL, "\x00",0x00,0x00,ID_None }
};
GSM_Phone_Functions N6510Phone = {
- "1100|1100a|1100b|3100|3100b|3108|3200|3200a|3300|3510|3510i|3530|3589i|3590|3595|5100|6100|6200|6220|6230|6310|6310i|6385|6510|6610|6800|7210|7250|7250i|7600|8310|8390|8910|8910i",
+ "1100|1100a|1100b|3100|3100b|3108|3200|3200a|3300|3510|3510i|3530|3589i|3590|3595|5100|5140|6100|6200|6220|6230|6310|6310i|6385|6510|6610|6610i|6800|6810|6820|7210|7250|7250i|7600|8310|8390|8910|8910i",
N6510ReplyFunctions,
N6510_Initialise,
NONEFUNCTION, /* Terminate */
GSM_DispatchMessage,
N6510_ShowStartInfo,
NOKIA_GetManufacturer,
DCT3DCT4_GetModel,
DCT3DCT4_GetFirmware,
DCT4_GetIMEI,
N6510_GetOriginalIMEI,
N6510_GetManufactureMonth,
DCT4_GetProductCode,
DCT4_GetHardware,
N6510_GetPPM,
NOTSUPPORTED, /* GetSIMIMSI */
N6510_GetDateTime,
N6510_SetDateTime,
N6510_GetAlarm,
N6510_SetAlarm,
N6510_GetLocale,
NOTSUPPORTED, /* SetLocale */
N6510_PressKey,
DCT4_Reset,
NOTIMPLEMENTED, /* ResetPhoneSettings */
N6510_EnterSecurityCode,
N6510_GetSecurityStatus,
NOTSUPPORTED, /* GetDisplayStatus */
NOTIMPLEMENTED, /* SetAutoNetworkLogin */
N6510_GetBatteryCharge,
N6510_GetSignalQuality,
N6510_GetNetworkInfo,
NOTSUPPORTED, /* GetCategory */
NOTSUPPORTED, /* AddCategory */
NOTSUPPORTED, /* GetCategoryStatus */
N6510_GetMemoryStatus,
N6510_GetMemory,
NOTIMPLEMENTED, /* GetNextMemory */
N6510_SetMemory,
NOTIMPLEMENTED, /* AddMemory */
N6510_DeleteMemory,
NOTIMPLEMENTED, /* DeleteAllMemory */
N6510_GetSpeedDial,
NOTIMPLEMENTED, /* SetSpeedDial */
N6510_GetSMSC,
N6510_SetSMSC,
N6510_GetSMSStatus,
N6510_GetSMSMessage,
N6510_GetNextSMSMessage,
N6510_SetSMS,
N6510_AddSMS,
N6510_DeleteSMSMessage,
N6510_SendSMSMessage,
NOTSUPPORTED, /* SendSavedSMS */
+ NOTSUPPORTED, /* SetFastSMSSending */
NOKIA_SetIncomingSMS,
NOTIMPLEMENTED, /* SetIncomingCB */
N6510_GetSMSFolders,
N6510_AddSMSFolder,
NOTIMPLEMENTED, /* DeleteSMSFolder */
N6510_DialVoice,
N6510_AnswerCall,
N6510_CancelCall,
NOTIMPLEMENTED, /* HoldCall */
NOTIMPLEMENTED, /* UnholdCall */
NOTIMPLEMENTED, /* ConferenceCall */
NOTIMPLEMENTED, /* SplitCall */
NOTIMPLEMENTED, /* TransferCall */
NOTIMPLEMENTED, /* SwitchCall */
DCT3DCT4_GetCallDivert,
DCT3DCT4_SetCallDivert,
DCT3DCT4_CancelAllDiverts,
NOKIA_SetIncomingCall,
NOKIA_SetIncomingUSSD,
DCT3DCT4_SendDTMF,
N6510_GetRingtone,
N6510_SetRingtone,
N6510_GetRingtonesInfo,
N6510_DeleteUserRingtones,
N6510_PlayTone,
N6510_GetWAPBookmark,
N6510_SetWAPBookmark,
N6510_DeleteWAPBookmark,
N6510_GetWAPSettings,
N6510_SetWAPSettings,
N6510_GetMMSSettings,
N6510_SetMMSSettings,
N6510_GetSyncMLSettings,
NOTSUPPORTED, /* SetSyncMLSettings */
N6510_GetChatSettings,
NOTSUPPORTED, /* SetChatSettings */
N6510_GetBitmap,
N6510_SetBitmap,
N6510_GetToDoStatus,
NOTIMPLEMENTED, /* GetToDo */
N6510_GetNextToDo,
NOTIMPLEMENTED, /* SetToDo */
N6510_AddToDo,
N6510_DeleteToDo2,
N6510_DeleteAllToDo1,
N6510_GetCalendarStatus,
NOTIMPLEMENTED, /* GetCalendar */
N6510_GetNextCalendar,
NOTIMPLEMENTED, /* SetCalendar */
N6510_AddCalendar,
N71_65_DelCalendar,
NOTIMPLEMENTED, /* DeleteAllCalendar */
N6510_GetCalendarSettings,
NOTSUPPORTED, /* SetCalendarSettings */
- NOTIMPLEMENTED, /* GetNote */
+ N6510_GetNextNote,
N6510_GetProfile,
N6510_SetProfile,
N6510_GetFMStation,
N6510_SetFMStation,
N6510_ClearFMStations,
N6510_GetNextFileFolder,
N6510_GetFilePart,
N6510_AddFilePart,
N6510_GetFileSystemStatus,
N6510_DeleteFile,
N6510_AddFolder,
N6510_GetGPRSAccessPoint,
N6510_SetGPRSAccessPoint
};
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/nokia/dct4/n6510.h b/gammu/emb/common/phone/nokia/dct4/n6510.h
index 4717aeb..26623d6 100644
--- a/gammu/emb/common/phone/nokia/dct4/n6510.h
+++ b/gammu/emb/common/phone/nokia/dct4/n6510.h
@@ -1,90 +1,92 @@
/* (c) 2002-2004 by Marcin Wiacek */
#ifndef n6510_h
#define n6510_h
#include "../ncommon.h"
#include "../../../service/sms/gsmsms.h"
typedef enum {
N6510_MMS_SETTINGS = 0x01,
N6510_CHAT_SETTINGS,
N6510_WAP_SETTINGS,
N6510_SYNCML_SETTINGS
} N6510_Connection_Settings;
typedef enum {
N6510_LIGHT_DISPLAY = 0x01,
N6510_LIGHT_KEYPAD = 0x03,
N6510_LIGHT_TORCH = 0x10
} N6510_PHONE_LIGHTS;
typedef struct {
int LastCalendarYear;
int LastCalendarPos;
GSM_NOKIACalToDoLocations LastCalendar;
int FirstCalendarPos;
unsigned char CalendarIcons[10];
GSM_CalendarNoteType CalendarIconsTypes[10];
int CalendarIconsNum;
GSM_NOKIASMSFolder LastSMSFolder;
GSM_SMSFolders LastSMSFolders;
GSM_NOKIACalToDoLocations LastToDo;
+ GSM_NOKIACalToDoLocations LastNote;
+
unsigned char RingtoneID; /* When set with preview */
int FilesLocations[1000];
int FilesLevels[1000];
int FilesLocationsUsed;
int FilesLocationsCurrent;
int FileToken;
int ParentID;
int FileCheckSum;
unsigned char FMStatus[4000];
int FMStatusLength;
unsigned char GPRSPoints[4000];
int GPRSPointsLength;
int BearerNumber;
unsigned char PhoneMode;
} GSM_Phone_N6510Data;
void N6510_EncodeFMFrequency(double freq, unsigned char *buff);
void N6510_DecodeFMFrequency(double *freq, unsigned char *buff);
#ifndef GSM_USED_MBUS2
# define GSM_USED_MBUS2
#endif
#ifndef GSM_USED_FBUS2
# define GSM_USED_FBUS2
#endif
#ifndef GSM_USED_FBUS2DLR3
# define GSM_USED_FBUS2DLR3
#endif
#ifndef GSM_USED_FBUS2DKU5
# define GSM_USED_FBUS2DKU5
#endif
#ifndef GSM_USED_PHONETBLUE
# define GSM_USED_PHONETBLUE
#endif
#ifndef GSM_USED_IRDAPHONET
# define GSM_USED_IRDAPHONET
#endif
#ifndef GSM_USED_BLUEPHONET
# define GSM_USED_BLUEPHONET
#endif
#ifndef GSM_USED_FBUS2PL2303
# define GSM_USED_FBUS2PL2303
#endif
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/nokia/nauto.c b/gammu/emb/common/phone/nokia/nauto.c
index bf74bc9..3bb53ec 100644
--- a/gammu/emb/common/phone/nokia/nauto.c
+++ b/gammu/emb/common/phone/nokia/nauto.c
@@ -1,144 +1,144 @@
/* (c) 2002-2003 by Marcin Wiacek */
#include <string.h>
#include <time.h>
#include "../../gsmcomon.h"
#include "../../gsmstate.h"
#include "nfunc.h"
#if defined(GSM_ENABLE_NOKIA_DCT3) || defined(GSM_ENABLE_NOKIA_DCT4)
static GSM_Reply_Function NAUTOReplyFunctions[] = {
{DCT3DCT4_ReplyGetModelFirmware,"\xD2",0x02,0x00,ID_GetModel },
{DCT3DCT4_ReplyGetModelFirmware,"\xD2",0x02,0x00,ID_GetFirmware },
{NULL, "\x00",0x00,0x00,ID_None }
};
GSM_Phone_Functions NAUTOPhone = {
"NAUTO",
NAUTOReplyFunctions,
NONEFUNCTION, /* Initialise */
NONEFUNCTION, /* Terminate */
GSM_DispatchMessage,
NOTSUPPORTED, /* ShowStartInfo */
NOKIA_GetManufacturer,
DCT3DCT4_GetModel,
DCT3DCT4_GetFirmware,
NOTSUPPORTED, /* GetIMEI */
NOTSUPPORTED, /* GetOriginalIMEI */
NOTSUPPORTED, /* GetManufactureMonth */
NOTSUPPORTED, /* GetProductCode */
NOTSUPPORTED, /* GetHardware */
NOTSUPPORTED, /* GetPPM */
NOTSUPPORTED, /* GetSIMIMSI */
NOTSUPPORTED, /* GetDateTime */
NOTSUPPORTED, /* SetDateTime */
NOTSUPPORTED, /* GetAlarm */
NOTSUPPORTED, /* SetAlarm */
NOTSUPPORTED, /* GetLocale */
NOTSUPPORTED, /* SetLocale */
NOTSUPPORTED, /* PressKey */
NOTSUPPORTED, /* Reset */
NOTSUPPORTED, /* ResetPhoneSettings */
NOTSUPPORTED, /* EnterSecurityCode */
NOTSUPPORTED, /* GetSecurityStatus */
NOTSUPPORTED, /* GetDisplayStatus */
NOTSUPPORTED, /* SetAutoNetworkLogin */
NOTSUPPORTED, /* GetBatteryCharge */
NOTSUPPORTED, /* GetSignalQuality */
NOTSUPPORTED, /* GetNetworkInfo */
NOTSUPPORTED, /* GetCategory */
NOTSUPPORTED, /* AddCategory */
NOTSUPPORTED, /* GetCategoryStatus */
NOTSUPPORTED, /* GetMemoryStatus */
NOTSUPPORTED, /* GetMemory */
NOTSUPPORTED, /* GetNextMemory */
NOTSUPPORTED, /* SetMemory */
NOTSUPPORTED, /* AddMemory */
NOTSUPPORTED, /* DeleteMemory */
NOTIMPLEMENTED, /* DeleteAllMemory */
NOTSUPPORTED, /* GetSpeedDial */
NOTSUPPORTED, /* SetSpeedDial */
NOTSUPPORTED, /* GetSMSC */
NOTSUPPORTED, /* SetSMSC */
NOTSUPPORTED, /* GetSMSStatus */
NOTSUPPORTED, /* GetSMS */
NOTSUPPORTED, /* GetNextSMS */
NOTSUPPORTED, /* SetSMS */
NOTSUPPORTED, /* AddSMS */
NOTSUPPORTED, /* DeleteSMS */
NOTSUPPORTED, /* SendSMSMessage */
NOTSUPPORTED, /* SendSavedSMS */
NOTSUPPORTED, /* SetIncomingSMS */
NOTSUPPORTED, /* SetIncomingCB */
NOTSUPPORTED, /* GetSMSFolders */
NOTSUPPORTED, /* AddSMSFolder */
NOTSUPPORTED, /* DeleteSMSFolder */
NOTSUPPORTED, /* DialVoice */
NOTSUPPORTED, /* AnswerCall */
NOTSUPPORTED, /* CancelCall */
NOTSUPPORTED, /* HoldCall */
NOTSUPPORTED, /* UnholdCall */
NOTSUPPORTED, /* ConferenceCall */
NOTSUPPORTED, /* SplitCall */
NOTSUPPORTED, /* TransferCall */
NOTSUPPORTED, /* SwitchCall */
NOTSUPPORTED, /* GetCallDivert */
NOTSUPPORTED, /* SetCallDivert */
NOTSUPPORTED, /* CancelAllDiverts */
NOTSUPPORTED, /* SetIncomingCall */
NOTSUPPORTED, /* SetIncomingUSSD */
NOTSUPPORTED, /* SendDTMF */
NOTSUPPORTED, /* GetRingtone */
NOTSUPPORTED, /* SetRingtone */
NOTSUPPORTED, /* GetRingtonesInfo */
NOTSUPPORTED, /* DeleteUserRingtones */
NOTSUPPORTED, /* PlayTone */
NOTSUPPORTED, /* GetWAPBookmark */
NOTSUPPORTED, /* SetWAPBookmark */
NOTSUPPORTED, /* DeleteWAPBookmark */
NOTSUPPORTED, /* GetWAPSettings */
NOTSUPPORTED, /* SetWAPSettings */
NOTSUPPORTED, /* GetMMSSettings */
NOTSUPPORTED, /* SetMMSSettings */
NOTSUPPORTED, /* GetBitmap */
NOTSUPPORTED, /* SetBitmap */
NOTSUPPORTED, /* GetToDoStatus */
NOTSUPPORTED, /* GetToDo */
NOTSUPPORTED, /* GetNextToDo */
NOTSUPPORTED, /* SetToDo */
NOTSUPPORTED, /* AddToDo */
NOTSUPPORTED, /* DeleteToDo */
NOTSUPPORTED, /* DeleteAllToDo */
NOTSUPPORTED, /* GetCalendarStatus */
NOTSUPPORTED, /* GetCalendar */
NOTSUPPORTED, /* GetNextCalendar */
NOTSUPPORTED, /* SetCalendar */
NOTSUPPORTED, /* AddCalendar */
NOTSUPPORTED, /* DeleteCalendar */
NOTSUPPORTED, /* DeleteAllCalendar */
NOTSUPPORTED, /* GetCalendarSettings */
NOTSUPPORTED, /* SetCalendarSettings */
- NOTSUPPORTED, /* GetNote */
+ NOTSUPPORTED, /* GetNextNote */
NOTSUPPORTED, /* GetProfile */
NOTSUPPORTED, /* SetProfile */
NOTSUPPORTED, /* GetFMStation */
NOTSUPPORTED, /* SetFMStation */
NOTSUPPORTED, /* ClearFMStations */
NOTSUPPORTED, /* GetNextFileFolder */
NOTSUPPORTED, /* GetFilePart */
NOTSUPPORTED, /* AddFilePart */
NOTSUPPORTED, /* GetFileSystemStatus */
NOTSUPPORTED, /* DeleteFile */
NOTSUPPORTED, /* AddFolder */
NOTSUPPORTED, /* GetGPRSAccessPoint */
NOTSUPPORTED /* SetGPRSAccessPoint */
};
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/nokia/nfunc.c b/gammu/emb/common/phone/nokia/nfunc.c
index 3acfb10..d4d8b03 100644
--- a/gammu/emb/common/phone/nokia/nfunc.c
+++ b/gammu/emb/common/phone/nokia/nfunc.c
@@ -1204,413 +1204,427 @@ void NOKIA_FindFeatureValue(GSM_StateMachine *s,
if ((Value & PROFILE_CALLERGROUPS_GROUP2)==PROFILE_CALLERGROUPS_GROUP2) Data->Profile->CallerGroups[1] = true;
if ((Value & PROFILE_CALLERGROUPS_GROUP3)==PROFILE_CALLERGROUPS_GROUP3) Data->Profile->CallerGroups[2] = true;
if ((Value & PROFILE_CALLERGROUPS_GROUP4)==PROFILE_CALLERGROUPS_GROUP4) Data->Profile->CallerGroups[3] = true;
if ((Value & PROFILE_CALLERGROUPS_GROUP5)==PROFILE_CALLERGROUPS_GROUP5) Data->Profile->CallerGroups[4] = true;
return;
}
i = 0;
while (ProfileTable[i].ID != 0x00) {
if (ProfileTable[i].PhoneID == ID &&
ProfileTable[i].PhoneValue == Value) {
#ifdef DEBUG
switch (ProfileTable[i].ID) {
case Profile_KeypadTone : smprintf(s, "Keypad tones\n"); break;
case Profile_CallAlert : smprintf(s, "Call alert\n"); break;
case Profile_RingtoneVolume : smprintf(s, "Ringtone volume\n"); break;
case Profile_MessageTone : smprintf(s, "SMS message tones\n"); break;
case Profile_Vibration : smprintf(s, "Vibration\n"); break;
case Profile_WarningTone : smprintf(s, "Warning (ang games) tones\n"); break;
case Profile_AutoAnswer : smprintf(s, "Automatic answer\n"); break;
case Profile_Lights : smprintf(s, "Lights\n"); break;
case Profile_ScreenSaver : smprintf(s, "Screen Saver\n"); break;
case Profile_ScreenSaverTime : smprintf(s, "Screen Saver timeout\n"); break;
default : break;
}
#endif
Data->Profile->FeatureID [Data->Profile->FeaturesNumber] = ProfileTable[i].ID;
Data->Profile->FeatureValue [Data->Profile->FeaturesNumber] = ProfileTable[i].Value;
Data->Profile->FeaturesNumber++;
break;
}
i++;
}
}
GSM_Profile_PhoneTableValue Profile71_65[] = {
{Profile_KeypadTone, PROFILE_KEYPAD_OFF, 0x00,0x00},
{Profile_KeypadTone, PROFILE_KEYPAD_LEVEL1, 0x00,0x01},
{Profile_KeypadTone, PROFILE_KEYPAD_LEVEL2, 0x00,0x02},
{Profile_KeypadTone, PROFILE_KEYPAD_LEVEL3, 0x00,0x03},
/* Lights ? */
{Profile_CallAlert, PROFILE_CALLALERT_RINGING, 0x02,0x00},
{Profile_CallAlert, PROFILE_CALLALERT_ASCENDING, 0x02,0x01},
{Profile_CallAlert, PROFILE_CALLALERT_RINGONCE, 0x02,0x02},
{Profile_CallAlert, PROFILE_CALLALERT_BEEPONCE, 0x02,0x03},
{Profile_CallAlert, PROFILE_CALLALERT_OFF, 0x02,0x05},
/* {Profile_CallAlert, PROFILE_CALLALERT_CALLERGROUPS,0x02,0x07}, */
/* Ringtone ID */
{Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL1, 0x04,0x00},
{Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL2, 0x04,0x01},
{Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL3, 0x04,0x02},
{Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL4, 0x04,0x03},
{Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL5, 0x04,0x04},
{Profile_MessageTone, PROFILE_MESSAGE_NOTONE, 0x05,0x00},
{Profile_MessageTone, PROFILE_MESSAGE_STANDARD, 0x05,0x01},
{Profile_MessageTone, PROFILE_MESSAGE_SPECIAL, 0x05,0x02},
{Profile_MessageTone, PROFILE_MESSAGE_BEEPONCE, 0x05,0x03},
{Profile_MessageTone, PROFILE_MESSAGE_ASCENDING, 0x05,0x04},
{Profile_Vibration, PROFILE_VIBRATION_OFF, 0x06,0x00},
{Profile_Vibration, PROFILE_VIBRATION_ON, 0x06,0x01},
{Profile_WarningTone, PROFILE_WARNING_OFF, 0x07,0x00},
{Profile_WarningTone, PROFILE_WARNING_ON, 0x07,0x01},
/* Caller groups */
{Profile_AutoAnswer, PROFILE_AUTOANSWER_OFF, 0x09,0x00},
{Profile_AutoAnswer, PROFILE_AUTOANSWER_ON, 0x09,0x01},
{0x00, 0x00, 0x00,0x00}
};
GSM_Error NOKIA_SetIncomingSMS(GSM_StateMachine *s, bool enable)
{
s->Phone.Data.EnableIncomingSMS = enable;
#ifdef DEBUG
if (enable) {
smprintf(s, "Enabling incoming SMS\n");
} else {
smprintf(s, "Disabling incoming SMS\n");
}
#endif
return ERR_NONE;
}
GSM_Error N71_65_ReplyUSSDInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
unsigned char buffer[2000],buffer2[4000];
if (s->Phone.Data.RequestID == ID_Divert) return ERR_NONE;
memcpy(buffer,msg.Buffer+8,msg.Buffer[7]);
buffer[msg.Buffer[7]] = 0x00;
smprintf(s, "USSD reply: \"%s\"\n",buffer);
if (s->Phone.Data.EnableIncomingUSSD && s->User.IncomingUSSD!=NULL) {
EncodeUnicode(buffer2,buffer,strlen(buffer));
s->User.IncomingUSSD(s->CurrentConfig->Device, buffer2);
}
return ERR_NONE;
}
GSM_Error NOKIA_SetIncomingUSSD(GSM_StateMachine *s, bool enable)
{
s->Phone.Data.EnableIncomingUSSD = enable;
#ifdef DEBUG
if (enable) {
smprintf(s, "Enabling incoming USSD\n");
} else {
smprintf(s, "Disabling incoming USSD\n");
}
#endif
return ERR_NONE;
}
GSM_Error NOKIA_SetIncomingCall(GSM_StateMachine *s, bool enable)
{
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOCALLINFO)) return ERR_NOTSUPPORTED;
s->Phone.Data.EnableIncomingCall = enable;
#ifdef DEBUG
if (enable) {
smprintf(s, "Enabling incoming Call\n");
} else {
smprintf(s, "Disabling incoming Call\n");
}
#endif
return ERR_NONE;
}
GSM_Error N71_65_ReplyCallInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
GSM_Call call;
int tmp;
unsigned char buffer[200];
call.Status = 0;
call.CallIDAvailable = true;
smprintf(s, "Call info, ");
switch (msg.Buffer[3]) {
case 0x02:
smprintf(s, "Call established, waiting for answer\n");
call.Status = GSM_CALL_CallEstablished;
break;
case 0x03:
smprintf(s, "Call started\n");
smprintf(s, "Call mode : %i\n",msg.Buffer[5]);//such interpretation is in gnokii
tmp = 6;
NOKIA_GetUnicodeString(s, &tmp, msg.Buffer,buffer,false);
smprintf(s, "Number : \"%s\"\n",DecodeUnicodeString(buffer));
/* FIXME: read name from frame */
call.Status = GSM_CALL_CallStart;
break;
case 0x04:
smprintf(s, "Remote end hang up\n");
smprintf(s, "Cause Type : %i\n",msg.Buffer[5]);//such interpretation is in gnokii
smprintf(s, "CC : %i\n",msg.Buffer[6]);
smprintf(s, "MM(?) : %i\n",msg.Buffer[7]);
smprintf(s, "RR(?) : %i\n",msg.Buffer[8]);
call.Status = GSM_CALL_CallRemoteEnd;
call.StatusCode = msg.Buffer[6];
break;
case 0x05:
smprintf(s, "Incoming call\n");
smprintf(s, "Call mode : %i\n",msg.Buffer[5]);//such interpretation is in gnokii
tmp = 6;
NOKIA_GetUnicodeString(s, &tmp, msg.Buffer,buffer,false);
smprintf(s, "Number : \"%s\"\n",DecodeUnicodeString(buffer));
/* FIXME: read name from frame */
call.Status = GSM_CALL_IncomingCall;
tmp = 6;
NOKIA_GetUnicodeString(s, &tmp, msg.Buffer,call.PhoneNumber,false);
break;
case 0x07:
smprintf(s, "Call answer initiated\n");
break;
case 0x09:
smprintf(s, "Call released\n");
call.Status = GSM_CALL_CallLocalEnd;
break;
case 0x0a:
smprintf(s, "Call is being released\n");
break;
case 0x0b:
smprintf(s, "Meaning not known\n");
call.CallIDAvailable = false;
break;
case 0x0c:
smprintf(s, "Audio status\n");
if (msg.Buffer[4] == 0x01) smprintf(s, "Audio enabled\n");
else smprintf(s, "Audio disabled\n");
call.CallIDAvailable = false;
break;
+ case 0x0f:
+ case 0x10:
+ smprintf(s, "Meaning not known\n");
+ call.CallIDAvailable = false;
+ break;
case 0x23:
smprintf(s, "Call held\n");
call.Status = GSM_CALL_CallHeld;
break;
case 0x25:
smprintf(s, "Call resumed\n");
call.Status = GSM_CALL_CallResumed;
break;
case 0x27:
smprintf(s, "Call switched\n");
call.Status = GSM_CALL_CallSwitched;
break;
case 0x53:
smprintf(s, "Outgoing call\n");
smprintf(s, "Call mode : %i\n",msg.Buffer[5]);//such interpretation is in gnokii
tmp = 6;
NOKIA_GetUnicodeString(s, &tmp, msg.Buffer,buffer,false);
smprintf(s, "Number : \"%s\"\n",DecodeUnicodeString(buffer));
/* FIXME: read name from frame */
call.Status = GSM_CALL_OutgoingCall;
tmp = 6;
NOKIA_GetUnicodeString(s, &tmp, msg.Buffer,call.PhoneNumber,false);
break;
+ case 0xA6:
+ case 0xD2:
+ case 0xD3:
+ smprintf(s, "Meaning not known\n");
+ call.CallIDAvailable = false;
+ break;
}
if (call.CallIDAvailable) smprintf(s, "Call ID : %d\n",msg.Buffer[4]);
if (s->Phone.Data.EnableIncomingCall && s->User.IncomingCall!=NULL && call.Status != 0) {
if (call.CallIDAvailable) call.CallID = msg.Buffer[4];
s->User.IncomingCall(s->CurrentConfig->Device, call);
}
+ if (s->Phone.Data.RequestID == ID_DialVoice) {
+ if (msg.Buffer[3] == 0x10) return ERR_NOTSUPPORTED;
+ }
if (s->Phone.Data.RequestID == ID_CancelCall) {
if (msg.Buffer[3] == 0x09) {
if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
/* when we canceled call and see frame about other
* call releasing, we don't give ERR_NONE for "our"
* call release command
*/
return ERR_NEEDANOTHERANSWER;
}
}
if (s->Phone.Data.RequestID == ID_AnswerCall) {
if (msg.Buffer[3] == 0x07) {
if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
return ERR_NEEDANOTHERANSWER;
}
}
return ERR_NONE;
}
void N71_65_GetCalendarRecurrance(GSM_StateMachine *s, unsigned char *buffer, GSM_CalendarEntry *entry)
{
int Recurrance;
Recurrance = buffer[0]*256 + buffer[1];
/* 8760 hours = 1 year */
if (Recurrance == 0xffff) Recurrance=8760;
if (Recurrance != 0) {
smprintf(s, "Recurrance : %i hours\n",Recurrance);
entry->Entries[entry->EntriesNum].EntryType = CAL_RECURRANCE;
entry->Entries[entry->EntriesNum].Number = Recurrance;
entry->EntriesNum++;
}
}
/* method 2 */
GSM_Error N71_65_ReplyAddCalendar2(GSM_Protocol_Message msg, GSM_StateMachine *s)
{
smprintf(s, "Calendar note added\n");
return ERR_NONE;
}
/* method 2 */
GSM_Error N71_65_AddCalendar2(GSM_StateMachine *s, GSM_CalendarEntry *Note)
{
GSM_CalendarNoteType NoteType;
time_t t_time1,t_time2;
GSM_DateTime Date,date_time;
GSM_Error error;
long diff;
int Text, Time, Alarm, Phone, Recurrance, EndTime, Location, length=25;
unsigned char req[5000] = {
N6110_FRAME_HEADER,
0x40,
0x00, /* frame length - 7 */
0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00, /* start time saved as difference */
0x00,0x00,0xff,0xff, /* alarm saved as difference */
0x00, /* frame length - 7 */
0x00, /* note type */
0x00,0x00, /* recurrance */
0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00}; /* rest depends on note type */
NoteType = N71_65_FindCalendarType(Note->Type, s->Phone.Data.ModelInfo);
if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62) ||
IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL65)) {
switch(NoteType) {
case GSM_CAL_MEETING : req[18] = 0x01; length = 25; break;
case GSM_CAL_CALL : req[18] = 0x02; length = 27; break;
case GSM_CAL_BIRTHDAY: req[18] = 0x04; length = 28; break;
case GSM_CAL_MEMO : req[18] = 0x08; length = 25; break;
default : return ERR_UNKNOWN;
}
} else {
switch(NoteType) {
case GSM_CAL_REMINDER: req[18] = 0x01; length = 25; break;
case GSM_CAL_CALL : req[18] = 0x02; length = 27; break;
case GSM_CAL_BIRTHDAY: req[18] = 0x04; length = 28; break;
case GSM_CAL_MEMO : req[18] = 0x08; length = 25; break;
default : return ERR_UNKNOWN;
}
}
GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(Note, &Text, &Time, &Alarm, &Phone, &Recurrance, &EndTime, &Location);
if (Time == -1) return ERR_UNKNOWN;
if (NoteType != GSM_CAL_BIRTHDAY) {
Date.Year = 2030; Date.Month = 01; Date.Day = 01;
Date.Hour = 00; Date.Minute = 00; Date.Second = 00;
} else {
Date.Year = 2029; Date.Month = 12; Date.Day = 31;
Date.Hour = 22; Date.Minute = 59; Date.Second = 58;
}
t_time1 = Fill_Time_T(Date,8);
memcpy(&Date,&Note->Entries[Time].Date,sizeof(GSM_DateTime));
if (NoteType != GSM_CAL_BIRTHDAY) {
Date.Year -= 20;
} else {
Date.Year = 1980;
Date.Hour = 22; Date.Minute = 58; Date.Second = 58;
}
t_time2 = Fill_Time_T(Date,8);
diff = t_time1-t_time2;
smprintf(s, " Difference : %li seconds\n", -diff);
req[9] = (unsigned char)(-diff >> 24);
req[10] = (unsigned char)(-diff >> 16);
req[11] = (unsigned char)(-diff >> 8);
req[12] = (unsigned char)(-diff);
if (NoteType == GSM_CAL_BIRTHDAY) {
req[25] = Note->Entries[Time].Date.Year / 256;
req[26] = Note->Entries[Time].Date.Year % 256;
/* Recurrance = 1 year */
req[19] = 0xff;
req[20] = 0xff;
}
if (NoteType == GSM_CAL_CALL && Phone != -1) {
req[25] = UnicodeLength(Note->Entries[Phone].Text);
CopyUnicodeString(req+length,Note->Entries[Phone].Text);
length += UnicodeLength(Note->Entries[Phone].Text)*2;
}
if (Alarm != -1) {
if (NoteType == GSM_CAL_BIRTHDAY) {
if (Note->Entries[Alarm].EntryType == CAL_SILENT_ALARM_DATETIME) req[27] = 0x01;
error=s->Phone.Functions->GetDateTime(s,&date_time);
switch (error) {
case ERR_EMPTY:
case ERR_NOTIMPLEMENTED:
GSM_GetCurrentDateTime(&date_time);
break;
case ERR_NONE:
break;
default:
return error;
}
Date.Year = date_time.Year;
Date.Hour = 23;
Date.Minute = 59;
} else {
Date.Year += 20;
}
t_time2 = Fill_Time_T(Date,8);
t_time1 = Fill_Time_T(Note->Entries[Alarm].Date,8);
diff = t_time1-t_time2;
/* Sometimes we have difference in minutes */
if (NoteType == GSM_CAL_MEETING) diff = diff / 60;
if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL35)) {
if (NoteType == GSM_CAL_MEMO || NoteType == GSM_CAL_CALL) {
diff = diff / 60;
}
}
smprintf(s, " Difference : %li seconds or minutes\n", -diff);
req[13] = (unsigned char)(-diff >> 24);
req[14] = (unsigned char)(-diff >> 16);
req[15] = (unsigned char)(-diff >> 8);
req[16] = (unsigned char)(-diff);
}
if (Recurrance != -1) {
/* 8760 hours = 1 year */
if (Note->Entries[Recurrance].Number >= 8760) {
req[19] = 0xff;
req[20] = 0xff;
} else {
req[19] = Note->Entries[Recurrance].Number / 256;
req[20] = Note->Entries[Recurrance].Number % 256;
}
}
if (Text != -1) {
switch (NoteType) {
case GSM_CAL_CALL:
req[26] = UnicodeLength(Note->Entries[Text].Text);
break;
default:
req[length++] = UnicodeLength(Note->Entries[Text].Text);
if (NoteType == GSM_CAL_MEMO || NoteType == GSM_CAL_MEETING) req[length++] = 0x00;
}
CopyUnicodeString(req+length,Note->Entries[Text].Text);
length += UnicodeLength(Note->Entries[Text].Text)*2;
}
req[length++] = 0x00;
req[length++] = 0x00;
req[4] = req[17] = length-7;
smprintf(s, "Writing calendar note method 2\n");
diff --git a/gammu/emb/common/phone/obex/obexgen.c b/gammu/emb/common/phone/obex/obexgen.c
index dd14f8e..3106369 100644
--- a/gammu/emb/common/phone/obex/obexgen.c
+++ b/gammu/emb/common/phone/obex/obexgen.c
@@ -585,267 +585,268 @@ static GSM_Error OBEXGEN_GetNextFileFolder(GSM_StateMachine *s, GSM_File *File,
if (size != NULL) {
Priv->Files[Priv->FilesLocationsCurrent+pos2].ModifiedEmpty = false;
ReadVCALDateTime(size+10, &Priv->Files[Priv->FilesLocationsCurrent+pos2].Modified);
}
Priv->FilesLocationsUsed++;
pos2++;
}
}
z = Priv->FilesLocationsCurrent;
if (z != 1) {
while (1) {
if (z == Priv->FilesLocationsUsed) break;
if (Priv->Files[z].Folder) {
if (Priv->Files[z].Level > File->Level) {
smprintf(s,"Changing path down\n");
error=OBEXGEN_ChangePath(s, File->Name, 2);
if (error != ERR_NONE) return error;
}
break;
}
z++;
}
}
Priv->FileLev = File->Level;
free(File->Buffer);
} else {
File->Used = Priv->Files[Priv->FilesLocationsCurrent-1].Used;
File->ModifiedEmpty = Priv->Files[Priv->FilesLocationsCurrent-1].ModifiedEmpty;
if (!File->ModifiedEmpty) {
memcpy(&File->Modified,&Priv->Files[Priv->FilesLocationsCurrent-1].Modified,sizeof(GSM_DateTime));
}
File->ReadOnly = false;
File->Protected = false;
File->Hidden = false;
File->System = false;
}
return ERR_NONE;
}
}
static GSM_Error OBEXGEN_DeleteFile(GSM_StateMachine *s, unsigned char *ID)
{
GSM_Error error;
unsigned int Current = 0, Pos;
unsigned char req[200],req2[200];
if (!strcmp(s->CurrentConfig->Model,"seobex")) return ERR_NOTSUPPORTED;
error = OBEXGEN_Connect(s,OBEX_BrowsingFolders);
if (error != ERR_NONE) return error;
smprintf(s,"Changing to root\n");
error = OBEXGEN_ChangePath(s, NULL, 2);
if (error != ERR_NONE) return error;
Pos = 0;
do {
OBEXGEN_FindNextDir(ID, &Pos, req2);
smprintf(s,"%s %i %i\n",DecodeUnicodeString(req2),Pos,strlen(ID));
if (Pos == strlen(ID)) break;
smprintf(s,"Changing path down\n");
error=OBEXGEN_ChangePath(s, req2, 2);
if (error != ERR_NONE) return error;
} while (1);
/* Name block */
OBEXAddBlock(req, &Current, 0x01, req2, UnicodeLength(req2)*2+2);
/* connection ID block */
req[Current++] = 0xCB; // ID
req[Current++] = 0x00; req[Current++] = 0x00;
req[Current++] = 0x00; req[Current++] = 0x01;
return GSM_WaitFor (s, req, Current, 0x82, 4, ID_AddFile);
}
static GSM_Error OBEXGEN_AddFolder(GSM_StateMachine *s, GSM_File *File)
{
GSM_Error error;
unsigned char req2[200];
unsigned int Pos;
if (!strcmp(s->CurrentConfig->Model,"seobex")) return ERR_NOTSUPPORTED;
error = OBEXGEN_Connect(s,OBEX_BrowsingFolders);
if (error != ERR_NONE) return error;
smprintf(s,"Changing to root\n");
error = OBEXGEN_ChangePath(s, NULL, 2);
if (error != ERR_NONE) return error;
Pos = 0;
do {
OBEXGEN_FindNextDir(File->ID_FullName, &Pos, req2);
smprintf(s,"%s %i %i\n",DecodeUnicodeString(req2),Pos,strlen(File->ID_FullName));
smprintf(s,"Changing path down\n");
error=OBEXGEN_ChangePath(s, req2, 2);
if (error != ERR_NONE) return error;
if (Pos == strlen(File->ID_FullName)) break;
} while (1);
smprintf(s,"Adding directory\n");
return OBEXGEN_ChangePath(s, File->Name, 0);
}
GSM_Reply_Function OBEXGENReplyFunctions[] = {
/* CONTINUE block */
{OBEXGEN_ReplyAddFilePart, "\x90",0x00,0x00,ID_AddFile },
{OBEXGEN_ReplyGetFilePart, "\x90",0x00,0x00,ID_GetFile },
{OBEXGEN_ReplyGetFileInfo, "\x90",0x00,0x00,ID_GetFileInfo },
/* OK block */
{OBEXGEN_ReplyChangePath, "\xA0",0x00,0x00,ID_SetPath },
{OBEXGEN_ReplyConnect, "\xA0",0x00,0x00,ID_Initialise },
{OBEXGEN_ReplyAddFilePart, "\xA0",0x00,0x00,ID_AddFile },
{OBEXGEN_ReplyGetFilePart, "\xA0",0x00,0x00,ID_GetFile },
{OBEXGEN_ReplyGetFileInfo, "\xA0",0x00,0x00,ID_GetFileInfo },
/* FOLDER CREATED block */
{OBEXGEN_ReplyChangePath, "\xA1",0x00,0x00,ID_SetPath },
/* NOT UNDERSTAND block */
{OBEXGEN_ReplyAddFilePart, "\xC0",0x00,0x00,ID_AddFile },
/* FORBIDDEN block */
{OBEXGEN_ReplyChangePath, "\xC3",0x00,0x00,ID_SetPath },
{OBEXGEN_ReplyGetFilePart, "\xC3",0x00,0x00,ID_GetFile },
/* NOT FOUND block */
{OBEXGEN_ReplyGetFilePart, "\xC4",0x00,0x00,ID_GetFile },
{NULL, "\x00",0x00,0x00,ID_None }
};
GSM_Phone_Functions OBEXGENPhone = {
"obex|seobex",
OBEXGENReplyFunctions,
OBEXGEN_Initialise,
NONEFUNCTION, /* Terminate */
GSM_DispatchMessage,
NOTIMPLEMENTED, /* ShowStartInfo */
NONEFUNCTION, /* GetManufacturer */
NONEFUNCTION, /* GetModel */
NONEFUNCTION, /* GetFirmware */
NOTIMPLEMENTED, /* GetIMEI */
NOTIMPLEMENTED, /* GetOriginalIMEI */
NOTIMPLEMENTED, /* GetManufactureMonth */
NOTIMPLEMENTED, /* GetProductCode */
NOTIMPLEMENTED, /* GetHardware */
NOTIMPLEMENTED, /* GetPPM */
NOTIMPLEMENTED, /* GetSIMIMSI */
NOTIMPLEMENTED, /* GetDateTime */
NOTIMPLEMENTED, /* SetDateTime */
NOTIMPLEMENTED, /* GetAlarm */
NOTIMPLEMENTED, /* SetAlarm */
NOTSUPPORTED, /* GetLocale */
NOTSUPPORTED, /* SetLocale */
NOTIMPLEMENTED, /* PressKey */
NOTIMPLEMENTED, /* Reset */
NOTIMPLEMENTED, /* ResetPhoneSettings */
NOTIMPLEMENTED, /* EnterSecurityCode */
NOTIMPLEMENTED, /* GetSecurityStatus */
NOTIMPLEMENTED, /* GetDisplayStatus */
NOTIMPLEMENTED, /* SetAutoNetworkLogin */
NOTIMPLEMENTED, /* GetBatteryCharge */
NOTIMPLEMENTED, /* GetSignalQuality */
NOTIMPLEMENTED, /* GetNetworkInfo */
NOTIMPLEMENTED, /* GetCategory */
NOTSUPPORTED, /* AddCategory */
NOTIMPLEMENTED, /* GetCategoryStatus */
NOTIMPLEMENTED, /* GetMemoryStatus */
NOTIMPLEMENTED, /* GetMemory */
NOTIMPLEMENTED, /* GetNextMemory */
NOTIMPLEMENTED, /* SetMemory */
NOTIMPLEMENTED, /* AddMemory */
NOTIMPLEMENTED, /* DeleteMemory */
NOTIMPLEMENTED, /* DeleteAllMemory */
NOTIMPLEMENTED, /* GetSpeedDial */
NOTIMPLEMENTED, /* SetSpeedDial */
NOTIMPLEMENTED, /* GetSMSC */
NOTIMPLEMENTED, /* SetSMSC */
NOTIMPLEMENTED, /* GetSMSStatus */
NOTIMPLEMENTED, /* GetSMS */
NOTIMPLEMENTED, /* GetNextSMS */
NOTIMPLEMENTED, /* SetSMS */
NOTIMPLEMENTED, /* AddSMS */
NOTIMPLEMENTED, /* DeleteSMS */
NOTIMPLEMENTED, /* SendSMSMessage */
NOTSUPPORTED, /* SendSavedSMS */
+ NOTSUPPORTED, /* SetFastSMSSending */
NOTIMPLEMENTED, /* SetIncomingSMS */
NOTIMPLEMENTED, /* SetIncomingCB */
NOTIMPLEMENTED, /* GetSMSFolders */
NOTIMPLEMENTED, /* AddSMSFolder */
NOTIMPLEMENTED, /* DeleteSMSFolder */
NOTIMPLEMENTED, /* DialVoice */
NOTIMPLEMENTED, /* AnswerCall */
NOTIMPLEMENTED, /* CancelCall */
NOTIMPLEMENTED, /* HoldCall */
NOTIMPLEMENTED, /* UnholdCall */
NOTIMPLEMENTED, /* ConferenceCall */
NOTIMPLEMENTED, /* SplitCall */
NOTIMPLEMENTED, /* TransferCall */
NOTIMPLEMENTED, /* SwitchCall */
NOTIMPLEMENTED, /* GetCallDivert */
NOTIMPLEMENTED, /* SetCallDivert */
NOTIMPLEMENTED, /* CancelAllDiverts */
NOTIMPLEMENTED, /* SetIncomingCall */
NOTIMPLEMENTED, /* SetIncomingUSSD */
NOTIMPLEMENTED, /* SendDTMF */
NOTIMPLEMENTED, /* GetRingtone */
NOTIMPLEMENTED, /* SetRingtone */
NOTIMPLEMENTED, /* GetRingtonesInfo */
NOTIMPLEMENTED, /* DeleteUserRingtones */
NOTIMPLEMENTED, /* PlayTone */
NOTIMPLEMENTED, /* GetWAPBookmark */
NOTIMPLEMENTED, /* SetWAPBookmark */
NOTIMPLEMENTED, /* DeleteWAPBookmark */
NOTIMPLEMENTED, /* GetWAPSettings */
NOTIMPLEMENTED, /* SetWAPSettings */
NOTIMPLEMENTED, /* GetMMSSettings */
NOTIMPLEMENTED, /* SetMMSSettings */
NOTSUPPORTED, /* GetSyncMLSettings */
NOTSUPPORTED, /* SetSyncMLSettings */
NOTSUPPORTED, /* GetChatSettings */
NOTSUPPORTED, /* SetChatSettings */
NOTIMPLEMENTED, /* GetBitmap */
NOTIMPLEMENTED, /* SetBitmap */
NOTIMPLEMENTED, /* GetToDoStatus */
NOTIMPLEMENTED, /* GetToDo */
NOTIMPLEMENTED, /* GetNextToDo */
NOTIMPLEMENTED, /* SetToDo */
NOTIMPLEMENTED, /* AddToDo */
NOTIMPLEMENTED, /* DeleteToDo */
NOTIMPLEMENTED, /* DeleteAllToDo */
NOTIMPLEMENTED, /* GetCalendarStatus */
NOTIMPLEMENTED, /* GetCalendar */
NOTIMPLEMENTED, /* GetNextCalendar */
NOTIMPLEMENTED, /* SetCalendar */
NOTIMPLEMENTED, /* AddCalendar */
NOTIMPLEMENTED, /* DeleteCalendar */
NOTIMPLEMENTED, /* DeleteAllCalendar */
NOTSUPPORTED, /* GetCalendarSettings */
NOTSUPPORTED, /* SetCalendarSettings */
- NOTSUPPORTED, /* GetNote */
+ NOTSUPPORTED, /* GetNextNote */
NOTIMPLEMENTED, /* GetProfile */
NOTIMPLEMENTED, /* SetProfile */
NOTIMPLEMENTED, /* GetFMStation */
NOTIMPLEMENTED, /* SetFMStation */
NOTIMPLEMENTED, /* ClearFMStations */
OBEXGEN_GetNextFileFolder,
OBEXGEN_GetFilePart,
OBEXGEN_AddFilePart,
NOTIMPLEMENTED, /* GetFileSystemStatus */
OBEXGEN_DeleteFile,
OBEXGEN_AddFolder,
NOTIMPLEMENTED, /* GetGPRSAccessPoint */
NOTIMPLEMENTED /* SetGPRSAccessPoint */
};
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/obex/obexgen.h b/gammu/emb/common/phone/obex/obexgen.h
index 466fef5..b7033de 100644
--- a/gammu/emb/common/phone/obex/obexgen.h
+++ b/gammu/emb/common/phone/obex/obexgen.h
@@ -1,38 +1,42 @@
/* (c) 2003 by Marcin Wiacek */
#ifndef obexgen_h
#define obexgen_h
#include "../../gsmcomon.h"
#include "../../gsmstate.h"
#include "../../service/gsmmisc.h"
#include "../../service/sms/gsmsms.h"
#ifndef GSM_USED_IRDAOBEX
# define GSM_USED_IRDAOBEX
#endif
#ifndef GSM_USED_BLUEOBEX
# define GSM_USED_BLUEOBEX
#endif
typedef enum {
OBEX_None = 1,
OBEX_BrowsingFolders
} OBEX_Service;
typedef struct {
int FileLev;
int FilesLocationsUsed;
int FilesLocationsCurrent;
GSM_File Files[500];
bool FileLastPart;
int FrameSize;
OBEX_Service Service;
} GSM_Phone_OBEXGENData;
+GSM_Error OBEXGEN_GetFilePart (GSM_StateMachine *s, GSM_File *File);
+GSM_Error OBEXGEN_AddFilePart (GSM_StateMachine *s, GSM_File *File, int *Pos);
+GSM_Error OBEXGEN_Disconnect (GSM_StateMachine *s);
+
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/phone/symbian/mroutgen.c b/gammu/emb/common/phone/symbian/mroutgen.c
index 2c339be..a7382cf 100644
--- a/gammu/emb/common/phone/symbian/mroutgen.c
+++ b/gammu/emb/common/phone/symbian/mroutgen.c
@@ -1,220 +1,221 @@
/* (c) 2003 by Marcin Wiacek */
/* EXPERIMENTAL. NOT FUNCTIONAL */
#include <string.h>
#include <time.h>
#include "../../gsmcomon.h"
#include "../../gsmstate.h"
#include "../../misc/coding/coding.h"
#include "../../service/gsmmisc.h"
#ifdef GSM_ENABLE_MROUTERGEN
GSM_Error MROUTERGEN_StartModem(GSM_StateMachine *s)
{
return ERR_NONE;
}
GSM_Error MROUTERGEN_Initialise(GSM_StateMachine *s)
{
unsigned char req2[]={0xFF,0x03,0x80,0xFD,0x04,0x01,0x00,0x09,0x11,
0x05,0x00,0x01,0x03,0x77,0xBC};
unsigned char req0[]={
0xFF,0x7D,0x23,0xC0,0x21,0x7D,0x21,0x7D,0x24,0x7D,
0x20,0x7D,0x2E,0x7D,0x22,0x7D,0x26,0x7D,0x20,0x7D,
0x20,0x7D,0x20,0x7D,0x20,0x7D,0x27,0x7D,0x22,0x7D,
0x28,0x7D,0x22,0x69,0x27,
0x7E,
0x7E,
0xFF,0x7D,0x23,0xC0,0x21,0x7D,0x22,0x7D,0x21,0x7D,
0x20,0x7D,0x34,0x7D,0x25,0x7D,0x26,0x87,0xB9,0x7D,
0x28,0xCF,0x7D,0x22,0x7D,0x26,0x7D,0x20,0x7D,0x20,
0x7D,0x20,0x7D,0x20,0x7D,0x27,0x7D,0x22,0x7D,0x28,
0x7D,0x22,0x82,0xB0,
0x7E,
0x7E,
0xFF,0x7D,0x23,0xC0,0x21,0x7D,0x21,0x7D,0x24,0x7D,
0x20,0x7D,0x2E,0x7D,0x22,0x7D,0x26,0x7D,0x20,0x7D,
0x20,0x7D,0x20,0x7D,0x20,0x7D,0x27,0x7D,0x22,0x7D,
0x28,0x7D,0x22,0x69,0x27,
0x7E,
0x7E,
0xFF,0x7D,0x23,0xC0,0x21,0x7D,0x22,0x7D,0x21,0x7D,
0x20,0x7D,0x34,0x7D,0x25,0x7D,0x26,0x87,0xB9,0x7D,
0x28,0xCF,0x7D,0x22,0x7D,0x26,0x7D,0x20,0x7D,0x20,
0x7D,0x20,0x7D,0x20,0x7D,0x27,0x7D,0x22,0x7D,0x28,
0x7D,0x22,0x82,0xB0};
unsigned char req[]={0x2F,0x45,0x00,0x00,0x34,0x00,0xC6,
0x00,0x00,0x0A,0x0D,0x59,0xB4,0xA9,0xFE,0x01,
0x44,0xA9,0xFE,0x01,0x0A,0x04,0x09,0x0B,0xB8,
0x10,0x00,0x02,0x79,0x69,0x81,0x74,0x99,0x50,
0x18,0x60,0x00,0x9D,0x0C,0x00,0x00,0x08,0x00,
0x00,0x00,0x12,0x00,0x41,0x00,0x01,0x14,0x00,
0x00,0xBA,0x4A};
unsigned char req3[]={0x2D,0x5C,0x0D,0xEC,0x4C,0x10,0x26,0x08,0x00,
0x00,0x00,0x12,0x00,0x15,0x00,0x01,0x08,0x00,0x00,
0xAD,0xDE};
smprintf(s,"writing\n");
GSM_WaitFor (s, req0, 164, 0x00, 200, ID_Initialise);
smprintf(s,"writing\n");
GSM_WaitFor (s, req3, 21, 0x00, 200, ID_Initialise);
GSM_WaitFor (s, req, 55, 0x00, 200, ID_Initialise);
GSM_WaitFor (s, req2, 15, 0x00, 200, ID_Initialise);
while (1) {
GSM_ReadDevice(s,false);
}
while (1) {
GSM_ReadDevice(s,false);
}
return ERR_UNKNOWN;
}
static GSM_Reply_Function MROUTERGENReplyFunctions[] = {
{NULL, "\x00",0x00,0x00,ID_None }
};
GSM_Phone_Functions MROUTERGENPhone = {
"mrouter",
MROUTERGENReplyFunctions,
MROUTERGEN_Initialise,
NONEFUNCTION, /* Terminate */
GSM_DispatchMessage,
NOTSUPPORTED, /* ShowStartInfo */
NONEFUNCTION, /* GetManufacturer */
NONEFUNCTION, /* GetModel */
NONEFUNCTION, /* GetFirmware */
NOTIMPLEMENTED, /* GetIMEI */
NOTSUPPORTED, /* GetOriginalIMEI */
NOTSUPPORTED, /* GetManufactureMonth */
NOTSUPPORTED, /* GetProductCode */
NOTSUPPORTED, /* GetHardware */
NOTSUPPORTED, /* GetPPM */
NOTSUPPORTED, /* GetSIMIMSI */
NOTSUPPORTED, /* GetDateTime */
NOTSUPPORTED, /* SetDateTime */
NOTSUPPORTED, /* GetAlarm */
NOTSUPPORTED, /* SetAlarm */
NOTSUPPORTED, /* GetLocale */
NOTSUPPORTED, /* SetLocale */
NOTSUPPORTED, /* PressKey */
NOTSUPPORTED, /* Reset */
NOTSUPPORTED, /* ResetPhoneSettings */
NOTSUPPORTED, /* EnterSecurityCode */
NOTSUPPORTED, /* GetSecurityStatus */
NOTSUPPORTED, /* GetDisplayStatus */
NOTSUPPORTED, /* SetAutoNetworkLogin */
NOTSUPPORTED, /* GetBatteryCharge */
NOTSUPPORTED, /* GetSignalQuality */
NOTSUPPORTED, /* GetNetworkInfo */
NOTSUPPORTED, /* GetCategory */
NOTSUPPORTED, /* GetCategoryStatus */
NOTSUPPORTED, /* GetMemoryStatus */
NOTSUPPORTED, /* GetMemory */
NOTSUPPORTED, /* GetNextMemory */
NOTSUPPORTED, /* SetMemory */
NOTSUPPORTED, /* AddMemory */
NOTSUPPORTED, /* DeleteMemory */
NOTIMPLEMENTED, /* DeleteAllMemory */
NOTSUPPORTED, /* GetSpeedDial */
NOTSUPPORTED, /* SetSpeedDial */
NOTSUPPORTED, /* GetSMSC */
NOTSUPPORTED, /* SetSMSC */
NOTSUPPORTED, /* GetSMSStatus */
NOTSUPPORTED, /* GetSMS */
NOTSUPPORTED, /* GetNextSMS */
NOTSUPPORTED, /* SetSMS */
NOTSUPPORTED, /* AddSMS */
NOTSUPPORTED, /* DeleteSMS */
NOTSUPPORTED, /* SendSMSMessage */
NOTSUPPORTED, /* SendSavedSMS */
+ NOTSUPPORTED, /* SetFastSMSSending */
NOTSUPPORTED, /* SetIncomingSMS */
NOTSUPPORTED, /* SetIncomingCB */
NOTSUPPORTED, /* GetSMSFolders */
NOTSUPPORTED, /* AddSMSFolder */
NOTSUPPORTED, /* DeleteSMSFolder */
NOTSUPPORTED, /* DialVoice */
NOTSUPPORTED, /* AnswerCall */
NOTSUPPORTED, /* CancelCall */
NOTSUPPORTED, /* HoldCall */
NOTSUPPORTED, /* UnholdCall */
NOTSUPPORTED, /* ConferenceCall */
NOTSUPPORTED, /* SplitCall */
NOTSUPPORTED, /* TransferCall */
NOTSUPPORTED, /* SwitchCall */
NOTSUPPORTED, /* GetCallDivert */
NOTSUPPORTED, /* SetCallDivert */
NOTSUPPORTED, /* CancelAllDiverts */
NOTSUPPORTED, /* SetIncomingCall */
NOTSUPPORTED, /* SetIncomingUSSD */
NOTSUPPORTED, /* SendDTMF */
NOTSUPPORTED, /* GetRingtone */
NOTSUPPORTED, /* SetRingtone */
NOTSUPPORTED, /* GetRingtonesInfo */
NOTSUPPORTED, /* DeleteUserRingtones */
NOTSUPPORTED, /* PlayTone */
NOTSUPPORTED, /* GetWAPBookmark */
NOTSUPPORTED, /* SetWAPBookmark */
NOTSUPPORTED, /* DeleteWAPBookmark */
NOTSUPPORTED, /* GetWAPSettings */
NOTSUPPORTED, /* SetWAPSettings */
NOTSUPPORTED, /* GetMMSSettings */
NOTSUPPORTED, /* SetMMSSettings */
NOTSUPPORTED, /* GetSyncMLSettings */
NOTSUPPORTED, /* SetSyncMLSettings */
NOTSUPPORTED, /* GetChatSettings */
NOTSUPPORTED, /* SetChatSettings */
NOTSUPPORTED, /* GetBitmap */
NOTSUPPORTED, /* SetBitmap */
NOTSUPPORTED, /* GetToDoStatus */
NOTSUPPORTED, /* GetToDo */
NOTSUPPORTED, /* GetNextToDo */
NOTSUPPORTED, /* SetToDo */
NOTSUPPORTED, /* AddToDo */
NOTSUPPORTED, /* DeleteToDo */
NOTSUPPORTED, /* DeleteAllToDo */
NOTSUPPORTED, /* GetCalendarStatus */
NOTSUPPORTED, /* GetCalendar */
NOTSUPPORTED, /* GetNextCalendar */
NOTSUPPORTED, /* SetCalendar */
NOTSUPPORTED, /* AddCalendar */
NOTSUPPORTED, /* DeleteCalendar */
NOTSUPPORTED, /* DeleteAllCalendar */
NOTSUPPORTED, /* GetCalendarSettings */
NOTSUPPORTED, /* SetCalendarSettings */
- NOTSUPPORTED, /* GetNote */
+ NOTSUPPORTED, /* GetNextNote */
NOTSUPPORTED, /* GetProfile */
NOTSUPPORTED, /* SetProfile */
NOTSUPPORTED, /* GetFMStation */
NOTSUPPORTED, /* SetFMStation */
NOTSUPPORTED, /* ClearFMStations */
NOTSUPPORTED, /* GetNextFileFolder */
NOTSUPPORTED, /* GetFilePart */
NOTSUPPORTED, /* AddFilePart */
NOTSUPPORTED, /* GetFileSystemStatus */
NOTSUPPORTED, /* DeleteFile */
NOTSUPPORTED, /* AddFolder */
NOTSUPPORTED, /* GetGPRSAccessPoint */
NOTSUPPORTED /* SetGPRSAccessPoint */
};
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/protocol/at/at.c b/gammu/emb/common/protocol/at/at.c
index f4a75b7..f8ddc06 100644
--- a/gammu/emb/common/protocol/at/at.c
+++ b/gammu/emb/common/protocol/at/at.c
@@ -1,229 +1,233 @@
/* (c) 2002-2004 by Marcin Wiacek and Michal Cihar */
#include "../../gsmstate.h"
#if defined(GSM_ENABLE_AT) || defined(GSM_ENABLE_BLUEAT) || defined(GSM_ENABLE_IRDAAT)
#include <stdio.h>
#include <string.h>
#include "../../gsmcomon.h"
#include "at.h"
static GSM_Error AT_WriteMessage (GSM_StateMachine *s, unsigned char *buffer,
int length, unsigned char type)
{
int i,sent = 0;
GSM_DumpMessageLevel2(s, buffer, length, type);
GSM_DumpMessageLevel3(s, buffer, length, type);
if (s->Protocol.Data.AT.FastWrite) {
while (sent != length) {
if ((i = s->Device.Functions->WriteDevice(s,buffer + sent, length - sent)) == 0) {
return ERR_DEVICEWRITEERROR;
}
sent += i;
}
} else {
for (i=0;i<length;i++) {
if (s->Device.Functions->WriteDevice(s,buffer+i,1)!=1) return ERR_DEVICEWRITEERROR;
/* For some phones like Siemens M20 we need to wait a little
* after writing each char. Possible reason: these phones
* can't receive so fast chars or there is bug here in Gammu */
my_sleep(1);
}
my_sleep(400);
}
return ERR_NONE;
}
typedef struct {
char *text;
int lines;
} SpecialAnswersStruct;
static GSM_Error AT_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
{
GSM_Protocol_Message Msg2;
GSM_Protocol_ATData *d = &s->Protocol.Data.AT;
int i;
/* These are lines with end of "normal" answers */
static char *StartStrings[] = {
"OK" , "ERROR" ,
"+CME ERROR:" , "+CMS ERROR:" ,
"+CPIN: " , /*A2D issue*/
NULL};
/* Some info from phone can be inside "normal" answers
* It starts with strings written here
*/
static SpecialAnswersStruct SpecialAnswers[] = {
{"_OSIGQ:" ,1}, {"_OBS:" ,1},
{"^SCN:" ,1}, {"+CGREG:" ,1},
{"+CBM:" ,1}, {"+CMT:" ,2},
{"+CMTI:" ,1}, {"+CDS:" ,2},
- {"+CREG:" ,1},
+ {"+CREG:" ,1}, {"+CUSD" ,1},
{"RING" ,1}, {"NO CARRIER" ,1},
{"NO ANSWER" ,1}, {"+COLP" ,1},
{"+CLIP" ,1},
+ {"SDNDCRC =" ,1}, /* Samsung binary transfer end */
+
{NULL ,1}};
+//printf("%c",rx_char);
+
/* Ignore leading CR, LF and ESC */
if (d->Msg.Length == 0) {
if (rx_char == 10 || rx_char == 13 || rx_char == 27) return ERR_NONE;
d->LineStart = d->Msg.Length;
}
if (d->Msg.BufferUsed < d->Msg.Length + 2) {
d->Msg.BufferUsed = d->Msg.Length + 2;
d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed);
}
d->Msg.Buffer[d->Msg.Length++] = rx_char;
d->Msg.Buffer[d->Msg.Length ] = 0;
switch (rx_char) {
case 0:
break;
case 10:
case 13:
if (!d->wascrlf) d->LineEnd = d->Msg.Length-1;
d->wascrlf = true;
if (d->Msg.Length > 0 && rx_char == 10 && d->Msg.Buffer[d->Msg.Length-2]==13) {
i = 0;
while (StartStrings[i] != NULL) {
if (strncmp(StartStrings[i],d->Msg.Buffer+d->LineStart,strlen(StartStrings[i])) == 0) {
s->Phone.Data.RequestMsg = &d->Msg;
s->Phone.Data.DispatchError = s->Phone.Functions->DispatchMessage(s);
d->Msg.Length = 0;
break;
}
i++;
}
if (d->Msg.Length == 0) break;
i = 0;
while (SpecialAnswers[i].text != NULL) {
if (strncmp(SpecialAnswers[i].text,d->Msg.Buffer+d->LineStart,strlen(SpecialAnswers[i].text)) == 0) {
/* We need something better here */
if (s->Phone.Data.RequestID == ID_GetNetworkInfo && strncmp(SpecialAnswers[i].text,"+CREG:",6) == 0) {
i++;
continue;
}
d->SpecialAnswerStart = d->LineStart;
d->SpecialAnswerLines = SpecialAnswers[i].lines;
}
i++;
}
if (d->SpecialAnswerLines == 1) {
/* This is end of special answer. We copy it and send to phone module */
Msg2.Buffer = malloc(d->LineEnd - d->SpecialAnswerStart + 3);
memcpy(Msg2.Buffer,d->Msg.Buffer+d->SpecialAnswerStart,d->LineEnd - d->SpecialAnswerStart + 2);
Msg2.Length = d->LineEnd - d->SpecialAnswerStart + 2;
Msg2.Buffer[Msg2.Length] = 0;
s->Phone.Data.RequestMsg = &Msg2;
s->Phone.Data.DispatchError = s->Phone.Functions->DispatchMessage(s);
free(Msg2.Buffer);
/* We cut special answer from main buffer */
d->Msg.Length = d->SpecialAnswerStart;
if (d->Msg.Length != 0) d->Msg.Length = d->Msg.Length - 2;
/* We need to find earlier values of all variables */
d->wascrlf = false;
d->LineStart = 0;
for (i=0;i<d->Msg.Length;i++) {
switch(d->Msg.Buffer[i]) {
case 0:
break;
case 10:
case 13:
if (!d->wascrlf) d->LineEnd = d->Msg.Length-1;
d->wascrlf = true;
break;
default:
if (d->wascrlf) {
d->LineStart = d->Msg.Length-1;
d->wascrlf = false;
}
}
}
d->Msg.Buffer[d->Msg.Length] = 0;
}
if (d->SpecialAnswerLines > 0) d->SpecialAnswerLines--;
}
break;
case 'T':
/* When CONNECT string received, we know there will not follow
* anything AT related, after CONNECT can follow ppp data, alcabus
* data and also other things.
*/
if (strncmp(d->Msg.Buffer+d->LineStart, "CONNECT", 7) == 0) {
s->Phone.Data.RequestMsg = &d->Msg;
s->Phone.Data.DispatchError = s->Phone.Functions->DispatchMessage(s);
d->LineStart = -1;
d->Msg.Length = 0;
break;
}
default:
if (d->wascrlf) {
d->LineStart = d->Msg.Length-1;
d->wascrlf = false;
}
if (d->EditMode) {
if (strlen(d->Msg.Buffer+d->LineStart) == 2 && strncmp(d->Msg.Buffer+d->LineStart,"> ",2)==0) {
s->Phone.Data.RequestMsg = &d->Msg;
s->Phone.Data.DispatchError = s->Phone.Functions->DispatchMessage(s);
}
}
}
return ERR_NONE;
}
static GSM_Error AT_Initialise(GSM_StateMachine *s)
{
GSM_Protocol_ATData *d = &s->Protocol.Data.AT;
d->Msg.Buffer = NULL;
d->Msg.BufferUsed = 0;
d->Msg.Length = 0;
d->Msg.Type = 0;
d->SpecialAnswerLines = 0;
d->LineStart = -1;
d->LineEnd = -1;
d->wascrlf = false;
d->EditMode = false;
d->FastWrite = false;
s->Device.Functions->DeviceSetDtrRts(s,true,true);
return s->Device.Functions->DeviceSetSpeed(s,s->Speed);
}
static GSM_Error AT_Terminate(GSM_StateMachine *s)
{
free(s->Protocol.Data.AT.Msg.Buffer);
return ERR_NONE;
}
GSM_Protocol_Functions ATProtocol = {
AT_WriteMessage,
AT_StateMachine,
AT_Initialise,
AT_Terminate
};
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/protocol/nokia/fbus2.c b/gammu/emb/common/protocol/nokia/fbus2.c
index 8b3e024..2b41f8b 100644
--- a/gammu/emb/common/protocol/nokia/fbus2.c
+++ b/gammu/emb/common/protocol/nokia/fbus2.c
@@ -1,194 +1,198 @@
/* (c) 2002-2003 by Marcin Wiacek */
-/* based on some work from Gnokii and MyGnokii */
+/* based on some work from MyGnokii (www.mwiacek.com) */
+/* Based on some work from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
#include "../../gsmstate.h"
#if defined(GSM_ENABLE_FBUS2) || defined(GSM_ENABLE_FBUS2IRDA) || defined(GSM_ENABLE_FBUS2DLR3) || defined(GSM_ENABLE_FBUS2BLUE) || defined(GSM_ENABLE_BLUEFBUS2) || defined(GSM_ENABLE_FBUS2DKU5) || defined(GSM_ENABLE_FBUS2PL2303)
#include <stdio.h>
#include <string.h>
#include "../../gsmcomon.h"
#include "fbus2.h"
static GSM_Error FBUS2_WriteFrame(GSM_StateMachine *s,
unsigned char *MsgBuffer,
int MsgLength,
unsigned char MsgType)
{
unsigned char buffer2[FBUS2_MAX_TRANSMIT_LENGTH + 10];
unsigned char checksum=0;
int i, len, sent;
buffer2[0] = FBUS2_FRAME_ID;
if (s->ConnectionType==GCT_FBUS2IRDA) buffer2[0] = FBUS2_IRDA_FRAME_ID;
buffer2[1] = FBUS2_DEVICE_PHONE; //destination
buffer2[2] = FBUS2_DEVICE_PC; //source
buffer2[3] = MsgType;
buffer2[4] = MsgLength / 256;
buffer2[5] = MsgLength % 256;
memcpy(buffer2 + 6, MsgBuffer, MsgLength);
len = MsgLength + 6;
/* Odd messages require additional 0x00 byte */
if (MsgLength % 2) buffer2[len++] = 0x00;
checksum = 0;
for (i = 0; i < len; i+=2) checksum ^= buffer2[i];
buffer2[len++] = checksum;
checksum = 0;
for (i = 1; i < len; i+=2) checksum ^= buffer2[i];
buffer2[len++] = checksum;
/* Sending to phone */
sent=s->Device.Functions->WriteDevice(s,buffer2,len);
if (sent!=len) return ERR_DEVICEWRITEERROR;
return ERR_NONE;
}
static GSM_Error FBUS2_WriteMessage (GSM_StateMachine *s,
unsigned char *MsgBuffer,
int MsgLength,
unsigned char MsgType)
{
int i, nom, togo, thislength; /* number of messages, ... */
unsigned char buffer2[FBUS2_MAX_TRANSMIT_LENGTH + 2], seqnum;
GSM_Protocol_FBUS2Data *d = &s->Protocol.Data.FBUS2;
GSM_Error error;
GSM_DumpMessageLevel3(s, MsgBuffer, MsgLength, MsgType);
nom = (MsgLength + FBUS2_MAX_TRANSMIT_LENGTH - 1) / FBUS2_MAX_TRANSMIT_LENGTH;
togo = MsgLength;
for (i = 0; i < nom; i++) {
seqnum = d->MsgSequenceNumber;
if (i==0) seqnum = seqnum + 0x40;
d->MsgSequenceNumber = (d->MsgSequenceNumber + 1) & 0x07;
thislength = togo;
if (togo > FBUS2_MAX_TRANSMIT_LENGTH) thislength = FBUS2_MAX_TRANSMIT_LENGTH;
memcpy(buffer2, MsgBuffer + (MsgLength - togo), thislength);
buffer2[thislength] = nom - i;
buffer2[thislength + 1] = seqnum;
togo = togo - thislength;
GSM_DumpMessageLevel2(s, buffer2, thislength, MsgType);
error=FBUS2_WriteFrame(s, buffer2, thislength + 2, MsgType);
if (error!=ERR_NONE) return error;
}
return ERR_NONE;
}
static GSM_Error FBUS2_SendAck(GSM_StateMachine *s,
unsigned char MsgType,
unsigned char MsgSequence)
{
unsigned char buffer2[2];
buffer2[0] = MsgType;
buffer2[1] = MsgSequence;
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
smprintf(s,"[Sending Ack of type %02x, seq %x]\n",buffer2[0],buffer2[1]);
}
/* Sending to phone */
return FBUS2_WriteFrame(s, buffer2, 2, FBUS2_ACK_BYTE);
}
static GSM_Error FBUS2_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
{
GSM_Protocol_FBUS2Data *d = &s->Protocol.Data.FBUS2;
unsigned char frm_num, seq_num;
bool correct = false;
/* XOR the byte with the earlier checksum */
d->Msg.CheckSum[d->Msg.Count & 1] ^= rx_char;
if (d->MsgRXState == RX_GetMessage) {
d->Msg.Buffer[d->Msg.Count] = rx_char;
d->Msg.Count++;
/* This is not last byte in frame */
if (d->Msg.Count != d->Msg.Length+(d->Msg.Length%2)+2) return ERR_NONE;
/* Checksum is incorrect */
if (d->Msg.CheckSum[0] != d->Msg.CheckSum[1]) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
smprintf(s,"[ERROR: checksum]\n");
}
free(d->Msg.Buffer);
d->Msg.Length = 0;
d->Msg.Buffer = NULL;
d->MsgRXState = RX_Sync;
return ERR_NONE;
}
seq_num = d->Msg.Buffer[d->Msg.Length-1];
if (d->Msg.Type == FBUS2_ACK_BYTE) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
smprintf(s, "[Received Ack of type %02x, seq %02x]\n",d->Msg.Buffer[0],seq_num);
}
d->MsgRXState = RX_Sync;
return ERR_NONE;
}
frm_num = d->Msg.Buffer[d->Msg.Length-2];
if ((seq_num & 0x40) == 0x40) {
d->FramesToGo = frm_num;
d->MultiMsg.Length = 0;
d->MultiMsg.Type = d->Msg.Type;
d->MultiMsg.Destination = d->Msg.Destination;
d->MultiMsg.Source = d->Msg.Source;
}
if ((seq_num & 0x40) != 0x40 && d->FramesToGo != frm_num) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
smprintf(s, "[ERROR: Missed part of multiframe msg]\n");
}
free(d->Msg.Buffer);
d->Msg.Length = 0;
d->Msg.Buffer = NULL;
d->MsgRXState = RX_Sync;
return ERR_NONE;
}
if ((seq_num & 0x40) != 0x40 && d->Msg.Type != d->MultiMsg.Type) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
smprintf(s, "[ERROR: Multiframe msg in multiframe msg]\n");
}
free(d->Msg.Buffer);
d->Msg.Length = 0;
d->Msg.Buffer = NULL;
d->MsgRXState = RX_Sync;
return ERR_NONE;
}
if (d->MultiMsg.BufferUsed < d->MultiMsg.Length+d->Msg.Length-2) {
d->MultiMsg.BufferUsed = d->MultiMsg.Length+d->Msg.Length-2;
d->MultiMsg.Buffer = (unsigned char *)realloc(d->MultiMsg.Buffer,d->MultiMsg.BufferUsed);
}
memcpy(d->MultiMsg.Buffer+d->MultiMsg.Length,d->Msg.Buffer,d->Msg.Length-2);
d->MultiMsg.Length = d->MultiMsg.Length+d->Msg.Length-2;
free(d->Msg.Buffer);
diff --git a/gammu/emb/common/protocol/nokia/fbus2.h b/gammu/emb/common/protocol/nokia/fbus2.h
index 5dd45d7..8dbcb07 100644
--- a/gammu/emb/common/protocol/nokia/fbus2.h
+++ b/gammu/emb/common/protocol/nokia/fbus2.h
@@ -1,38 +1,42 @@
/* (c) 2002-2003 by Marcin Wiacek */
-/* based on some work from Gnokii and MyGnokii */
+/* based on some work from MyGnokii (www.mwiacek.com) */
+/* Based on some work from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
#ifndef fbus2_h
#define fbus2_h
#include "../protocol.h"
#define FBUS2_FRAME_ID 0x1e
#define FBUS2_IRDA_FRAME_ID 0x1c
#define FBUS2_DEVICE_PHONE 0x00 /* Nokia mobile phone */
#define FBUS2_DEVICE_PC 0x0c /* Our PC */
#define FBUS2_ACK_BYTE 0x7f /* Acknowledge of the received frame */
#define FBUS2_MAX_TRANSMIT_LENGTH 120
typedef struct {
int MsgSequenceNumber;
int MsgRXState;
int FramesToGo;
GSM_Protocol_Message MultiMsg;
GSM_Protocol_Message Msg;
} GSM_Protocol_FBUS2Data;
#ifndef GSM_USED_SERIALDEVICE
# define GSM_USED_SERIALDEVICE
#endif
#if defined(GSM_ENABLE_BLUEFBUS2)
# ifndef GSM_USED_BLUETOOTHDEVICE
# define GSM_USED_BLUETOOTHDEVICE
# endif
#endif
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/protocol/nokia/mbus2.c b/gammu/emb/common/protocol/nokia/mbus2.c
index f07d6c5..8353b46 100644
--- a/gammu/emb/common/protocol/nokia/mbus2.c
+++ b/gammu/emb/common/protocol/nokia/mbus2.c
@@ -1,194 +1,194 @@
/* (c) 2001-2003 by Marcin Wiacek */
-/* based on some work from MyGnokii */
+/* based on some work from MyGnokii (www.mwiacek.com) */
#include "../../gsmstate.h"
#ifdef GSM_ENABLE_MBUS2
#include <stdio.h>
#include <string.h>
#include "../../gsmcomon.h"
#include "mbus2.h"
static GSM_Error MBUS2_WriteMessage (GSM_StateMachine *s,
unsigned char *MsgBuffer,
int MsgLength,
unsigned char MsgType)
{
unsigned char *buffer2, checksum = 0;
GSM_Protocol_MBUS2Data *d = &s->Protocol.Data.MBUS2;
int i, sent, len;
GSM_DumpMessageLevel3(s, MsgBuffer, MsgLength, MsgType);
buffer2 = (unsigned char *)malloc(MsgLength + 8);
buffer2[0] = MBUS2_FRAME_ID;
buffer2[1] = MBUS2_DEVICE_PHONE; // destination
buffer2[2] = MBUS2_DEVICE_PC; // source
buffer2[3] = MsgType;
buffer2[4] = MsgLength / 256;
buffer2[5] = MsgLength % 256;
memcpy(buffer2 + 6, MsgBuffer, MsgLength);
len = 6 + MsgLength;
/* According to http://www.flosys.com/tdma/n5160.html some phones
* can have problems with checksum equal 0x1F. Phones can recognize
* received frame, but won't send ACK for it. When checksum is 0x1F,
* we increment the sequence number
*/
do {
d->MsgSequenceNumber++;
buffer2[len] = d->MsgSequenceNumber;
/* Calculating checksum */
checksum = 0;
for (i = 0; i < len + 1; i++) checksum ^= buffer2[i];
} while (checksum == 0x1f);
buffer2[len++] = d->MsgSequenceNumber;
buffer2[len++] = checksum;
GSM_DumpMessageLevel2(s, buffer2+6, MsgLength, MsgType);
/* Sending to phone */
my_sleep(10);
sent=s->Device.Functions->WriteDevice(s,buffer2,len);
free(buffer2);
if (sent!=len) return ERR_DEVICEWRITEERROR;
return ERR_NONE;
}
static GSM_Error MBUS2_SendAck(GSM_StateMachine *s,
unsigned char type,
unsigned char sequence)
{
GSM_Device_Functions *Device = s->Device.Functions;
unsigned char buffer2[6];
int i;
buffer2[0] = MBUS2_FRAME_ID;
buffer2[1] = MBUS2_DEVICE_PHONE; //destination
buffer2[2] = MBUS2_DEVICE_PC; //source
buffer2[3] = MBUS2_ACK_BYTE;
buffer2[4] = sequence;
buffer2[5] = 0;
/* Calculating checksum */
for (i = 0; i < 5; i++) buffer2[5] ^= buffer2[i];
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
smprintf(s,"[Sending Ack of type %02x, seq: %x]\n",type,sequence);
}
/* Sending to phone */
my_sleep(10);
if (Device->WriteDevice(s,buffer2,6)!=6) return ERR_DEVICEWRITEERROR;
return ERR_NONE;
}
static GSM_Error MBUS2_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
{
GSM_Phone_Functions *Phone = s->Phone.Functions;
GSM_Protocol_MBUS2Data *d = &s->Protocol.Data.MBUS2;
d->Msg.CheckSum[0] = d->Msg.CheckSum[1];
d->Msg.CheckSum[1] ^= rx_char;
if (d->MsgRXState == RX_GetMessage) {
d->Msg.Buffer[d->Msg.Count] = rx_char;
d->Msg.Count++;
/* This is not last byte in frame */
if (d->Msg.Count != d->Msg.Length+2) return ERR_NONE;
/* Checksum is incorrect */
if (d->Msg.CheckSum[0] != rx_char) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
smprintf(s,"[ERROR: checksum]\n");
}
d->MsgRXState = RX_Sync;
return ERR_NONE;
}
if (d->Msg.Destination != MBUS2_DEVICE_PHONE) {
MBUS2_SendAck(s, d->Msg.Type, d->Msg.Buffer[d->Msg.Count-2]);
s->Phone.Data.RequestMsg = &d->Msg;
s->Phone.Data.DispatchError = Phone->DispatchMessage(s);
}
d->MsgRXState = RX_Sync;
return ERR_NONE;
}
if (d->MsgRXState == RX_GetLength2) {
if (d->Msg.Type == MBUS2_ACK_BYTE) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
smprintf(s,"[Received Ack]\n");
}
d->MsgRXState = RX_Sync;
return ERR_NONE;
}
d->Msg.Length = d->Msg.Length + rx_char;
if (d->Msg.BufferUsed < d->Msg.Length+2) {
d->Msg.BufferUsed = d->Msg.Length+2;
d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed);
}
d->MsgRXState = RX_GetMessage;
return ERR_NONE;
}
if (d->MsgRXState == RX_GetLength1) {
d->Msg.Length = rx_char * 256;
d->MsgRXState = RX_GetLength2;
return ERR_NONE;
}
if (d->MsgRXState == RX_GetType) {
d->Msg.Type = rx_char;
d->MsgRXState = RX_GetLength1;
return ERR_NONE;
}
if (d->MsgRXState == RX_GetSource) {
if (rx_char != MBUS2_DEVICE_PHONE && rx_char != MBUS2_DEVICE_PC) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
smprintf(s,"[ERROR: incorrect char - %02x, not %02x and %02x]\n", rx_char, MBUS2_DEVICE_PHONE, MBUS2_DEVICE_PC);
}
d->MsgRXState = RX_Sync;
return ERR_NONE;
}
d->Msg.Source = rx_char;
d->MsgRXState = RX_GetType;
return ERR_NONE;
}
if (d->MsgRXState == RX_GetDestination) {
if (rx_char != MBUS2_DEVICE_PC && rx_char != MBUS2_DEVICE_PHONE) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
smprintf(s,"[ERROR: incorrect char - %02x, not %02x and %02x]\n", rx_char, MBUS2_DEVICE_PHONE, MBUS2_DEVICE_PC);
}
d->MsgRXState = RX_Sync;
return ERR_NONE;
}
d->Msg.Destination = rx_char;
d->MsgRXState = RX_GetSource;
return ERR_NONE;
}
if (d->MsgRXState == RX_Sync) {
if (rx_char != MBUS2_FRAME_ID) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
diff --git a/gammu/emb/common/protocol/nokia/mbus2.h b/gammu/emb/common/protocol/nokia/mbus2.h
index 86fcab6..5dbd8cb 100644
--- a/gammu/emb/common/protocol/nokia/mbus2.h
+++ b/gammu/emb/common/protocol/nokia/mbus2.h
@@ -1,28 +1,28 @@
/* (c) 2001-2003 by Marcin Wiacek */
-/* based on some work from MyGnokii */
+/* based on some work from MyGnokii (www.mwiacek.com) */
#ifndef mbus2_h
#define mbus2_h
#include "../protocol.h"
#define MBUS2_FRAME_ID 0x1f
#define MBUS2_DEVICE_PHONE 0x00 /* Nokia mobile phone */
#define MBUS2_DEVICE_PC 0x10 /* Our PC (MBUS) */
#define MBUS2_ACK_BYTE 0x7f /* Acknowledge of the received frame */
typedef struct {
int MsgSequenceNumber;
int MsgRXState;
GSM_Protocol_Message Msg;
} GSM_Protocol_MBUS2Data;
#ifndef GSM_USED_SERIALDEVICE
# define GSM_USED_SERIALDEVICE
#endif
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/protocol/nokia/phonet.c b/gammu/emb/common/protocol/nokia/phonet.c
index bc5717d..db5bd72 100644
--- a/gammu/emb/common/protocol/nokia/phonet.c
+++ b/gammu/emb/common/protocol/nokia/phonet.c
@@ -1,194 +1,197 @@
/* (c) 2002-2003 by Marcin Wiacek */
-/* based on some work from Gnokii */
+/* Based on some work from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
#include "../../gsmstate.h"
#if defined(GSM_ENABLE_IRDA) || defined(GSM_ENABLE_PHONETBLUE) || defined(GSM_ENABLE_BLUEPHONET)
#include <stdio.h>
#include <string.h>
#include "../../gsmcomon.h"
#include "phonet.h"
static GSM_Error PHONET_WriteMessage (GSM_StateMachine *s,
unsigned char *MsgBuffer,
int MsgLength,
unsigned char MsgType)
{
unsigned char *buffer2;
int sent;
GSM_DumpMessageLevel3(s, MsgBuffer, MsgLength, MsgType);
buffer2 = (unsigned char *)malloc(MsgLength + 6);
buffer2[0] = PHONET_FRAME_ID,
buffer2[1] = PHONET_DEVICE_PHONE; //destination
buffer2[2] = PHONET_DEVICE_PC; //source
if (s->ConnectionType==GCT_PHONETBLUE || s->ConnectionType==GCT_BLUEPHONET) {
buffer2[0] = PHONET_BLUE_FRAME_ID;
buffer2[1] = PHONET_DEVICE_PHONE; //destination
buffer2[2] = PHONET_BLUE_DEVICE_PC; //source
}
buffer2[3] = MsgType;
buffer2[4] = MsgLength / 256;
buffer2[5] = MsgLength % 256;
memcpy(buffer2 + 6, MsgBuffer, MsgLength);
GSM_DumpMessageLevel2(s, buffer2+6, MsgLength, MsgType);
/* Sending to phone */
sent = s->Device.Functions->WriteDevice(s,buffer2,MsgLength+6);
free(buffer2);
if (sent!=MsgLength+6) return ERR_DEVICEWRITEERROR;
return ERR_NONE;
}
static GSM_Error PHONET_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
{
GSM_Protocol_PHONETData *d = &s->Protocol.Data.PHONET;
bool correct = false;
if (d->MsgRXState==RX_GetMessage) {
d->Msg.Buffer[d->Msg.Count] = rx_char;
d->Msg.Count++;
/* This is not last byte in frame */
if (d->Msg.Count != d->Msg.Length) return ERR_NONE;
s->Phone.Data.RequestMsg = &d->Msg;
s->Phone.Data.DispatchError = s->Phone.Functions->DispatchMessage(s);
free(d->Msg.Buffer);
d->Msg.Length = 0;
d->Msg.Buffer = NULL;
d->MsgRXState = RX_Sync;
return ERR_NONE;
}
if (d->MsgRXState==RX_GetLength2) {
d->Msg.Length = d->Msg.Length + rx_char;
d->Msg.Buffer = (unsigned char *)malloc(d->Msg.Length);
d->MsgRXState = RX_GetMessage;
return ERR_NONE;
}
if (d->MsgRXState==RX_GetLength1) {
d->Msg.Length = rx_char * 256;
d->MsgRXState = RX_GetLength2;
return ERR_NONE;
}
if (d->MsgRXState==RX_GetType) {
d->Msg.Type = rx_char;
d->MsgRXState = RX_GetLength1;
return ERR_NONE;
}
if (d->MsgRXState==RX_GetSource) {
if (rx_char != PHONET_DEVICE_PHONE) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, PHONET_DEVICE_PHONE);
}
d->MsgRXState = RX_Sync;
return ERR_NONE;
}
d->Msg.Source = rx_char;
d->MsgRXState = RX_GetType;
return ERR_NONE;
}
if (d->MsgRXState==RX_GetDestination) {
switch (s->ConnectionType) {
case GCT_IRDAPHONET:
if (rx_char == PHONET_DEVICE_PC) correct = true;
break;
case GCT_PHONETBLUE:
case GCT_BLUEPHONET:
if (rx_char == PHONET_BLUE_DEVICE_PC) correct = true;
break;
default:
break;
}
if (!correct) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, PHONET_DEVICE_PC);
}
d->MsgRXState = RX_Sync;
return ERR_NONE;
}
d->Msg.Destination = rx_char;
d->MsgRXState = RX_GetSource;
return ERR_NONE;
}
if (d->MsgRXState==RX_Sync) {
switch (s->ConnectionType) {
case GCT_IRDAPHONET:
if (rx_char == PHONET_FRAME_ID) correct = true;
break;
case GCT_PHONETBLUE:
case GCT_BLUEPHONET:
if (rx_char == PHONET_BLUE_FRAME_ID) correct = true;
break;
default:
break;
}
if (!correct) {
if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, PHONET_FRAME_ID);
}
return ERR_NONE;
}
d->Msg.Count = 0;
d->MsgRXState = RX_GetDestination;
return ERR_NONE;
}
return ERR_NONE;
}
static GSM_Error PHONET_Initialise(GSM_StateMachine *s)
{
int total = 0, i, n;
GSM_Protocol_PHONETData *d = &s->Protocol.Data.PHONET;
unsigned char req[50];
d->Msg.Length = 0;
d->Msg.Buffer = NULL;
d->MsgRXState = RX_Sync;
if (s->ConnectionType == GCT_PHONETBLUE || s->ConnectionType == GCT_BLUEPHONET) {
/* Send frame in PHONET style */
req[0] = PHONET_BLUE_FRAME_ID; req[1] = PHONET_DEVICE_PHONE;
req[2] = PHONET_BLUE_DEVICE_PC; req[3] = 0xD0;
req[4] = 0x00; req[5] = 0x01;
req[6] = 0x04;
if (s->Device.Functions->WriteDevice(s,req,7) != 7) return ERR_DEVICEWRITEERROR;
while (total < 7) {
n = s->Device.Functions->ReadDevice(s, req + total, 50 - total);
total += n;
}
/* Answer frame in PHONET style */
req[10] = PHONET_BLUE_FRAME_ID; req[11] = PHONET_BLUE_DEVICE_PC;
req[12] = PHONET_DEVICE_PHONE; req[13] = 0xD0;
req[14] = 0x00; req[15] = 0x01;
req[16] = 0x05;
for (i = 0; i < 7; i++) {
if (req[i] != req[10+i]) {
smprintf(s,"Incorrect byte in the answer\n");
return ERR_UNKNOWN;
}
}
diff --git a/gammu/emb/common/protocol/nokia/phonet.h b/gammu/emb/common/protocol/nokia/phonet.h
index 2f6e836..e750bbd 100644
--- a/gammu/emb/common/protocol/nokia/phonet.h
+++ b/gammu/emb/common/protocol/nokia/phonet.h
@@ -1,35 +1,38 @@
/* (c) 2002-2003 by Marcin Wiacek */
-/* based on some work from Gnokii */
+/* Based on some work from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
#ifndef PHONET_h
#define PHONET_h
#include "../protocol.h"
#define PHONET_FRAME_ID 0x14
#define PHONET_BLUE_FRAME_ID 0x19
#define PHONET_DEVICE_PHONE 0x00 /* Nokia mobile phone */
#define PHONET_DEVICE_PC 0x0c /* Our PC */
#define PHONET_BLUE_DEVICE_PC 0x10 /* Our PC */
typedef struct {
int MsgRXState;
GSM_Protocol_Message Msg;
} GSM_Protocol_PHONETData;
#if defined(GSM_ENABLE_IRDAPHONET)
# ifndef GSM_USED_IRDADEVICE
# define GSM_USED_IRDADEVICE
# endif
#endif
#if defined(GSM_ENABLE_BLUEPHONET)
# ifndef GSM_USED_BLUETOOTHDEVICE
# define GSM_USED_BLUETOOTHDEVICE
# endif
#endif
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/service/backup/backgen.h b/gammu/emb/common/service/backup/backgen.h
index 9d7d973..9a930fc 100644
--- a/gammu/emb/common/service/backup/backgen.h
+++ b/gammu/emb/common/service/backup/backgen.h
@@ -1,69 +1,73 @@
/* (c) 2002-2004 by Marcin Wiacek */
#ifndef __gsm_backgen_h
#define __gsm_backgen_h
#include "../../config.h"
#include "../../misc/misc.h"
#include "../gsmpbk.h"
#include "../gsmcal.h"
#include "../gsmlogo.h"
#include "../gsmring.h"
#include "../gsmdata.h"
#include "../gsmprof.h"
#include "../gsmmisc.h"
#include "../sms/gsmsms.h"
#define GSM_BACKUP_MAX_PHONEPHONEBOOK 501
#define GSM_BACKUP_MAX_SIMPHONEBOOK 251
#define GSM_BACKUP_MAX_CALLER 6
#define GSM_BACKUP_MAX_SMSC 10
#define GSM_BACKUP_MAX_WAPBOOKMARK 40
#define GSM_BACKUP_MAX_WAPSETTINGS 30
#define GSM_BACKUP_MAX_MMSSETTINGS 30
+#define GSM_BACKUP_MAX_SYNCMLSETTINGS 10
+#define GSM_BACKUP_MAX_CHATSETTINGS 10
#define GSM_BACKUP_MAX_RINGTONES 30
#define GSM_BACKUP_MAX_PROFILES 10
#define GSM_BACKUP_MAX_FMSTATIONS 20
#define GSM_BACKUP_MAX_GPRSPOINT 10
#define GSM_BACKUP_MAX_NOTE 10 /* FIXME */
typedef struct {
char IMEI [MAX_IMEI_LENGTH];
char Model [MAX_MODEL_LENGTH+MAX_VERSION_LENGTH];
char Creator [80];
GSM_DateTime DateTime;
bool DateTimeAvailable;
char MD5Original [100];
char MD5Calculated [100];
GSM_MemoryEntry *PhonePhonebook [GSM_BACKUP_MAX_PHONEPHONEBOOK + 1];
GSM_MemoryEntry *SIMPhonebook [GSM_BACKUP_MAX_SIMPHONEBOOK + 1];
GSM_CalendarEntry *Calendar [GSM_MAXCALENDARTODONOTES + 1];
GSM_Bitmap *CallerLogos [GSM_BACKUP_MAX_CALLER + 1];
GSM_SMSC *SMSC [GSM_BACKUP_MAX_SMSC + 1];
GSM_WAPBookmark *WAPBookmark [GSM_BACKUP_MAX_WAPBOOKMARK + 1];
GSM_MultiWAPSettings *WAPSettings [GSM_BACKUP_MAX_WAPSETTINGS + 1];
GSM_MultiWAPSettings *MMSSettings [GSM_BACKUP_MAX_MMSSETTINGS + 1];
+ GSM_SyncMLSettings *SyncMLSettings [GSM_BACKUP_MAX_SYNCMLSETTINGS + 1];
+ GSM_ChatSettings *ChatSettings [GSM_BACKUP_MAX_CHATSETTINGS + 1];
GSM_Ringtone *Ringtone [GSM_BACKUP_MAX_RINGTONES + 1];
GSM_ToDoEntry *ToDo [GSM_MAXCALENDARTODONOTES + 1];
GSM_Profile *Profiles [GSM_BACKUP_MAX_PROFILES + 1];
GSM_FMStation *FMStation [GSM_BACKUP_MAX_FMSTATIONS +1];
GSM_GPRSAccessPoint *GPRSPoint [GSM_BACKUP_MAX_GPRSPOINT + 1];
GSM_NoteEntry *Note [GSM_BACKUP_MAX_NOTE + 1];
GSM_Bitmap *StartupLogo;
GSM_Bitmap *OperatorLogo;
} GSM_Backup;
#define GSM_BACKUP_MAX_SMS 500
typedef struct {
GSM_SMSMessage *SMS[GSM_BACKUP_MAX_SMS];
} GSM_SMS_Backup;
extern GSM_Error GSM_ReadSMSBackupFile(char *FileName, GSM_SMS_Backup *backup);
extern GSM_Error GSM_SaveSMSBackupFile(char *FileName, GSM_SMS_Backup *backup);
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/service/backup/backtext.c b/gammu/emb/common/service/backup/backtext.c
index fee0f73..4cb1bb7 100644
--- a/gammu/emb/common/service/backup/backtext.c
+++ b/gammu/emb/common/service/backup/backtext.c
@@ -1,1304 +1,1380 @@
/* (c) 2002-2004 by Marcin Wiacek, Walek and Michal Cihar */
#include <string.h>
#include <ctype.h>
#include "../../phone/nokia/nfunc.h"
#include "../../phone/nokia/dct3/n7110.h"
#include "../../misc/cfg.h"
#include "../../misc/coding/coding.h"
#include "../../misc/coding/md5.h"
#include "../gsmlogo.h"
#include "../gsmmisc.h"
#include "backtext.h"
#ifdef GSM_ENABLE_BACKUP
GSM_Error FindBackupChecksum(char *FileName, bool UseUnicode, char *checksum)
{
INI_Section *file_info, *h;
INI_Entry *e;
char *buffer = NULL,buff[100];
int len=0;
//int i;
file_info = INI_ReadFile(FileName, UseUnicode);
if (UseUnicode) {
for (h = file_info; h != NULL; h = h->Next) {
EncodeUnicode(buff,"Checksum",8);
if (mywstrncasecmp(buff, h->SectionName, 8)) continue;
buffer = (unsigned char *)realloc(buffer,len+UnicodeLength(h->SectionName)*2+2);
CopyUnicodeString(buffer+len,h->SectionName);
len+=UnicodeLength(h->SectionName)*2;
// dbgprintf("[%s]\n",DecodeUnicodeConsole(h->SectionName));
for (e = h->SubEntries; e != NULL; e = e->Next) {
buffer = (unsigned char *)realloc(buffer,len+UnicodeLength(e->EntryName)*2+2);
CopyUnicodeString(buffer+len,e->EntryName);
len+=UnicodeLength(e->EntryName)*2;
buffer = (unsigned char *)realloc(buffer,len+UnicodeLength(e->EntryValue)*2+2);
CopyUnicodeString(buffer+len,e->EntryValue);
len+=UnicodeLength(e->EntryValue)*2;
// dbgprintf("\"%s\"",DecodeUnicodeConsole(e->EntryName));
// dbgprintf("=\"%s\"\n",DecodeUnicodeConsole(e->EntryValue));
}
}
} else {
for (h = file_info; h != NULL; h = h->Next) {
if (mystrncasecmp("Checksum", h->SectionName, 8)) continue;
buffer = (unsigned char *)realloc(buffer,len+strlen(h->SectionName)+1);
strcpy(buffer+len,h->SectionName);
len+=strlen(h->SectionName);
for (e = h->SubEntries; e != NULL; e = e->Next) {
// dbgprintf("%s=%s\n",e->EntryName,e->EntryValue);
buffer = (unsigned char *)realloc(buffer,len+strlen(e->EntryName)+1);
strcpy(buffer+len,e->EntryName);
len+=strlen(e->EntryName);
buffer = (unsigned char *)realloc(buffer,len+strlen(e->EntryValue)+1);
strcpy(buffer+len,e->EntryValue);
len+=strlen(e->EntryValue);
}
}
}
//for (i=0;i<len;i++) printf("%02x",buffer[i]);
CalculateMD5(buffer, len, checksum);
free(buffer);
return ERR_NONE;
}
static unsigned char *ReadCFGText(INI_Section *cfg, unsigned char *section, unsigned char *key, bool Unicode)
{
unsigned char Buffer[500],Buffer2[500],*retval;
if (Unicode) {
EncodeUnicode(Buffer2,key,strlen(key));
retval = INI_GetValue(cfg,section,Buffer2,Unicode);
if (retval != NULL) return DecodeUnicodeString(retval);
return NULL;
} else {
strcpy(Buffer,section);
strcpy(Buffer2,key);
return INI_GetValue(cfg,section,key,Unicode);
}
}
static void SaveLinkedBackupText(FILE *file, char *myname, char *myvalue, bool UseUnicode)
{
int w,current;
unsigned char buffer2[1000],buffer3[1000];
current = strlen(myvalue); w = 0;
while (true) {
if (current > 200) {
memcpy(buffer2,myvalue+(strlen(myvalue)-current),200);
buffer2[200] = 0;
current = current - 200;
} else {
memcpy(buffer2,myvalue+(strlen(myvalue)-current),current);
buffer2[current] = 0;
current = 0;
}
if (UseUnicode) {
sprintf(buffer3,"%s%02i = %s%c%c",myname,w,buffer2,13,10);
EncodeUnicode(buffer2,buffer3,strlen(buffer3));
fwrite(buffer2,1,strlen(buffer3)*2,file);
} else {
fprintf(file,"%s%02i = %s%c%c",myname,w,buffer2,13,10);
}
if (current == 0) break;
w++;
}
}
static void ReadLinkedBackupText(INI_Section *file_info, char *section, char *myname, char *myvalue, bool UseUnicode)
{
unsigned char buffer2[300];
char *readvalue;
int i;
i=0;
myvalue[0] = 0;
while (true) {
sprintf(buffer2,"%s%02i",myname,i);
readvalue = ReadCFGText(file_info, section, buffer2, UseUnicode);
if (readvalue!=NULL) {
myvalue[strlen(myvalue)+strlen(readvalue)]=0;
memcpy(myvalue+strlen(myvalue),readvalue,strlen(readvalue));
} else break;
i++;
}
}
static void SaveBackupText(FILE *file, char *myname, char *myvalue, bool UseUnicode)
{
unsigned char buffer[10000], buffer2[10000];
if (myname[0] == 0x00) {
if (UseUnicode) {
EncodeUnicode(buffer,myvalue,strlen(myvalue));
fwrite(buffer,1,strlen(myvalue)*2,file);
} else fprintf(file,"%s",myvalue);
} else {
if (UseUnicode) {
sprintf(buffer,"%s = \"",myname);
EncodeUnicode(buffer2,buffer,strlen(buffer));
fwrite(buffer2,1,strlen(buffer)*2,file);
- fwrite(myvalue,1,UnicodeLength(myvalue)*2,file);
+ fwrite(EncodeUnicodeSpecialChars(myvalue),1,UnicodeLength(EncodeUnicodeSpecialChars(myvalue))*2,file);
sprintf(buffer,"\"%c%c",13,10);
EncodeUnicode(buffer2,buffer,strlen(buffer));
fwrite(buffer2,1,strlen(buffer)*2,file);
} else {
- sprintf(buffer,"%s = \"%s\"%c%c",myname,DecodeUnicodeString(myvalue),13,10);
+ sprintf(buffer,"%s = \"%s\"%c%c",myname,EncodeSpecialChars(DecodeUnicodeString(myvalue)),13,10);
fprintf(file,"%s",buffer);
EncodeHexBin(buffer,myvalue,UnicodeLength(myvalue)*2);
fprintf(file,"%sUnicode = %s%c%c",myname,buffer,13,10);
}
}
}
static bool ReadBackupText(INI_Section *file_info, char *section, char *myname, char *myvalue, bool UseUnicode)
{
- unsigned char paramname[10000],*readvalue;
+ unsigned char paramname[10000],*readvalue;
if (UseUnicode) {
EncodeUnicode(paramname,myname,strlen(myname));
readvalue = INI_GetValue(file_info, section, paramname, UseUnicode);
if (readvalue!=NULL) {
- CopyUnicodeString(myvalue,readvalue+2);
- myvalue[UnicodeLength(readvalue)*2-4]=0;
- myvalue[UnicodeLength(readvalue)*2-3]=0;
+ CopyUnicodeString(myvalue,DecodeUnicodeSpecialChars(readvalue+2));
+ myvalue[UnicodeLength(myvalue)*2-2]=0;
+ myvalue[UnicodeLength(myvalue)*2-1]=0;
+
dbgprintf("%s\n",DecodeUnicodeString(readvalue));
} else {
myvalue[0]=0;
myvalue[1]=0;
return false;
}
} else {
strcpy(paramname,myname);
strcat(paramname,"Unicode");
readvalue = ReadCFGText(file_info, section, paramname, UseUnicode);
if (readvalue!=NULL) {
dbgprintf("%s %i\n",readvalue,strlen(readvalue));
DecodeHexBin (myvalue, readvalue, strlen(readvalue));
myvalue[strlen(readvalue)/2]=0;
myvalue[strlen(readvalue)/2+1]=0;
dbgprintf("%s\n",DecodeUnicodeString(myvalue));
} else {
strcpy(paramname,myname);
readvalue = ReadCFGText(file_info, section, paramname, UseUnicode);
if (readvalue!=NULL) {
- EncodeUnicode(myvalue,readvalue+1,strlen(readvalue)-2);
+ EncodeUnicode(myvalue,DecodeSpecialChars(readvalue+1),strlen(DecodeSpecialChars(readvalue+1))-1);
} else {
myvalue[0]=0;
myvalue[1]=0;
return false;
}
}
}
return true;
}
static void SaveVCalDateTime(FILE *file, GSM_DateTime *dt, bool UseUnicode)
{
unsigned char buffer[100];
int Length = 3;
sprintf(buffer, " = ");
SaveVCALDateTime(buffer, &Length, dt, NULL);
SaveBackupText(file, "", buffer, UseUnicode);
}
static void SaveVCalDate(FILE *file, GSM_DateTime *dt, bool UseUnicode)
{
unsigned char buffer[100];
sprintf(buffer, " = %04d%02d%02d%c%c", dt->Year, dt->Month, dt->Day,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
/* ---------------------- backup files ------------------------------------- */
static void SavePbkEntry(FILE *file, GSM_MemoryEntry *Pbk, bool UseUnicode)
{
bool text;
char buffer[1000];
int j, i;
sprintf(buffer,"Location = %03i%c%c",Pbk->Location,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
for (j=0;j<Pbk->EntriesNum;j++) {
text = true;
switch (Pbk->Entries[j].EntryType) {
case PBK_Number_General:
sprintf(buffer,"Entry%02iType = NumberGeneral%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Number_Mobile:
sprintf(buffer,"Entry%02iType = NumberMobile%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Number_Work:
sprintf(buffer,"Entry%02iType = NumberWork%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Number_Fax:
sprintf(buffer,"Entry%02iType = NumberFax%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Number_Home:
sprintf(buffer,"Entry%02iType = NumberHome%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Number_Pager:
sprintf(buffer,"Entry%02iType = NumberPager%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Number_Other:
sprintf(buffer,"Entry%02iType = NumberOther%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_Note:
sprintf(buffer,"Entry%02iType = Note%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_Postal:
sprintf(buffer,"Entry%02iType = Postal%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_Email:
sprintf(buffer,"Entry%02iType = Email%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_Email2:
sprintf(buffer,"Entry%02iType = Email2%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_URL:
sprintf(buffer,"Entry%02iType = URL%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_Name:
sprintf(buffer,"Entry%02iType = Name%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Caller_Group:
sprintf(buffer,"Entry%02iType = CallerGroup%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"Entry%02iNumber = %i%c%c",j,Pbk->Entries[j].Number,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
text = false;
break;
case PBK_RingtoneID:
sprintf(buffer,"Entry%02iType = RingtoneID%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"Entry%02iNumber = %i%c%c",j,Pbk->Entries[j].Number,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
text = false;
break;
case PBK_PictureID:
sprintf(buffer,"Entry%02iType = PictureID%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"Entry%02iNumber = %i%c%c",j,Pbk->Entries[j].Number,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
text = false;
break;
case PBK_Text_UserID:
sprintf(buffer,"Entry%02iType = UserID%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Category:
sprintf(buffer,"Entry%02iType = Category%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"Entry%02iNumber = %i%c%c",j,Pbk->Entries[j].Number,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
text = false;
break;
case PBK_Private:
sprintf(buffer,"Entry%02iType = Private%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"Entry%02iNumber = %i%c%c",j,Pbk->Entries[j].Number,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
text = false;
break;
case PBK_Text_LastName:
sprintf(buffer,"Entry%02iType = LastName%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_FirstName:
sprintf(buffer,"Entry%02iType = FirstName%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_Company:
sprintf(buffer,"Entry%02iType = Company%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_JobTitle:
sprintf(buffer,"Entry%02iType = JobTitle%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_StreetAddress:
sprintf(buffer,"Entry%02iType = Address%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_City:
sprintf(buffer,"Entry%02iType = City%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_State:
sprintf(buffer,"Entry%02iType = State%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_Zip:
sprintf(buffer,"Entry%02iType = Zip%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_Country:
sprintf(buffer,"Entry%02iType = Country%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_Custom1:
sprintf(buffer,"Entry%02iType = Custom1%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_Custom2:
sprintf(buffer,"Entry%02iType = Custom2%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_Custom3:
sprintf(buffer,"Entry%02iType = Custom3%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_Text_Custom4:
sprintf(buffer,"Entry%02iType = Custom4%c%c",j,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case PBK_SMSListID:
case PBK_RingtoneFileSystemID:
case PBK_Date:
break;
}
if (text) {
sprintf(buffer,"Entry%02iText",j);
SaveBackupText(file,buffer,Pbk->Entries[j].Text, UseUnicode);
}
switch (Pbk->Entries[j].EntryType) {
case PBK_Number_General:
case PBK_Number_Mobile:
case PBK_Number_Work:
case PBK_Number_Fax:
case PBK_Number_Home:
case PBK_Number_Other:
case PBK_Number_Pager:
if (Pbk->Entries[j].VoiceTag!=0) {
sprintf(buffer,"Entry%02iVoiceTag = %i%c%c",j,Pbk->Entries[j].VoiceTag,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
i = 0;
while (Pbk->Entries[j].SMSList[i]!=0) {
sprintf(buffer,"Entry%02iSMSList%02i = %i%c%c",j,i,Pbk->Entries[j].SMSList[i],13,10);
SaveBackupText(file, "", buffer, UseUnicode);
i++;
}
break;
default:
break;
}
}
sprintf(buffer,"%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
+static void SaveNoteEntry(FILE *file, GSM_NoteEntry *Note, bool UseUnicode)
+{
+ char buffer[1000];
+
+ sprintf(buffer,"Location = %d%c%c", Note->Location,13,10);
+ SaveBackupText(file, "", buffer, UseUnicode);
+ SaveBackupText(file, "Text", Note->Text, UseUnicode);
+ sprintf(buffer, "%c%c",13,10);
+ SaveBackupText(file, "", buffer, UseUnicode);
+}
+
static void SaveCalendarEntry(FILE *file, GSM_CalendarEntry *Note, bool UseUnicode)
{
int i;
char buffer[1000];
sprintf(buffer,"Location = %d%c%c", Note->Location,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveBackupText(file, "", "Type = ", UseUnicode);
switch (Note->Type) {
case GSM_CAL_REMINDER : sprintf(buffer,"Reminder%c%c", 13,10); break;
case GSM_CAL_CALL : sprintf(buffer,"Call%c%c", 13,10); break;
case GSM_CAL_MEETING : sprintf(buffer,"Meeting%c%c", 13,10); break;
case GSM_CAL_BIRTHDAY : sprintf(buffer,"Birthday%c%c", 13,10); break;
case GSM_CAL_TRAVEL : sprintf(buffer,"Travel%c%c", 13,10); break;
case GSM_CAL_VACATION : sprintf(buffer,"Vacation%c%c", 13,10); break;
- case GSM_CAL_MEMO : sprintf(buffer,"Memo%c%c", 13,10); break;
+ case GSM_CAL_MEMO : sprintf(buffer,"Memo%c%c", 13,10); break;
case GSM_CAL_ALARM : sprintf(buffer,"Alarm%c%c", 13,10); break;
- case GSM_CAL_DAILY_ALARM : sprintf(buffer,"DailyAlarm%c%c", 13,10); break;
+ case GSM_CAL_DAILY_ALARM: sprintf(buffer,"DailyAlarm%c%c", 13,10); break;
case GSM_CAL_T_ATHL : sprintf(buffer,"Training/Athletism%c%c", 13,10); break;
case GSM_CAL_T_BALL : sprintf(buffer,"Training/BallGames%c%c", 13,10); break;
case GSM_CAL_T_CYCL : sprintf(buffer,"Training/Cycling%c%c", 13,10); break;
case GSM_CAL_T_BUDO : sprintf(buffer,"Training/Budo%c%c", 13,10); break;
case GSM_CAL_T_DANC : sprintf(buffer,"Training/Dance%c%c", 13,10); break;
case GSM_CAL_T_EXTR : sprintf(buffer,"Training/ExtremeSports%c%c", 13,10); break;
case GSM_CAL_T_FOOT : sprintf(buffer,"Training/Football%c%c", 13,10); break;
case GSM_CAL_T_GOLF : sprintf(buffer,"Training/Golf%c%c", 13,10); break;
case GSM_CAL_T_GYM : sprintf(buffer,"Training/Gym%c%c", 13,10); break;
case GSM_CAL_T_HORS : sprintf(buffer,"Training/HorseRaces%c%c", 13,10); break;
case GSM_CAL_T_HOCK : sprintf(buffer,"Training/Hockey%c%c", 13,10); break;
case GSM_CAL_T_RACE : sprintf(buffer,"Training/Races%c%c", 13,10); break;
case GSM_CAL_T_RUGB : sprintf(buffer,"Training/Rugby%c%c", 13,10); break;
case GSM_CAL_T_SAIL : sprintf(buffer,"Training/Sailing%c%c", 13,10); break;
case GSM_CAL_T_STRE : sprintf(buffer,"Training/StreetGames%c%c", 13,10); break;
case GSM_CAL_T_SWIM : sprintf(buffer,"Training/Swimming%c%c", 13,10); break;
case GSM_CAL_T_TENN : sprintf(buffer,"Training/Tennis%c%c", 13,10); break;
case GSM_CAL_T_TRAV : sprintf(buffer,"Training/Travels%c%c", 13,10); break;
case GSM_CAL_T_WINT : sprintf(buffer,"Training/WinterGames%c%c", 13,10); break;
}
SaveBackupText(file, "", buffer, UseUnicode);
for (i=0;i<Note->EntriesNum;i++) {
switch (Note->Entries[i].EntryType) {
case CAL_START_DATETIME:
SaveBackupText(file, "", "StartTime", UseUnicode);
SaveVCalDateTime(file, &Note->Entries[i].Date, UseUnicode);
break;
case CAL_END_DATETIME:
SaveBackupText(file, "", "StopTime", UseUnicode);
SaveVCalDateTime(file, &Note->Entries[i].Date, UseUnicode);
break;
case CAL_ALARM_DATETIME:
SaveBackupText(file, "", "Alarm", UseUnicode);
SaveVCalDateTime(file, &Note->Entries[i].Date, UseUnicode);
sprintf(buffer,"AlarmType = Tone%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case CAL_SILENT_ALARM_DATETIME:
SaveBackupText(file, "", "Alarm", UseUnicode);
SaveVCalDateTime(file, &Note->Entries[i].Date, UseUnicode);
sprintf(buffer,"AlarmType = Silent%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case CAL_PRIVATE:
sprintf(buffer, "Private = %d%c%c",Note->Entries[i].Number,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case CAL_LOCATION:
SaveBackupText(file, "EventLocation", Note->Entries[i].Text, UseUnicode);
break;
case CAL_CONTACTID:
sprintf(buffer, "ContactID = %d%c%c",Note->Entries[i].Number,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case CAL_RECURRANCE:
sprintf(buffer, "Recurrance = %d%c%c",Note->Entries[i].Number/24,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case CAL_TEXT:
SaveBackupText(file, "Text", Note->Entries[i].Text, UseUnicode);
break;
case CAL_PHONE:
SaveBackupText(file, "Phone", Note->Entries[i].Text, UseUnicode);
break;
case CAL_REPEAT_STOPDATE:
SaveBackupText(file, "", "RepeatStopDate", UseUnicode);
SaveVCalDate(file, &Note->Entries[i].Date, UseUnicode);
break;
case CAL_REPEAT_STARTDATE:
SaveBackupText(file, "", "RepeatStartDate", UseUnicode);
SaveVCalDate(file, &Note->Entries[i].Date, UseUnicode);
break;
case CAL_REPEAT_DAYOFWEEK:
sprintf(buffer, "RepeatDayOfWeek = %d%c%c",Note->Entries[i].Number,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case CAL_REPEAT_DAY:
sprintf(buffer, "RepeatDay = %d%c%c",Note->Entries[i].Number,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case CAL_REPEAT_WEEKOFMONTH:
sprintf(buffer, "RepeatWeekOfMonth = %d%c%c",Note->Entries[i].Number,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case CAL_REPEAT_MONTH:
sprintf(buffer, "RepeatMonth = %d%c%c",Note->Entries[i].Number,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case CAL_REPEAT_FREQUENCY:
sprintf(buffer, "RepeatFrequency = %d%c%c",Note->Entries[i].Number,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
}
}
sprintf(buffer, "%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
static void SaveWAPSettingsEntry(FILE *file, GSM_MultiWAPSettings *settings, bool UseUnicode)
{
int i;
char buffer[10000];
if (settings->Active) {
sprintf(buffer,"Active = Yes%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
switch (settings->ActiveBearer) {
case WAPSETTINGS_BEARER_SMS : sprintf(buffer,"Bearer = SMS%c%c",13,10); break;
case WAPSETTINGS_BEARER_GPRS: sprintf(buffer,"Bearer = GPRS%c%c",13,10); break;
case WAPSETTINGS_BEARER_DATA: sprintf(buffer,"Bearer = Data%c%c",13,10); break;
case WAPSETTINGS_BEARER_USSD: sprintf(buffer,"Bearer = USSD%c%c",13,10);
}
SaveBackupText(file, "", buffer, UseUnicode);
if (settings->ReadOnly) {
sprintf(buffer,"ReadOnly = Yes%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
sprintf(buffer,"Proxy");
SaveBackupText(file, buffer, settings->Proxy, UseUnicode);
sprintf(buffer,"ProxyPort = %i%c%c",settings->ProxyPort,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"Proxy2");
SaveBackupText(file, buffer, settings->Proxy2, UseUnicode);
sprintf(buffer,"Proxy2Port = %i%c%c",settings->Proxy2Port,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
for (i=0;i<settings->Number;i++) {
sprintf(buffer,"Title%02i",i);
SaveBackupText(file, buffer, settings->Settings[i].Title, UseUnicode);
sprintf(buffer,"HomePage%02i",i);
SaveBackupText(file, buffer, settings->Settings[i].HomePage, UseUnicode);
if (settings->Settings[i].IsContinuous) {
sprintf(buffer,"Type%02i = Continuous%c%c",i,13,10);
} else {
sprintf(buffer,"Type%02i = Temporary%c%c",i,13,10);
}
SaveBackupText(file, "", buffer, UseUnicode);
if (settings->Settings[i].IsSecurity) {
sprintf(buffer,"Security%02i = On%c%c",i,13,10);
} else {
sprintf(buffer,"Security%02i = Off%c%c",i,13,10);
}
SaveBackupText(file, "", buffer, UseUnicode);
switch (settings->Settings[i].Bearer) {
case WAPSETTINGS_BEARER_SMS:
sprintf(buffer,"Bearer%02i = SMS%c%c",i,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"Server%02i",i);
SaveBackupText(file, buffer, settings->Settings[i].Server, UseUnicode);
sprintf(buffer,"Service%02i",i);
SaveBackupText(file, buffer, settings->Settings[i].Service, UseUnicode);
break;
case WAPSETTINGS_BEARER_GPRS:
sprintf(buffer,"Bearer%02i = GPRS%c%c",i,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"IP%02i",i);
SaveBackupText(file, buffer, settings->Settings[i].IPAddress, UseUnicode);
case WAPSETTINGS_BEARER_DATA:
if (settings->Settings[i].Bearer == WAPSETTINGS_BEARER_DATA) {
sprintf(buffer,"Bearer%02i = Data%c%c",i,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
if (settings->Settings[i].IsISDNCall) {
sprintf(buffer,"CallType%02i = ISDN%c%c",i,13,10);
} else {
sprintf(buffer,"CallType%02i = Analogue%c%c",i,13,10);
}
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"IP%02i",i);
SaveBackupText(file, buffer, settings->Settings[i].IPAddress, UseUnicode);
}
sprintf(buffer,"Number%02i",i);
SaveBackupText(file, buffer, settings->Settings[i].DialUp, UseUnicode);
if (settings->Settings[i].ManualLogin) {
sprintf(buffer,"Login%02i = Manual%c%c",i,13,10);
} else {
sprintf(buffer,"Login%02i = Automatic%c%c",i,13,10);
}
SaveBackupText(file, "", buffer, UseUnicode);
if (settings->Settings[i].IsNormalAuthentication) {
sprintf(buffer,"Authentication%02i = Normal%c%c",i,13,10);
} else {
sprintf(buffer,"Authentication%02i = Secure%c%c",i,13,10);
}
SaveBackupText(file, "", buffer, UseUnicode);
switch (settings->Settings[i].Speed) {
case WAPSETTINGS_SPEED_9600 : sprintf(buffer,"CallSpeed%02i = 9600%c%c" ,i,13,10); break;
case WAPSETTINGS_SPEED_14400: sprintf(buffer,"CallSpeed%02i = 14400%c%c",i,13,10); break;
case WAPSETTINGS_SPEED_AUTO : sprintf(buffer,"CallSpeed%02i = auto%c%c" ,i,13,10); break;
}
switch (settings->Settings[i].Speed) {
case WAPSETTINGS_SPEED_9600 :
case WAPSETTINGS_SPEED_14400:
case WAPSETTINGS_SPEED_AUTO :
SaveBackupText(file, "", buffer, UseUnicode);
default:
break;
}
sprintf(buffer,"User%02i",i);
SaveBackupText(file, buffer, settings->Settings[i].User, UseUnicode);
sprintf(buffer,"Password%02i",i);
SaveBackupText(file, buffer, settings->Settings[i].Password, UseUnicode);
break;
case WAPSETTINGS_BEARER_USSD:
sprintf(buffer,"Bearer%02i = USSD%c%c",i,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"ServiceCode%02i",i);
SaveBackupText(file, buffer, settings->Settings[i].Code, UseUnicode);
if (settings->Settings[i].IsIP) {
sprintf(buffer,"IP%02i",i);
} else {
sprintf(buffer,"Number%02i",i);
}
SaveBackupText(file, buffer, settings->Settings[i].Service, UseUnicode);
}
sprintf(buffer,"%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
}
+static void SaveChatSettingsEntry(FILE *file, GSM_ChatSettings *settings, bool UseUnicode)
+{
+ char buffer[10000];
+
+ sprintf(buffer,"HomePage");
+ SaveBackupText(file, buffer, settings->HomePage, UseUnicode);
+ sprintf(buffer,"User");
+ SaveBackupText(file, buffer, settings->User, UseUnicode);
+ sprintf(buffer,"Password");
+ SaveBackupText(file, buffer, settings->Password, UseUnicode);
+ SaveWAPSettingsEntry(file, &settings->Connection, UseUnicode);
+}
+
+static void SaveSyncMLSettingsEntry(FILE *file, GSM_SyncMLSettings *settings, bool UseUnicode)
+{
+ char buffer[10000];
+
+ sprintf(buffer,"User");
+ SaveBackupText(file, buffer, settings->User, UseUnicode);
+ sprintf(buffer,"Password");
+ SaveBackupText(file, buffer, settings->Password, UseUnicode);
+ sprintf(buffer,"PhonebookDB");
+ SaveBackupText(file, buffer, settings->PhonebookDataBase, UseUnicode);
+ sprintf(buffer,"CalendarDB");
+ SaveBackupText(file, buffer, settings->CalendarDataBase, UseUnicode);
+ sprintf(buffer,"Server");
+ SaveBackupText(file, buffer, settings->Server, UseUnicode);
+ if (settings->SyncPhonebook) {
+ sprintf(buffer,"SyncPhonebook = True%c%c",13,10);
+ } else {
+ sprintf(buffer,"SyncPhonebook = False%c%c",13,10);
+ }
+ SaveBackupText(file, "", buffer, UseUnicode);
+ if (settings->SyncCalendar) {
+ sprintf(buffer,"SyncCalendar = True%c%c",13,10);
+ } else {
+ sprintf(buffer,"SyncCalendar = False%c%c",13,10);
+ }
+ SaveBackupText(file, "", buffer, UseUnicode);
+ SaveWAPSettingsEntry(file, &settings->Connection, UseUnicode);
+}
+
static void SaveBitmapEntry(FILE *file, GSM_Bitmap *bitmap, bool UseUnicode)
{
unsigned char buffer[10000],buffer2[10000];
int x,y;
sprintf(buffer,"Width = %i%c%c",bitmap->BitmapWidth,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"Height = %i%c%c",bitmap->BitmapHeight,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
for (y=0;y<bitmap->BitmapHeight;y++) {
for (x=0;x<bitmap->BitmapWidth;x++) {
buffer[x] = ' ';
if (GSM_IsPointBitmap(bitmap,x,y)) buffer[x]='#';
}
buffer[bitmap->BitmapWidth] = 0;
sprintf(buffer2,"Bitmap%02i = \"%s\"%c%c",y,buffer,13,10);
SaveBackupText(file, "", buffer2, UseUnicode);
}
}
static void SaveCallerEntry(FILE *file, GSM_Bitmap *bitmap, bool UseUnicode)
{
unsigned char buffer[1000];
sprintf(buffer,"Location = %03i%c%c",bitmap->Location,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
if (!bitmap->DefaultName) SaveBackupText(file, "Name", bitmap->Text, UseUnicode);
if (!bitmap->DefaultRingtone) {
if (bitmap->FileSystemRingtone) {
sprintf(buffer,"FileRingtone = %02x%c%c",bitmap->RingtoneID,13,10);
} else {
sprintf(buffer,"Ringtone = %02x%c%c",bitmap->RingtoneID,13,10);
}
SaveBackupText(file, "", buffer, UseUnicode);
}
if (bitmap->BitmapEnabled) {
sprintf(buffer,"Enabled = True%c%c",13,10);
} else {
sprintf(buffer,"Enabled = False%c%c",13,10);
}
SaveBackupText(file, "", buffer, UseUnicode);
if (!bitmap->DefaultBitmap) SaveBitmapEntry(file, bitmap, UseUnicode);
sprintf(buffer,"%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
static void SaveWAPBookmarkEntry(FILE *file, GSM_WAPBookmark *bookmark, bool UseUnicode)
{
unsigned char buffer[1000];
SaveBackupText(file, "URL", bookmark->Address, UseUnicode);
SaveBackupText(file, "Title", bookmark->Title, UseUnicode);
sprintf(buffer,"%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
static void SaveStartupEntry(FILE *file, GSM_Bitmap *bitmap, bool UseUnicode)
{
unsigned char buffer[1000];
sprintf(buffer,"[Startup]%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
if (bitmap->Type == GSM_WelcomeNote_Text) {
SaveBackupText(file, "Text", bitmap->Text, UseUnicode);
}
if (bitmap->Type == GSM_StartupLogo) {
SaveBitmapEntry(file, bitmap, UseUnicode);
}
sprintf(buffer,"%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
static void SaveSMSCEntry(FILE *file, GSM_SMSC *SMSC, bool UseUnicode)
{
unsigned char buffer[1000];
sprintf(buffer,"Location = %03i%c%c",SMSC->Location,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveBackupText(file, "Name", SMSC->Name, UseUnicode);
SaveBackupText(file, "Number", SMSC->Number, UseUnicode);
SaveBackupText(file, "DefaultNumber", SMSC->DefaultNumber, UseUnicode);
SaveBackupText(file, "", "Format = ", UseUnicode);
switch (SMSC->Format) {
case SMS_FORMAT_Text : sprintf(buffer,"Text"); break;
case SMS_FORMAT_Fax : sprintf(buffer,"Fax"); break;
case SMS_FORMAT_Email : sprintf(buffer,"Email"); break;
case SMS_FORMAT_Pager : sprintf(buffer,"Pager"); break;
}
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"%c%cValidity = ",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
switch (SMSC->Validity.Relative) {
case SMS_VALID_1_Hour : sprintf(buffer, "1hour" ); break;
case SMS_VALID_6_Hours : sprintf(buffer, "6hours" ); break;
case SMS_VALID_1_Day : sprintf(buffer, "24hours" ); break;
case SMS_VALID_3_Days : sprintf(buffer, "72hours" ); break;
case SMS_VALID_1_Week : sprintf(buffer, "1week" ); break;
case SMS_VALID_Max_Time :
default : sprintf(buffer,"MaximumTime" ); break;
}
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"%c%c%c%c",13,10,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
static void SaveRingtoneEntry(FILE *file, GSM_Ringtone *ringtone, bool UseUnicode)
{
- unsigned char buffer[45000];
- int i,j;
+ unsigned char buffer[45000];
sprintf(buffer,"Location = %i%c%c",ringtone->Location,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveBackupText(file, "Name", ringtone->Name, UseUnicode);
switch (ringtone->Format) {
case RING_NOKIABINARY:
- j = 0; i = 0;
EncodeHexBin(buffer,ringtone->NokiaBinary.Frame,ringtone->NokiaBinary.Length);
SaveLinkedBackupText(file, "NokiaBinary", buffer, UseUnicode);
break;
case RING_MIDI:
- j = 0; i = 0;
EncodeHexBin(buffer,ringtone->NokiaBinary.Frame,ringtone->NokiaBinary.Length);
SaveLinkedBackupText(file, "Pure Midi", buffer, UseUnicode);
break;
+ case RING_MMF:
+ EncodeHexBin(buffer,ringtone->NokiaBinary.Frame,ringtone->NokiaBinary.Length);
+ SaveLinkedBackupText(file, "SMAF", buffer, UseUnicode);
+ break;
case RING_NOTETONE:
break;
}
sprintf(buffer,"%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
static void SaveOperatorEntry(FILE *file, GSM_Bitmap *bitmap, bool UseUnicode)
{
unsigned char buffer[1000];
sprintf(buffer,"[Operator]%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"Network = \"%s\"%c%c", bitmap->NetworkCode,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveBitmapEntry(file, bitmap, UseUnicode);
sprintf(buffer,"%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
static void SaveToDoEntry(FILE *file, GSM_ToDoEntry *ToDo, bool UseUnicode)
{
unsigned char buffer[1000];
int j;
sprintf(buffer,"Location = %i%c%c",ToDo->Location,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
switch (ToDo->Priority) {
case GSM_Priority_High:
sprintf(buffer,"Priority = High%c%c",13,10);
break;
case GSM_Priority_Medium:
sprintf(buffer,"Priority = Medium%c%c",13,10);
break;
case GSM_Priority_Low:
sprintf(buffer,"Priority = Low%c%c",13,10);
break;
}
SaveBackupText(file, "", buffer, UseUnicode);
for (j=0;j<ToDo->EntriesNum;j++) {
switch (ToDo->Entries[j].EntryType) {
case TODO_END_DATETIME:
SaveBackupText(file, "", "DueTime", UseUnicode);
SaveVCalDateTime(file, &ToDo->Entries[j].Date, UseUnicode);
break;
case TODO_COMPLETED:
sprintf(buffer,"Completed = %s%c%c",ToDo->Entries[j].Number == 1 ? "yes" : "no" ,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case TODO_ALARM_DATETIME:
SaveBackupText(file, "", "Alarm", UseUnicode);
SaveVCalDateTime(file, &ToDo->Entries[j].Date, UseUnicode);
break;
case TODO_SILENT_ALARM_DATETIME:
SaveBackupText(file, "", "SilentAlarm", UseUnicode);
SaveVCalDateTime(file, &ToDo->Entries[j].Date, UseUnicode);
break;
case TODO_TEXT:
SaveBackupText(file, "Text", ToDo->Entries[j].Text, UseUnicode);
break;
case TODO_PRIVATE:
sprintf(buffer,"Private = %i%c%c",ToDo->Entries[j].Number,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case TODO_CATEGORY:
sprintf(buffer,"Category = %i%c%c",ToDo->Entries[j].Number,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case TODO_CONTACTID:
sprintf(buffer,"ContactID = %i%c%c",ToDo->Entries[j].Number,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case TODO_PHONE:
SaveBackupText(file, "Phone", ToDo->Entries[j].Text, UseUnicode);
break;
}
}
sprintf(buffer,"%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
static void SaveProfileEntry(FILE *file, GSM_Profile *Profile, bool UseUnicode)
{
int j,k;
bool special;
unsigned char buffer[1000];
sprintf(buffer,"Location = %i%c%c",Profile->Location,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveBackupText(file, "Name",Profile->Name, UseUnicode);
if (Profile->DefaultName) {
sprintf(buffer,"DefaultName = true%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
if (Profile->HeadSetProfile) {
sprintf(buffer,"HeadSetProfile = true%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
if (Profile->CarKitProfile) {
sprintf(buffer,"CarKitProfile = true%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
for (j=0;j<Profile->FeaturesNumber;j++) {
sprintf(buffer,"Feature%02i = ",j);
SaveBackupText(file, "", buffer, UseUnicode);
special = false;
switch (Profile->FeatureID[j]) {
case Profile_MessageToneID:
case Profile_RingtoneID:
special = true;
if (Profile->FeatureID[j] == Profile_RingtoneID) {
sprintf(buffer,"RingtoneID%c%c",13,10);
} else {
sprintf(buffer,"MessageToneID%c%c",13,10);
}
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"Value%02i = %i%c%c",j,Profile->FeatureValue[j],13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case Profile_CallerGroups:
special = true;
sprintf(buffer,"CallerGroups%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"Value%02i = ",j);
SaveBackupText(file, "", buffer, UseUnicode);
for (k=0;k<5;k++) {
if (Profile->CallerGroups[k]) {
sprintf(buffer,"%i",k);
SaveBackupText(file, "", buffer, UseUnicode);
}
}
sprintf(buffer,"%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case Profile_ScreenSaverNumber:
special = true;
sprintf(buffer,"ScreenSaverNumber%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"Value%02i = %i%c%c",j,Profile->FeatureValue[j],13,10);
SaveBackupText(file, "", buffer, UseUnicode);
break;
case Profile_CallAlert : sprintf(buffer,"IncomingCallAlert%c%c",13,10); break;
case Profile_RingtoneVolume : sprintf(buffer,"RingtoneVolume%c%c",13,10); break;
case Profile_Vibration : sprintf(buffer,"Vibrating%c%c",13,10); break;
case Profile_MessageTone : sprintf(buffer,"MessageTone%c%c",13,10); break;
case Profile_KeypadTone : sprintf(buffer,"KeypadTones%c%c",13,10); break;
case Profile_WarningTone : sprintf(buffer,"WarningTones%c%c",13,10); break;
case Profile_ScreenSaver : sprintf(buffer,"ScreenSaver%c%c",13,10); break;
case Profile_ScreenSaverTime : sprintf(buffer,"ScreenSaverTimeout%c%c",13,10); break;
case Profile_AutoAnswer : sprintf(buffer,"AutomaticAnswer%c%c",13,10); break;
case Profile_Lights : sprintf(buffer,"Lights%c%c",13,10); break;
default : special = true;
}
if (!special) {
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"Value%02i = ",j);
SaveBackupText(file, "", buffer, UseUnicode);
switch (Profile->FeatureValue[j]) {
case PROFILE_VOLUME_LEVEL1 :
case PROFILE_KEYPAD_LEVEL1 : sprintf(buffer,"Level1%c%c",13,10); break;
case PROFILE_VOLUME_LEVEL2 :
case PROFILE_KEYPAD_LEVEL2 : sprintf(buffer,"Level2%c%c",13,10); break;
case PROFILE_VOLUME_LEVEL3 :
case PROFILE_KEYPAD_LEVEL3 : sprintf(buffer,"Level3%c%c",13,10); break;
case PROFILE_VOLUME_LEVEL4 : sprintf(buffer,"Level4%c%c",13,10); break;
case PROFILE_VOLUME_LEVEL5 : sprintf(buffer,"Level5%c%c",13,10); break;
case PROFILE_MESSAGE_NOTONE :
case PROFILE_AUTOANSWER_OFF :
case PROFILE_LIGHTS_OFF :
case PROFILE_SAVER_OFF :
case PROFILE_WARNING_OFF :
case PROFILE_CALLALERT_OFF :
case PROFILE_VIBRATION_OFF :
case PROFILE_KEYPAD_OFF : sprintf(buffer,"Off%c%c",13,10); break;
case PROFILE_CALLALERT_RINGING : sprintf(buffer,"Ringing%c%c",13,10); break;
case PROFILE_CALLALERT_RINGONCE : sprintf(buffer,"RingOnce%c%c",13,10); break;
case PROFILE_CALLALERT_ASCENDING : sprintf(buffer,"Ascending%c%c",13,10); break;
case PROFILE_CALLALERT_CALLERGROUPS : sprintf(buffer,"CallerGroups%c%c",13,10); break;
case PROFILE_MESSAGE_STANDARD : sprintf(buffer,"Standard%c%c",13,10); break;
case PROFILE_MESSAGE_SPECIAL : sprintf(buffer,"Special%c%c",13,10); break;
case PROFILE_MESSAGE_BEEPONCE :
case PROFILE_CALLALERT_BEEPONCE : sprintf(buffer,"BeepOnce%c%c",13,10); break;
case PROFILE_MESSAGE_ASCENDING : sprintf(buffer,"Ascending%c%c",13,10); break;
case PROFILE_MESSAGE_PERSONAL : sprintf(buffer,"Personal%c%c",13,10); break;
case PROFILE_AUTOANSWER_ON :
case PROFILE_WARNING_ON :
case PROFILE_SAVER_ON :
case PROFILE_VIBRATION_ON : sprintf(buffer,"On%c%c",13,10); break;
case PROFILE_VIBRATION_FIRST : sprintf(buffer,"VibrateFirst%c%c",13,10); break;
case PROFILE_LIGHTS_AUTO : sprintf(buffer,"Auto%c%c",13,10); break;
case PROFILE_SAVER_TIMEOUT_5SEC : sprintf(buffer,"5Seconds%c%c",13,10); break;
case PROFILE_SAVER_TIMEOUT_20SEC : sprintf(buffer,"20Seconds%c%c",13,10); break;
case PROFILE_SAVER_TIMEOUT_1MIN : sprintf(buffer,"1Minute%c%c",13,10); break;
case PROFILE_SAVER_TIMEOUT_2MIN : sprintf(buffer,"2Minutes%c%c",13,10); break;
case PROFILE_SAVER_TIMEOUT_5MIN : sprintf(buffer,"5Minutes%c%c",13,10); break;
case PROFILE_SAVER_TIMEOUT_10MIN : sprintf(buffer,"10Minutes%c%c",13,10); break;
default : sprintf(buffer,"UNKNOWN%c%c",13,10);
}
SaveBackupText(file, "", buffer, UseUnicode);
}
}
sprintf(buffer,"%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
static void SaveFMStationEntry(FILE *file, GSM_FMStation *FMStation, bool UseUnicode)
{
unsigned char buffer[1000];
sprintf(buffer,"Location = %i%c%c",FMStation->Location,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveBackupText(file, "StationName", FMStation->StationName, UseUnicode);
sprintf(buffer,"Frequency = %f%c%c",FMStation->Frequency,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
static void SaveGPRSPointEntry(FILE *file, GSM_GPRSAccessPoint *GPRSPoint, bool UseUnicode)
{
unsigned char buffer[1000];
sprintf(buffer,"Location = %i%c%c",GPRSPoint->Location,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveBackupText(file, "Name", GPRSPoint->Name, UseUnicode);
SaveBackupText(file, "URL", GPRSPoint->URL, UseUnicode);
if (GPRSPoint->Active) {
sprintf(buffer,"Active = Yes%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
sprintf(buffer,"%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
GSM_Error SaveBackup(char *FileName, GSM_Backup *backup, bool UseUnicode)
{
int i;
unsigned char buffer[1000],checksum[200];
FILE *file;
file = fopen(FileName, "wb");
if (file == NULL) return ERR_CANTOPENFILE;
if (UseUnicode) {
sprintf(buffer,"%c%c", 0xFE, 0xFF);
SaveBackupText(file, "", buffer, false);
}
sprintf(buffer,"# Format of this file was designed for Gammu (see www.mwiacek.com)%c%c%c%c",13,10,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"[Backup]%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"IMEI = \"%s\"%c%c",backup->IMEI,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"Phone = \"%s\"%c%c",backup->Model,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
if (backup->Creator[0] != 0) {
sprintf(buffer,"Creator = \"%s\"%c%c",backup->Creator,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
}
if (backup->DateTimeAvailable) {
SaveBackupText(file, "", "DateTime", UseUnicode);
SaveVCalDateTime(file, &backup->DateTime, UseUnicode);
}
sprintf(buffer,"Format = 1.03%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
i=0;
while (backup->PhonePhonebook[i]!=NULL) {
sprintf(buffer,"[PhonePBK%03i]%c%c",i+1,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SavePbkEntry(file, backup->PhonePhonebook[i], UseUnicode);
i++;
}
i=0;
while (backup->SIMPhonebook[i]!=NULL) {
sprintf(buffer,"[SIMPBK%03i]%c%c",i+1,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SavePbkEntry(file, backup->SIMPhonebook[i], UseUnicode);
i++;
}
i=0;
while (backup->Calendar[i]!=NULL) {
sprintf(buffer,"[Calendar%03i]%c%c",i+1,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveCalendarEntry(file, backup->Calendar[i], UseUnicode);
i++;
}
i=0;
+ while (backup->Note[i]!=NULL) {
+ sprintf(buffer,"[Note%03i]%c%c",i+1,13,10);
+ SaveBackupText(file, "", buffer, UseUnicode);
+ SaveNoteEntry(file, backup->Note[i], UseUnicode);
+ i++;
+ }
+ i=0;
while (backup->CallerLogos[i]!=NULL) {
sprintf(buffer,"[Caller%03i]%c%c",i+1,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveCallerEntry(file, backup->CallerLogos[i], UseUnicode);
i++;
}
i=0;
while (backup->SMSC[i]!=NULL) {
sprintf(buffer,"[SMSC%03i]%c%c",i+1,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveSMSCEntry(file, backup->SMSC[i], UseUnicode);
i++;
}
i=0;
while (backup->WAPBookmark[i]!=NULL) {
sprintf(buffer,"[WAPBookmark%03i]%c%c",i+1,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveWAPBookmarkEntry(file, backup->WAPBookmark[i], UseUnicode);
i++;
}
i=0;
while (backup->WAPSettings[i]!=NULL) {
sprintf(buffer,"[WAPSettings%03i]%c%c",i+1,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveWAPSettingsEntry(file, backup->WAPSettings[i], UseUnicode);
i++;
}
i=0;
while (backup->MMSSettings[i]!=NULL) {
sprintf(buffer,"[MMSSettings%03i]%c%c",i+1,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveWAPSettingsEntry(file, backup->MMSSettings[i], UseUnicode);
i++;
}
i=0;
+ while (backup->SyncMLSettings[i]!=NULL) {
+ sprintf(buffer,"[SyncMLSettings%03i]%c%c",i+1,13,10);
+ SaveBackupText(file, "", buffer, UseUnicode);
+ SaveSyncMLSettingsEntry(file, backup->SyncMLSettings[i], UseUnicode);
+ i++;
+ }
+ i=0;
+ while (backup->ChatSettings[i]!=NULL) {
+ sprintf(buffer,"[ChatSettings%03i]%c%c",i+1,13,10);
+ SaveBackupText(file, "", buffer, UseUnicode);
+ SaveChatSettingsEntry(file, backup->ChatSettings[i], UseUnicode);
+ i++;
+ }
+ i=0;
while (backup->Ringtone[i]!=NULL) {
sprintf(buffer,"[Ringtone%03i]%c%c",i+1,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveRingtoneEntry(file, backup->Ringtone[i], UseUnicode);
i++;
}
i=0;
while (backup->ToDo[i]!=NULL) {
sprintf(buffer,"[TODO%03i]%c%c",i+1,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveToDoEntry(file, backup->ToDo[i], UseUnicode);
i++;
}
i=0;
while (backup->Profiles[i]!=NULL) {
sprintf(buffer,"[Profile%03i]%c%c",i+1,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveProfileEntry(file, backup->Profiles[i], UseUnicode);
i++;
}
i=0;
while (backup->FMStation[i]!=NULL) {
sprintf(buffer,"[FMStation%03i]%c%c",i+1,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveFMStationEntry(file, backup->FMStation[i], UseUnicode);
i++;
}
i=0;
while (backup->GPRSPoint[i]!=NULL) {
sprintf(buffer,"[GPRSPoint%03i]%c%c",i+1,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
SaveGPRSPointEntry(file, backup->GPRSPoint[i], UseUnicode);
i++;
}
if (backup->StartupLogo!=NULL) {
SaveStartupEntry(file, backup->StartupLogo, UseUnicode);
}
if (backup->OperatorLogo!=NULL) {
SaveOperatorEntry(file, backup->OperatorLogo, UseUnicode);
}
fclose(file);
FindBackupChecksum(FileName, UseUnicode, checksum);
file = fopen(FileName, "ab");
if (file == NULL) return ERR_CANTOPENFILE;
sprintf(buffer,"[Checksum]%c%c",13,10);
SaveBackupText(file, "", buffer, UseUnicode);
sprintf(buffer,"MD5=%s%c%c",checksum,13,10);
SaveBackupText(file, "", buffer, UseUnicode);
fclose(file);
return ERR_NONE;
}
static void ReadPbkEntry(INI_Section *file_info, char *section, GSM_MemoryEntry *Pbk, bool UseUnicode)
{
unsigned char buffer[10000];
char *readvalue;
int num,i;
INI_Entry *e;
Pbk->EntriesNum = 0;
e = INI_FindLastSectionEntry(file_info, section, UseUnicode);
while (e != NULL) {
num = -1;
if (UseUnicode) {
sprintf(buffer,"%s",DecodeUnicodeString(e->EntryName));
} else {
sprintf(buffer,"%s",e->EntryName);
}
if (strlen(buffer) == 11) {
if (mystrncasecmp("Entry", buffer, 5) &&
mystrncasecmp("Type", buffer+7, 4)) {
num = atoi(buffer+5);
}
}
e = e->Prev;
if (num != -1) {
sprintf(buffer,"Entry%02iType",num);
readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
if (mystrncasecmp(readvalue,"NumberGeneral",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_General;
} else if (mystrncasecmp(readvalue,"NumberMobile",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Mobile;
} else if (mystrncasecmp(readvalue,"NumberWork",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Work;
} else if (mystrncasecmp(readvalue,"NumberFax",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Fax;
} else if (mystrncasecmp(readvalue,"NumberHome",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Home;
} else if (mystrncasecmp(readvalue,"NumberOther",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Other;
} else if (mystrncasecmp(readvalue,"NumberPager",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Pager;
} else if (mystrncasecmp(readvalue,"Note",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Note;
} else if (mystrncasecmp(readvalue,"Postal",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Postal;
} else if (mystrncasecmp(readvalue,"Email",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Email;
} else if (mystrncasecmp(readvalue,"Email2",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Email2;
} else if (mystrncasecmp(readvalue,"URL",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_URL;
} else if (mystrncasecmp(readvalue,"FirstName",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_FirstName;
} else if (mystrncasecmp(readvalue,"LastName",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_LastName;
} else if (mystrncasecmp(readvalue,"Company",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Company;
} else if (mystrncasecmp(readvalue,"JobTitle",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_JobTitle;
} else if (mystrncasecmp(readvalue,"Address",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_StreetAddress;
} else if (mystrncasecmp(readvalue,"City",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_City;
} else if (mystrncasecmp(readvalue,"State",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_State;
} else if (mystrncasecmp(readvalue,"Zip",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Zip;
} else if (mystrncasecmp(readvalue,"Country",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Country;
} else if (mystrncasecmp(readvalue,"Custom1",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Custom1;
} else if (mystrncasecmp(readvalue,"Custom2",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Custom2;
} else if (mystrncasecmp(readvalue,"Custom3",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Custom3;
} else if (mystrncasecmp(readvalue,"Custom4",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Custom4;
} else if (mystrncasecmp(readvalue,"Name",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Name;
} else if (mystrncasecmp(readvalue,"Category",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Category;
Pbk->Entries[Pbk->EntriesNum].Number = 0;
sprintf(buffer,"Entry%02iNumber",num);
readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
if (readvalue!=NULL) {
Pbk->Entries[Pbk->EntriesNum].Number = atoi(readvalue);
}
Pbk->EntriesNum ++;
continue;
} else if (mystrncasecmp(readvalue,"Private",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Private;
Pbk->Entries[Pbk->EntriesNum].Number = 0;
sprintf(buffer,"Entry%02iNumber",num);
readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
if (readvalue!=NULL) {
Pbk->Entries[Pbk->EntriesNum].Number = atoi(readvalue);
}
Pbk->EntriesNum ++;
continue;
} else if (mystrncasecmp(readvalue,"CallerGroup",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Caller_Group;
Pbk->Entries[Pbk->EntriesNum].Number = 0;
sprintf(buffer,"Entry%02iNumber",num);
readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
if (readvalue!=NULL) {
Pbk->Entries[Pbk->EntriesNum].Number = atoi(readvalue);
}
Pbk->EntriesNum ++;
continue;
} else if (mystrncasecmp(readvalue,"RingtoneID",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_RingtoneID;
Pbk->Entries[Pbk->EntriesNum].Number = 0;
sprintf(buffer,"Entry%02iNumber",num);
readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
if (readvalue!=NULL) {
Pbk->Entries[Pbk->EntriesNum].Number = atoi(readvalue);
}
Pbk->EntriesNum ++;
continue;
} else if (mystrncasecmp(readvalue,"PictureID",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_PictureID;
Pbk->Entries[Pbk->EntriesNum].Number = 0;
sprintf(buffer,"Entry%02iNumber",num);
readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
if (readvalue!=NULL) {
Pbk->Entries[Pbk->EntriesNum].Number = atoi(readvalue);
}
Pbk->EntriesNum ++;
continue;
} else if (mystrncasecmp(readvalue,"UserID",0)) {
Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_UserID;
}
sprintf(buffer,"Entry%02iText",num);
ReadBackupText(file_info, section, buffer, Pbk->Entries[Pbk->EntriesNum].Text,UseUnicode);
dbgprintf("text \"%s\", type %i\n",DecodeUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text),Pbk->Entries[Pbk->EntriesNum].EntryType);
@@ -2467,385 +2543,510 @@ GSM_Error LoadBackup(char *FileName, GSM_Backup *backup, bool UseUnicode)
} else {
if (mystrncasecmp("WAPSettings", h->SectionName, 11)) found = true;
if (!found) {
if (mystrncasecmp("Settings", h->SectionName, 8)) found = true;
}
}
if (found) {
readvalue = ReadCFGText(file_info, h->SectionName, "Title00", UseUnicode);
if (readvalue==NULL) break;
if (num < GSM_BACKUP_MAX_WAPSETTINGS) {
backup->WAPSettings[num] = malloc(sizeof(GSM_MultiWAPSettings));
if (backup->WAPSettings[num] == NULL) return ERR_MOREMEMORY;
backup->WAPSettings[num + 1] = NULL;
} else {
dbgprintf("Increase GSM_BACKUP_MAX_WAPSETTINGS\n");
return ERR_MOREMEMORY;
}
backup->WAPSettings[num]->Location = num + 1;
dbgprintf("reading wap settings\n");
ReadWAPSettingsEntry(file_info, h->SectionName, backup->WAPSettings[num],UseUnicode);
num++;
}
}
num = 0;
for (h = file_info; h != NULL; h = h->Next) {
found = false;
if (UseUnicode) {
EncodeUnicode(buffer,"MMSSettings",8);
if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
} else {
if (mystrncasecmp("MMSSettings", h->SectionName, 8)) found = true;
}
if (found) {
readvalue = ReadCFGText(file_info, h->SectionName, "Title00", UseUnicode);
if (readvalue==NULL) break;
if (num < GSM_BACKUP_MAX_MMSSETTINGS) {
backup->MMSSettings[num] = malloc(sizeof(GSM_MultiWAPSettings));
if (backup->MMSSettings[num] == NULL) return ERR_MOREMEMORY;
backup->MMSSettings[num + 1] = NULL;
} else {
dbgprintf("Increase GSM_BACKUP_MAX_MMSSETTINGS\n");
return ERR_MOREMEMORY;
}
backup->MMSSettings[num]->Location = num + 1;
dbgprintf("reading mms settings\n");
ReadWAPSettingsEntry(file_info, h->SectionName, backup->MMSSettings[num],UseUnicode);
num++;
}
}
num = 0;
for (h = file_info; h != NULL; h = h->Next) {
found = false;
if (UseUnicode) {
EncodeUnicode(buffer,"Ringtone",8);
if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
} else {
if (mystrncasecmp("Ringtone", h->SectionName, 8)) found = true;
}
if (found) {
readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
if (readvalue==NULL) break;
if (num < GSM_BACKUP_MAX_RINGTONES) {
backup->Ringtone[num] = malloc(sizeof(GSM_Ringtone));
if (backup->Ringtone[num] == NULL) return ERR_MOREMEMORY;
backup->Ringtone[num + 1] = NULL;
} else {
dbgprintf("Increase GSM_BACKUP_MAX_RINGTONES\n");
return ERR_MOREMEMORY;
}
ReadRingtoneEntry(file_info, h->SectionName, backup->Ringtone[num],UseUnicode);
num++;
}
}
num = 0;
for (h = file_info; h != NULL; h = h->Next) {
found = false;
if (UseUnicode) {
EncodeUnicode(buffer,"TODO",4);
if (mywstrncasecmp(buffer, h->SectionName, 4)) found = true;
} else {
if (mystrncasecmp("TODO", h->SectionName, 4)) found = true;
}
if (found) {
readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
if (readvalue==NULL) break;
if (num < GSM_MAXCALENDARTODONOTES) {
backup->ToDo[num] = malloc(sizeof(GSM_ToDoEntry));
if (backup->ToDo[num] == NULL) return ERR_MOREMEMORY;
backup->ToDo[num + 1] = NULL;
} else {
dbgprintf("Increase GSM_MAXCALENDARTODONOTES\n");
return ERR_MOREMEMORY;
}
backup->ToDo[num]->Location = num + 1;
ReadToDoEntry(file_info, h->SectionName, backup->ToDo[num],UseUnicode);
num++;
}
}
sprintf(buffer,"Startup");
readvalue = ReadCFGText(file_info, buffer, "Text", UseUnicode);
if (readvalue==NULL) {
readvalue = ReadCFGText(file_info, buffer, "Width", UseUnicode);
}
if (readvalue!=NULL) {
backup->StartupLogo = malloc(sizeof(GSM_Bitmap));
if (backup->StartupLogo == NULL) return ERR_MOREMEMORY;
ReadStartupEntry(file_info, buffer, backup->StartupLogo,UseUnicode);
}
sprintf(buffer,"Operator");
readvalue = ReadCFGText(file_info, buffer, "Network", UseUnicode);
if (readvalue!=NULL) {
backup->OperatorLogo = malloc(sizeof(GSM_Bitmap));
if (backup->OperatorLogo == NULL) return ERR_MOREMEMORY;
ReadOperatorEntry(file_info, buffer, backup->OperatorLogo,UseUnicode);
}
num = 0;
for (h = file_info; h != NULL; h = h->Next) {
found = false;
if (UseUnicode) {
EncodeUnicode(buffer,"FMStation",9);
if (mywstrncasecmp(buffer, h->SectionName, 9)) found = true;
} else {
if (mystrncasecmp("FMStation", h->SectionName, 9)) found = true;
}
if (found) {
readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
if (readvalue==NULL) break;
if (num < GSM_BACKUP_MAX_FMSTATIONS) {
backup->FMStation[num] = malloc(sizeof(GSM_FMStation));
if (backup->FMStation[num] == NULL) return ERR_MOREMEMORY;
backup->FMStation[num + 1] = NULL;
} else {
dbgprintf("Increase GSM_BACKUP_MAX_FMSTATIONS\n");
return ERR_MOREMEMORY;
}
backup->FMStation[num]->Location = num + 1;
ReadFMStationEntry(file_info, h->SectionName, backup->FMStation[num],UseUnicode);
num++;
}
}
num = 0;
for (h = file_info; h != NULL; h = h->Next) {
found = false;
if (UseUnicode) {
EncodeUnicode(buffer,"GPRSPoint",9);
if (mywstrncasecmp(buffer, h->SectionName, 9)) found = true;
} else {
if (mystrncasecmp("GPRSPoint", h->SectionName, 9)) found = true;
}
if (found) {
readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
if (readvalue==NULL) break;
if (num < GSM_BACKUP_MAX_GPRSPOINT) {
backup->GPRSPoint[num] = malloc(sizeof(GSM_GPRSAccessPoint));
if (backup->GPRSPoint[num] == NULL) return ERR_MOREMEMORY;
backup->GPRSPoint[num + 1] = NULL;
} else {
dbgprintf("Increase GSM_BACKUP_MAX_GPRSPOINT\n");
return ERR_MOREMEMORY;
}
backup->GPRSPoint[num]->Location = num + 1;
ReadGPRSPointEntry(file_info, h->SectionName, backup->GPRSPoint[num],UseUnicode);
num++;
}
}
num = 0;
for (h = file_info; h != NULL; h = h->Next) {
found = false;
if (UseUnicode) {
EncodeUnicode(buffer,"Note",4);
if (mywstrncasecmp(buffer, h->SectionName, 4)) found = true;
} else {
if (mystrncasecmp("Note", h->SectionName, 4)) found = true;
}
if (found) {
readvalue = ReadCFGText(file_info, h->SectionName, "Text", UseUnicode);
if (readvalue==NULL) break;
if (num < GSM_BACKUP_MAX_NOTE) {
backup->Note[num] = malloc(sizeof(GSM_NoteEntry));
if (backup->Note[num] == NULL) return ERR_MOREMEMORY;
backup->Note[num + 1] = NULL;
} else {
dbgprintf("Increase GSM_BACKUP_MAX_NOTE\n");
return ERR_MOREMEMORY;
}
ReadNoteEntry(file_info, h->SectionName, backup->Note[num],UseUnicode);
num++;
}
}
if (backup->MD5Original[0]!=0) {
FindBackupChecksum(FileName, UseUnicode, backup->MD5Calculated);
}
-
+ for (h = file_info; h != NULL; h = h->Next) {
+ found = false;
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"Backup",4);
+ if (mywstrncasecmp(buffer, h->SectionName, 6)) found = true;
+ } else {
+ if (mystrncasecmp("Backup", h->SectionName, 6)) found = true;
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"Checksum",4);
+ if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
+ } else {
+ if (mystrncasecmp("Checksum", h->SectionName, 8)) found = true;
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"Profile",7);
+ if (mywstrncasecmp(buffer, h->SectionName, 7)) found = true;
+ } else {
+ if (mystrncasecmp("Profile", h->SectionName, 7)) found = true;
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"PhonePBK",8);
+ if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
+ } else {
+ if (mystrncasecmp("PhonePBK", h->SectionName, 8)) found = true;
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"SIMPBK",6);
+ if (mywstrncasecmp(buffer, h->SectionName, 6)) found = true;
+ } else {
+ if (mystrncasecmp("SIMPBK", h->SectionName, 6)) found = true;
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"Calendar",8);
+ if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
+ } else {
+ if (mystrncasecmp("Calendar", h->SectionName, 8)) found = true;
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"Caller",6);
+ if (mywstrncasecmp(buffer, h->SectionName, 6)) found = true;
+ } else {
+ if (mystrncasecmp("Caller", h->SectionName, 6)) found = true;
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"SMSC",4);
+ if (mywstrncasecmp(buffer, h->SectionName, 4)) found = true;
+ } else {
+ if (mystrncasecmp("SMSC", h->SectionName, 4)) found = true;
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"WAPBookmark",11);
+ if (mywstrncasecmp(buffer, h->SectionName, 11)) found = true;
+ if (!found) {
+ EncodeUnicode(buffer,"Bookmark",8);
+ if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
+ }
+ } else {
+ if (mystrncasecmp("WAPBookmark", h->SectionName, 11)) found = true;
+ if (!found) {
+ if (mystrncasecmp("Bookmark", h->SectionName, 8)) found = true;
+ }
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"WAPSettings",11);
+ if (mywstrncasecmp(buffer, h->SectionName, 11)) found = true;
+ if (!found) {
+ EncodeUnicode(buffer,"Settings",8);
+ if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
+ }
+ } else {
+ if (mystrncasecmp("WAPSettings", h->SectionName, 11)) found = true;
+ if (!found) {
+ if (mystrncasecmp("Settings", h->SectionName, 8)) found = true;
+ }
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"MMSSettings",8);
+ if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
+ } else {
+ if (mystrncasecmp("MMSSettings", h->SectionName, 8)) found = true;
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"Ringtone",8);
+ if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
+ } else {
+ if (mystrncasecmp("Ringtone", h->SectionName, 8)) found = true;
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"TODO",4);
+ if (mywstrncasecmp(buffer, h->SectionName, 4)) found = true;
+ } else {
+ if (mystrncasecmp("TODO", h->SectionName, 4)) found = true;
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"Startup",7);
+ if (mywstrncasecmp(buffer, h->SectionName, 7)) found = true;
+ } else {
+ if (mystrncasecmp("Startup", h->SectionName, 7)) found = true;
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"Operator",7);
+ if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
+ } else {
+ if (mystrncasecmp("Operator", h->SectionName, 8)) found = true;
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"FMStation",9);
+ if (mywstrncasecmp(buffer, h->SectionName, 9)) found = true;
+ } else {
+ if (mystrncasecmp("FMStation", h->SectionName, 9)) found = true;
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"GPRSPoint",9);
+ if (mywstrncasecmp(buffer, h->SectionName, 9)) found = true;
+ } else {
+ if (mystrncasecmp("GPRSPoint", h->SectionName, 9)) found = true;
+ }
+ if (UseUnicode) {
+ EncodeUnicode(buffer,"Note",4);
+ if (mywstrncasecmp(buffer, h->SectionName, 4)) found = true;
+ } else {
+ if (mystrncasecmp("Note", h->SectionName, 4)) found = true;
+ }
+ if (!found) return ERR_NOTIMPLEMENTED;
+ }
return ERR_NONE;
}
/* ---------------------- backup files for SMS ----------------------------- */
static void ReadSMSBackupEntry(INI_Section *file_info, char *section, GSM_SMSMessage *SMS)
{
unsigned char buffer[10000], *readvalue;
GSM_SetDefaultSMSData(SMS);
SMS->PDU = SMS_Submit;
SMS->SMSC.Location = 0;
sprintf(buffer,"SMSC");
ReadBackupText(file_info, section, buffer, SMS->SMSC.Number, false);
sprintf(buffer,"ReplySMSC");
SMS->ReplyViaSameSMSC = false;
readvalue = ReadCFGText(file_info, section, buffer, false);
if (readvalue!=NULL) {
if (mystrncasecmp(readvalue,"True",0)) SMS->ReplyViaSameSMSC = true;
}
sprintf(buffer,"Class");
SMS->Class = -1;
readvalue = ReadCFGText(file_info, section, buffer, false);
if (readvalue!=NULL) SMS->Class = atoi(readvalue);
sprintf(buffer,"Sent");
readvalue = ReadCFGText(file_info, section, buffer, false);
if (readvalue!=NULL) {
ReadVCALDateTime(readvalue, &SMS->DateTime);
SMS->PDU = SMS_Deliver;
}
sprintf(buffer,"RejectDuplicates");
SMS->RejectDuplicates = false;
readvalue = ReadCFGText(file_info, section, buffer, false);
if (readvalue!=NULL) {
if (mystrncasecmp(readvalue,"True",0)) SMS->RejectDuplicates = true;
}
sprintf(buffer,"ReplaceMessage");
SMS->ReplaceMessage = 0;
readvalue = ReadCFGText(file_info, section, buffer, false);
if (readvalue!=NULL) SMS->ReplaceMessage = atoi(readvalue);
sprintf(buffer,"MessageReference");
SMS->MessageReference = 0;
readvalue = ReadCFGText(file_info, section, buffer, false);
if (readvalue!=NULL) SMS->MessageReference = atoi(readvalue);
sprintf(buffer,"State");
SMS->State = SMS_UnRead;
readvalue = ReadCFGText(file_info, section, buffer, false);
if (readvalue!=NULL) {
if (mystrncasecmp(readvalue,"Read",0)) SMS->State = SMS_Read;
else if (mystrncasecmp(readvalue,"Sent",0)) SMS->State = SMS_Sent;
else if (mystrncasecmp(readvalue,"UnSent",0)) SMS->State = SMS_UnSent;
}
sprintf(buffer,"Number");
ReadBackupText(file_info, section, buffer, SMS->Number, false);
sprintf(buffer,"Name");
ReadBackupText(file_info, section, buffer, SMS->Name, false);
sprintf(buffer,"Length");
SMS->Length = 0;
readvalue = ReadCFGText(file_info, section, buffer, false);
if (readvalue!=NULL) SMS->Length = atoi(readvalue);
sprintf(buffer,"Coding");
SMS->Coding = SMS_Coding_Default;
readvalue = ReadCFGText(file_info, section, buffer, false);
if (readvalue!=NULL) {
if (mystrncasecmp(readvalue,"Unicode",0)) {
SMS->Coding = SMS_Coding_Unicode;
} else if (mystrncasecmp(readvalue,"8bit",0)) {
SMS->Coding = SMS_Coding_8bit;
}
}
ReadLinkedBackupText(file_info, section, "Text", buffer, false);
DecodeHexBin (SMS->Text, buffer, strlen(buffer));
SMS->Text[strlen(buffer)/2] = 0;
SMS->Text[strlen(buffer)/2+1] = 0;
sprintf(buffer,"Folder");
readvalue = ReadCFGText(file_info, section, buffer, false);
if (readvalue!=NULL) SMS->Folder = atoi(readvalue);
SMS->UDH.Type = UDH_NoUDH;
SMS->UDH.Length = 0;
SMS->UDH.ID8bit = -1;
SMS->UDH.ID16bit = -1;
SMS->UDH.PartNumber = -1;
SMS->UDH.AllParts = -1;
sprintf(buffer,"UDH");
readvalue = ReadCFGText(file_info, section, buffer, false);
if (readvalue!=NULL) {
DecodeHexBin (SMS->UDH.Text, readvalue, strlen(readvalue));
SMS->UDH.Length = strlen(readvalue)/2;
GSM_DecodeUDHHeader(&SMS->UDH);
}
}
static GSM_Error GSM_ReadSMSBackupTextFile(char *FileName, GSM_SMS_Backup *backup)
{
INI_Section *file_info, *h;
char *readvalue;
int num;
backup->SMS[0] = NULL;
file_info = INI_ReadFile(FileName, false);
num = 0;
for (h = file_info; h != NULL; h = h->Next) {
if (mystrncasecmp("SMSBackup", h->SectionName, 9)) {
readvalue = ReadCFGText(file_info, h->SectionName, "Number", false);
if (readvalue==NULL) break;
if (num < GSM_BACKUP_MAX_SMS) {
backup->SMS[num] = malloc(sizeof(GSM_SMSMessage));
if (backup->SMS[num] == NULL) return ERR_MOREMEMORY;
backup->SMS[num + 1] = NULL;
} else {
dbgprintf("Increase GSM_BACKUP_MAX_SMS\n");
return ERR_MOREMEMORY;
}
backup->SMS[num]->Location = num + 1;
ReadSMSBackupEntry(file_info, h->SectionName, backup->SMS[num]);
num++;
}
}
return ERR_NONE;
}
GSM_Error GSM_ReadSMSBackupFile(char *FileName, GSM_SMS_Backup *backup)
{
FILE *file;
backup->SMS[0] = NULL;
file = fopen(FileName, "rb");
if (file == NULL) return(ERR_CANTOPENFILE);
fclose(file);
return GSM_ReadSMSBackupTextFile(FileName, backup);
}
GSM_Error SaveSMSBackupTextFile(FILE *file, GSM_SMS_Backup *backup)
{
int i,w,current;
unsigned char buffer[10000];
GSM_DateTime DT;
fprintf(file,"\n# File created by Gammu (www.mwiacek.com) version %s\n",VERSION);
GSM_GetCurrentDateTime (&DT);
fprintf(file,"# Saved %s\n\n",OSDateTime(DT,false));
i=0;
while (backup->SMS[i]!=NULL) {
fprintf(file,"[SMSBackup%03i]\n",i);
switch (backup->SMS[i]->Coding) {
case SMS_Coding_Unicode:
case SMS_Coding_Default:
sprintf(buffer,"%s",DecodeUnicodeString(backup->SMS[i]->Text));
fprintf(file,"#");
current = 0;
for (w=0;w<(int)(strlen(buffer));w++) {
switch (buffer[w]) {
case 10:
fprintf(file,"\n#");
current = 0;
break;
case 13:
break;
default:
if (isprint(buffer[w])) {
fprintf(file,"%c",buffer[w]);
current ++;
}
if (current == 75) {
fprintf(file,"\n#");
current = 0;
}
}
}
fprintf(file,"\n");
break;
default:
break;
}
if (backup->SMS[i]->PDU == SMS_Deliver) {
SaveBackupText(file, "SMSC", backup->SMS[i]->SMSC.Number, false);
if (backup->SMS[i]->ReplyViaSameSMSC) fprintf(file,"SMSCReply = true\n");
fprintf(file,"Sent");
SaveVCalDateTime(file,&backup->SMS[i]->DateTime, false);
}
fprintf(file,"State = ");
switch (backup->SMS[i]->State) {
case SMS_UnRead : fprintf(file,"UnRead\n"); break;
case SMS_Read : fprintf(file,"Read\n"); break;
case SMS_Sent : fprintf(file,"Sent\n"); break;
diff --git a/gammu/emb/common/service/backup/gsmback.c b/gammu/emb/common/service/backup/gsmback.c
index 91ac745..c94a4d2 100644
--- a/gammu/emb/common/service/backup/gsmback.c
+++ b/gammu/emb/common/service/backup/gsmback.c
@@ -1,280 +1,298 @@
/* (c) 2002-2004 by Marcin Wiacek & Michal Cihar */
#include <string.h>
#include <ctype.h>
#include "../../phone/nokia/nfunc.h"
#include "../../phone/nokia/dct3/n7110.h"
#include "../../misc/coding/coding.h"
#include "../../misc/cfg.h"
#include "../gsmlogo.h"
#include "../gsmmisc.h"
#include "../gsmcal.h"
#include "gsmback.h"
#include "backtext.h"
#include "backldif.h"
#include "backlmb.h"
#include "backvcs.h"
#include "backvcf.h"
#include "backics.h"
#ifdef GSM_ENABLE_BACKUP
void GSM_FreeBackup(GSM_Backup *backup)
{
int i;
i=0;
while (backup->PhonePhonebook[i]!=NULL) {
free(backup->PhonePhonebook[i]);
backup->PhonePhonebook[i] = NULL;
i++;
}
i=0;
while (backup->SIMPhonebook[i]!=NULL) {
free(backup->SIMPhonebook[i]);
backup->SIMPhonebook[i] = NULL;
i++;
}
i=0;
while (backup->Calendar[i]!=NULL) {
free(backup->Calendar[i]);
backup->Calendar[i] = NULL;
i++;
}
i=0;
while (backup->CallerLogos[i]!=NULL) {
free(backup->CallerLogos[i]);
backup->CallerLogos[i] = NULL;
i++;
}
i=0;
while (backup->SMSC[i]!=NULL) {
free(backup->SMSC[i]);
backup->SMSC[i] = NULL;
i++;
}
i=0;
while (backup->WAPBookmark[i]!=NULL) {
free(backup->WAPBookmark[i]);
backup->WAPBookmark[i] = NULL;
i++;
}
i=0;
while (backup->WAPSettings[i]!=NULL) {
free(backup->WAPSettings[i]);
backup->WAPSettings[i] = NULL;
i++;
}
i=0;
while (backup->MMSSettings[i]!=NULL) {
free(backup->MMSSettings[i]);
backup->MMSSettings[i] = NULL;
i++;
}
i=0;
+ while (backup->SyncMLSettings[i]!=NULL) {
+ free(backup->SyncMLSettings[i]);
+ backup->SyncMLSettings[i] = NULL;
+ i++;
+ }
+ i=0;
+ while (backup->ChatSettings[i]!=NULL) {
+ free(backup->ChatSettings[i]);
+ backup->ChatSettings[i] = NULL;
+ i++;
+ }
+ i=0;
while (backup->Ringtone[i]!=NULL) {
free(backup->Ringtone[i]);
backup->Ringtone[i] = NULL;
i++;
}
i=0;
while (backup->ToDo[i]!=NULL) {
free(backup->ToDo[i]);
backup->ToDo[i] = NULL;
i++;
}
i=0;
while (backup->Profiles[i]!=NULL) {
free(backup->Profiles[i]);
backup->Profiles[i] = NULL;
i++;
}
i=0;
while (backup->FMStation[i]!=NULL) {
free(backup->FMStation[i]);
backup->FMStation[i] = NULL;
i++;
}
if (backup->StartupLogo!=NULL) {
free(backup->StartupLogo);
backup->StartupLogo = NULL;
}
if (backup->OperatorLogo!=NULL) {
free(backup->OperatorLogo);
backup->OperatorLogo = NULL;
}
i=0;
while (backup->GPRSPoint[i]!=NULL) {
free(backup->GPRSPoint[i]);
backup->GPRSPoint[i] = NULL;
i++;
}
i=0;
while (backup->Note[i]!=NULL) {
free(backup->Note[i]);
backup->Note[i] = NULL;
i++;
}
}
GSM_Error GSM_SaveBackupFile(char *FileName, GSM_Backup *backup, bool UseUnicode)
{
- if (strstr(FileName,".lmb")) {
+ if (mystrcasestr(FileName,".lmb")) {
return SaveLMB(FileName,backup);
- } else if (strstr(FileName,".vcs")) {
+ } else if (mystrcasestr(FileName,".vcs")) {
return SaveVCalendar(FileName,backup);
- } else if (strstr(FileName,".vcf")) {
+ } else if (mystrcasestr(FileName,".vcf")) {
return SaveVCard(FileName,backup);
- } else if (strstr(FileName,".ldif")) {
+ } else if (mystrcasestr(FileName,".ldif")) {
return SaveLDIF(FileName,backup);
- } else if (strstr(FileName,".ics")) {
+ } else if (mystrcasestr(FileName,".ics")) {
return SaveICS(FileName,backup);
} else {
return SaveBackup(FileName,backup, UseUnicode);
}
}
GSM_Error GSM_ReadBackupFile(char *FileName, GSM_Backup *backup)
{
FILE *file;
unsigned char buffer[300];
file = fopen(FileName, "rb");
if (file == NULL) return ERR_CANTOPENFILE;
fread(buffer, 1, 9, file); /* Read the header of the file. */
fclose(file);
GSM_ClearBackup(backup);
/* Attempt to identify filetype */
- if (strstr(FileName,".vcs")) {
+ if (mystrcasestr(FileName,".vcs")) {
return LoadVCalendar(FileName,backup);
- } else if (strstr(FileName,".vcf")) {
+ } else if (mystrcasestr(FileName,".vcf")) {
return LoadVCard(FileName,backup);
- } else if (strstr(FileName,".ldif")) {
+ } else if (mystrcasestr(FileName,".ldif")) {
return LoadLDIF(FileName,backup);
- } else if (strstr(FileName,".ics")) {
+ } else if (mystrcasestr(FileName,".ics")) {
return LoadICS(FileName,backup);
} else if (memcmp(buffer, "LMB ",4)==0) {
return LoadLMB(FileName,backup);
} else if (buffer[0] == 0xFE && buffer[1] == 0xFF) {
return LoadBackup(FileName,backup,true);
} else if (buffer[0] == 0xFF && buffer[1] == 0xFE) {
return LoadBackup(FileName,backup,true);
} else {
return LoadBackup(FileName,backup,false);
}
}
void GSM_ClearBackup(GSM_Backup *backup)
{
backup->PhonePhonebook [0] = NULL;
backup->SIMPhonebook [0] = NULL;
backup->Calendar [0] = NULL;
backup->CallerLogos [0] = NULL;
backup->SMSC [0] = NULL;
backup->WAPBookmark [0] = NULL;
backup->WAPSettings [0] = NULL;
backup->MMSSettings [0] = NULL;
+ backup->SyncMLSettings [0] = NULL;
+ backup->ChatSettings [0] = NULL;
backup->Ringtone [0] = NULL;
backup->Profiles [0] = NULL;
backup->ToDo [0] = NULL;
backup->GPRSPoint [0] = NULL;
backup->FMStation [0] = NULL;
backup->Note [0] = NULL;
backup->StartupLogo = NULL;
backup->OperatorLogo = NULL;
backup->Creator [0] = 0;
backup->IMEI [0] = 0;
backup->Model [0] = 0;
backup->DateTimeAvailable = false;
backup->MD5Original [0] = 0;
backup->MD5Calculated [0] = 0;
}
void GSM_GetBackupFormatFeatures(char *FileName, GSM_Backup_Info *info)
{
info->UseUnicode = false;
info->IMEI = false;
info->Model = false;
info->DateTime = false;
info->PhonePhonebook = false;
info->SIMPhonebook = false;
info->ToDo = false;
info->Calendar = false;
info->CallerLogos = false;
info->SMSC = false;
info->WAPBookmark = false;
info->WAPSettings = false;
info->MMSSettings = false;
+ info->SyncMLSettings = false;
+ info->ChatSettings = false;
info->Ringtone = false;
info->StartupLogo = false;
info->OperatorLogo = false;
info->Profiles = false;
info->FMStation = false;
info->GPRSPoint = false;
info->Note = false;
if (strstr(FileName,".lmb")) {
info->PhonePhonebook = true;
info->SIMPhonebook = true;
info->CallerLogos = true;
info->StartupLogo = true;
} else if (strstr(FileName,".vcs")) {
info->ToDo = true;
info->Calendar = true;
} else if (strstr(FileName,".vcf")) {
info->PhonePhonebook = true;
} else if (strstr(FileName,".ics")) {
info->ToDo = true;
info->Calendar = true;
} else if (strstr(FileName,".ldif")) {
info->PhonePhonebook = true;
} else {
info->UseUnicode = true;
info->IMEI = true;
info->Model = true;
info->DateTime = true;
info->PhonePhonebook = true;
info->SIMPhonebook = true;
info->ToDo = true;
info->Calendar = true;
info->CallerLogos = true;
info->SMSC = true;
info->WAPBookmark = true;
info->WAPSettings = true;
info->MMSSettings = true;
+ info->SyncMLSettings = true;
+ info->ChatSettings = true;
info->Ringtone = true;
info->StartupLogo = true;
info->OperatorLogo = true;
info->Profiles = true;
info->FMStation = true;
info->GPRSPoint = true;
info->Note = true;
}
}
void GSM_GetBackupFileFeatures(char *FileName, GSM_Backup_Info *info, GSM_Backup *backup)
{
GSM_GetBackupFormatFeatures(FileName, info);
if (info->PhonePhonebook && backup->PhonePhonebook[0] == NULL) info->PhonePhonebook = false;
if (info->SIMPhonebook && backup->SIMPhonebook[0] == NULL) info->SIMPhonebook = false;
if (info->Calendar && backup->Calendar[0] == NULL) info->Calendar = false;
if (info->ToDo && backup->ToDo[0] == NULL) info->ToDo = false;
if (info->WAPBookmark && backup->WAPBookmark[0] == NULL) info->WAPBookmark = false;
if (info->WAPSettings && backup->WAPSettings[0] == NULL) info->WAPSettings = false;
if (info->MMSSettings && backup->MMSSettings[0] == NULL) info->MMSSettings = false;
if (info->FMStation && backup->FMStation[0] == NULL) info->FMStation = false;
if (info->GPRSPoint && backup->GPRSPoint[0] == NULL) info->GPRSPoint = false;
if (info->Profiles && backup->Profiles[0] == NULL) info->Profiles = false;
/* .... */
}
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/service/backup/gsmback.h b/gammu/emb/common/service/backup/gsmback.h
index 1fd99b0..791e81d 100644
--- a/gammu/emb/common/service/backup/gsmback.h
+++ b/gammu/emb/common/service/backup/gsmback.h
@@ -1,48 +1,50 @@
/* (c) 2003-2004 by Marcin Wiacek */
#ifndef __gsm_back_h
#define __gsm_back_h
#include "backgen.h"
#ifdef GSM_ENABLE_BACKUP
GSM_Error GSM_SaveBackupFile(char *FileName, GSM_Backup *backup, bool UseUnicode);
GSM_Error GSM_ReadBackupFile(char *FileName, GSM_Backup *backup);
void GSM_ClearBackup (GSM_Backup *backup);
void GSM_FreeBackup (GSM_Backup *backup);
typedef struct {
bool UseUnicode;
bool IMEI;
bool Model;
bool DateTime;
bool ToDo;
bool PhonePhonebook;
bool SIMPhonebook;
bool Calendar;
bool CallerLogos;
bool SMSC;
bool WAPBookmark;
bool Profiles;
bool WAPSettings;
bool MMSSettings;
+ bool SyncMLSettings;
+ bool ChatSettings;
bool Ringtone;
bool StartupLogo;
bool OperatorLogo;
bool FMStation;
bool GPRSPoint;
bool Note;
} GSM_Backup_Info;
void GSM_GetBackupFormatFeatures(char *FileName, GSM_Backup_Info *info);
void GSM_GetBackupFileFeatures (char *FileName, GSM_Backup_Info *info, GSM_Backup *backup);
#endif
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/service/gsmcal.h b/gammu/emb/common/service/gsmcal.h
index 067a4a4..0a41b7b 100644
--- a/gammu/emb/common/service/gsmcal.h
+++ b/gammu/emb/common/service/gsmcal.h
@@ -216,230 +216,230 @@ typedef struct {
*/
unsigned char Text[(MAX_CALENDAR_TEXT_LENGTH + 1)*2];
/**
* Date and time of value, if applicable.
*/
GSM_DateTime Date;
/**
* Number of value, if applicable.
*/
unsigned int Number;
} GSM_SubCalendarEntry;
/**
* Calendar note values.
*/
typedef struct {
/**
* Type of calendar note.
*/
GSM_CalendarNoteType Type;
/**
* Location in memory.
*/
int Location;
/**
* Number of entries.
*/
int EntriesNum;
/**
* Values of entries.
*/
GSM_SubCalendarEntry Entries[GSM_CALENDAR_ENTRIES];
} GSM_CalendarEntry;
void GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(GSM_CalendarEntry *entry, int *Text, int *Time, int *Alarm, int *Phone, int *Recurrance, int *EndTime, int *Location);
typedef enum {
Nokia_VCalendar = 1,
Siemens_VCalendar,
SonyEricsson_VCalendar
} GSM_VCalendarVersion;
GSM_Error GSM_EncodeVCALENDAR(char *Buffer, int *Length, GSM_CalendarEntry *note, bool header, GSM_VCalendarVersion Version);
bool IsCalendarNoteFromThePast(GSM_CalendarEntry *note);
typedef struct {
/**
* Monday = 1, Tuesday = 2,...
*/
int StartDay;
/**
* 0 = no delete, 1 = after day,...
*/
int AutoDelete;
} GSM_CalendarSettings;
/**
* Structure used for returning calendar status.
*/
typedef struct {
/**
* Number of used positions.
*/
int Used;
} GSM_CalendarStatus;
/* ------------------------------ to-do ------------------------------------ */
#define GSM_TODO_ENTRIES 7
#define MAX_TODO_TEXT_LENGTH 50 /* Alcatel BE5 50 chars */
/**
* Types of to do values. In parenthesis is member of @ref GSM_SubToDoEntry,
* where value is stored.
*/
typedef enum {
/**
* Due date. (Date)
*/
TODO_END_DATETIME = 1,
/**
* Whether is completed. (Number)
*/
TODO_COMPLETED,
/**
* When should alarm be fired (Date).
*/
TODO_ALARM_DATETIME,
/**
* When should silent alarm be fired (Date).
*/
TODO_SILENT_ALARM_DATETIME,
/**
* Text of to do (Text).
*/
TODO_TEXT,
/**
* Whether entry is private (Number).
*/
TODO_PRIVATE,
/**
* Category of entry (Number).
*/
TODO_CATEGORY,
/**
* Related contact ID (Number).
*/
TODO_CONTACTID,
/**
* Number to call (Text).
*/
TODO_PHONE
} GSM_ToDoType;
/**
* Priority of to do.
*/
typedef enum {
GSM_Priority_High = 1,
GSM_Priority_Medium,
GSM_Priority_Low
} GSM_ToDo_Priority;
/**
* Value of to do entry.
*/
typedef struct {
/**
* Type of entry.
*/
GSM_ToDoType EntryType;
/**
* Text of value, if appropriate, see @ref GSM_ToDoType.
*/
unsigned char Text[(MAX_TODO_TEXT_LENGTH + 1)*2];
/**
* Date of value, if appropriate, see @ref GSM_ToDoType.
*/
GSM_DateTime Date;
/**
* Number of value, if appropriate, see @ref GSM_ToDoType.
*/
unsigned int Number;
} GSM_SubToDoEntry;
/**
* To do entry.
*/
typedef struct {
/**
* Priority of entry.
*/
GSM_ToDo_Priority Priority;
/**
* Location in memory.
*/
int Location;
/**
* Number of entries.
*/
int EntriesNum;
/**
* Values of current entry.
*/
GSM_SubToDoEntry Entries[GSM_TODO_ENTRIES];
} GSM_ToDoEntry;
void GSM_ToDoFindDefaultTextTimeAlarmCompleted(GSM_ToDoEntry *entry, int *Text, int *Alarm, int *Completed, int *EndTime, int *Phone);
typedef enum {
Nokia_VToDo = 1,
SonyEricsson_VToDo
} GSM_VToDoVersion;
GSM_Error GSM_EncodeVTODO(char *Buffer, int *Length, GSM_ToDoEntry *note, bool header, GSM_VToDoVersion Version);
/**
* Status of to do entries.
*/
typedef struct {
/**
* Number of used positions.
*/
int Used;
} GSM_ToDoStatus;
/* --------------------------- note ---------------------------------------- */
typedef struct {
int Location;
- char Text[100];
+ char Text[3000*2];
} GSM_NoteEntry;
GSM_Error GSM_EncodeVNTFile(unsigned char *Buffer, int *Length, GSM_NoteEntry *Note);
/* --------------------------- alarm --------------------------------------- */
/**
* Alarm values.
*/
typedef struct {
/**
* Location where it is stored.
*/
int Location;
/**
* Date and time of alarm.
*/
GSM_DateTime DateTime;
/**
* Whether it repeats each day.
*/
bool Repeating;
/**
* Text that is shown on display.
*/
char Text[(MAX_CALENDAR_TEXT_LENGTH + 1) * 2];
} GSM_Alarm;
/* --------------------------- calendar & todo ----------------------------- */
GSM_Error GSM_DecodeVCALENDAR_VTODO(unsigned char *Buffer, int *Pos, GSM_CalendarEntry *Calendar, GSM_ToDoEntry *ToDo, GSM_VCalendarVersion CalVer, GSM_VToDoVersion ToDoVer);
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/service/gsmdata.c b/gammu/emb/common/service/gsmdata.c
index 94e9b7b..9303b57 100644
--- a/gammu/emb/common/service/gsmdata.c
+++ b/gammu/emb/common/service/gsmdata.c
@@ -57,310 +57,388 @@ static void AddWAPSMSParameterText(unsigned char *Buffer, int *Length, unsigned
int i;
Buffer[(*Length)++] = 0x87; //PARM with attributes
Buffer[(*Length)++] = ID;
Buffer[(*Length)++] = 0x11; //VALUE
Buffer[(*Length)++] = 0x03; //Inline string
for (i=0;i<Len;i++) {
Buffer[(*Length)++] = Text[i]; //Text
}
Buffer[(*Length)++] = 0x00; //END Inline string
Buffer[(*Length)++] = 0x01; //END PARMeter
}
/* http://forum.nokia.com: OTA MMS Settings 1.0, OTA Settings 7.0 */
static void AddWAPSMSParameterInt(unsigned char *Buffer, int *Length, unsigned char ID, unsigned char Value)
{
Buffer[(*Length)++] = 0x87; //PARM with attributes
Buffer[(*Length)++] = ID;
Buffer[(*Length)++] = Value;
Buffer[(*Length)++] = 0x01; //END PARMeter
}
/* http://forum.nokia.com : OTA MMS Settings 1.0, OTA Settings 7.0
* http://www.wapforum.org : Wireless Datagram Protocol
*/
void NOKIA_EncodeWAPMMSSettingsSMSText(unsigned char *Buffer, int *Length, GSM_WAPSettings *settings, bool MMS)
{
int i;
unsigned char buffer[400];
Buffer[(*Length)++] = 0x01; //Push ID
Buffer[(*Length)++] = 0x06; //PDU Type (push)
Buffer[(*Length)++] = 0x2C; //Headers length (content type + headers)
strcpy(Buffer+(*Length),"\x1F\x2A");
(*Length)=(*Length)+2; //Value length
strcpy(Buffer+(*Length),"application/x-wap-prov.browser-settings");
(*Length)=(*Length)+39; //MIME-Type
Buffer[(*Length)++] = 0x00; //end inline string
strcpy(Buffer+(*Length),"\x81\xEA");
(*Length)=(*Length)+2; //charset UTF-8 short int.
strcpy(Buffer+(*Length),"\x01\x01");
(*Length)=(*Length)+2; //version WBXML 1.1
Buffer[(*Length)++] = 0x6A; //charset UTF-8
Buffer[(*Length)++] = 0x00; //string table length
Buffer[(*Length)++] = 0x45; //CHARACTERISTIC-LIST with content
Buffer[(*Length)++] = 0xC6; //CHARACTERISTIC with content and attributes
Buffer[(*Length)++] = 0x06; //TYPE=ADDRESS
Buffer[(*Length)++] = 0x01; //END PARMeter
switch (settings->Bearer) {
case WAPSETTINGS_BEARER_GPRS:
/* Bearer */
AddWAPSMSParameterInt(Buffer, Length, 0x12, 0x49);
/* PPP_LOGINTYPE (manual login or not) */
if (settings->ManualLogin) {
AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x65);
} else {
AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x64);
}
/* PPP_AUTHTYPE*/
if (settings->IsNormalAuthentication) {
/* OTA_CSD_AUTHTYPE_PAP */
AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x70);
} else {
/* OTA_CSD_AUTHTYPE_CHAP */
AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x71);
}
/* GPRS_ACCESSPOINTNAME */
AddWAPSMSParameterText(Buffer, Length, 0x1C, DecodeUnicodeString(settings->DialUp), UnicodeLength(settings->DialUp));
/* PROXY */
AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->IPAddress), UnicodeLength(settings->IPAddress));
/* PPP_AUTHNAME (user) */
AddWAPSMSParameterText(Buffer, Length, 0x23, DecodeUnicodeString(settings->User), UnicodeLength(settings->User));
/* PPP_AUTHSECRET (password) */
AddWAPSMSParameterText(Buffer, Length, 0x24, DecodeUnicodeString(settings->Password), UnicodeLength(settings->Password));
break;
case WAPSETTINGS_BEARER_DATA:
/* Bearer */
AddWAPSMSParameterInt(Buffer, Length, 0x12, 0x45);
/* CSD_DIALSTRING */
AddWAPSMSParameterText(Buffer, Length, 0x21, DecodeUnicodeString(settings->DialUp), UnicodeLength(settings->DialUp));
/* PROXY */
AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->IPAddress), UnicodeLength(settings->IPAddress));
/* PPP_LOGINTYPE (manual login or not) */
if (settings->ManualLogin) {
AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x65);
} else {
AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x64);
}
/* PPP_AUTHTYPE*/
if (settings->IsNormalAuthentication) {
/* OTA_CSD_AUTHTYPE_PAP */
AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x70);
} else {
/* OTA_CSD_AUTHTYPE_CHAP */
AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x71);
}
/* CSD_CALLTYPE (type of call) */
if (settings->IsISDNCall) {
/* ISDN */
AddWAPSMSParameterInt(Buffer, Length, 0x28, 0x73);
} else {
/* analogue */
AddWAPSMSParameterInt(Buffer, Length, 0x28, 0x72);
}
/* CSD_CALLSPEED (speed of call) */
switch (settings->Speed) {
case WAPSETTINGS_SPEED_AUTO:
AddWAPSMSParameterInt(Buffer, Length, 0x29, 0x6A);
break;
case WAPSETTINGS_SPEED_9600:
AddWAPSMSParameterInt(Buffer, Length, 0x29, 0x6B);
break;
case WAPSETTINGS_SPEED_14400:
AddWAPSMSParameterInt(Buffer, Length, 0x29, 0x6C);
}
/* PPP_AUTHNAME (user) */
AddWAPSMSParameterText(Buffer, Length, 0x23, DecodeUnicodeString(settings->User), UnicodeLength(settings->User));
/* PPP_AUTHSECRET (password) */
AddWAPSMSParameterText(Buffer, Length, 0x24, DecodeUnicodeString(settings->Password), UnicodeLength(settings->Password));
break;
#ifdef DEVELOP
case WAPSETTINGS_BEARER_SMS:
/* Bearer */
AddWAPSMSParameterInt(Buffer, Length, 0x12, 0x41);
/* PROXY */
AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->Server), UnicodeLength(settings->Server));
/* SMS_SMSC_ADDRESS */
// .....
break;
case WAPSETTINGS_BEARER_USSD:
/* FIXME */
/* Bearer */
AddWAPSMSParameterInt(Buffer, Length, 0x12, 0x41);
/* PROXY */
AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->Service), UnicodeLength(settings->Service));
/* USSD_SERVICE_CODE */
/* FIXME */
AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->Code), UnicodeLength(settings->Code));
#else
case WAPSETTINGS_BEARER_SMS:
case WAPSETTINGS_BEARER_USSD:
break;
#endif
}
/* PORT */
if (settings->IsSecurity) {
if (settings->IsContinuous) {
/* Port = 9203. Continuous */
AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x63);
} else {
/* Port = 9202. Temporary */
AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x62);
}
} else {
if (settings->IsContinuous) {
/* Port = 9201. Continuous */
AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x61);
} else {
/* Port = 9200. Temporary */
AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x60);
}
}
Buffer[(*Length)++] = 0x01; //END PARMeter
/* URL */
Buffer[(*Length)++] = 0x86; //CHARACTERISTIC-LIST with attributes
if (MMS) {
Buffer[(*Length)++] = 0x7C; //TYPE = MMSURL
} else {
Buffer[(*Length)++] = 0x07; //TYPE = URL
}
Buffer[(*Length)++] = 0x11; //VALUE
Buffer[(*Length)++] = 0x03; //Inline string
sprintf(buffer,"%s",DecodeUnicodeString(settings->HomePage));
for (i=0;i<(int)strlen(buffer);i++) {
Buffer[(*Length)++] = buffer[i];//Text
}
Buffer[(*Length)++] = 0x00; //END Inline string
Buffer[(*Length)++] = 0x01; //END PARMeter
/* ISP_NAME (name) */
Buffer[(*Length)++] = 0xC6; //CHARACTERISTIC with content and attributes
Buffer[(*Length)++] = 0x08; //TYPE=NAME
Buffer[(*Length)++] = 0x01; //END PARMeter
/* Settings name */
AddWAPSMSParameterText(Buffer, Length, 0x15, DecodeUnicodeString(settings->Title), UnicodeLength(settings->Title));
Buffer[(*Length)++] = 0x01; //END PARMeter
Buffer[(*Length)++] = 0x01; //END PARMeter
}
/* http://forum.nokia.com: OTA Settings 7.0 */
+/* first it used default/ISO coding */
+/* Joergen Thomsen changed to UTF8 */
void NOKIA_EncodeWAPBookmarkSMSText(unsigned char *Buffer, int *Length, GSM_WAPBookmark *bookmark)
{
unsigned char buffer[100];
- bool UnicodeCoding = false;
- EncodeUTF8QuotedPrintable(buffer,bookmark->Title);
- if (UnicodeLength(bookmark->Title)!=strlen(buffer)) UnicodeCoding = true;
+// bool UnicodeCoding = false;
+// EncodeUTF8QuotedPrintable(buffer,bookmark->Title);
+// if (UnicodeLength(bookmark->Title)!=strlen(buffer)) UnicodeCoding = true;
Buffer[(*Length)++] = 0x01; //Push ID
Buffer[(*Length)++] = 0x06; //PDU Type (push)
Buffer[(*Length)++] = 0x2D; //Headers length (content type + headers)
strcpy(Buffer+(*Length),"\x1F\x2B");
(*Length)=(*Length)+2; //Value length
strcpy(Buffer+(*Length),"application/x-wap-prov.browser-bookmarks");
(*Length)=(*Length)+40; //MIME-Type
Buffer[(*Length)++] = 0x00; //end inline string
strcpy(Buffer+(*Length),"\x81\xEA");
(*Length)=(*Length)+2; //charset UTF-8 short int.
+ /* removed by Joergen Thomsen */
/* Block from sniffs. UNKNOWN */
- if (!UnicodeCoding) {
- Buffer[(*Length)++] = 0x00;
- Buffer[(*Length)++] = 0x01;
- } else {
- strcpy(Buffer+(*Length),"\x01\x01\x87\x68");
- (*Length)=(*Length)+4;
- }
- Buffer[(*Length)++] = 0x00;
+// if (!UnicodeCoding) {
+// Buffer[(*Length)++] = 0x00;
+// Buffer[(*Length)++] = 0x01;
+// } else {
+// strcpy(Buffer+(*Length),"\x01\x01\x87\x68");
+// (*Length)=(*Length)+4;
+// }
+// Buffer[(*Length)++] = 0x00;
+
+ /* added by Joergen Thomsen */
+ Buffer[(*Length)++] = 0x01; // Version WBXML 1.1
+ Buffer[(*Length)++] = 0x01; // Unknown public identifier
+ Buffer[(*Length)++] = 0x6A; // charset UTF-8
+ Buffer[(*Length)++] = 0x00; // string table length
Buffer[(*Length)++] = 0x45; //CHARACTERISTIC-LIST with content
/* URL */
Buffer[(*Length)++] = 0xC6; //CHARACTERISTIC with content and attributes
Buffer[(*Length)++] = 0x7F; //TYPE = BOOKMARK
Buffer[(*Length)++] = 0x01; //END PARMeter
- if (!UnicodeCoding) {
- /* TITLE */
- AddWAPSMSParameterText(Buffer, Length, 0x15, DecodeUnicodeString(bookmark->Title), UnicodeLength(bookmark->Title));
- /* URL */
- AddWAPSMSParameterText(Buffer, Length, 0x17, DecodeUnicodeString(bookmark->Address), UnicodeLength(bookmark->Address));
- } else {
- /* TITLE */
- AddWAPSMSParameterText(Buffer, Length, 0x15, bookmark->Title, UnicodeLength(bookmark->Title)*2+1);
- /* URL */
- AddWAPSMSParameterText(Buffer, Length, 0x17, bookmark->Address, UnicodeLength(bookmark->Address)*2+1);
+
+ /* removed by Joergen Thomsen */
+// if (!UnicodeCoding) {
+// /* TITLE */
+// AddWAPSMSParameterText(Buffer, Length, 0x15, DecodeUnicodeString(bookmark->Title), UnicodeLength(bookmark->Title));
+// /* URL */
+// AddWAPSMSParameterText(Buffer, Length, 0x17, DecodeUnicodeString(bookmark->Address), UnicodeLength(bookmark->Address));
+// } else {
+// /* TITLE */
+// AddWAPSMSParameterText(Buffer, Length, 0x15, bookmark->Title, UnicodeLength(bookmark->Title)*2+1);
+// /* URL */
+// AddWAPSMSParameterText(Buffer, Length, 0x17, bookmark->Address, UnicodeLength(bookmark->Address)*2+1);
+// }
+
+ /* added by Joergen Thomsen */
+ /* TITLE */
+ EncodeUTF8(buffer, bookmark->Title);
+ AddWAPSMSParameterText(Buffer, Length, 0x15, buffer, strlen(buffer));
+ /* URL */
+ EncodeUTF8(buffer, bookmark->Address);
+ AddWAPSMSParameterText(Buffer, Length, 0x17, buffer, strlen(buffer));
+
+ Buffer[(*Length)++] = 0x01; //END (CHARACTERISTIC)
+ Buffer[(*Length)++] = 0x01; //END (CHARACTERISTIC-LIST)
+}
+
+void GSM_EncodeWAPIndicatorSMSText(unsigned char *Buffer, int *Length, char *Text, char *URL)
+{
+ int i;
+
+ Buffer[(*Length)++] = 0x01; //Push ID
+ Buffer[(*Length)++] = 0x06; //PDU Type (push)
+ Buffer[(*Length)++] = 28; //Headers length (content type + headers)
+ strcpy(Buffer+(*Length),"\x1F\x23");
+ (*Length)=(*Length)+2; //Value length
+ strcpy(Buffer+(*Length),"application/vnd.wap.sic");
+ (*Length)=(*Length)+23; //MIME-Type
+ Buffer[(*Length)++] = 0x00; //end inline string
+ strcpy(Buffer+(*Length),"\x81\xEA");
+ (*Length)=(*Length)+2; //charset UTF-8 short int.
+
+ Buffer[(*Length)++] = 0x02; // WBXML 1.2
+ Buffer[(*Length)++] = 0x05; // SI 1.0 Public Identifier
+ Buffer[(*Length)++] = 0x6A; // charset UTF-8
+ Buffer[(*Length)++] = 0x00; // string table length
+ Buffer[(*Length)++] = 0x45; // SI with content
+ Buffer[(*Length)++] = 0xC6; // indication with content and attributes
+ Buffer[(*Length)++] = 0x0B; // address
+ Buffer[(*Length)++] = 0x03; // Inline string
+ for (i=0;i<(int)strlen(URL);i++) {
+ Buffer[(*Length)++] = URL[i];//Text
}
- Buffer[(*Length)++] = 0x01; //END PARMeter
- Buffer[(*Length)++] = 0x01; //END PARMeter
+ Buffer[(*Length)++] = 0x00; // END Inline string
+
+#ifdef XXX
+ Buffer[(*Length)++] = 0x0A; // created...
+ Buffer[(*Length)++] = 0xC3; // OPAQUE
+ Buffer[(*Length)++] = 0x07; // length
+ Buffer[(*Length)++] = 0x19; // year
+ Buffer[(*Length)++] = 0x80; // year
+ Buffer[(*Length)++] = 0x21; // month
+ Buffer[(*Length)++] = 0x12; // ..
+ Buffer[(*Length)++] = 0x00; // ..
+ Buffer[(*Length)++] = 0x00; // ..
+ Buffer[(*Length)++] = 0x00; // ..
+ Buffer[(*Length)++] = 0x10; // expires
+ Buffer[(*Length)++] = 0xC3; // OPAQUE
+ Buffer[(*Length)++] = 0x04; // length
+ Buffer[(*Length)++] = 0x20; // year
+ Buffer[(*Length)++] = 0x10; // year
+ Buffer[(*Length)++] = 0x06; // month
+ Buffer[(*Length)++] = 0x25; // day
+#endif
+
+ Buffer[(*Length)++] = 0x01; // END (indication)
+ Buffer[(*Length)++] = 0x03; // Inline string
+ for (i=0;i<(int)strlen(Text);i++) {
+ Buffer[(*Length)++] = Text[i]; //Text
+ }
+ Buffer[(*Length)++] = 0x00; // END Inline string
+ Buffer[(*Length)++] = 0x01; // END (indication)
+ Buffer[(*Length)++] = 0x01; // END (SI)
}
void GSM_EncodeMMSFile(GSM_EncodeMultiPartMMSInfo *Info, unsigned char *Buffer, int *Length)
{
int i;
strcpy(Buffer+(*Length),"\x8C\x80\x98\x4F");
(*Length)=(*Length)+4;
/* Unique MMS ID ? */
strcpy(Buffer+(*Length),"123456789");
(*Length)=(*Length)+9;
Buffer[(*Length)++] = 0x00;
strcpy(Buffer+(*Length),"\x8D\x90\x89");
(*Length)=(*Length)+3;
strcpy(Buffer+(*Length),"\x01\x81\x86\x81\x96");
(*Length)=(*Length)+5;
if (UnicodeLength(Info->Subject) != 0) {
sprintf(Buffer+(*Length),"%s",DecodeUnicodeString(Info->Subject));
(*Length)=(*Length)+UnicodeLength(Info->Subject);
Buffer[(*Length)++] = 0x00;
}
for (i=0;i<Info->EntriesNum;i++) {
switch(Info->Entries[i].ID) {
case MMS_Text:
strcpy(Buffer+(*Length),"\x84\xA3\x01\x04\x04\x03\x83\x81\xEA");
(*Length)=(*Length)+9;
sprintf(Buffer+(*Length),"%s",DecodeUnicodeString(Info->Entries[i].Buffer));
(*Length)=(*Length)+UnicodeLength(Info->Entries[i].Buffer);
break;
default:
break;
}
}
}
void GSM_ClearMultiPartMMSInfo(GSM_EncodeMultiPartMMSInfo *Info)
{
Info->EntriesNum = 0;
Info->Subject[0] = 0x00;
Info->Subject[1] = 0x00;
Info->Source[0] = 0x00;
Info->Source[1] = 0x00;
Info->Destination[0] = 0x00;
Info->Destination[1] = 0x00;
}
GSM_Error GSM_EncodeURLFile(unsigned char *Buffer, int *Length, GSM_WAPBookmark *bookmark)
{
*Length+=sprintf(Buffer+(*Length), "BEGIN:VBKM%c%c",13,10);
*Length+=sprintf(Buffer+(*Length), "VERSION:1.0%c%c",13,10);
*Length+=sprintf(Buffer+(*Length), "TITLE:%s%c%c",DecodeUnicodeString(bookmark->Title),13,10);
*Length+=sprintf(Buffer+(*Length), "URL:%s%c%c",DecodeUnicodeString(bookmark->Address),13,10);
*Length+=sprintf(Buffer+(*Length), "BEGIN:ENV%c%c",13,10);
*Length+=sprintf(Buffer+(*Length), "X-IRMC-URL;QUOTED-PRINTABLE:=%c%c",13,10);
*Length+=sprintf(Buffer+(*Length), "[InternetShortcut] =%c%c",13,10);
*Length+=sprintf(Buffer+(*Length), "URL=%s%c%c",DecodeUnicodeString(bookmark->Address),13,10);
*Length+=sprintf(Buffer+(*Length), "END:ENV%c%c",13,10);
*Length+=sprintf(Buffer+(*Length), "END:VBKM%c%c",13,10);
return ERR_NONE;
}
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/service/gsmdata.h b/gammu/emb/common/service/gsmdata.h
index f5f8e07..e81589f 100644
--- a/gammu/emb/common/service/gsmdata.h
+++ b/gammu/emb/common/service/gsmdata.h
@@ -1,152 +1,154 @@
/* (c) 2001-2004 by Marcin Wiacek */
#ifndef __gsm_wap_h
#define __gsm_wap_h
#include "gsmmisc.h"
#include "../misc/misc.h"
/* --------------------------- WAP or MMS settings ------------------------- */
typedef enum {
WAPSETTINGS_SPEED_9600,
WAPSETTINGS_SPEED_14400,
WAPSETTINGS_SPEED_AUTO
} WAPSettings_Speed;
typedef enum {
WAPSETTINGS_BEARER_SMS = 1,
WAPSETTINGS_BEARER_DATA,
WAPSETTINGS_BEARER_USSD,
WAPSETTINGS_BEARER_GPRS
} WAPSettings_Bearer;
typedef struct {
char Title [(20+1)*2];
char HomePage [(100+1)*2];
WAPSettings_Bearer Bearer;
bool IsSecurity;
bool IsContinuous;
/* for data bearer */
bool IsISDNCall;
bool IsNormalAuthentication;
/* for sms bearer */
char Server [(21+1)*2];
/* for sms or ussd bearer */
char Service [(20+1)*2];
bool IsIP;
/* for ussd bearer */
char Code [(10+1)*2];
/* for data or gprs */
char IPAddress [(20+1)*2];
bool ManualLogin;
char DialUp [(20+1)*2];
char User [(50+1)*2]; /*is length OK ?*/
char Password [(50+1)*2]; /*is length OK ?*/
WAPSettings_Speed Speed;
} GSM_WAPSettings;
typedef struct {
int Location;
unsigned char Number;
GSM_WAPSettings Settings[4];
bool Active;
bool ReadOnly;
char Proxy [(100+1)*2];
int ProxyPort;
char Proxy2 [(100+1)*2];
int Proxy2Port;
WAPSettings_Bearer ActiveBearer;
} GSM_MultiWAPSettings;
void NOKIA_EncodeWAPMMSSettingsSMSText(unsigned char *Buffer, int *Length, GSM_WAPSettings *settings, bool MMS);
/* -------------------------------- WAP Bookmark --------------------------- */
typedef struct {
char Address [(255+1)*2];
char Title [(50+1)*2];
int Location;
} GSM_WAPBookmark;
void NOKIA_EncodeWAPBookmarkSMSText (unsigned char *Buffer, int *Length, GSM_WAPBookmark *bookmark);
GSM_Error GSM_EncodeURLFile (unsigned char *Buffer, int *Length, GSM_WAPBookmark *bookmark);
/* ------------------------------ MMS Indicator ---------------------------- */
typedef struct {
unsigned char Address[500];
unsigned char Title[200];
unsigned char Sender[200];
} GSM_MMSIndicator;
void GSM_EncodeMMSIndicatorSMSText(unsigned char *Buffer, int *Length, GSM_MMSIndicator Indicator);
+void GSM_EncodeWAPIndicatorSMSText(unsigned char *Buffer, int *Length, char *Text, char *URL);
+
/* ------------------------------ MMS file --------------------------------- */
#define MAX_MULTI_MMS 20
typedef enum {
MMS_Text = 1,
MMS_Bitmap_JPG
} EncodeMultiPartMMSID;
typedef struct {
EncodeMultiPartMMSID ID;
GSM_File File;
unsigned char *Buffer;
} EncodeMultiPartMMSEntry;
typedef struct {
/* Input values */
EncodeMultiPartMMSEntry Entries[MAX_MULTI_MMS];
int EntriesNum;
unsigned char Source[200];
unsigned char Destination[200];
unsigned char Subject[200];
} GSM_EncodeMultiPartMMSInfo;
void GSM_EncodeMMSFile (GSM_EncodeMultiPartMMSInfo *Info, unsigned char *Buffer, int *Length);
void GSM_ClearMultiPartMMSInfo (GSM_EncodeMultiPartMMSInfo *Info);
/* ------------------------------------------------------------------------ */
typedef struct {
int Location;
bool Active;
bool SyncPhonebook;
bool SyncCalendar;
char Name[(20+1)*2];
char PhonebookDataBase[(50+1)*2];
char CalendarDataBase[(50+1)*2];
char User[(30+1)*2];
char Password[(20+1)*2];
char Server[(128+1)*2];
GSM_MultiWAPSettings Connection;
} GSM_SyncMLSettings;
/* ------------------------------------------------------------------------ */
typedef struct {
char Name[(50+1)*2];
char HomePage[(200+1)*2];
char User[(50+1)*2];
char Password[(50+1)*2];
int Location;
bool Active;
GSM_MultiWAPSettings Connection;
} GSM_ChatSettings;
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/service/gsmlogo.c b/gammu/emb/common/service/gsmlogo.c
index c992915..7c19967 100644
--- a/gammu/emb/common/service/gsmlogo.c
+++ b/gammu/emb/common/service/gsmlogo.c
@@ -1,355 +1,357 @@
/* (c) 2001-2004 by Marcin Wiacek */
#include <string.h>
#include <stdlib.h>
+#include <sys/stat.h>
#include "../misc/misc.h"
#include "../misc/coding/coding.h"
#include "gsmlogo.h"
#include "gsmnet.h"
void PHONE_GetBitmapWidthHeight(GSM_Phone_Bitmap_Types Type, int *width, int *height)
{
*width = 0;
*height = 0;
switch (Type) {
case GSM_EMSSmallPicture : *width=8; *height=8; break;
case GSM_EMSMediumPicture : *width=16; *height=16; break;
case GSM_EMSBigPicture : *width=32; *height=32; break;
case GSM_NokiaOperatorLogo :
case GSM_NokiaCallerLogo : *width=72; *height=14; break;
case GSM_NokiaPictureImage : *width=72; *height=28; break;
case GSM_Nokia7110OperatorLogo :
case GSM_Nokia6510OperatorLogo : *width=78; *height=21; break;
case GSM_NokiaStartupLogo : *width=84; *height=48; break;
case GSM_Nokia6210StartupLogo : *width=96; *height=60; break;
case GSM_Nokia7110StartupLogo : *width=96; *height=65; break;
case GSM_EMSVariablePicture : break;
case GSM_AlcatelBMMIPicture : break;
}
}
int PHONE_GetBitmapSize(GSM_Phone_Bitmap_Types Type, int Width, int Height)
{
int width, height, x;
PHONE_GetBitmapWidthHeight(Type, &width, &height);
if (width == 0 && height == 0) {
width = Width;
height = Height;
}
switch (Type) {
case GSM_Nokia6510OperatorLogo:
x = width * height;
return x/8 + (x%8 > 0);
case GSM_Nokia7110OperatorLogo:
return (width*height + 7)/8;
case GSM_NokiaStartupLogo:
case GSM_NokiaOperatorLogo:
case GSM_NokiaCallerLogo:
case GSM_NokiaPictureImage:
case GSM_EMSSmallPicture:
case GSM_EMSMediumPicture:
case GSM_EMSBigPicture:
case GSM_EMSVariablePicture:
return height*width/8;
case GSM_Nokia7110StartupLogo:
case GSM_Nokia6210StartupLogo:
return (height+7)/8*width;
case GSM_AlcatelBMMIPicture:
return width*((height+7)/8);
}
return 0;
}
static bool PHONE_IsPointBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int x, int y, int width, int height)
{
int i=0, pixel;
switch (Type) {
case GSM_NokiaStartupLogo:
case GSM_Nokia6210StartupLogo:
case GSM_Nokia7110StartupLogo:
case GSM_Nokia6510OperatorLogo:
i=(buffer[(y/8*width) + x] & 1<<(y%8));
break;
case GSM_NokiaOperatorLogo:
case GSM_Nokia7110OperatorLogo:
case GSM_NokiaCallerLogo:
case GSM_EMSVariablePicture:
case GSM_EMSSmallPicture:
case GSM_EMSMediumPicture:
case GSM_EMSBigPicture:
pixel=width*y + x;
i=(buffer[pixel/8] & 1<<(7-(pixel%8)));
break;
case GSM_NokiaPictureImage:
i=(buffer[9*y + x/8] & 1<<(7-(x%8)));
break;
case GSM_AlcatelBMMIPicture:
break;
}
if (i) return true; else return false;
}
static void PHONE_SetPointBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int x, int y, int width, int height)
{
int pixel;
switch (Type) {
case GSM_NokiaStartupLogo:
case GSM_Nokia6210StartupLogo:
case GSM_Nokia7110StartupLogo:
case GSM_Nokia6510OperatorLogo:
buffer[(y/8*width)+x] |= 1 << (y%8);
break;
case GSM_NokiaOperatorLogo:
case GSM_Nokia7110OperatorLogo:
case GSM_NokiaCallerLogo:
case GSM_EMSSmallPicture:
case GSM_EMSMediumPicture:
case GSM_EMSBigPicture:
case GSM_EMSVariablePicture:
pixel = width*y + x;
buffer[pixel/8] |= 1 << (7-(pixel%8));
break;
case GSM_NokiaPictureImage:
buffer[9*y + x/8] |= 1 << (7-(x%8));
break;
case GSM_AlcatelBMMIPicture:
pixel = height / 8;
if ((height % 8) != 0) pixel++;
buffer[pixel*x + y/8] |= 1 << (7 - (y%8));
break;
}
}
void PHONE_DecodeBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap)
{
int width, height, x,y;
PHONE_GetBitmapWidthHeight(Type, &width, &height);
if (Type != GSM_Nokia6510OperatorLogo && Type != GSM_Nokia7110OperatorLogo && Type != GSM_EMSVariablePicture) {
Bitmap->BitmapHeight = height;
Bitmap->BitmapWidth = width;
}
switch (Type) {
case GSM_NokiaOperatorLogo :
case GSM_Nokia7110OperatorLogo :
case GSM_Nokia6510OperatorLogo : Bitmap->Type=GSM_OperatorLogo; break;
case GSM_NokiaCallerLogo : Bitmap->Type=GSM_CallerGroupLogo; break;
case GSM_AlcatelBMMIPicture :
case GSM_NokiaStartupLogo :
case GSM_Nokia7110StartupLogo :
case GSM_Nokia6210StartupLogo : Bitmap->Type=GSM_StartupLogo; break;
case GSM_NokiaPictureImage :
case GSM_EMSVariablePicture :
case GSM_EMSSmallPicture :
case GSM_EMSMediumPicture :
case GSM_EMSBigPicture : Bitmap->Type=GSM_PictureImage; break;
}
Bitmap->Location = 0;
Bitmap->Text[0] = 0;
Bitmap->Text[1] = 0;
Bitmap->BitmapEnabled = false;
Bitmap->DefaultName = false;
Bitmap->DefaultBitmap = false;
Bitmap->DefaultRingtone = false;
Bitmap->RingtoneID = 0;
Bitmap->NetworkCode[0] = 0;
Bitmap->Sender[0] = 0;
Bitmap->Sender[1] = 0;
Bitmap->ID = 0;
+ Bitmap->Name = NULL;
GSM_ClearBitmap(Bitmap);
for (x=0;x<Bitmap->BitmapWidth;x++) {
for (y=0;y<Bitmap->BitmapHeight;y++) {
if (PHONE_IsPointBitmap(Type, buffer, x, y, Bitmap->BitmapWidth, Bitmap->BitmapHeight)) {
GSM_SetPointBitmap(Bitmap,x,y);
}
}
}
}
void PHONE_ClearBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int width, int height)
{
memset(buffer,0,PHONE_GetBitmapSize(Type,width,height));
}
void PHONE_EncodeBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap)
{
int width, height, x, y;
GSM_Bitmap dest;
PHONE_GetBitmapWidthHeight(Type, &width, &height);
if (width == 0 && height == 0) {
width = Bitmap->BitmapWidth;
height = Bitmap->BitmapHeight;
}
GSM_ResizeBitmap(&dest, Bitmap, width, height);
PHONE_ClearBitmap(Type, buffer, width, height);
for (x=0;x<width;x++) {
for (y=0;y<height;y++) {
if (GSM_IsPointBitmap(&dest,x,y)) PHONE_SetPointBitmap(Type, buffer, x, y, width, height);
}
}
}
void GSM_GetMaxBitmapWidthHeight(GSM_Bitmap_Types Type, unsigned char *width, unsigned char *height)
{
switch (Type) {
case GSM_CallerGroupLogo: *width=72; *height=14; break;
case GSM_OperatorLogo : *width=101;*height=21; break;
case GSM_StartupLogo : *width=96; *height=65; break;
case GSM_PictureImage : *width=72; *height=28; break;
default : break;
}
}
void GSM_SetPointBitmap(GSM_Bitmap *bmp, int x, int y)
{
SetBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x);
}
void GSM_ClearPointBitmap(GSM_Bitmap *bmp, int x, int y)
{
ClearBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x);
}
bool GSM_IsPointBitmap(GSM_Bitmap *bmp, int x, int y)
{
if (GetBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x)) return true; else return false;
}
void GSM_ClearBitmap(GSM_Bitmap *bmp)
{
memset(bmp->BitmapPoints,0,GSM_GetBitmapSize(bmp));
}
int GSM_GetBitmapSize(GSM_Bitmap *bmp)
{
return bmp->BitmapWidth*bmp->BitmapHeight/8+1;
}
void GSM_PrintBitmap(FILE *file, GSM_Bitmap *bitmap)
{
int x,y;
for (y=0;y<bitmap->BitmapHeight;y++) {
for (x=0;x<bitmap->BitmapWidth;x++) {
if (GSM_IsPointBitmap(bitmap,x,y)) {
fprintf(file,"#");
} else {
fprintf(file," ");
}
}
fprintf(file,"\n");
}
}
void GSM_ReverseBitmap(GSM_Bitmap *Bitmap)
{
int x, y;
for (x=0;x<Bitmap->BitmapWidth;x++) {
for (y=0;y<Bitmap->BitmapHeight;y++) {
if (GSM_IsPointBitmap(Bitmap,x,y)) {
GSM_ClearPointBitmap(Bitmap, x, y);
} else {
GSM_SetPointBitmap(Bitmap, x, y);
}
}
}
}
void GSM_ResizeBitmap(GSM_Bitmap *dest, GSM_Bitmap *src, int width, int height)
{
int startx=0,endx=0,setx=0, starty=0,endy=0,sety=0, x, y;
if (src->BitmapWidth<=width) {
startx = 0;
endx = src->BitmapWidth;
setx = (width-src->BitmapWidth)/2;
} else {
startx = (src->BitmapWidth-width)/2;
endx = startx + width;
setx = 0;
}
if (src->BitmapHeight<=height) {
starty = 0;
endy = src->BitmapHeight;
sety = (height-src->BitmapHeight)/2;
} else {
starty = (src->BitmapHeight-height)/2;
endy = starty + height;
sety = 0;
}
dest->BitmapHeight = height;
dest->BitmapWidth = width;
GSM_ClearBitmap(dest);
for (x=startx;x<endx;x++) {
for (y=starty;y<endy;y++) {
if (GSM_IsPointBitmap(src,x,y))
GSM_SetPointBitmap(dest,setx+x-startx,sety+y-starty);
}
}
}
GSM_Error Bitmap2BMP(unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap)
{
int x,y,pos,i,sizeimage,buffpos=0;
unsigned char buff[1];
div_t division;
bool isfile=false;
unsigned char header[]={
/*1'st header*/ 'B','M', /* BMP file ID */
0x00,0x00,0x00,0x00, /* Size of file */
0x00,0x00, /* Reserved for future use */
0x00,0x00, /* Reserved for future use */
62,0x00,0x00,0x00, /* Offset for image data */
/*2'nd header*/ 40,0x00,0x00,0x00, /* Length of this part of header */
0x00,0x00,0x00,0x00, /* Width of image */
0x00,0x00,0x00,0x00, /* Height of image */
1,0x00, /* How many planes in target device */
1,0x00, /* How many colors in image. 1 means 2^1=2 colors */
0x00,0x00,0x00,0x00, /* Type of compression. 0 means no compression */
/*Sometimes */ 0x00,0x00,0x00,0x00, /* Size of part with image data */
/*ttttttt...*/ 0xE8,0x03,0x00,0x00, /* XPelsPerMeter */
/*hhiiiiissss*/ 0xE8,0x03,0x00,0x00, /* YPelsPerMeter */
/*part of header*/0x02,0x00,0x00,0x00, /* How many colors from palette is used */
/*doesn't exist*/ 0x00,0x00,0x00,0x00, /* How many colors from palette is required to display image. 0 means all */
/*Color palette*/ 0x00,0x00,0x00, /* First color in palette in Blue, Green, Red. Here white */
0x00, /* Each color in palette is end by 4'th byte */
102, 204, 102, /* Second color in palette in Blue, Green, Red. Here green */
0x00}; /* Each color in palette is end by 4'th byte */
if (file!=NULL) isfile=true;
header[22]=bitmap->BitmapHeight;
header[18]=bitmap->BitmapWidth;
pos = 7;
sizeimage = 0;
/*lines are written from the last to the first*/
for (y=bitmap->BitmapHeight-1;y>=0;y--) {
i=1;
for (x=0;x<bitmap->BitmapWidth;x++) {
/*new byte !*/
if (pos==7) {
if (x!=0) sizeimage++;
i++;
/*each line is written in multiply of 4 bytes*/
if(i==5) i=1;
}
pos--;
/*going to new byte*/
if (pos<0) pos=7;
}
/*going to new byte*/
pos=7;
sizeimage++;
@@ -437,567 +439,600 @@ static GSM_Error savebmp(FILE *file, GSM_MultiBitmap *bitmap)
}
static void PrivSaveNLMWBMP(FILE *file, GSM_Bitmap *Bitmap)
{
unsigned char buffer[1000];
int x,y,pos,pos2;
div_t division;
pos=0;pos2=7;
for (y=0;y<Bitmap->BitmapHeight;y++) {
for (x=0;x<Bitmap->BitmapWidth;x++) {
if (pos2==7) buffer[pos]=0;
if (GSM_IsPointBitmap(Bitmap,x,y)) buffer[pos]|=(1<<pos2);
pos2--;
/* going to new line */
if (pos2<0) {pos2=7;pos++;}
}
/* for startup logos - new line with new byte */
if (pos2!=7) {pos2=7;pos++;}
}
division=div(Bitmap->BitmapWidth,8);
/* For startup logos */
if (division.rem!=0) division.quot++;
fwrite(buffer,1,(division.quot*Bitmap->BitmapHeight),file);
}
static GSM_Error savenlm(FILE *file, GSM_MultiBitmap *bitmap)
{
int i;
char header[]={
'N','L','M',' ', /* Nokia Logo Manager file ID. */
0x01,
0x00, /* 0x00 (OP), 0x01 (CLI), 0x02 (Startup), 0x03 (Picture)*/
0x00, /* Number of images inside file - 1. 0x01==2 images, 0x03==4 images, etc. */
0x00, /* Width. */
0x00, /* Height. */
0x01};
switch (bitmap->Bitmap[0].Type) {
case GSM_OperatorLogo : header[5]=0x00; break;
case GSM_CallerGroupLogo : header[5]=0x01; break;
case GSM_StartupLogo : header[5]=0x02; break;
case GSM_PictureImage : header[5]=0x03; break;
default : return ERR_UNKNOWN;
}
header[6] = bitmap->Number - 1;
header[7] = bitmap->Bitmap[0].BitmapWidth;
header[8] = bitmap->Bitmap[0].BitmapHeight;
fwrite(header,1,sizeof(header),file);
for (i=0;i<bitmap->Number;i++) {
PrivSaveNLMWBMP(file, &bitmap->Bitmap[i]);
}
return ERR_NONE;
}
static void PrivSaveNGGNOL(FILE *file, GSM_MultiBitmap *bitmap)
{
char buffer[GSM_BITMAP_SIZE];
int x,y,current=0;
for (y=0;y<bitmap->Bitmap[0].BitmapHeight;y++) {
for (x=0;x<bitmap->Bitmap[0].BitmapWidth;x++) {
if (GSM_IsPointBitmap(&bitmap->Bitmap[0],x,y)) {
buffer[current++] = '1';
} else {
buffer[current++] = '0';
}
}
}
fwrite(buffer,1,current,file);
}
static GSM_Error savengg(FILE *file, GSM_MultiBitmap *bitmap)
{
char header[]={
'N','G','G',0x00,0x01,0x00,
0x00,0x00, /* Width */
0x00,0x00, /* Height */
0x01,0x00,0x01,0x00,
0x00, /* Unknown.Can't be checksum - for */
/* the same logo files can be different */
0x00};
header[6] = bitmap->Bitmap[0].BitmapWidth;
header[8] = bitmap->Bitmap[0].BitmapHeight;
fwrite(header,1,sizeof(header),file);
PrivSaveNGGNOL(file,bitmap);
return ERR_NONE;
}
static GSM_Error savenol(FILE *file, GSM_MultiBitmap *bitmap)
{
int country,net;
char header[]={
'N','O','L',0x00,0x01,0x00,
0x00,0x00, /* MCC */
0x00,0x00, /* MNC */
0x00,0x00, /* Width */
0x00,0x00, /* Height */
0x01,0x00,0x01,0x00,
0x00, /* Unknown.Can't be checksum - for */
/* the same logo files can be different */
0x00};
if (bitmap->Bitmap[0].Type == GSM_OperatorLogo) sscanf(bitmap->Bitmap[0].NetworkCode, "%d %d", &country, &net);
header[6] = country%256;
header[7] = country/256;
header[8] = net%256;
header[9] = net/256;
header[10] = bitmap->Bitmap[0].BitmapWidth;
header[12] = bitmap->Bitmap[0].BitmapHeight;
fwrite(header,1,sizeof(header),file);
PrivSaveNGGNOL(file,bitmap);
return ERR_NONE;
}
static GSM_Error savexpm(FILE *file, GSM_MultiBitmap *bitmap)
{
int x,y;
fprintf(file,"/* XPM */\n");
fprintf(file,"static char * ala_xpm[] = {\n");
fprintf(file,"\"%i %i 2 1\",\n",bitmap->Bitmap[0].BitmapWidth,bitmap->Bitmap[0].BitmapHeight);
fprintf(file,"\". s c m #000000 g4 #000000 g #000000 c #000000\",\n");
fprintf(file,"\"# s c m #ffffff g4 #ffffff g #ffffff c #ffffff\",\n");
for (y=0;y<bitmap->Bitmap[0].BitmapHeight;y++) {
fprintf(file,"\"");
for (x=0;x<bitmap->Bitmap[0].BitmapWidth;x++)
if (GSM_IsPointBitmap(&bitmap->Bitmap[0],x,y)) {
fprintf(file,".");
} else {
fprintf(file,"#");
}
fprintf(file,"\"");
if (y==bitmap->Bitmap[0].BitmapHeight-1) {
fprintf(file,"};\n");
} else {
fprintf(file,",\n");
}
}
return ERR_NONE;
}
static GSM_Error savensl(FILE *file, GSM_MultiBitmap *bitmap)
{
char buffer[GSM_BITMAP_SIZE];
unsigned char header[]={
'F','O','R','M', 0x01,0xFE, /* File ID block, size 1*256+0xFE=510*/
'N','S','L','D', 0x01,0xF8}; /* Startup Logo block, size 1*256+0xF8=504*/
fwrite(header,1,sizeof(header),file);
PHONE_EncodeBitmap(GSM_NokiaStartupLogo, buffer, &bitmap->Bitmap[0]);
fwrite(buffer,1,PHONE_GetBitmapSize(GSM_NokiaStartupLogo,0,0),file);
return ERR_NONE;
}
static GSM_Error savewbmp(FILE *file, GSM_MultiBitmap *bitmap)
{
unsigned char buffer[4];
buffer[0] = 0x00;
buffer[1] = 0x00;
buffer[2] = bitmap->Bitmap[0].BitmapWidth;
buffer[3] = bitmap->Bitmap[0].BitmapHeight;
fwrite(buffer,1,4,file);
PrivSaveNLMWBMP(file, &bitmap->Bitmap[0]);
return ERR_NONE;
}
GSM_Error GSM_SaveBitmapFile(char *FileName, GSM_MultiBitmap *bitmap)
{
FILE *file;
GSM_Error error=ERR_NONE;
file = fopen(FileName, "wb");
if (file == NULL) return ERR_CANTOPENFILE;
/* Attempt to identify filetype */
- if (strstr(FileName,".nlm")) {
+ if (mystrcasestr(FileName,".nlm")) {
error=savenlm(file,bitmap);
- } else if (strstr(FileName,".ngg")) {
+ } else if (mystrcasestr(FileName,".ngg")) {
error=savengg(file,bitmap);
- } else if (strstr(FileName,".nol")) {
+ } else if (mystrcasestr(FileName,".nol")) {
error=savenol(file,bitmap);
- } else if (strstr(FileName,".xpm")) {
+ } else if (mystrcasestr(FileName,".xpm")) {
error=savexpm(file,bitmap);
- } else if (strstr(FileName,".nsl")) {
+ } else if (mystrcasestr(FileName,".nsl")) {
error=savensl(file,bitmap);
- } else if (strstr(FileName,".wbmp")) {
+ } else if (mystrcasestr(FileName,".wbmp")) {
error=savewbmp(file,bitmap);
} else {
error=savebmp(file,bitmap);
}
fclose(file);
return error;
}
GSM_Error BMP2Bitmap(unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap)
{
bool first_white,isfile=false;
unsigned char buff[34];
int w,h,pos,y,x,i,buffpos=0;
#ifdef DEBUG
int sizeimage=0;
#endif
if (bitmap->Type == GSM_None) bitmap->Type = GSM_StartupLogo;
if (file!=NULL) isfile=true;
if (isfile) {
fread(buff, 1, 34, file);
} else {
memcpy(buff,buffer,34);
}
/* height and width of image in the file */
h=buff[22]+256*buff[21];
w=buff[18]+256*buff[17];
dbgprintf("Image Size in BMP file: %dx%d\n",w,h);
GSM_GetMaxBitmapWidthHeight(bitmap->Type, &bitmap->BitmapWidth, &bitmap->BitmapHeight);
if (h<bitmap->BitmapHeight) bitmap->BitmapHeight=h;
if (w<bitmap->BitmapWidth) bitmap->BitmapWidth=w;
dbgprintf("Height %i %i, width %i %i\n",h,bitmap->BitmapHeight,w,bitmap->BitmapWidth);
GSM_ClearBitmap(bitmap);
#ifdef DEBUG
dbgprintf("Number of colors in BMP file: ");
switch (buff[28]) {
case 1 : dbgprintf("2 (supported)\n"); break;
case 4 : dbgprintf("16 (NOT SUPPORTED)\n"); break;
case 8 : dbgprintf("256 (NOT SUPPORTED)\n"); break;
case 24 : dbgprintf("True Color (NOT SUPPORTED)\n"); break;
default : dbgprintf("unknown\n"); break;
}
#endif
if (buff[28]!=1) {
dbgprintf("Wrong number of colors\n");
return ERR_FILENOTSUPPORTED;
}
#ifdef DEBUG
dbgprintf("Compression in BMP file: ");
switch (buff[30]) {
case 0 :dbgprintf("no compression (supported)\n"); break;
case 1 :dbgprintf("RLE8 (NOT SUPPORTED)\n"); break;
case 2 :dbgprintf("RLE4 (NOT SUPPORTED)\n"); break;
default :dbgprintf("unknown\n"); break;
}
#endif
if (buff[30]!=0) {
dbgprintf("Compression type not supported\n");
return ERR_FILENOTSUPPORTED;
}
/* read rest of header (if exists) and color palette */
if (isfile) {
pos=buff[10]-34;
fread(buff, 1, pos, file);
} else {
pos=buff[10]-34;
buffpos=buff[10];
memcpy (buff,buffer+34,pos);
}
#ifdef DEBUG
dbgprintf("First color in BMP file: %i %i %i ",buff[pos-8], buff[pos-7], buff[pos-6]);
if (buff[pos-8]==0 && buff[pos-7]==0 && buff[pos-6]==0) dbgprintf("(white)");
if (buff[pos-8]==0xFF && buff[pos-7]==0xFF && buff[pos-6]==0xFF) dbgprintf("(black)");
if (buff[pos-8]==102 && buff[pos-7]==204 && buff[pos-6]==102) dbgprintf("(green)");
dbgprintf("\n");
dbgprintf("Second color in BMP file: %i %i %i ",buff[pos-38], buff[pos-37], buff[pos-36]);
if (buff[pos-4]==0 && buff[pos-3]==0 && buff[pos-2]==0) dbgprintf("(white)");
if (buff[pos-4]==0xFF && buff[pos-3]==0xFF && buff[pos-2]==0xFF) dbgprintf("(black)");
dbgprintf("\n");
#endif
first_white=true;
if (buff[pos-8]!=0 || buff[pos-7]!=0 || buff[pos-6]!=0) first_white=false;
pos=7;
/* lines are written from the last to the first */
for (y=h-1;y>=0;y--) { i=1;
for (x=0;x<w;x++) { /* new byte ! */
if (pos==7) { if (isfile) {
fread(buff, 1, 1, file);
} else {
memcpy (buff,buffer+buffpos,1);
buffpos++;
}
#ifdef DEBUG
sizeimage++;
#endif
i++;
/* each line is written in multiply of 4 bytes */
if(i==5) i=1;
}
/* we have top left corner ! */
if (x<=bitmap->BitmapWidth && y<=bitmap->BitmapHeight) { if (first_white) {
if ((buff[0]&(1<<pos))<=0) GSM_SetPointBitmap(bitmap,x,y);
} else {
if ((buff[0]&(1<<pos))>0) GSM_SetPointBitmap(bitmap,x,y);
}
}
pos--;
/* going to new byte */
if (pos<0) pos=7;
}
/* going to new byte */
pos=7;
if (i!=1) {
/* each line is written in multiply of 4 bytes */
while (i!=5) {
if (isfile) {
fread(buff, 1, 1, file);
} else {
memcpy (buff,buffer+buffpos,1);
buffpos++;
}
#ifdef DEBUG
sizeimage++;
#endif
i++;
}
}
}
#ifdef DEBUG
dbgprintf("Data size in BMP file: %i\n",sizeimage);
#endif
return(ERR_NONE);
}
static GSM_Error loadbmp(FILE *file, GSM_MultiBitmap *bitmap)
{
GSM_Error error;
error=BMP2Bitmap(NULL,file,&bitmap->Bitmap[0]);
bitmap->Number = 1;
return error;
}
static GSM_Error loadnlm (FILE *file, GSM_MultiBitmap *bitmap)
{
unsigned char buffer[1000];
int pos,pos2,x,y,h,w,i,number;
div_t division;
fread(buffer,1,5,file);
fread(buffer,1,1,file);
switch (buffer[0]) {
case 0x00:
dbgprintf("Operator logo\n");
if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_OperatorLogo;
break;
case 0x01:
dbgprintf("Caller logo\n");
if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_CallerGroupLogo;
break;
case 0x02:
dbgprintf("Startup logo\n");
if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_StartupLogo;
break;
case 0x03:
dbgprintf("Picture Image logo\n");
if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_PictureImage;
break;
}
bitmap->Number = 0;
fread(buffer,1,4,file);
number = buffer[0] + 1;
w = buffer[1];
h = buffer[2];
for (i=0;i<number;i++) {
bitmap->Bitmap[i].Type = bitmap->Bitmap[0].Type;
GSM_GetMaxBitmapWidthHeight(bitmap->Bitmap[i].Type, &bitmap->Bitmap[i].BitmapWidth, &bitmap->Bitmap[i].BitmapHeight);
if (h < bitmap->Bitmap[i].BitmapHeight) bitmap->Bitmap[i].BitmapHeight = h;
if (w < bitmap->Bitmap[i].BitmapWidth) bitmap->Bitmap[i].BitmapWidth = w;
division=div(w,8);
/* For startup logos */
if (division.rem!=0) division.quot++;
if (fread(buffer,1,(division.quot*h),file)!=(unsigned int)(division.quot*h)) return ERR_UNKNOWN;
GSM_ClearBitmap(&bitmap->Bitmap[i]);
pos=0;pos2=7;
for (y=0;y<h;y++) {
for (x=0;x<w;x++) {
if ((buffer[pos]&(1<<pos2))>0) {
if (y<bitmap->Bitmap[i].BitmapHeight && x<bitmap->Bitmap[i].BitmapWidth) GSM_SetPointBitmap(&bitmap->Bitmap[i],x,y);
}
pos2--;
/* going to new byte */
if (pos2<0) {pos2=7;pos++;}
}
/* for startup logos-new line means new byte */
if (pos2!=7) {pos2=7;pos++;}
}
bitmap->Number++;
if (bitmap->Number == MAX_MULTI_BITMAP) break;
}
return (ERR_NONE);
}
static GSM_Error loadnolngg(FILE *file, GSM_MultiBitmap *bitmap, bool nolformat)
{
unsigned char buffer[2000];
int i,h,w,x,y;
fread(buffer, 1, 6, file);
if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_CallerGroupLogo;
if (nolformat) {
fread(buffer, 1, 4, file);
sprintf(bitmap->Bitmap[0].NetworkCode, "%d %02d", buffer[0]+256*buffer[1], buffer[2]);
if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_OperatorLogo;
}
fread(buffer, 1, 4, file);
w = buffer[0];
h = buffer[2];
GSM_GetMaxBitmapWidthHeight(bitmap->Bitmap[0].Type, &bitmap->Bitmap[0].BitmapWidth, &bitmap->Bitmap[0].BitmapHeight);
if (h < bitmap->Bitmap[0].BitmapHeight) bitmap->Bitmap[0].BitmapHeight = h;
if (w < bitmap->Bitmap[0].BitmapWidth) bitmap->Bitmap[0].BitmapWidth = w;
/* Unknown bytes. */
fread(buffer, 1, 6, file);
GSM_ClearBitmap(&bitmap->Bitmap[0]);
x=0; y=0;
for (i=0; i<w*h; i++) {
if (fread(buffer, 1, 1, file)!=1) return ERR_UNKNOWN;
if (buffer[0]=='1') GSM_SetPointBitmap(&bitmap->Bitmap[0],x,y);
x++;
if (x==w) {x=0; y++;}
}
#ifdef DEBUG
/* Some programs writes here fileinfo */
if (fread(buffer, 1, 1, file)==1) {
dbgprintf("Fileinfo: %c",buffer[0]);
while (fread(buffer, 1, 1, file)==1) {
if (buffer[0]!=0x0A) dbgprintf("%c",buffer[0]);
}
dbgprintf("\n");
}
#endif
bitmap->Number = 1;
return(ERR_NONE);
}
static GSM_Error loadnsl(FILE *file, GSM_MultiBitmap *bitmap)
{
unsigned char block[6],buffer[505];
int block_size;
GSM_Bitmap_Types OldType;
while (fread(block,1,6,file)==6) {
block_size = block[4]*256 + block[5];
dbgprintf("Block %c%c%c%c, size %i\n",block[0],block[1],block[2],block[3],block_size);
if (!strncmp(block, "FORM", 4)) {
dbgprintf("File ID\n");
} else {
if (block_size>504) return ERR_UNKNOWN;
if (block_size!=0) {
fread(buffer,1,block_size,file);
/* if it's string, we end it with 0 */
buffer[block_size]=0;
#ifdef DEBUG
if (!strncmp(block, "VERS", 4)) dbgprintf("File saved by: %s\n",buffer);
if (!strncmp(block, "MODL", 4)) dbgprintf("Logo saved from: %s\n",buffer);
if (!strncmp(block, "COMM", 4)) dbgprintf("Phone was connected to COM port: %s\n",buffer);
#endif
if (!strncmp(block, "NSLD", 4)) {
bitmap->Bitmap[0].BitmapHeight = 48;
bitmap->Bitmap[0].BitmapWidth = 84;
OldType = bitmap->Bitmap[0].Type;
PHONE_DecodeBitmap(GSM_NokiaStartupLogo, buffer, &bitmap->Bitmap[0]);
if (OldType != GSM_None) bitmap->Bitmap[0].Type = OldType;
dbgprintf("Startup logo (size %i)\n",block_size);
}
}
}
}
bitmap->Number = 1;
return(ERR_NONE);
}
static GSM_Error loadwbmp(FILE *file, GSM_MultiBitmap *bitmap)
{
unsigned char buffer[10000];
fread(buffer,1,4,file);
bitmap->Bitmap[0].BitmapWidth = buffer[2];
bitmap->Bitmap[0].BitmapHeight = buffer[3];
bitmap->Number = 1;
fread(buffer,1,10000,file);
PHONE_DecodeBitmap(GSM_Nokia7110OperatorLogo, buffer, &bitmap->Bitmap[0]);
GSM_ReverseBitmap(&bitmap->Bitmap[0]);
return ERR_NONE;
}
+static GSM_Error loadgif(FILE *file, GSM_MultiBitmap *bitmap)
+{
+ GSM_Bitmap *bmap = &bitmap->Bitmap[0];
+ char *buffer;
+ struct stat st;
+ int length;
+
+ dbgprintf("loading gif file\n");
+ fstat(fileno(file), &st);
+ bmap->BinaryPic.Length = length = st.st_size;
+ bmap->BinaryPic.Buffer = buffer = malloc(length);
+ if (bmap->BinaryPic.Buffer == NULL)
+ return ERR_MOREMEMORY;
+
+ fread(buffer, 1, length, file);
+ dbgprintf("Length %i name \"%s\"\n", length,
+ DecodeUnicodeString(bmap->Name));
+
+ bmap->Type = GSM_PictureBinary;
+ bmap->BinaryPic.Type = PICTURE_GIF;
+ bmap->BitmapWidth = 256 * buffer[7] + buffer[6];
+ bmap->BitmapHeight = 256 * buffer[9] + buffer[8];
+ bitmap->Number = 1;
+
+ return ERR_NONE;
+}
+
GSM_Error GSM_ReadBitmapFile(char *FileName, GSM_MultiBitmap *bitmap)
{
FILE *file;
unsigned char buffer[300];
file = fopen(FileName, "rb");
if (file == NULL) return ERR_CANTOPENFILE;
+ bitmap->Bitmap[0].Name = malloc((strlen(FileName) + 1) * 2);
+ if (bitmap->Bitmap[0].Name == NULL) return ERR_MOREMEMORY;
+ EncodeUnicode(bitmap->Bitmap[0].Name, FileName, strlen(FileName));
+
fread(buffer, 1, 9, file); /* Read the header of the file. */
rewind(file);
bitmap->Bitmap[0].DefaultBitmap = false;
/* Attempt to identify filetype */
if (memcmp(buffer, "BM",2)==0) {
return loadbmp(file,bitmap);
} else if (buffer[0] == 0x00 && buffer[1] == 0x00) {
return loadwbmp(file,bitmap);
} else if (memcmp(buffer, "NLM",3)==0) {
return loadnlm(file,bitmap);
} else if (memcmp(buffer, "NOL",3)==0) {
return loadnolngg(file,bitmap,true);
} else if (memcmp(buffer, "NGG",3)==0) {
return loadnolngg(file,bitmap,false);
} else if (memcmp(buffer, "FORM",4)==0) {
return loadnsl(file,bitmap);
+ } else if (memcmp(buffer, "GIF",3)==0) {
+ return loadgif(file,bitmap);
}
return ERR_UNKNOWN;
}
void NOKIA_CopyBitmap(GSM_Phone_Bitmap_Types Type, GSM_Bitmap *Bitmap, char *Buffer, int *Length)
{
int Width, Height;
Buffer[(*Length)++] = 0x00;
PHONE_GetBitmapWidthHeight(Type, &Width, &Height);
Buffer[(*Length)++] = Width;
Buffer[(*Length)++] = Height;
Buffer[(*Length)++] = 0x01;
PHONE_EncodeBitmap(Type, Buffer + (*Length), Bitmap);
(*Length) = (*Length) + PHONE_GetBitmapSize(Type,0,0);
}
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/service/gsmlogo.h b/gammu/emb/common/service/gsmlogo.h
index b1b579d..6c6e2d8 100644
--- a/gammu/emb/common/service/gsmlogo.h
+++ b/gammu/emb/common/service/gsmlogo.h
@@ -1,180 +1,206 @@
/* (c) 2002-2004 by Marcin Wiacek */
#ifndef __gsm_bitmaps_h
#define __gsm_bitmaps_h
#include "../gsmcomon.h"
+typedef enum {
+ PICTURE_BMP = 1,
+ PICTURE_GIF,
+ PICTURE_JPG,
+ PICTURE_ICN,
+ PICTURE_PNG
+} GSM_BinaryPicture_Types;
+
+typedef struct {
+ GSM_BinaryPicture_Types Type;
+ unsigned char *Buffer;
+ int Length;
+} GSM_BinaryPicture;
+
/**
* Enum to handle all possible bitmaps, which are not saved in various filesystems.
*/
typedef enum {
GSM_None = 1,
/**
* ID of static file in filesystem displayed during startup
*/
GSM_ColourStartupLogo_ID,
/**
* Static mono bitmap/ID of animated mono bitmap displayed during startup
*/
GSM_StartupLogo,
/**
* ID of static file in filesystem displayed instead of operator name
*/
GSM_ColourOperatorLogo_ID,
/**
* Mono bitmap displayed instead of operator name
*/
GSM_OperatorLogo,
/**
* ID of static file in filesystem displayed as wallpaper
*/
GSM_ColourWallPaper_ID,
/**
* Mono bitmap assigned to caller group
*/
GSM_CallerGroupLogo,
/**
* Text displayed during startup, which can't be removed from phone menu
*/
GSM_DealerNote_Text,
/**
* Text displayed during startup
*/
GSM_WelcomeNote_Text,
/**
* Image defined in Smart Messaging specification
*/
- GSM_PictureImage
+ GSM_PictureImage,
+ /**
+ * Binary picture (BMP, GIF, etc.)
+ */
+ GSM_PictureBinary
} GSM_Bitmap_Types;
#define GSM_BITMAP_SIZE (65+7)/8*96
#define GSM_BITMAP_TEXT_LENGTH 128
/**
* Structure for all possible bitmaps, which are not saved in various filesystems
*/
typedef struct {
/**
* For all: bitmap type
*/
GSM_Bitmap_Types Type;
/**
* For caller group logos: number of group
* For startup logos: number of animated bitmap
*/
unsigned char Location;
/**
* For dealer/welcome note text: text
* For caller group logo: name of group
* For picture images: text assigned to it
*/
unsigned char Text[2 * (GSM_BITMAP_TEXT_LENGTH + 1)];
/**
* For caller group logo: true, when logo is enabled in group
*/
bool BitmapEnabled;
/**
* For caller group logo: true, when group has default name
*/
bool DefaultName;
/**
* For caller group logo: true, when group has default bitmap
*/
bool DefaultBitmap;
/**
* For caller group logo: true, when group has default ringtone
*/
bool DefaultRingtone;
/**
* For caller group logo: ringtone ID. Phone model specific
*/
unsigned char RingtoneID;
bool FileSystemRingtone;
/**
* For mono bitmaps: body of bitmap
*/
unsigned char BitmapPoints[GSM_BITMAP_SIZE];
/**
* For mono bitmaps: height specified in pixels
*/
unsigned char BitmapHeight;
/**
* For mono bitmaps: width specified in pixels
*/
unsigned char BitmapWidth;
/**
* For operator logos: Network operator code
*/
char NetworkCode[7];
/**
* For picture images: number of sender
*/
unsigned char Sender[2 * (GSM_MAX_NUMBER_LENGTH + 1)];
/**
* For colour bitmaps: ID
*/
unsigned char ID;
+ /**
+ * For binary pictures (GIF, BMP, etc.): frame and length
+ */
+ GSM_BinaryPicture BinaryPic;
+ /**
+ * Bitmap name
+ */
+ char *Name;
} GSM_Bitmap;
#define MAX_MULTI_BITMAP 6
/**
* Structure to handle more than one bitmap
*/
typedef struct {
/**
* Number of bitmaps
*/
unsigned char Number;
/**
* All bitmaps
*/
GSM_Bitmap Bitmap[MAX_MULTI_BITMAP];
} GSM_MultiBitmap;
typedef enum {
GSM_NokiaStartupLogo = 1, /*size 84*48*/
GSM_NokiaOperatorLogo, /*size 72*14*/
GSM_Nokia7110OperatorLogo, /*size 78*21*/
GSM_Nokia6510OperatorLogo, /*size 78*21*/
GSM_NokiaCallerLogo, /*size 72*14*/
GSM_NokiaPictureImage, /*size 72*28*/
GSM_Nokia7110StartupLogo, /*size 96*65*/
GSM_Nokia6210StartupLogo, /*size 96*60*/
GSM_AlcatelBMMIPicture,
GSM_EMSSmallPicture, /*size 8* 8*/
GSM_EMSMediumPicture, /*size 16*16*/
GSM_EMSBigPicture, /*size 32*32*/
GSM_EMSVariablePicture
} GSM_Phone_Bitmap_Types;
bool GSM_IsPointBitmap (GSM_Bitmap *bmp, int x, int y);
void GSM_SetPointBitmap (GSM_Bitmap *bmp, int x, int y);
void GSM_ClearPointBitmap (GSM_Bitmap *bmp, int x, int y);
void GSM_ClearBitmap (GSM_Bitmap *bmp);
void GSM_ResizeBitmap (GSM_Bitmap *dest, GSM_Bitmap *src, int width, int height);
void GSM_ReverseBitmap (GSM_Bitmap *Bitmap);
void GSM_GetMaxBitmapWidthHeight(GSM_Bitmap_Types Type, unsigned char *width, unsigned char *height);
int GSM_GetBitmapSize (GSM_Bitmap *bmp);
void GSM_PrintBitmap (FILE *file, GSM_Bitmap *bitmap);
GSM_Error GSM_SaveBitmapFile (char *FileName, GSM_MultiBitmap *bitmap);
GSM_Error GSM_ReadBitmapFile (char *FileName, GSM_MultiBitmap *bitmap);
GSM_Error BMP2Bitmap (unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap);
GSM_Error Bitmap2BMP (unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap);
void PHONE_GetBitmapWidthHeight (GSM_Phone_Bitmap_Types Type, int *width, int *height);
int PHONE_GetBitmapSize (GSM_Phone_Bitmap_Types Type, int width, int height);
void PHONE_ClearBitmap (GSM_Phone_Bitmap_Types Type, char *buffer, int width, int height);
void PHONE_DecodeBitmap (GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap);
void PHONE_EncodeBitmap (GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap);
void NOKIA_CopyBitmap (GSM_Phone_Bitmap_Types Type, GSM_Bitmap *Bitmap, char *Buffer, int *Length);
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/service/gsmmisc.h b/gammu/emb/common/service/gsmmisc.h
index 37501ad..793d3d1 100644
--- a/gammu/emb/common/service/gsmmisc.h
+++ b/gammu/emb/common/service/gsmmisc.h
@@ -103,214 +103,219 @@ typedef struct {
*/
char Code[GSM_SECURITY_CODE_LEN+1];
/**
* Type of the code.
*/
GSM_SecurityCodeType Type;
} GSM_SecurityCode;
/* ---------------------------- keyboard ----------------------------------- */
typedef enum {
GSM_KEY_NONE = 0x00,
GSM_KEY_1 = 0x01,
GSM_KEY_2,
GSM_KEY_3,
GSM_KEY_4,
GSM_KEY_5,
GSM_KEY_6,
GSM_KEY_7,
GSM_KEY_8,
GSM_KEY_9,
GSM_KEY_0,
/**
* #
*/
GSM_KEY_HASH,
/**
* *
*/
GSM_KEY_ASTERISK,
GSM_KEY_POWER,
/**
* in some phone ie. N5110 sometimes works identical to POWER
*/
GSM_KEY_GREEN,
/**
* (c) key in some phone: ie. N5110
*/
GSM_KEY_RED,
/**
* doesn't available in some phones as separate button: ie. N5110
*/
GSM_KEY_INCREASEVOLUME,
/**
* doesn't available in some phones as separate button: ie. N5110
*/
GSM_KEY_DECREASEVOLUME,
GSM_KEY_UP = 0x17,
GSM_KEY_DOWN,
GSM_KEY_MENU,
/**
* doesn't available in some phone: ie. N5110
*/
GSM_KEY_NAMES
} GSM_KeyCode;
GSM_Error MakeKeySequence(char *text, GSM_KeyCode *KeyCode, int *Length);
/* ------------------------------- display features ------------------------ */
typedef enum {
GSM_CallActive = 1,
/**
* blinking envelope
*/
GSM_SMSMemoryFull,
GSM_FaxCall,
GSM_UnreadSMS,
GSM_DataCall,
GSM_VoiceCall,
GSM_KeypadLocked
} GSM_DisplayFeature;
typedef struct {
int Number;
GSM_DisplayFeature Feature[7];
} GSM_DisplayFeatures;
/* ----------------------------- power source ------------------------------ */
typedef enum {
GSM_BatteryPowered = 1,
GSM_BatteryConnected,
GSM_BatteryNotConnected,
GSM_PowerFault
} GSM_ChargeState;
typedef struct {
/**
* Signal strength in percent, -1 = unknown
*/
int BatteryPercent;
/**
* Charge state
*/
GSM_ChargeState ChargeState;
} GSM_BatteryCharge;
/* ------------------------------ categories ------------------------------- */
#define GSM_MAX_CATEGORY_NAME_LENGTH 50
typedef enum {
Category_ToDo = 1,
Category_Phonebook
} GSM_CategoryType;
typedef struct {
GSM_CategoryType Type;
int Location;
unsigned char Name[(GSM_MAX_CATEGORY_NAME_LENGTH + 1)*2];
} GSM_Category;
typedef struct {
GSM_CategoryType Type;
int Used;
} GSM_CategoryStatus;
/* ------------------- radio FM stations ---------------------------------- */
#define GSM_MAX_FMSTATION_LENGTH 12
#define GSM_MAX_FM_STATION 20
typedef struct {
int Location;
char StationName [(GSM_MAX_FMSTATION_LENGTH+1)*2];
double Frequency;
} GSM_FMStation;
/* ----------------------- filesystem ------------------------------------- */
typedef enum {
GSM_File_Java_JAR = 1,
GSM_File_Image_JPG,
GSM_File_Image_BMP,
GSM_File_Image_GIF,
GSM_File_Image_PNG,
GSM_File_Image_WBMP,
GSM_File_Video_3GP,
GSM_File_Sound_AMR,
GSM_File_Sound_NRT, /* DCT4 binary format */
GSM_File_Sound_MIDI,
#ifdef DEVELOP
GSM_File_MMS,
#endif
GSM_File_Other
} GSM_FileType;
typedef struct {
int Used; /* how many bytes used */
unsigned char Name[300]; /* Name */
bool Folder; /* true, when folder */
int Level;
GSM_FileType Type;
unsigned char ID_FullName[400];
unsigned char *Buffer;
GSM_DateTime Modified;
bool ModifiedEmpty;
/* File attributes */
bool Protected;
bool ReadOnly;
bool Hidden;
bool System;
} GSM_File;
GSM_Error GSM_ReadFile(char *FileName, GSM_File *File);
GSM_Error GSM_JADFindData(GSM_File File, char *Vendor, char *Name, char *JAR, char *Version, int *Size);
void GSM_IdentifyFileFormat(GSM_File *File);
typedef struct {
int Free;
int Used;
} GSM_FileSystemStatus;
/* ----------------------------- GPRS access points ----------------------- */
typedef struct {
int Location;
unsigned char Name[300];
unsigned char URL[500];
bool Active;
} GSM_GPRSAccessPoint;
/* ------------------------------------------------------------------------ */
typedef enum {
GSM_Date_DDMMYYYY = 1,
GSM_Date_MMDDYYYY,
- GSM_Date_YYYYMMDD
+ GSM_Date_YYYYMMDD,
+ GSM_Date_DDMMMYY,
+ GSM_Date_MMDDYY,
+ GSM_Date_DDMMYY,
+ GSM_Date_YYMMDD,
+ GSM_Date_OFF
} GSM_DateFormat;
typedef struct {
unsigned char DateSeparator;
GSM_DateFormat DateFormat;
bool AMPMTime;
} GSM_Locale;
/* ------------------------------------------------------------------------ */
void ReadVCALDateTime(char *Buffer, GSM_DateTime *dt);
void SaveVCALDateTime(char *Buffer, int *Length, GSM_DateTime *Date, char *Start);
void SaveVCALText(char *Buffer, int *Length, char *Text, char *Start);
bool ReadVCALText(char *Buffer, char *Start, char *Value);
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/service/gsmring.c b/gammu/emb/common/service/gsmring.c
index 7df46f1..dab028c 100644
--- a/gammu/emb/common/service/gsmring.c
+++ b/gammu/emb/common/service/gsmring.c
@@ -1,1036 +1,1077 @@
/* (c) 2001-2004 by Marcin Wiacek */
-/* Based on some work from Ralf Thelen (7110 ringtones),
- * Gnokii (RTTL and SM) and others
+/* Based on some work from Ralf Thelen (7110 ringtones) and others */
+/* Based on some work (RTTL and SM) from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
*/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
+#include <sys/stat.h>
#ifdef WIN32
# include <windows.h>
#endif
#include "../gsmcomon.h"
#include "../misc/coding/coding.h"
#include "../gsmstate.h"
#include "gsmring.h"
#include "sms/gsmsms.h"
int GSM_RingNoteGetFrequency(GSM_RingNote Note)
{
double freq=0;
/* 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)'
*/
switch (Note.Note) {
case Note_C : freq = 523.3; break;
case Note_Cis: freq = 554.4; break;
case Note_D : freq = 587.3; break;
case Note_Dis: freq = 622.3; break;
case Note_E : freq = 659.3; break;
case Note_F : freq = 698.5; break;
case Note_Fis: freq = 740; break;
case Note_G : freq = 784; break;
case Note_Gis: freq = 830.6; break;
case Note_A : freq = 880; break;
case Note_Ais: freq = 932.3; break;
case Note_H : freq = 987.8; break;
case Note_Pause: break;
}
switch (Note.Scale) {
case Scale_440 : freq = freq / 2; break;
case Scale_880 : break;
case Scale_1760: freq = freq * 2; break;
case Scale_3520: freq = freq * 4; break;
default : break;
}
return (int)freq;
}
int GSM_RingNoteGetFullDuration(GSM_RingNote Note)
{
int duration = 1;
switch (Note.Duration) {
case Duration_Full : duration = 128; break;
case Duration_1_2 : duration = 64; break;
case Duration_1_4 : duration = 32; break;
case Duration_1_8 : duration = 16; break;
case Duration_1_16 : duration = 8; break;
case Duration_1_32 : duration = 4; break;
}
switch (Note.DurationSpec) {
case NoSpecialDuration : break;
case DottedNote : duration = duration * 3/2; break;
case DoubleDottedNote : duration = duration * 9/4; break;
case Length_2_3 : duration = duration * 2/3; break;
}
return duration;
}
#ifndef PI
# define PI 3.141592654
#endif
#define WAV_SAMPLE_RATE 44100
GSM_Error savewav(FILE *file, GSM_Ringtone *ringtone)
{
unsigned char WAV_Header[] = {
'R','I','F','F',
0x00,0x00,0x00,0x00, /* Length */
'W','A','V','E'};
unsigned char FMT_Header[] = {'f','m','t',' ',
0x10,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x44,0xac,
0x00,0x00,0x88,0x58,0x01,0x00,0x02,0x00,0x10,0x00};
unsigned char DATA_Header[] = {
'd','a','t','a',
0x00,0x00,0x00,0x00}; /* Length */
short DATA_Buffer[60000];
long wavfilesize;
GSM_RingNote *Note;
long i,j,length=0;
double phase=0,phase_step;
fwrite(&WAV_Header, 1, sizeof(WAV_Header), file);
fwrite(&FMT_Header, 1, sizeof(FMT_Header), file);
fwrite(&DATA_Header, 1, sizeof(DATA_Header), file);
for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
Note = &ringtone->NoteTone.Commands[i].Note;
phase_step = GSM_RingNoteGetFrequency(*Note)*WAV_SAMPLE_RATE*1.5;
for (j=0;j<((long)(GSM_RingNoteGetFullDuration(*Note)*WAV_SAMPLE_RATE/70));j++) {
#ifdef DESKTOP_VERSION
DATA_Buffer[j] = ((int)(sin(phase*PI)*50000));
#else
// we have no sin on Zaurus
DATA_Buffer[j] = ((int)(0.5*50000));
#endif
phase = phase + phase_step;
length++;
}
fwrite(&DATA_Buffer,sizeof(short),j,file);
}
}
wavfilesize = sizeof(WAV_Header) + sizeof(FMT_Header) + sizeof(DATA_Header) + length*2;
WAV_Header[4] = ((unsigned char)wavfilesize % 256);
WAV_Header[5] = ((unsigned char)wavfilesize / 256);
WAV_Header[6] = ((unsigned char)wavfilesize / (256*256));
WAV_Header[7] = ((unsigned char)wavfilesize / (256*256*256));
wavfilesize = wavfilesize - 54;
DATA_Header[4] = ((unsigned char)wavfilesize % 256);
DATA_Header[5] = ((unsigned char)wavfilesize / 256);
DATA_Header[6] = ((unsigned char)wavfilesize / (256*256));
DATA_Header[7] = ((unsigned char)wavfilesize / (256*256*256));
fseek( file, 0, SEEK_SET);
fwrite(&WAV_Header, 1, sizeof(WAV_Header), file);
fwrite(&FMT_Header, 1, sizeof(FMT_Header), file);
fwrite(&DATA_Header, 1, sizeof(DATA_Header), file);
return ERR_NONE;
}
static GSM_Error savebin(FILE *file, GSM_Ringtone *ringtone)
{
char nullchar=0x00;
fwrite(&nullchar,1,1,file);
fwrite(&nullchar,1,1,file);
fprintf(file,"\x0C\x01\x2C");
fprintf(file,"%s",DecodeUnicodeString(ringtone->Name));
fwrite(&nullchar,1,1,file);
fwrite(&nullchar,1,1,file);
fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
return ERR_NONE;
}
static GSM_Error savepuremidi(FILE *file, GSM_Ringtone *ringtone)
{
fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
return ERR_NONE;
}
+static GSM_Error savemmf(FILE *file, GSM_Ringtone *ringtone)
+{
+ fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
+ return ERR_NONE;
+}
+
GSM_Error saverttl(FILE *file, GSM_Ringtone *ringtone)
{
GSM_RingNoteScale DefNoteScale;
GSM_RingNoteDuration DefNoteDuration;
GSM_RingNoteStyle DefNoteStyle=0;
int DefNoteTempo=0;
bool started = false, firstcomma = true;
GSM_RingNote *Note;
unsigned char buffer[15];
int i,j,k=0;
/* Saves ringtone name */
fprintf(file,"%s:",DecodeUnicodeString(ringtone->Name));
/* Find the most frequently used duration */
for (i=0;i<6;i++) buffer[i]=0;
for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
Note = &ringtone->NoteTone.Commands[i].Note;
/* some durations need 2 bytes in file, some 1 */
if (Note->Duration >= Duration_Full && Note->Duration <= Duration_1_8) {
buffer[Note->Duration/32]++;
}
if (Note->Duration >= Duration_1_16 && Note->Duration <= Duration_1_32) {
buffer[Note->Duration/32]+=2;
}
}
}
/* Now find the most frequently used */
j=0;
for (i=0;i<6;i++) {
if (buffer[i]>j) {
k=i;
j=buffer[i];
}
}
/* Finally convert the default duration */
DefNoteDuration = k * 32;
dbgprintf("DefNoteDuration=%d\n", DefNoteDuration);
switch (DefNoteDuration) {
case Duration_Full:fprintf(file,"d=1"); break;
case Duration_1_2 :fprintf(file,"d=2"); break;
case Duration_1_4 :fprintf(file,"d=4"); break;
case Duration_1_8 :fprintf(file,"d=8"); break;
case Duration_1_16:fprintf(file,"d=16");break;
case Duration_1_32:fprintf(file,"d=32");break;
}
/* Find the most frequently used scale */
for (i=0;i<9;i++) buffer[i]=0;
for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
Note = &ringtone->NoteTone.Commands[i].Note;
if (Note->Note!=Note_Pause &&
Note->Scale >= Scale_55 && Note->Scale <= Scale_14080) {
buffer[Note->Scale - 1]++;
}
}
}
j=0;
for (i=0;i<9;i++) {
if (buffer[i]>j) {
k = i;
j=buffer[i];
}
}
DefNoteScale = k + 1;
/* Save the default scale */
fprintf(file,",o=%i,",DefNoteScale);
dbgprintf("DefNoteScale=%d\n", DefNoteScale);
for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
if (ringtone->NoteTone.Commands[i].Type != RING_Note) continue;
Note = &ringtone->NoteTone.Commands[i].Note;
/* Trick from PPM Edit */
if (Note->DurationSpec == DoubleDottedNote) {
switch (Note->Duration) {
case Duration_Full:Note->Duration = Duration_Full;break;
case Duration_1_2 :Note->Duration = Duration_Full;break;
case Duration_1_4 :Note->Duration = Duration_1_2; break;
case Duration_1_8 :Note->Duration = Duration_1_4; break;
case Duration_1_16:Note->Duration = Duration_1_8; break;
case Duration_1_32:Note->Duration = Duration_1_16;break;
}
Note->DurationSpec = NoSpecialDuration;
}
if (!started) {
DefNoteTempo=Note->Tempo;
DefNoteStyle=Note->Style;
switch (Note->Style) {
case StaccatoStyle : fprintf(file,"s=S,"); break;
case NaturalStyle : fprintf(file,"s=N,"); break;
case ContinuousStyle : break;
}
/* Save the default tempo */
fprintf(file,"b=%i:",DefNoteTempo);
dbgprintf("DefNoteTempo=%d\n", DefNoteTempo);
started = true;
firstcomma = true;
}
if (!started) continue;
if (Note->Style!=DefNoteStyle) {
/* And a separator */
if (!firstcomma) fprintf(file,",");
firstcomma = false;
DefNoteStyle=Note->Style;
switch (Note->Style) {
case StaccatoStyle : fprintf(file,"s=S"); break;
case NaturalStyle : fprintf(file,"s=N"); break;
case ContinuousStyle: fprintf(file,"s=C"); break;
}
}
if (Note->Tempo!=DefNoteTempo) {
/* And a separator */
if (!firstcomma) fprintf(file,",");
firstcomma = false;
DefNoteTempo=Note->Tempo;
fprintf(file,"b=%i",DefNoteTempo);
}
/* This note has a duration different than the default. We must save it */
if (Note->Duration!=DefNoteDuration) {
/* And a separator */
if (!firstcomma) fprintf(file,",");
firstcomma = false;
switch (Note->Duration) {
case Duration_Full:fprintf(file,"1"); break;
case Duration_1_2 :fprintf(file,"2"); break;
case Duration_1_4 :fprintf(file,"4"); break;
case Duration_1_8 :fprintf(file,"8"); break;
case Duration_1_16:fprintf(file,"16");break;
case Duration_1_32:fprintf(file,"32");break;
}
} else {
/* And a separator */
if (!firstcomma) fprintf(file,",");
firstcomma = false;
}
/* Now save the actual note */
switch (Note->Note) {
case Note_C :fprintf(file,"c"); break;
case Note_Cis:fprintf(file,"c#"); break;
case Note_D :fprintf(file,"d"); break;
case Note_Dis:fprintf(file,"d#"); break;
case Note_E :fprintf(file,"e"); break;
case Note_F :fprintf(file,"f"); break;
case Note_Fis:fprintf(file,"f#"); break;
case Note_G :fprintf(file,"g"); break;
case Note_Gis:fprintf(file,"g#"); break;
case Note_A :fprintf(file,"a"); break;
case Note_Ais:fprintf(file,"a#"); break;
case Note_H :fprintf(file,"h"); break;
default :fprintf(file,"p"); break; /*Pause ?*/
}
switch (Note->DurationSpec) {
case DottedNote : fprintf(file,"."); break;
default : break;
}
if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) {
fprintf(file,"%i",Note->Scale);
}
}
return ERR_NONE;
}
void saveimelody(FILE *file, GSM_Ringtone *ringtone)
{
char Buffer[2000];
int i=2000;
GSM_EncodeEMSSound(*ringtone, Buffer, &i, (float)1.2, true);
fwrite(Buffer, 1, i, file);
}
#ifndef ENABLE_LGPL
static void WriteVarLen(unsigned char* midifile, int* current, long value)
{
long buffer;
buffer = value & 0x7f;
while (value >>= 7) {
buffer <<= 8;
buffer |= 0x80;
buffer += (value & 0x7f);
}
while (1) {
midifile[(*current)++] = (unsigned char)buffer;
if (buffer & 0x80) {
buffer >>= 8;
} else {
break;
}
}
}
#define singlepauses
/* FIXME: need adding tempo before each note and scale too ? */
void savemid(FILE* file, GSM_Ringtone *ringtone)
{
int pause = 0, current = 26, duration, i, note=0, length = 20;
bool started = false;
GSM_RingNote *Note;
unsigned char midifile[3000] = {
0x4D, 0x54, 0x68, 0x64, // MThd
0x00, 0x00, 0x00, 0x06, // chunk length
0x00, 0x00, // format 0
0x00, 0x01, // one track
0x00, 0x20, // 32 per quarter note
0x4D, 0x54, 0x72, 0x6B, // MTrk
0x00, 0x00, 0x00, 0x00, // chunk length
0x00, 0xFF, 0x51, 0x03, // tempo meta event
0x00, 0x00, 0x00}; // 3 bytes for us for a quarter note
for (i = 0; i < ringtone->NoteTone.NrCommands; i++) {
if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
Note = &ringtone->NoteTone.Commands[i].Note;
if (!started) {
/* readmid does not read pauses at the beginning */
if (Note->Note != Note_Pause) {
/* FIXME: we need add tempo before each note or so... */
long duration=60000000/Note->Tempo;
midifile[current++] = (unsigned char)(duration >> 16);
midifile[current++] = (unsigned char)(duration >> 8);
midifile[current++] = (unsigned char)duration;
started = true;
}
}
if (!started) continue;
duration = GSM_RingNoteGetFullDuration(*Note);
if (Note->Note == Note_Pause) {
pause += duration;
#ifdef singlepauses
WriteVarLen(midifile,&current,pause);
pause=0;
midifile[current++]=0x00; // pause
midifile[current++]=0x00;
#endif
} else {
if (Note->Note >= Note_C && Note->Note <= Note_H) {
note = Note->Note/16 + 12 * Note->Scale - 1;
}
WriteVarLen(midifile,&current,pause);
pause=0;
midifile[current++]=0x90; // note on
midifile[current++]=note;
midifile[current++]=0x64; // forte
WriteVarLen(midifile,&current,duration);
midifile[current++]=0x80; // note off
midifile[current++]=note;
midifile[current++]=0x64;
}
}
}
if (pause) {
WriteVarLen(midifile,&current,pause);
midifile[current++]=0x00; // pause
midifile[current++]=0x00; //
}
midifile[current++] = 0x00;
midifile[current++] = 0xFF; // track end
midifile[current++] = 0x2F;
midifile[current++] = 0x00;
midifile[length++] = (current-22) >> 8;
midifile[length++] = current-22;
fwrite(midifile,1,current,file);
}
#endif
void saveott(FILE *file, GSM_Ringtone *ringtone)
{
char Buffer[2000];
int i=2000;
GSM_EncodeNokiaRTTLRingtone(*ringtone, Buffer, &i);
fwrite(Buffer, 1, i, file);
}
GSM_Error GSM_SaveRingtoneFile(char *FileName, GSM_Ringtone *ringtone)
{
FILE *file;
file = fopen(FileName, "wb");
if (file == NULL) return ERR_CANTOPENFILE;
switch (ringtone->Format) {
case RING_NOTETONE:
if (strstr(FileName,".ott")) {
saveott(file,ringtone);
#ifndef ENABLE_LGPL
} else if (strstr(FileName,".mid")) {
savemid(file,ringtone);
#endif
} else if (strstr(FileName,".rng")) {
saveott(file,ringtone);
} else if (strstr(FileName,".imy")) {
saveimelody(file,ringtone);
} else if (strstr(FileName,".ime")) {
saveimelody(file,ringtone);
} else if (strstr(FileName,".wav")) {
savewav(file,ringtone);
} else {
saverttl(file, ringtone);
}
break;
case RING_NOKIABINARY:
savebin(file, ringtone);
break;
case RING_MIDI:
savepuremidi(file, ringtone);
break;
+ case RING_MMF:
+ savemmf(file, ringtone);
+ break;
}
fclose(file);
return ERR_NONE;
}
static GSM_Error loadrttl(FILE *file, GSM_Ringtone *ringtone)
{
GSM_RingNoteScale DefNoteScale = Scale_880;
GSM_RingNoteDuration DefNoteDuration = Duration_1_4;
GSM_RingNoteStyle DefNoteStyle = NaturalStyle;
int DefNoteTempo = 63, i=0;
unsigned char buffer[2000],Name[100];
GSM_RingNote *Note;
fread(buffer, 2000, 1, file);
ringtone->NoteTone.NrCommands = 0;
/* -------------- name ---------------- */
while (buffer[i] != ':') {
if (buffer[i] == 0x00) return ERR_NONE;
i++;
}
if (i == 0) {
/* This is for RTTL ringtones without name. */
EncodeUnicode(ringtone->Name,"Gammu",5);
} else {
memcpy(Name,buffer,i);
Name[i] = 0x00;
EncodeUnicode(ringtone->Name,Name,strlen(Name));
}
i++;
/* --------- section with default ringtone settings ----------- */
while(1) {
switch (buffer[i]) {
case ':':
break;
case 0x00:
return ERR_NONE;
case 'd': case 'D':
switch (atoi(buffer+i+2)) {
case 1: DefNoteDuration = Duration_Full; break;
case 2: DefNoteDuration = Duration_1_2 ; break;
case 4: DefNoteDuration = Duration_1_4 ; break;
case 8: DefNoteDuration = Duration_1_8 ; break;
case 16: DefNoteDuration = Duration_1_16; break;
case 32: DefNoteDuration = Duration_1_32; break;
}
break;
case 'o': case 'O':
switch (atoi(buffer+i+2)) {
case 4: DefNoteScale = Scale_440 ; break;
case 5: DefNoteScale = Scale_880 ; break;
case 6: DefNoteScale = Scale_1760; break;
case 7: DefNoteScale = Scale_3520; break;
}
break;
case 'b': case 'B':
DefNoteTempo=atoi(buffer+i+2);
dbgprintf("Tempo = %i\n",DefNoteTempo);
break;
case 's': case 'S':
switch (buffer[i+1]) {
case 'C': case 'c': DefNoteStyle=ContinuousStyle; break;
case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
}
switch (buffer[i+2]) {
case 'C': case 'c': DefNoteStyle=ContinuousStyle; break;
case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
}
break;
}
while (buffer[i] != ':' && buffer[i] != ',') {
if (buffer[i] == 0x00) return ERR_NONE;
i++;
}
if (buffer[i] == ',') i++;
if (buffer[i] == ':') break;
}
dbgprintf("DefNoteDuration=%d\n", DefNoteDuration);
dbgprintf("DefNoteScale=%d\n", DefNoteScale);
i++;
/* ------------------------- notes ------------------------------ */
while (buffer[i] != 0x00 && ringtone->NoteTone.NrCommands != MAX_RINGTONE_NOTES) {
switch(buffer[i]) {
case 'z': case 'Z':
switch (buffer[i+1]) {
case 'd':
ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLED;
ringtone->NoteTone.NrCommands++;
break;
case 'D':
ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLED;
ringtone->NoteTone.NrCommands++;
break;
case 'v':
ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableVibra;
ringtone->NoteTone.NrCommands++;
break;
case 'V':
ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableVibra;
ringtone->NoteTone.NrCommands++;
break;
case 'l':
ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLight;
ringtone->NoteTone.NrCommands++;
break;
case 'L':
ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLight;
ringtone->NoteTone.NrCommands++;
}
break;
case 'o': case 'O':
switch (buffer[i+2]) {
case 4: DefNoteScale = Scale_440 ; break;
case 5: DefNoteScale = Scale_880 ; break;
case 6: DefNoteScale = Scale_1760; break;
case 7: DefNoteScale = Scale_3520; break;
}
break;
case 's': case 'S':
switch (buffer[i+1]) {
case 'C': case 'c': DefNoteStyle=ContinuousStyle; break;
case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
}
switch (buffer[i+2]) {
case 'C': case 'c': DefNoteStyle=ContinuousStyle; break;
case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
}
break;
default:
ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note;
Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note;
Note->Style = DefNoteStyle;
Note->Tempo = DefNoteTempo;
Note->Scale = DefNoteScale;
Note->Duration = DefNoteDuration;
Note->DurationSpec = NoSpecialDuration;
Note->Note = Note_Pause;
/* Duration */
switch (atoi(buffer+i)) {
case 1: Note->Duration = Duration_Full ; break;
case 2: Note->Duration = Duration_1_2 ; break;
case 4: Note->Duration = Duration_1_4 ; break;
case 8: Note->Duration = Duration_1_8 ; break;
case 16: Note->Duration = Duration_1_16 ; break;
case 32: Note->Duration = Duration_1_32 ; break;
}
/* We skip all numbers from duration specification */
while(isdigit(buffer[i])) i++;
/* Some files can have special duration here */
if (buffer[i]=='.') {
Note->DurationSpec = DottedNote;
i++;
}
/* Note */
/* B or b is not in specs, but I decided to put it, because
* it's in some RTTL files. It's the same to H note */
switch (buffer[i]) {
case 'A': case 'a': Note->Note = Note_A; break;
case 'B': case 'b': Note->Note = Note_H; break;
case 'C': case 'c': Note->Note = Note_C; break;
case 'D': case 'd': Note->Note = Note_D; break;
case 'E': case 'e': Note->Note = Note_E; break;
case 'F': case 'f': Note->Note = Note_F; break;
case 'G': case 'g': Note->Note = Note_G; break;
case 'H': case 'h': Note->Note = Note_H; break;
}
i++;
if (buffer[i]=='#') {
switch (Note->Note) {
case Note_A : Note->Note = Note_Ais; break;
case Note_C : Note->Note = Note_Cis; break;
case Note_D : Note->Note = Note_Dis; break;
case Note_F : Note->Note = Note_Fis; break;
case Note_G : Note->Note = Note_Gis; break;
default : break;
}
i++;
}
/* Some files can have special duration here */
if (buffer[i]=='.') {
Note->DurationSpec = DottedNote;
i++;
}
/* Scale */
if (Note->Note!=Note_Pause && isdigit(buffer[i])) {
switch (atoi(buffer+i)) {
case 4: Note->Scale = Scale_440 ; break;
case 5: Note->Scale = Scale_880 ; break;
case 6: Note->Scale = Scale_1760; break;
case 7: Note->Scale = Scale_3520; break;
}
i++;
}
ringtone->NoteTone.NrCommands++;
break;
}
while (buffer[i] != ',') {
if (buffer[i] == 0x00) return ERR_NONE;
i++;
}
if (buffer[i] == ',') i++;
}
return ERR_NONE;
}
static GSM_Error loadott(FILE *file, GSM_Ringtone *ringtone)
{
char Buffer[2000];
int i;
i=fread(Buffer, 1, 2000, file);
return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer, i);
}
static GSM_Error loadcommunicator(FILE *file, GSM_Ringtone *ringtone)
{
char Buffer[4000];
int i,j;
i=fread(Buffer, 1, 4000, file);
i=0;j=0;
while (true) {
if (Buffer[j] ==0x00 && Buffer[j+1]==0x02 &&
Buffer[j+2]==0x4a && Buffer[j+3]==0x3a) break;
if (j==i-4) return ERR_UNKNOWN;
j++;
}
j++;
return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer+j, i-j);
}
static GSM_Error loadbin(FILE *file, GSM_Ringtone *ringtone)
{
int i;
unsigned char buffer[2000];
dbgprintf("loading binary\n");
ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file);
i=5;
while (buffer[i]!=0x00) i++;
EncodeUnicode(ringtone->Name,buffer+5,i-5);
while (buffer[i]!=0x02 && buffer[i+1]!=0xFC && buffer[i+2]!=0x09) {
i++;
}
ringtone->NokiaBinary.Length=ringtone->NokiaBinary.Length-i;
memcpy(ringtone->NokiaBinary.Frame,buffer+i,ringtone->NokiaBinary.Length);
dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name));
return ERR_NONE;
}
static GSM_Error loadpuremidi(FILE *file, GSM_Ringtone *ringtone)
{
unsigned char buffer[30000];
dbgprintf("loading midi\n");
EncodeUnicode(ringtone->Name,"MIDI",4);
ringtone->NokiaBinary.Length=fread(buffer, 1, 30000, file);
memcpy(ringtone->NokiaBinary.Frame,buffer,ringtone->NokiaBinary.Length);
dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name));
return ERR_NONE;
}
+static GSM_Error loadmmf(FILE *file, GSM_Ringtone *ringtone)
+{
+ struct stat st;
+ char *buffer;
+ int length;
+
+ dbgprintf("loading smaf file\n");
+ fstat(fileno(file), &st);
+ ringtone->BinaryTone.Length = length = st.st_size;
+ ringtone->BinaryTone.Buffer = buffer = malloc(length);
+ if (buffer == NULL)
+ return ERR_MOREMEMORY;
+ fread(buffer, 1, length, file);
+
+ dbgprintf("Length %i name \"%s\"\n", length,
+ DecodeUnicodeString(ringtone->Name));
+
+ return ERR_NONE;
+}
+
static GSM_Error loadre(FILE *file, GSM_Ringtone *ringtone)
{
unsigned char buffer[2000];
ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file);
if (buffer[18]==0x00 && buffer[21]!=0x02) {
/* DCT3, Unicode subformat, 62xx & 7110 */
CopyUnicodeString(ringtone->Name,buffer+18);
ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (21+UnicodeLength(ringtone->Name)*2);
memcpy(ringtone->NokiaBinary.Frame,buffer+21+UnicodeLength(ringtone->Name)*2,ringtone->NokiaBinary.Length);
} else {
/* DCT3, normal subformat, 32xx/33xx/51xx/5210/5510/61xx/8xxx */
EncodeUnicode(ringtone->Name,buffer+17,buffer[16]);
ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (19+UnicodeLength(ringtone->Name));
memcpy(ringtone->NokiaBinary.Frame,buffer+19+UnicodeLength(ringtone->Name),ringtone->NokiaBinary.Length);
}
dbgprintf("Name \"%s\"\n",DecodeUnicodeString(ringtone->Name));
return ERR_NONE;
}
GSM_Error GSM_ReadRingtoneFile(char *FileName, GSM_Ringtone *ringtone)
{
FILE *file;
unsigned char buffer[300];
GSM_Error error = ERR_UNKNOWN;
dbgprintf("Loading ringtone %s\n",FileName);
file = fopen(FileName, "rb");
if (file == NULL) return ERR_CANTOPENFILE;
/* Read the header of the file. */
fread(buffer, 1, 4, file);
if (ringtone->Format == 0x00) {
ringtone->Format = RING_NOTETONE;
if (buffer[0]==0x00 && buffer[1]==0x00 &&
buffer[2]==0x0C && buffer[3]==0x01) {
ringtone->Format = RING_NOKIABINARY;
}
if (buffer[0]==0x00 && buffer[1]==0x00 &&
buffer[2]==0x00) {
ringtone->Format = RING_NOKIABINARY;
}
if (buffer[0]==0x4D && buffer[1]==0x54 &&
buffer[2]==0x68 && buffer[3]==0x64) {
ringtone->Format = RING_MIDI;
}
+ if (buffer[0]==0x4D && buffer[1]==0x4D &&
+ buffer[2]==0x4D && buffer[3]==0x44) {
+ ringtone->Format = RING_MMF;
+ }
}
rewind(file);
switch (ringtone->Format) {
case RING_NOTETONE:
if (buffer[0]==0x02 && buffer[1]==0x4A) {
error=loadott(file,ringtone);
} else if (buffer[0]==0xC7 && buffer[1]==0x45) {
error=loadcommunicator(file,ringtone);
} else {
error=loadrttl(file,ringtone);
}
ringtone->NoteTone.AllNotesScale=false;
break;
case RING_NOKIABINARY:
if (buffer[0]==0x00 && buffer[1]==0x00 &&
buffer[2]==0x0C && buffer[3]==0x01) {
error=loadbin(file,ringtone);
}
if (buffer[0]==0x00 && buffer[1]==0x00 &&
buffer[2]==0x00) {
error=loadre(file,ringtone);
}
break;
case RING_MIDI:
EncodeUnicode(ringtone->Name,FileName,strlen(FileName));
error = loadpuremidi(file,ringtone);
+ break;
+ case RING_MMF:
+ EncodeUnicode(ringtone->Name,FileName,strlen(FileName));
+ error = loadmmf(file,ringtone);
+ break;
}
fclose(file);
return(error);
}
/* -------------------------- required with Nokia & RTTL ------------------- */
/* Beats per Minute like written in Smart Messaging */
static int SM_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
};
int GSM_RTTLGetTempo(int Beats)
{
int i=0;
while (Beats > SM_BeatsPerMinute[i] && SM_BeatsPerMinute[i] != 900) i++;
return i<<3;
}
/* 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" */
unsigned char GSM_EncodeNokiaRTTLRingtone(GSM_Ringtone ringtone, unsigned char *package, int *maxlength)
{
unsigned char CommandLength = 0x02;
unsigned char Loop = 0x15; /* Infinite */
unsigned char Buffer[200];
int StartBit=0, OldStartBit;
int StartBitHowManyCommands;
int HowManyCommands = 0; /* How many instructions packed */
int HowManyNotes = 0;
int i,j;
bool started;
GSM_RingNote *Note;
GSM_RingNoteScale DefScale = 255;
GSM_RingNoteStyle DefStyle = 255;
int DefTempo = 255;
AddBufferByte(package, &StartBit, CommandLength, 8);
AddBufferByte(package, &StartBit, SM_Command_RingingToneProgramming, 7);
/* According to specification we need have next part octet-aligned */
BufferAlign(package, &StartBit);
AddBufferByte(package, &StartBit, SM_Command_Sound, 7);
AddBufferByte(package, &StartBit, SM_Song_BasicSongType, 3);
/* Packing the name of the tune. */
EncodeUnicodeSpecialNOKIAChars(Buffer, ringtone.Name, UnicodeLength(ringtone.Name));
AddBufferByte(package, &StartBit, ((unsigned char)(UnicodeLength(Buffer)<<4)), 4);
AddBuffer(package, &StartBit, DecodeUnicodeString(Buffer), 8*UnicodeLength(Buffer));
/* Packing info about song pattern */
AddBufferByte(package, &StartBit, 0x01, 8); //one pattern
AddBufferByte(package, &StartBit, SM_InstructionID_PatternHeaderId, 3);
AddBufferByte(package, &StartBit, SM_PatternID_A_part, 2);
AddBufferByte(package, &StartBit, ((unsigned char)(Loop<<4)), 4);
/* Later here will be HowManyCommands */
StartBitHowManyCommands=StartBit;
StartBit = StartBit + 8;
started = false;
for (i=0; i<ringtone.NoteTone.NrCommands; i++) {
if (ringtone.NoteTone.Commands[i].Type != RING_Note) {
HowManyNotes++;
continue;
}
Note = &ringtone.NoteTone.Commands[i].Note;
if (!started) {
/* First note can't be Pause - it makes problems
* for example with PC Composer
*/
if (Note->Note != Note_Pause) started = true;
}
if (!started) {
HowManyNotes++;
continue;
}
OldStartBit = StartBit;
/* we don't write Scale & Style info before "Pause" note - it saves place */
if (Note->Note!=Note_Pause) {
if (DefScale != Note->Scale || ringtone.NoteTone.AllNotesScale) {
j = StartBit+5+8;
BufferAlignNumber(&j);
if ((j/8)>(*maxlength)) {
StartBit = OldStartBit;
break;
}
DefScale = Note->Scale;
AddBufferByte(package, &StartBit, SM_InstructionID_ScaleInstructionId, 3);
AddBufferByte(package, &StartBit, ((unsigned char)((DefScale-4)<<6)), 2);
HowManyCommands++;
}
if (DefStyle != Note->Style) {
j = StartBit+5+8;
BufferAlignNumber(&j);
if ((j/8)>(*maxlength)) {
StartBit = OldStartBit;
break;
}
DefStyle = Note->Style;
AddBufferByte(package, &StartBit, SM_InstructionID_StyleInstructionId, 3);
AddBufferByte(package, &StartBit, ((unsigned char)DefStyle), 2);
HowManyCommands++;
}
}
/* Beats per minute/tempo of the tune */
if (DefTempo != GSM_RTTLGetTempo(Note->Tempo)) {
j = StartBit+8+8;
BufferAlignNumber(&j);
if ((j/8)>(*maxlength)) {
StartBit = OldStartBit;
break;
}
DefTempo=GSM_RTTLGetTempo(Note->Tempo);
/* Adding beats per minute (tempo) of the tune */
AddBufferByte(package, &StartBit, SM_InstructionID_TempoInstructionId, 3);
AddBufferByte(package, &StartBit, ((unsigned char)DefTempo), 5);
HowManyCommands++;
}
j = StartBit+12+8;
BufferAlignNumber(&j);
if ((j/8)>(*maxlength)) {
StartBit = OldStartBit;
break;
}
/* Note */
AddBufferByte(package, &StartBit, SM_InstructionID_NoteInstructionId, 3);
AddBufferByte(package, &StartBit, ((unsigned char)Note->Note), 4);
AddBufferByte(package, &StartBit, ((unsigned char)Note->Duration), 3);
AddBufferByte(package, &StartBit, ((unsigned char)Note->DurationSpec), 2);
HowManyCommands++;
/* 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 (HowManyNotes==130-1) break;
}
HowManyNotes++;
}
BufferAlign(package, &StartBit);
AddBufferByte(package, &StartBit, SM_CommandEnd_CommandEnd, 8);
OldStartBit = StartBit;
StartBit = StartBitHowManyCommands;
/* HowManyCommands */
AddBufferByte(package, &StartBit, ((unsigned char)HowManyCommands), 8);
StartBit = OldStartBit;
*maxlength=StartBit/8;
return(i);
}
GSM_Error GSM_DecodeNokiaRTTLRingtone(GSM_Ringtone *ringtone, unsigned char *package, int maxlength)
{
int StartBit=0, HowMany, l, q, i, spec;
char Buffer[100];
GSM_RingNote *Note;
/* Default ringtone parameters */
GSM_RingNoteScale DefScale = Scale_880;
GSM_RingNoteStyle DefStyle = NaturalStyle;
int DefTempo = 63;
ringtone->Format = RING_NOTETONE;
ringtone->NoteTone.NrCommands = 0;
GetBufferInt(package,&StartBit,&l,8);
if (l!=0x02) {
dbgprintf("Not header\n");
return ERR_NOTSUPPORTED;
}
GetBufferInt(package,&StartBit,&l,7);
if (l!=SM_Command_RingingToneProgramming) {
dbgprintf("Not RingingToneProgramming\n");
return ERR_NOTSUPPORTED;
}
/* According to specification we need have next part octet-aligned */
BufferAlignNumber(&StartBit);
diff --git a/gammu/emb/common/service/gsmring.h b/gammu/emb/common/service/gsmring.h
index 207cf31..2d2dd7a 100644
--- a/gammu/emb/common/service/gsmring.h
+++ b/gammu/emb/common/service/gsmring.h
@@ -1,202 +1,204 @@
/* (c) 2002-2004 by Marcin Wiacek */
#ifndef __gsm_ring_h
#define __gsm_ring_h
/* --------------- Smart Messaging Specification 2.0 & 3.0 ----------------- */
#define SM_CommandEnd_CommandEnd 0x00
/* specification gives also other */
#define SM_Command_RingingToneProgramming 0x25<<1
#define SM_Command_Sound 0x1d<<1
/* specification gives also other */
#define SM_Song_BasicSongType 0x01<<5
/* specification gives also other */
#define SM_PatternID_A_part 0x00<<6
/* specification gives also other */
#define SM_InstructionID_PatternHeaderId 0x00<<5
#define SM_InstructionID_NoteInstructionId 0x01<<5
#define SM_InstructionID_ScaleInstructionId 0x02<<5
#define SM_InstructionID_StyleInstructionId 0x03<<5
#define SM_InstructionID_TempoInstructionId 0x04<<5
#define SM_InstructionID_VolumeInstructionId 0x05<<5
/* ------ end of Smart Messaging Specification 2.0 & 3.0 definitions ------- */
#define MAX_RINGTONE_NOTES 255
typedef enum {
/**
* Natural style (rest between notes)
*/
NaturalStyle = 0x00<<6,
/**
* Continuous style (no rest between notes)
*/
ContinuousStyle = 0x01<<6,
/**
* Staccato style (shorter notes and longer rest period)
*/
StaccatoStyle = 0x02<<6
} GSM_RingNoteStyle;
typedef enum {
Note_Pause = 0x00<<4,
Note_C = 0x01<<4,
Note_Cis = 0x02<<4,
Note_D = 0x03<<4,
Note_Dis = 0x04<<4,
Note_E = 0x05<<4,
Note_F = 0x06<<4,
Note_Fis = 0x07<<4,
Note_G = 0x08<<4,
Note_Gis = 0x09<<4,
Note_A = 0x0a<<4,
Note_Ais = 0x0b<<4,
Note_H = 0x0c<<4
} GSM_RingNoteNote;
typedef enum {
Duration_Full = 0x00<<5,
Duration_1_2 = 0x01<<5,
Duration_1_4 = 0x02<<5,
Duration_1_8 = 0x03<<5,
Duration_1_16 = 0x04<<5,
Duration_1_32 = 0x05<<5
} GSM_RingNoteDuration;
typedef enum {
NoSpecialDuration = 0x00<<6,
DottedNote = 0x01<<6,
DoubleDottedNote = 0x02<<6,
Length_2_3 = 0x03<<6
} GSM_RingNoteDurationSpec;
typedef enum {
Scale_55 = 1, /* 55 Hz for note A */
Scale_110, /* 110 Hz for note A */
Scale_220,
Scale_440, /* first scale for Nokia */
Scale_880,
Scale_1760,
Scale_3520, /* last scale for Nokia */
Scale_7040,
Scale_14080
} GSM_RingNoteScale;
typedef struct {
GSM_RingNoteDuration Duration;
GSM_RingNoteDurationSpec DurationSpec;
GSM_RingNoteNote Note;
GSM_RingNoteStyle Style;
GSM_RingNoteScale Scale;
int Tempo;
} GSM_RingNote;
typedef enum {
RING_Note = 1,
RING_EnableVibra,
RING_DisableVibra,
RING_EnableLight,
RING_DisableLight,
RING_EnableLED,
RING_DisableLED,
RING_Repeat
} GSM_RingCommandType;
typedef struct {
GSM_RingCommandType Type;
GSM_RingNote Note;
unsigned char Value;
} GSM_RingCommand;
typedef struct {
int NrCommands;
GSM_RingCommand Commands[MAX_RINGTONE_NOTES];
bool AllNotesScale;
} GSM_NoteRingtone;
+/* FIXME: should use BinaryTone instead? */
/* Structure to hold Nokia binary ringtones. */
typedef struct {
- unsigned char Frame[30000];
+ unsigned char Frame[50000];
int Length;
} GSM_NokiaBinaryRingtone;
typedef struct {
- unsigned char *Frame;
+ unsigned char *Buffer;
int Length;
} GSM_BinaryTone;
typedef enum {
RING_NOTETONE = 1,
RING_NOKIABINARY,
- RING_MIDI
+ RING_MIDI,
+ RING_MMF
} GSM_RingtoneFormat;
/**
* Structure for saving various ringtones formats
*/
typedef struct {
/**
* Ringtone saved in one of three formats
*/
GSM_NokiaBinaryRingtone NokiaBinary;
GSM_BinaryTone BinaryTone;
GSM_NoteRingtone NoteTone;
/**
* Ringtone format
*/
GSM_RingtoneFormat Format;
/**
* Ringtone name
*/
char Name[20*2];
/**
* Ringtone location
*/
int Location;
} GSM_Ringtone;
typedef struct {
int Group; //Nokia specific
int ID;
char Name[30*2];
} GSM_RingtoneInfo;
typedef struct {
int Number;
GSM_RingtoneInfo Ringtone[100];
} GSM_AllRingtonesInfo;
GSM_Error GSM_SaveRingtoneFile(char *FileName, GSM_Ringtone *ringtone);
GSM_Error GSM_ReadRingtoneFile(char *FileName, GSM_Ringtone *ringtone);
void saveott(FILE *file, GSM_Ringtone *ringtone);
void savemid(FILE *file, GSM_Ringtone *ringtone);
void saverng(FILE *file, GSM_Ringtone *ringtone);
void saveimelody(FILE *file, GSM_Ringtone *ringtone);
GSM_Error savewav(FILE *file, GSM_Ringtone *ringtone);
GSM_Error saverttl(FILE *file, GSM_Ringtone *ringtone);
unsigned char GSM_EncodeNokiaRTTLRingtone (GSM_Ringtone ringtone, unsigned char *package, int *maxlength);
unsigned char GSM_EncodeEMSSound (GSM_Ringtone ringtone, unsigned char *package, int *maxlength, double version, bool start);
GSM_Error GSM_DecodeNokiaRTTLRingtone (GSM_Ringtone *ringtone, unsigned char *package, int maxlength);
GSM_Error GSM_RingtoneConvert(GSM_Ringtone *dest, GSM_Ringtone *src, GSM_RingtoneFormat Format);
int GSM_RTTLGetTempo (int Beats);
int GSM_RingNoteGetFrequency (GSM_RingNote Note);
int GSM_RingNoteGetFullDuration (GSM_RingNote Note);
char *GSM_GetRingtoneName(GSM_AllRingtonesInfo *Info, int ID);
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/service/sms/gsmmulti.c b/gammu/emb/common/service/sms/gsmmulti.c
index 6c1cdcd..bdb5ee9 100644
--- a/gammu/emb/common/service/sms/gsmmulti.c
+++ b/gammu/emb/common/service/sms/gsmmulti.c
@@ -298,384 +298,389 @@ GSM_Error GSM_EncodeAlcatelMultiPartSMS(GSM_MultiSMSMessage *SMS,
SMS->SMS[i].UDH.Text[0] += MyUDH.Length-1;
SMS->SMS[i].UDH.Length += MyUDH.Length-1;
}
SMS->SMS[i].Coding = SMS_Coding_8bit;
SMS->SMS[i].Class = 1;
}
p = 0;
while (p != Len) {
i = 140-SMS->SMS[SMS->Number].UDH.Length;
if (Len - p < i) i = Len - p;
memcpy(SMS->SMS[SMS->Number].Text,Data+p,i);
p += i;
SMS->SMS[SMS->Number].Length = i;
SMS->Number++;
}
/* Linked sms UDH */
if (SMS->Number != 1) {
UDHID = GSM_MakeSMSIDFromTime();
for (i=0;i<SMS->Number;i++) {
SMS->SMS[i].UDH.Text[SMS->SMS[i].UDH.Length-3] = UDHID;
SMS->SMS[i].UDH.Text[SMS->SMS[i].UDH.Length-2] = SMS->Number;
SMS->SMS[i].UDH.Text[SMS->SMS[i].UDH.Length-1] = i+1;
}
}
return ERR_NONE;
}
/* Alcatel docs from www.alcatel.com/wap/ahead and other */
GSM_Error GSM_EncodeMultiPartSMS(GSM_MultiPartSMSInfo *Info,
GSM_MultiSMSMessage *SMS)
{
unsigned char Buffer[GSM_MAX_SMS_LENGTH*2*MAX_MULTI_SMS];
unsigned char Buffer2[GSM_MAX_SMS_LENGTH*2*MAX_MULTI_SMS];
int Length = 0,smslen,i, Class = -1, j,p;
GSM_Error error;
GSM_Coding_Type Coding = SMS_Coding_8bit;
GSM_UDH UDH = UDH_NoUDH;
GSM_UDHHeader UDHHeader;
bool EMS = false;
int textnum = 0;
SMS->Number = 0;
if (Info->Entries[0].ID == SMS_AlcatelSMSTemplateName) {
Buffer[Length++] = 0x00; //number of elements
for (i=1;i<Info->EntriesNum;i++) {
switch (Info->Entries[i].ID) {
case SMS_EMSSound10:
case SMS_EMSSound12:
case SMS_EMSSonyEricssonSound:
case SMS_EMSSound10Long:
case SMS_EMSSound12Long:
case SMS_EMSSonyEricssonSoundLong:
case SMS_EMSVariableBitmap:
case SMS_EMSAnimation:
case SMS_EMSVariableBitmapLong:
break;
case SMS_EMSPredefinedSound:
Buffer[0]++;
Buffer[Length++] = 0x01; //type of data
Buffer[Length++] = 1 % 256; //len
Buffer[Length++] = 1 / 256; //len
Buffer[Length++] = Info->Entries[i].Number;
break;
case SMS_EMSPredefinedAnimation:
Buffer[0]++;
Buffer[Length++] = 0x02; //type of data
Buffer[Length++] = 1 % 256; //len
Buffer[Length++] = 1 / 256; //len
Buffer[Length++] = Info->Entries[i].Number;
break;
case SMS_ConcatenatedTextLong:
Buffer[0]++;
p = UnicodeLength(Info->Entries[i].Buffer);
EncodeDefault(Buffer2, Info->Entries[i].Buffer, &p, true, NULL);
Buffer[Length++] = 0x00; //type of data
Length = Length + 2;
smslen = GSM_PackSevenBitsToEight(0, Buffer2, Buffer+Length, p);
Buffer[Length-2] = smslen % 256; //len
Buffer[Length-1] = smslen / 256; //len
Length = Length + smslen;
break;
default:
return ERR_UNKNOWN;
}
}
Buffer[0] = Buffer[0] * 2;
return GSM_EncodeAlcatelMultiPartSMS(SMS,Buffer,Length,Info->Entries[0].Buffer,ALCATELTDD_SMSTEMPLATE);
}
for (i=0;i<Info->EntriesNum;i++) {
switch (Info->Entries[i].ID) {
case SMS_EMSPredefinedAnimation:
case SMS_EMSPredefinedSound:
case SMS_EMSSound10:
case SMS_EMSSound12:
case SMS_EMSSonyEricssonSound:
case SMS_EMSSound10Long:
case SMS_EMSSound12Long:
case SMS_EMSSonyEricssonSoundLong:
case SMS_EMSFixedBitmap:
case SMS_EMSVariableBitmap:
case SMS_EMSAnimation:
case SMS_EMSVariableBitmapLong:
EMS = true;
break;
case SMS_ConcatenatedTextLong:
case SMS_ConcatenatedTextLong16bit:
/* This covers situation, when somebody will call function
* with two or more SMS_Concatenated.... entries only.
* It will be still only linked sms, but functions below
* will pack only first entry according to own limits.
* We redirect to EMS functions, because they are more generic
* here and will handle it correctly and produce linked sms
* from all entries
*/
textnum ++;
if (textnum > 1) EMS = true;
if (Info->Entries[i].Left || Info->Entries[i].Right ||
Info->Entries[i].Center || Info->Entries[i].Large ||
Info->Entries[i].Small || Info->Entries[i].Bold ||
Info->Entries[i].Italic || Info->Entries[i].Underlined ||
Info->Entries[i].Strikethrough) {
EMS = true;
}
default:
break;
}
if (EMS) break;
}
if (EMS) {
error=GSM_EncodeEMSMultiPartSMS(Info,SMS,UDH_NoUDH);
if (error != ERR_NONE) return error;
if (SMS->Number != 1) {
SMS->Number = 0;
for (i=0;i<Info->EntriesNum;i++) {
if (Info->Entries[i].ID == SMS_ConcatenatedTextLong16bit) {
return GSM_EncodeEMSMultiPartSMS(Info,SMS,UDH_ConcatenatedMessages);
}
}
return GSM_EncodeEMSMultiPartSMS(Info,SMS,UDH_ConcatenatedMessages16bit);
}
return error;
}
if (Info->EntriesNum != 1) return ERR_UNKNOWN;
switch (Info->Entries[0].ID) {
case SMS_AlcatelMonoBitmapLong:
Buffer[0] = Info->Entries[0].Bitmap->Bitmap[0].BitmapWidth;
Buffer[1] = Info->Entries[0].Bitmap->Bitmap[0].BitmapHeight;
PHONE_EncodeBitmap(GSM_AlcatelBMMIPicture, Buffer+2, &Info->Entries[0].Bitmap->Bitmap[0]);
Length = PHONE_GetBitmapSize(GSM_AlcatelBMMIPicture,Info->Entries[0].Bitmap->Bitmap[0].BitmapWidth,Info->Entries[0].Bitmap->Bitmap[0].BitmapHeight)+2;
return GSM_EncodeAlcatelMultiPartSMS(SMS,Buffer,Length,Info->Entries[0].Bitmap->Bitmap[0].Text,ALCATELTDD_PICTURE);
case SMS_AlcatelMonoAnimationLong:
/* Number of sequence words */
Buffer[0] = (Info->Entries[0].Bitmap->Number+1) % 256;
Buffer[1] = (Info->Entries[0].Bitmap->Number+1) / 256;
/* Picture display time 1 second (1 = 100ms) */
Buffer[2] = 10 % 256;
Buffer[3] = 10 / 256 + 0xF0;
Length = 4;
j = 0;
/* Offsets to bitmaps */
for (i=0;i<Info->Entries[0].Bitmap->Number;i++) {
Buffer[Length++] = (4+j+Info->Entries[0].Bitmap->Number*2) % 256;
Buffer[Length++] = (4+j+Info->Entries[0].Bitmap->Number*2) / 256;
j += PHONE_GetBitmapSize(GSM_AlcatelBMMIPicture,Info->Entries[0].Bitmap->Bitmap[i].BitmapWidth,Info->Entries[0].Bitmap->Bitmap[i].BitmapHeight)+2;
}
/* Bitmaps */
for (i=0;i<Info->Entries[0].Bitmap->Number;i++) {
Buffer[Length++] = Info->Entries[0].Bitmap->Bitmap[i].BitmapWidth;
Buffer[Length++] = Info->Entries[0].Bitmap->Bitmap[i].BitmapHeight;
PHONE_EncodeBitmap(GSM_AlcatelBMMIPicture, Buffer+Length, &Info->Entries[0].Bitmap->Bitmap[i]);
Length += PHONE_GetBitmapSize(GSM_AlcatelBMMIPicture,Info->Entries[0].Bitmap->Bitmap[i].BitmapWidth,Info->Entries[0].Bitmap->Bitmap[i].BitmapHeight);
}
return GSM_EncodeAlcatelMultiPartSMS(SMS,Buffer,Length,Info->Entries[0].Bitmap->Bitmap[0].Text,ALCATELTDD_ANIMATION);
case SMS_MMSIndicatorLong:
Class = 1;
UDH = UDH_MMSIndicatorLong;
GSM_EncodeMMSIndicatorSMSText(Buffer,&Length,*Info->Entries[0].MMSIndicator);
break;
+ case SMS_WAPIndicatorLong:
+ Class = 1;
+ UDH = UDH_MMSIndicatorLong;
+ GSM_EncodeWAPIndicatorSMSText(Buffer,&Length,Info->Entries[0].MMSIndicator->Title,Info->Entries[0].MMSIndicator->Address);
+ break;
case SMS_NokiaRingtoneLong:
case SMS_NokiaRingtone:
UDH = UDH_NokiaRingtone;
Class = 1;
/* 7 = length of UDH_NokiaRingtone UDH header */
Length = GSM_MAX_8BIT_SMS_LENGTH-7;
Info->Entries[0].RingtoneNotes = GSM_EncodeNokiaRTTLRingtone(*Info->Entries[0].Ringtone,Buffer,&Length);
if (Info->Entries[0].ID == SMS_NokiaRingtone) break;
if (Info->Entries[0].RingtoneNotes != Info->Entries[0].Ringtone->NoteTone.NrCommands) {
UDH = UDH_NokiaRingtoneLong;
Length = (GSM_MAX_8BIT_SMS_LENGTH-12)*3;
Info->Entries[0].RingtoneNotes = GSM_EncodeNokiaRTTLRingtone(*Info->Entries[0].Ringtone,Buffer,&Length);
}
break;
case SMS_NokiaOperatorLogoLong:
if (Info->Entries[0].Bitmap->Bitmap[0].BitmapWidth > 72 || Info->Entries[0].Bitmap->Bitmap[0].BitmapHeight > 14) {
UDH = UDH_NokiaOperatorLogoLong;
Class = 1;
NOKIA_EncodeNetworkCode(Buffer, Info->Entries[0].Bitmap->Bitmap[0].NetworkCode);
Length = Length + 3;
NOKIA_CopyBitmap(GSM_Nokia7110OperatorLogo, &Info->Entries[0].Bitmap->Bitmap[0], Buffer, &Length);
break;
}
case SMS_NokiaOperatorLogo:
UDH = UDH_NokiaOperatorLogo;
Class = 1;
NOKIA_EncodeNetworkCode(Buffer, Info->Entries[0].Bitmap->Bitmap[0].NetworkCode);
Length = Length + 3;
NOKIA_CopyBitmap(GSM_NokiaOperatorLogo, &Info->Entries[0].Bitmap->Bitmap[0], Buffer, &Length);
break;
case SMS_NokiaCallerLogo:
UDH = UDH_NokiaCallerLogo;
Class = 1;
NOKIA_CopyBitmap(GSM_NokiaCallerLogo, &Info->Entries[0].Bitmap->Bitmap[0], Buffer, &Length);
break;
case SMS_NokiaProfileLong:
case SMS_NokiaPictureImageLong:
case SMS_NokiaScreenSaverLong:
Class = 1;
UDH = UDH_NokiaProfileLong;
GSM_EncodeSMS30MultiPartSMS(Info,Buffer,&Length);
break;
case SMS_NokiaWAPBookmarkLong:
Class = 1;
NOKIA_EncodeWAPBookmarkSMSText(Buffer,&Length,Info->Entries[0].Bookmark);
/* 7 = length of UDH_NokiaWAP UDH header */
if (Length>(GSM_MAX_8BIT_SMS_LENGTH-7)) {
UDH=UDH_NokiaWAPLong;
} else {
UDH=UDH_NokiaWAP;
}
break;
case SMS_NokiaWAPSettingsLong:
Class = 1;
UDH = UDH_NokiaWAPLong;
NOKIA_EncodeWAPMMSSettingsSMSText(Buffer,&Length,Info->Entries[0].Settings,false);
break;
case SMS_NokiaMMSSettingsLong:
Class = 1;
UDH = UDH_NokiaWAPLong;
NOKIA_EncodeWAPMMSSettingsSMSText(Buffer,&Length,Info->Entries[0].Settings,true);
break;
case SMS_NokiaVCARD10Long:
GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard10);
/* is 1 SMS ? 8 = length of ..SCKE2 */
if (Length<=GSM_MAX_SMS_LENGTH-8) {
sprintf(Buffer,"//SCKE2 ");
Length = 8;
GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard10);
} else {
/* FIXME: It wasn't checked */
UDH = UDH_NokiaPhonebookLong;
}
Coding = SMS_Coding_Default;
memcpy(Buffer2,Buffer,Length);
EncodeUnicode(Buffer,Buffer2,Length);
break;
case SMS_NokiaVCARD21Long:
GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard21);
/* Is 1 SMS ? 12 = length of ..SCKL23F4 */
if (Length<=GSM_MAX_SMS_LENGTH-12) {
sprintf(Buffer,"//SCKL23F4%c%c",13,10);
Length = 12;
GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard21);
} else {
UDH = UDH_NokiaPhonebookLong;
/* Here can be also 8 bit coding */
}
Coding = SMS_Coding_Default;
memcpy(Buffer2,Buffer,Length);
EncodeUnicode(Buffer,Buffer2,Length);
break;
case SMS_VCARD10Long:
GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard10);
if (Length>GSM_MAX_SMS_LENGTH) UDH = UDH_ConcatenatedMessages;
Coding = SMS_Coding_Default;
memcpy(Buffer2,Buffer,Length);
EncodeUnicode(Buffer,Buffer2,Length);
break;
case SMS_VCARD21Long:
GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard21);
if (Length>GSM_MAX_SMS_LENGTH) UDH = UDH_ConcatenatedMessages;
Coding = SMS_Coding_Default;
memcpy(Buffer2,Buffer,Length);
EncodeUnicode(Buffer,Buffer2,Length);
break;
case SMS_NokiaVCALENDAR10Long:
error=GSM_EncodeVCALENDAR(Buffer,&Length,Info->Entries[0].Calendar,true,Nokia_VCalendar);
if (error != ERR_NONE) return error;
/* Is 1 SMS ? 8 = length of ..SCKE4 */
if (Length<=GSM_MAX_SMS_LENGTH-8) {
sprintf(Buffer,"//SCKE4 ");
Length = 8;
GSM_EncodeVCALENDAR(Buffer,&Length,Info->Entries[0].Calendar,true,Nokia_VCalendar);
} else {
UDH = UDH_NokiaCalendarLong;
/* can be here 8 bit coding ? */
}
Coding = SMS_Coding_Default;
memcpy(Buffer2,Buffer,Length);
EncodeUnicode(Buffer,Buffer2,Length);
break;
case SMS_NokiaVTODOLong:
error=GSM_EncodeVTODO(Buffer,&Length,Info->Entries[0].ToDo,true,Nokia_VToDo);
if (error != ERR_NONE) return error;
UDH = UDH_NokiaCalendarLong;
Coding = SMS_Coding_Default;
memcpy(Buffer2,Buffer,Length);
EncodeUnicode(Buffer,Buffer2,Length);
break;
case SMS_DisableVoice:
case SMS_DisableFax:
case SMS_DisableEmail:
case SMS_EnableVoice:
case SMS_EnableFax:
case SMS_EnableEmail:
case SMS_VoidSMS:
case SMS_Text:
Class = Info->Class;
switch (Info->Entries[0].ID) {
case SMS_DisableVoice : UDH = UDH_DisableVoice; break;
case SMS_DisableFax : UDH = UDH_DisableFax; break;
case SMS_DisableEmail : UDH = UDH_DisableEmail; break;
case SMS_EnableVoice : UDH = UDH_EnableVoice; break;
case SMS_EnableFax : UDH = UDH_EnableFax; break;
case SMS_EnableEmail : UDH = UDH_EnableEmail; break;
case SMS_VoidSMS : UDH = UDH_VoidSMS; break;
case SMS_Text : UDH = UDH_NoUDH; break;
default : break;
}
UDHHeader.Type = UDH;
GSM_EncodeUDHHeader(&UDHHeader);
memcpy(Buffer,Info->Entries[0].Buffer,UnicodeLength(Info->Entries[0].Buffer)*2+2);
if (Info->UnicodeCoding) {
Coding = SMS_Coding_Unicode;
Length = UnicodeLength(Info->Entries[0].Buffer);
if (Length>(140-UDHHeader.Length)/2) Length = (140-UDHHeader.Length)/2;
} else {
Coding = SMS_Coding_Default;
FindDefaultAlphabetLen(Info->Entries[0].Buffer,&Length,&smslen,(GSM_MAX_8BIT_SMS_LENGTH-UDHHeader.Length)*8/7);
}
break;
case SMS_ConcatenatedAutoTextLong:
case SMS_ConcatenatedAutoTextLong16bit:
smslen = UnicodeLength(Info->Entries[0].Buffer);
memcpy(Buffer,Info->Entries[0].Buffer,smslen*2);
EncodeDefault(Buffer2, Buffer, &smslen, true, NULL);
DecodeDefault(Buffer, Buffer2, smslen, true, NULL);
#ifdef DEBUG
if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) {
dbgprintf("Info->Entries[0].Buffer:\n");
DumpMessage(di.df, di.dl, Info->Entries[0].Buffer, UnicodeLength(Info->Entries[0].Buffer)*2);
dbgprintf("Buffer:\n");
DumpMessage(di.df, di.dl, Buffer, UnicodeLength(Buffer)*2);
}
#endif
Info->UnicodeCoding = false;
for (smslen=0;smslen<(int)(UnicodeLength(Info->Entries[0].Buffer)*2);smslen++) {
if (Info->Entries[0].Buffer[smslen] != Buffer[smslen]) {
Info->UnicodeCoding = true;
dbgprintf("Setting to Unicode %i\n",smslen);
break;
}
}
/* No break here - we go to the SMS_ConcatenatedTextLong */
case SMS_ConcatenatedTextLong:
case SMS_ConcatenatedTextLong16bit:
Class = Info->Class;
memcpy(Buffer,Info->Entries[0].Buffer,UnicodeLength(Info->Entries[0].Buffer)*2+2);
UDH = UDH_NoUDH;
if (Info->UnicodeCoding) {
Coding = SMS_Coding_Unicode;
diff --git a/gammu/emb/common/service/sms/gsmmulti.h b/gammu/emb/common/service/sms/gsmmulti.h
index c672261..3f70d81 100644
--- a/gammu/emb/common/service/sms/gsmmulti.h
+++ b/gammu/emb/common/service/sms/gsmmulti.h
@@ -1,271 +1,280 @@
/* (c) 2002-2004 by Marcin Wiacek */
#ifndef __gsm_multi_h
#define __gsm_multi_h
+#if defined(_MSC_VER) && defined(__cplusplus)
+ extern "C" {
+#endif
+
#include "../../gsmcomon.h"
#include "../gsmlogo.h"
#include "../gsmcal.h"
#include "../gsmpbk.h"
#include "../gsmdata.h"
#include "../gsmring.h"
#include "gsmsms.h"
/* ---------------------- multi SMS --------------------------------------- */
/* Identifiers for Smart Messaging 3.0 multipart SMS */
#define SM30_ISOTEXT 0 /* ISO 8859-1 text */
#define SM30_UNICODETEXT 1
#define SM30_OTA 2
#define SM30_RINGTONE 3
#define SM30_PROFILENAME 4
/* ... */
#define SM30_SCREENSAVER 6
/* Identifiers for Alcatel Terminal Data Download */
#define ALCATELTDD_PICTURE 4
#define ALCATELTDD_ANIMATION 5
#define ALCATELTDD_SMSTEMPLATE 6
void GSM_SMSCounter(int MessageLength,
unsigned char *MessageBuffer,
GSM_UDH UDHType,
GSM_Coding_Type Coding,
int *SMSNum,
int *CharsLeft);
#define MAX_MULTI_SMS 10
/**
* Multiple SMS messages, used for Smart Messaging 3.0/EMS.
*/
typedef struct {
/**
* Sender or recipient number.
*/
unsigned char Number;
/**
* Array of SMSes.
*/
GSM_SMSMessage SMS[MAX_MULTI_SMS];
} GSM_MultiSMSMessage;
GSM_Error GSM_AddSMS_Text_UDH(GSM_MultiSMSMessage *SMS,
GSM_Coding_Type Coding,
char *Buffer,
int BufferLen,
bool UDH,
int *UsedText,
int *CopiedText,
int *CopiedSMSText);
void GSM_MakeMultiPartSMS(GSM_MultiSMSMessage *SMS,
unsigned char *MessageBuffer,
int MessageLength,
GSM_UDH UDHType,
GSM_Coding_Type Coding,
int Class,
unsigned char RejectDuplicates);
void GSM_Find_Free_Used_SMS2(GSM_Coding_Type Coding,GSM_SMSMessage SMS, int *UsedText, int *FreeText, int *FreeBytes);
unsigned char GSM_MakeSMSIDFromTime(void);
/**
* ID during packing SMS for Smart Messaging 3.0, EMS and other
*/
typedef enum {
/**
* 1 text SMS.
*/
SMS_Text = 1,
/**
* Contacenated SMS, when longer than 1 SMS.
*/
SMS_ConcatenatedTextLong,
/**
* Contacenated SMS, auto Default/Unicode coding.
*/
SMS_ConcatenatedAutoTextLong,
SMS_ConcatenatedTextLong16bit,
SMS_ConcatenatedAutoTextLong16bit,
/**
* Nokia profile = Name, Ringtone, ScreenSaver
*/
SMS_NokiaProfileLong,
/**
* Nokia Picture Image + (text)
*/
SMS_NokiaPictureImageLong,
/**
* Nokia screen saver + (text)
*/
SMS_NokiaScreenSaverLong,
/**
* Nokia ringtone - old SM2.0 format, 1 SMS
*/
SMS_NokiaRingtone,
/**
* Nokia ringtone contacenated, when very long
*/
SMS_NokiaRingtoneLong,
/**
* Nokia 72x14 operator logo, 1 SMS
*/
SMS_NokiaOperatorLogo,
/**
* Nokia 72x14 op logo or 78x21 in 2 SMS
*/
SMS_NokiaOperatorLogoLong,
/**
* Nokia 72x14 caller logo, 1 SMS
*/
SMS_NokiaCallerLogo,
/**
* Nokia WAP bookmark in 1 or 2 SMS
*/
SMS_NokiaWAPBookmarkLong,
/**
* Nokia WAP settings in 2 SMS
*/
SMS_NokiaWAPSettingsLong,
/**
* Nokia MMS settings in 2 SMS
*/
SMS_NokiaMMSSettingsLong,
/**
* Nokia VCARD 1.0 - only name and default number
*/
SMS_NokiaVCARD10Long,
/**
* Nokia VCARD 2.1 - all numbers + text
*/
SMS_NokiaVCARD21Long,
/**
* Nokia VCALENDAR 1.0 - can be in few sms
*/
SMS_NokiaVCALENDAR10Long,
SMS_NokiaVTODOLong,
SMS_VCARD10Long,
SMS_VCARD21Long,
SMS_DisableVoice,
SMS_DisableFax,
SMS_DisableEmail,
SMS_EnableVoice,
SMS_EnableFax,
SMS_EnableEmail,
SMS_VoidSMS,
/**
* IMelody 1.0
*/
SMS_EMSSound10,
/**
* IMelody 1.2
*/
SMS_EMSSound12,
/**
* IMelody without header - SonyEricsson extension
*/
SMS_EMSSonyEricssonSound,
/**
* IMelody 1.0 with UPI.
*/
SMS_EMSSound10Long,
- /***
+ /**
* IMelody 1.2 with UPI.
*/
SMS_EMSSound12Long,
/**
* IMelody without header with UPI.
*/
SMS_EMSSonyEricssonSoundLong,
SMS_EMSPredefinedSound,
SMS_EMSPredefinedAnimation,
SMS_EMSAnimation,
/**
* Fixed bitmap of size 16x16 or 32x32.
*/
SMS_EMSFixedBitmap,
SMS_EMSVariableBitmap,
SMS_EMSVariableBitmapLong,
SMS_MMSIndicatorLong,
+ SMS_WAPIndicatorLong,
/**
* Variable bitmap with black and white colors
*/
SMS_AlcatelMonoBitmapLong,
/**
* Variable animation with black and white colors
*/
SMS_AlcatelMonoAnimationLong,
SMS_AlcatelSMSTemplateName
} EncodeMultiPartSMSID;
typedef struct {
EncodeMultiPartSMSID ID;
int Number;
GSM_Ringtone *Ringtone;
GSM_MultiBitmap *Bitmap;
GSM_WAPBookmark *Bookmark;
GSM_WAPSettings *Settings;
GSM_MMSIndicator *MMSIndicator;
GSM_MemoryEntry *Phonebook;
GSM_CalendarEntry *Calendar;
GSM_ToDoEntry *ToDo;
bool Protected;
unsigned char *Buffer;
bool Left;
bool Right;
bool Center;
bool Large;
bool Small;
bool Bold;
bool Italic;
bool Underlined;
bool Strikethrough;
/* Return values */
int RingtoneNotes;
} MultiPartSMSEntry;
typedef struct {
MultiPartSMSEntry Entries[MAX_MULTI_SMS];
int EntriesNum;
bool UnicodeCoding;
int Class;
unsigned char ReplaceMessage;
bool Unknown;
} GSM_MultiPartSMSInfo;
/**
* Encodes multi part SMS from "readable" format.
*/
GSM_Error GSM_EncodeMultiPartSMS (GSM_MultiPartSMSInfo *Info, GSM_MultiSMSMessage *SMS);
/**
* Decodes multi part SMS to "readable" format.
*/
bool GSM_DecodeMultiPartSMS (GSM_MultiPartSMSInfo *Info, GSM_MultiSMSMessage *SMS, bool ems);
/**
* Clears @ref GSM_MultiPartSMSInfo to default values.
*/
void GSM_ClearMultiPartSMSInfo (GSM_MultiPartSMSInfo *Info);
/**
* Frees any allocated structures inside @ref GSM_MultiPartSMSInfo.
*/
void GSM_FreeMultiPartSMSInfo (GSM_MultiPartSMSInfo *Info);
/**
* Links SMS messages according to IDs.
*/
GSM_Error GSM_LinkSMS(GSM_MultiSMSMessage **INPUT, GSM_MultiSMSMessage **OUTPUT, bool ems);
+#if defined(_MSC_VER) && defined(__cplusplus)
+ }
+#endif
+
#endif
/* How should editor hadle tabs in this file? Add editor commands here.
* vim: noexpandtab sw=8 ts=8 sts=8:
*/
diff --git a/gammu/emb/common/service/sms/gsmsms.c b/gammu/emb/common/service/sms/gsmsms.c
index 9920835..feceba4 100644
--- a/gammu/emb/common/service/sms/gsmsms.c
+++ b/gammu/emb/common/service/sms/gsmsms.c
@@ -1,194 +1,197 @@
/* (c) 2001-2004 by Marcin Wiacek */
-/* based on some work from Pawel Kot, others and Gnokii */
+/* Based on some Pawel Kot and others work from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
#include <ctype.h>
#include <string.h>
#include <time.h>
#include "../../gsmcomon.h"
#include "../../misc/coding/coding.h"
#include "../gsmcal.h"
#include "../gsmpbk.h"
#include "../gsmlogo.h"
#include "../gsmring.h"
#include "../gsmdata.h"
#include "../gsmnet.h"
#include "gsmsms.h"
/* User data headers */
static GSM_UDHHeader UDHHeaders[] = {
/* See GSM 03.40 section 9.2.3.24.1
* 1 byte 0x00
* 1 byte 0x03
* 1 byte 0x01: unique ID for message series
* 1 byte 0x00: how many SMS in sequence
* 1 byte 0x00: number of current SMS in sequence */
{ UDH_ConcatenatedMessages, 0x05, "\x00\x03\x01\x00\x00",2,-1,4,3},
/* See GSM 03.40 section 9.2.3.24.2 for voice, fax and email messages */
{ UDH_DisableVoice, 0x04, "\x01\x02\x00\x00",-1,-1,-1,-1},
{ UDH_DisableFax, 0x04, "\x01\x02\x01\x00",-1,-1,-1,-1},
{ UDH_DisableEmail, 0x04, "\x01\x02\x02\x00",-1,-1,-1,-1},
{ UDH_EnableVoice, 0x04, "\x01\x02\x00\x01",-1,-1,-1,-1},
{ UDH_EnableFax, 0x04, "\x01\x02\x01\x01",-1,-1,-1,-1},
{ UDH_EnableEmail, 0x04, "\x01\x02\x02\x01",-1,-1,-1,-1},
/* When send such SMS to some phones, they don't display anything,
* only beep and enable vibra/light
*/
{ UDH_VoidSMS, 0x08, "\x01\x02\x02\x01\x01\x02\x02\x00",-1,-1,-1,-1},
/* Nokia Smart Messaging (short version) 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 */
{ UDH_NokiaRingtone, 0x06, "\x05\x04\x15\x81\x00\x00",-1,-1,-1,-1},
{ UDH_NokiaOperatorLogo, 0x06, "\x05\x04\x15\x82\x00\x00",-1,-1,-1,-1},
{ UDH_NokiaCallerLogo, 0x06, "\x05\x04\x15\x83\x00\x00",-1,-1,-1,-1},
{ UDH_NokiaWAP, 0x06, "\x05\x04\xc3\x4f\x00\x00",-1,-1,-1,-1},
/* Nokia Smart Messaging (long version) UDH and other
* 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 : SAR
* 1 byte 0x03 : SAR length
* 1 byte : diagram reference number (unique ID for message series)
* 1 byte : number of all SMS
* 1 byte : number of current SMS */
{ UDH_NokiaCalendarLong, 0x0b, "\x05\x04\x00\xe4\x00\x00\x00\x03\xc7\x00\x00",8,-1,10,9},
{ UDH_MMSIndicatorLong, 0x0b, "\x05\x04\x0b\x84\x23\xf0\x00\x03\xe5\x00\x00",8,-1,10,9},
{ UDH_NokiaRingtoneLong, 0x0b, "\x05\x04\x15\x81\x00\x00\x00\x03\x01\x00\x00",8,-1,10,9},
{ UDH_NokiaOperatorLogoLong, 0x0b, "\x05\x04\x15\x82\x00\x00\x00\x03\x02\x00\x00",8,-1,10,9},
{ UDH_NokiaProfileLong, 0x0b, "\x05\x04\x15\x8a\x00\x00\x00\x03\xce\x00\x00",8,-1,10,9},
{ UDH_NokiaPhonebookLong, 0x0b, "\x05\x04\x23\xf4\x00\x00\x00\x03\x01\x00\x00",8,-1,10,9},
{ UDH_NokiaWAPLong, 0x0b, "\x05\x04\xc3\x4f\x00\x00\x00\x03\x7f\x00\x00",8,-1,10,9},
{ UDH_ConcatenatedMessages16bit,0x06, "\x08\x04\x00\x00\x00\x00",-1,2,5,4},
{ UDH_NoUDH, 0x00, "",-1,-1,-1,-1}
};
/* --------------------------- Unpacking SMS ------------------------------- */
/* See GSM 03.40 section 9.2.3.11 */
static GSM_Error GSM_DecodeSMSDateTime(GSM_DateTime *DT, unsigned char *req)
{
DT->Year = DecodeWithBCDAlphabet(req[0]);
if (DT->Year<90) DT->Year=DT->Year+2000; else DT->Year=DT->Year+1990;
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]);
/* Base for timezone is GMT. It's in quarters */
DT->Timezone=(10*(req[6]&0x07)+(req[6]>>4))/4;
if (req[6]&0x08) DT->Timezone = -DT->Timezone;
dbgprintf("Decoding date & time: ");
dbgprintf("%s %4d/%02d/%02d ", DayOfWeek(DT->Year, DT->Month, DT->Day),
DT->Year, DT->Month, DT->Day);
dbgprintf("%02d:%02d:%02d %02d00\n", DT->Hour, DT->Minute, DT->Second, DT->Timezone);
return ERR_NONE;
}
void GSM_DecodeUDHHeader(GSM_UDHHeader *UDH)
{
int i, tmp, w;
bool UDHOK;
UDH->Type = UDH_UserUDH;
UDH->ID8bit = -1;
UDH->ID16bit = -1;
UDH->PartNumber = -1;
UDH->AllParts = -1;
i=-1;
while (true) {
i++;
if (UDHHeaders[i].Type==UDH_NoUDH) break;
tmp=UDHHeaders[i].Length;
/* if length is the same */
if (tmp==UDH->Text[0]) {
if (tmp==0x05) tmp=tmp-3;/*three last bytes can be different for such UDH*/
if (tmp==0x0b) tmp=tmp-3;/*three last bytes can be different for such UDH*/
if (tmp==0x06 && UDH->Text[1] == 0x08) tmp=tmp-4;
UDHOK=true;
for (w=0;w<tmp;w++) {
if (UDHHeaders[i].Text[w]!=UDH->Text[w+1]) {
UDHOK=false;
break;
}
}
if (UDHOK) {
UDH->Type=UDHHeaders[i].Type;
if (UDHHeaders[i].ID8bit !=-1) UDH->ID8bit = UDH->Text[UDHHeaders[i].ID8bit+1];
if (UDHHeaders[i].ID16bit !=-1) UDH->ID16bit = UDH->Text[UDHHeaders[i].ID16bit+1]*256+UDH->Text[UDHHeaders[i].ID16bit+2];
if (UDHHeaders[i].PartNumber !=-1) UDH->PartNumber = UDH->Text[UDHHeaders[i].PartNumber+1];
if (UDHHeaders[i].AllParts !=-1) UDH->AllParts = UDH->Text[UDHHeaders[i].AllParts+1];
break;
}
}
}
#ifdef DEBUG
dbgprintf("Type of UDH: ");
switch (UDH->Type) {
case UDH_ConcatenatedMessages : dbgprintf("Concatenated (linked) message"); break;
case UDH_ConcatenatedMessages16bit : dbgprintf("Concatenated (linked) message"); break;
case UDH_DisableVoice : dbgprintf("Disables voice indicator"); break;
case UDH_EnableVoice : dbgprintf("Enables voice indicator"); break;
case UDH_DisableFax : dbgprintf("Disables fax indicator"); break;
case UDH_EnableFax : dbgprintf("Enables fax indicator"); break;
case UDH_DisableEmail : dbgprintf("Disables email indicator"); break;
case UDH_EnableEmail : dbgprintf("Enables email indicator"); break;
case UDH_VoidSMS : dbgprintf("Void SMS"); break;
case UDH_NokiaWAP : dbgprintf("Nokia WAP Bookmark"); break;
case UDH_NokiaOperatorLogoLong : dbgprintf("Nokia operator logo"); break;
case UDH_NokiaWAPLong : dbgprintf("Nokia WAP Bookmark or WAP/MMS Settings"); break;
case UDH_NokiaRingtone : dbgprintf("Nokia ringtone"); break;
case UDH_NokiaRingtoneLong : dbgprintf("Nokia ringtone"); break;
case UDH_NokiaOperatorLogo : dbgprintf("Nokia GSM operator logo"); break;
case UDH_NokiaCallerLogo : dbgprintf("Nokia caller logo"); break;
case UDH_NokiaProfileLong : dbgprintf("Nokia profile"); break;
case UDH_NokiaCalendarLong : dbgprintf("Nokia calendar note"); break;
case UDH_NokiaPhonebookLong : dbgprintf("Nokia phonebook entry"); break;
case UDH_UserUDH : dbgprintf("User UDH"); break;
case UDH_MMSIndicatorLong : dbgprintf("MMS indicator"); break;
case UDH_NoUDH: break;
}
if (UDH->ID8bit != -1) dbgprintf(", ID 8 bit %i",UDH->ID8bit);
if (UDH->ID16bit != -1) dbgprintf(", ID 16 bit %i",UDH->ID16bit);
if (UDH->PartNumber != -1 && UDH->AllParts != -1) {
dbgprintf(", part %i of %i",UDH->PartNumber,UDH->AllParts);
}
dbgprintf("\n");
if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, UDH->Text, UDH->Length);
#endif
}
GSM_Error GSM_DecodeSMSFrameText(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout)
{
int off=0; // length of the User Data Header
int w,i,tmp=0;
unsigned char output[161];
SMS->UDH.Length = 0;
/* UDH header available */
if (buffer[Layout.firstbyte] & 64) {
/* Length of UDH header */
off = (buffer[Layout.Text] + 1);
SMS->UDH.Length = off;
dbgprintf("UDH header available (length %i)\n",off);
diff --git a/gammu/emb/common/service/sms/gsmsms.h b/gammu/emb/common/service/sms/gsmsms.h
index d87ff60..0b950d3 100644
--- a/gammu/emb/common/service/sms/gsmsms.h
+++ b/gammu/emb/common/service/sms/gsmsms.h
@@ -1,194 +1,197 @@
/* (c) 2001-2004 by Marcin Wiacek */
-/* based on some work from Pawel Kot, others and Gnokii */
+/* Based on some Pawel Kot and others work from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
+ */
#ifndef __gsm_sms_h
#define __gsm_sms_h
#include "../../gsmcomon.h"
#include "../gsmlogo.h"
#include "../gsmcal.h"
#include "../gsmpbk.h"
#include "../gsmdata.h"
#include "../gsmring.h"
/* --------------------- Some general definitions ------------------------- */
#define GSM_MAX_UDH_LENGTH 140
#define GSM_MAX_SMS_LENGTH 160
#define GSM_MAX_8BIT_SMS_LENGTH 140
/* -------------------- Cell Broadcast ------------------------------------ */
/**
* Structure for Cell Broadcast messages.
*/
typedef struct {
/**
* Message text.
*/
char Text[300];
/**
* Channel number.
*/
int Channel;
} GSM_CBMessage;
/* ------------------------ SMS status ------------------------------------ */
/**
* Status of SMS memory.
*/
typedef struct {
/**
* Number of unread messages on SIM.
*/
int SIMUnRead;
/**
* Number of all saved messages (including unread) on SIM.
*/
int SIMUsed;
/**
* Number of all possible messages on SIM.
*/
int SIMSize;
/**
* Number of used templates (62xx/63xx/7110/etc.).
*/
int TemplatesUsed;
/**
* Number of unread messages in phone.
*/
int PhoneUnRead;
/**
* Number of all saved messages in phone.
*/
int PhoneUsed;
/**
* Number of all possible messages on phone.
*/
int PhoneSize;
} GSM_SMSMemoryStatus;
/* --------------------- SMS Center --------------------------------------- */
/**
* Enum defines format of SMS messages. See GSM 03.40 section 9.2.3.9
*/
typedef enum {
SMS_FORMAT_Pager = 1,
SMS_FORMAT_Fax,
SMS_FORMAT_Email,
SMS_FORMAT_Text
/* Some values not handled here */
} GSM_SMSFormat;
/**
* Enum defines some the most often used validity lengths for SMS messages
* for relative validity format. See GSM 03.40 section 9.2.3.12.1 - it gives
* more values
*/
typedef enum {
SMS_VALID_1_Hour = 0x0b,
SMS_VALID_6_Hours = 0x47,
SMS_VALID_1_Day = 0xa7,
SMS_VALID_3_Days = 0xa9,
SMS_VALID_1_Week = 0xad,
SMS_VALID_Max_Time = 0xff
} GSM_ValidityPeriod;
/**
* Enum defines format of validity period for SMS messages.
* See GSM 03.40 section 9.2.3.12
*/
typedef enum {
SMS_Validity_NotAvailable = 1,
SMS_Validity_RelativeFormat
/* Specification gives also other possibilities */
} GSM_ValidityPeriodFormat;
/**
* Structure for validity of SMS messages
*/
typedef struct {
GSM_ValidityPeriodFormat Format;
/**
* Value defines period for relative format
*/
GSM_ValidityPeriod Relative;
} GSM_SMSValidity;
#define GSM_MAX_SMSC_NAME_LENGTH 30
/**
* Structure for SMSC (SMS Center) information.
*/
typedef struct {
/**
* Number of the SMSC on SIM
*/
int Location;
/**
* Name of the SMSC
*/
unsigned char Name[(GSM_MAX_SMSC_NAME_LENGTH+1)*2];
/**
* SMSC phone number.
*/
unsigned char Number[(GSM_MAX_NUMBER_LENGTH+1)*2];
/**
* Validity of SMS messages.
*/
GSM_SMSValidity Validity;
/**
* Format of sent SMS messages.
*/
GSM_SMSFormat Format;
/**
* Default recipient number. In old DCT3 ignored
*/
unsigned char DefaultNumber[(GSM_MAX_NUMBER_LENGTH+1)*2];
} GSM_SMSC;
/* --------------------- single SMS --------------------------------------- */
/**
* Status of SMS message.
*/
typedef enum {
SMS_Sent = 1,
SMS_UnSent,
SMS_Read,
SMS_UnRead
} GSM_SMS_State;
/**
* Coding type of SMS.
*/
typedef enum {
/**
* Unicode
*/
SMS_Coding_Unicode = 1,
/**
* Default GSM aplhabet.
*/
SMS_Coding_Default,
/**
* 8-bit.
*/
SMS_Coding_8bit
} GSM_Coding_Type;
/**
* Types of UDH (User Data Header).
*/
typedef enum {
UDH_NoUDH = 1,
/**
* Linked SMS.
*/
UDH_ConcatenatedMessages,
/**
* Linked SMS with 16 bit reference.
*/
UDH_ConcatenatedMessages16bit,